home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume9 / elm2 / part13 < prev    next >
Text File  |  1987-03-09  |  44KB  |  1,424 lines

  1. Subject:  v09i013:  ELM Mail System, Part13/19
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: Dave Taylor <hplabs!taylor>
  6. Mod.sources: Volume 9, Issue 13
  7. Archive-name: elm2/Part13
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If this archive is complete, you will see the message:
  13. #        "End of archive 13 (of 19)."
  14. # Contents:  test/test.notes utils/arepdaemon.c utils/newalias.c
  15. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  16. echo shar: Extracting \"test/test.notes\" \(13582 characters\)
  17. if test -f test/test.notes ; then 
  18.   echo shar: Will not over-write existing file \"test/test.notes\"
  19. else
  20. sed "s/^X//" >test/test.notes <<'END_OF_test/test.notes'
  21. X/***** hpfloat:net.micro.68K / barrett /  2:39 pm  Dec 16, 1985*/
  22. XDoes anyone here at this site know anything about hang-gliding? 
  23. X
  24. XI am thinking of learning to hang-glide, but am afraid of heights.  I
  25. Xdo fly light planes and love the hairiest roller coaster rides available
  26. Xhowever.  My main question is "is there a way to learn to hang-glide 
  27. Xgradually?"  I have seen some films of people learning on big sand dunes
  28. Xan such before leaping off of cliffs with the things.  
  29. X
  30. XDave Barrett
  31. Xhpfcla!barrett
  32. X/* ---------- */
  33. X/***** hpcnof:fsd.rec / hpfcla!ajs /  5:57 pm  Dec 16, 1985*/
  34. X> Does anyone here at this site know anything about hang-gliding? 
  35. X
  36. XYeah.  Don't waste your time, don't waste your money, don't risk your life.
  37. X
  38. X> I am thinking of learning to hang-glide, but am afraid of heights.
  39. X
  40. XI wasn't, but it still got me a broken arm.
  41. X
  42. X> My main question is "is there a way to learn to hang-glide gradually?"
  43. X
  44. XProbably not (yet).  Five years ago, simulators were in practice non-
  45. Xexistent.  We got twenty seconds hanging in a triangular control bar
  46. Xwith a person pushing.  Next stop, rocky slopes, real gliders, and cheap
  47. Xwalkie-talkies.
  48. X
  49. XYou'd be amazed how easy it is to injure yourself.  It's the nature of
  50. Xthe hobby.  People with plenty of experience die doing it every day,
  51. Xdue to circumstances often beyond their control.  There are better ways
  52. Xto get thrills.
  53. X
  54. XAlan
  55. X/* ---------- */
  56. X/***** hpcnof:fsd.rec / hpfcms!mpm /  8:58 pm  Dec 16, 1985*/
  57. X
  58. X>You'd be amazed how easy it is to injure yourself.  It's the nature of
  59. X>the hobby.  People with plenty of experience die doing it every day,
  60. X>due to circumstances often beyond their control.  There are better ways
  61. X>to get thrills.
  62. X>Alan
  63. X
  64. X     I haven't done any hang-gliding myself, but I would like to try it
  65. Xsome day.  (I have a moderate fear of heights; it depends on the altitude
  66. Xand the apparent stability of my "perch".)
  67. X
  68. X     I read (or heard) that MOST hang-gliding accidents fall into two
  69. Xcategories:
  70. X
  71. X     1) novices attempt something beyond their experience (like jumping
  72. X    off a tall building after one lesson on a gently sloped hill),
  73. X
  74. X     2) experts attempt VERY dramatic stuff (like jumping off El
  75. X    Capitan in unpredictable thermal up- and down- drafts).
  76. X
  77. X     Please note:  Alan Silverstein doesn't fall in EITHER category.  I
  78. Xtook some sport parachuting lessons a few years ago.  It turned out to be
  79. Xquite safe GIVEN ADEQUATE TRAINING as I had at the time.  I suspect the
  80. Xsame would hold true for hang-gliding (or rapelling, or ice climbing, or
  81. X...).  The best way to find out if you can overcome your fears is by con-
  82. Xfronting them in a safe and supportive environment.
  83. X
  84. X     My recommendation:  check out any "school" before you sign up.  Ask
  85. Xabout their safety record, the terrain where they offer lessons, amount of
  86. X"ground school" training before first "flight", etc.  Above all, make sure
  87. Xthat you TRUST any prospective teacher.  Even if you have no logical reason
  88. Xto distrust someone, don't try something like this unless you trust them.
  89. X(This is where your rational mind needs to work with your intuition.)
  90. XOtherwise you could easily get hurt.
  91. X
  92. X     This is likely to be unknown territory for you, so be prepared and
  93. Xyou will likely have a more enjoyable (and safe) experience.  Of course,
  94. Xthere is ALWAYS the chance for an accident.
  95. X
  96. X    -- Mike "no I wasn't crazy at the time; I WANTED to do it" McCarthy
  97. X       hpfcla!mpm
  98. X/* ---------- */
  99. X/***** hpcnof:fsd.rec / dat / 12:12 pm  Dec 19, 1985*/
  100. X>> Does anyone here at this site know anything about hang-gliding? 
  101. X>Yeah.  Don't waste your time, don't waste your money, don't risk your life.
  102. X
  103. X    Strong stuff!  I think you're out on a limb this time, Alan.
  104. XI've known lots of people who've hang-glided and never gotten hurt.
  105. X(and we're talking the La Jolla cliffs in San Diego!!) (they also
  106. Xthink it's the best 'high' in the world (and they've tried some
  107. Xpretty strange things to compare!))
  108. X
  109. X>> I am thinking of learning to hang-glide, but am afraid of heights.
  110. X>I wasn't, but it still got me a broken arm.
  111. X
  112. X    Fine.  So I broke my arm a long time ago jumping off a bunk
  113. Xbed.  Does this mean that bunk beds are too dangerous and that I 
  114. Xshouldn't ever sleep in one???
  115. X
  116. X    The point is that anything you do is dangerous and that the
  117. Xway to minimize the danger is to take things gradually and only 
  118. Xprogress when you feel comfortable with your current level of learning.
  119. XAt the same time realize that even sitting in a chair in a warm room
  120. Xcould be dangerous, so don't be so foolishly optimistic to think that
  121. Xyou cannot get seriously hurt hang-gliding.
  122. X
  123. X    On the other hand - if you want to go for it - GO FOR IT!!!
  124. X
  125. X            -- Dave "Cheap Thrills, Inc." Taylor
  126. X/* ---------- */
  127. X/***** hpcnof:fsd.rec / hpfcmp!rjn / 11:33 pm  Dec 16, 1985*/
  128. Xre: hang gliding
  129. X
  130. XI am a licensed [so what] pilot in powered  aircraft and  sailplanes.  I was
  131. Xtaking  hang  gliding  (HG)  instruction  four years ago (prior to moving to
  132. XColorado).  I gave it up when I moved here.  My impressions:
  133. X
  134. X* If your  introduction  to piloting flying machines is via HG, you will not
  135. X  have enough  understanding of aerodynamics to safely operate your craft in
  136. X  calm or steady-wind conditions.
  137. X
  138. X* HGs which are controlled by weight  shifting do not have adequate  control
  139. X  authority   for   normal   conditions,   unless   you  have  lots  of  the
  140. X  aforementioned  understanding and fly only in ideal  conditions.  HGs with
  141. X  3-axis control offer a little more margin.
  142. X
  143. X* HGs are typically operated close to the ground.  No HG designs have enough
  144. X  control  authority  to handle  gusty  conditions.  You can  safely  land a
  145. X  parachute in conditions  which are dangerous for HG  operation.  Flying in
  146. X  gusty  conditions  is the most  popular  way to crash a HG.  If you  think
  147. X  jumping is dangerous, don't take up HG.  (I used to room with a jumpmaster
  148. X  and have made one jump myself.  I think jumping is safer.)
  149. X
  150. X* HGs operated at higher altitudes (away from ground  reference) suffer from
  151. X  lack of  instrumentation.  It is easy to enter a spiral dive, spin or deep
  152. X  stall (luff the sail on Rogallo machines)  without  instruments or lots of
  153. X  experience.  Spiral dives usually  overstress  the airframe; the resulting
  154. X  collection of parts crashes.
  155. X
  156. XIf you  insist on K-Mart  aviating,  I suggest a 2-place  ultra-light  (with
  157. Xparachute), a good instructor and a calm day.  At least the ground is level.
  158. XBring earplugs.
  159. X
  160. XBob Niland  TN-226-4014   HP-UX: hpfcla!rjn    DESK: rjn (hpfcla) /HP4000/UX
  161. X/* ---------- */
  162. X/***** hpcnof:fsd.rec / hpfloat!jim /  9:10 am  Dec 17, 1985*/
  163. XTry flying across the waves on a windsurfer!  I once met a guy from
  164. XDenver who said he had tried them all--hang gliding, sky diving.  Windsurfing
  165. Xoffered just as much thrill with almost no risk.
  166. X
  167. XThe crash landings are rather painless.  I've gotten 5 feet of air right
  168. Xhere in Colorado.
  169. X
  170. X        "Jumping Jim" Tear
  171. X
  172. X/* ---------- */
  173. X/***** hpcnof:fsd.rec / hpfcmt!ron /  7:56 am  Dec 17, 1985*/
  174. X
  175. X
  176. XI also am a "regular" aircraft (and sailplane) pilot.
  177. X
  178. XI have not tried hang gliding however I have a fairly close friend who 
  179. Xwas into it before he totally demolished his craft. He was only bruised
  180. Xby the impact but came away considerably more careful about his sports.
  181. X
  182. XBesides the previously mentioned drawbacks I would like to mention the 
  183. Xfollowing:
  184. X
  185. XA perfect landing consists of
  186. X
  187. X   (a) Correct airspeed
  188. X   (b) Level wings ( tolerance to prevent wingtip dragging)
  189. X   (c) Correct yaw alignment   (within tolerance of landing gear)
  190. X   (d) Correct pitch
  191. X   (e) Correct rate of descent  (within tolerance of landing gear)
  192. X   (f) Correct altitude
  193. X   (g) Correct groundspeed (within tolerance of landing gear) 
  194. X
  195. XConsider that the landing gear on an HG is your legs and gear collapse
  196. Xis fairly common due to the low maximum speed for the gear and the 
  197. Xairspeed being right in that range at touchdown.
  198. XConsider also that even calm air has some "breezes" going. 
  199. XAdd to the "breezes" the fact that your control authority relative to the
  200. Xvelocity of the breezes is poor and you can wind up with all the ingredients
  201. Xfor a face plant.
  202. X
  203. XNow to moderate the above, the idea of simple flight appeals greatly to
  204. Xme. Unfortunately my personal risk-taking threshold is below the minimum
  205. Xrisk for this sport.  
  206. XI agree with Bob, try ultra-lights if you MUST . At least they have wheels.
  207. X
  208. X
  209. XRon Miller
  210. X
  211. X
  212. X"Show me a country where the newspapers are filled with good news
  213. Xand I'll show you a country where the jails are filled with good people."
  214. X                    -<I forgot>
  215. X
  216. XService Engineering  (Hardware Support)
  217. XHewlett-Packard Co.
  218. XFt. Collins Systems Div. Home of the HP 9000 Series 200,300 & 500
  219. XFt. Collins Colorado
  220. X303-226-3800
  221. X
  222. Xat: {ihnp4}hpfcla!ron
  223. X/* ---------- */
  224. X/***** hpcnof:fsd.rec / hpfcla!ajs /  6:36 pm  Dec 19, 1985*/
  225. X> Strong stuff!  I think you're out on a limb this time, Alan.
  226. X> I've known lots of people who've hang-glided and never gotten hurt.
  227. X
  228. XYes, but, --
  229. X
  230. X> Fine.  So I broke my arm a long time ago jumping off a bunk
  231. X> bed.  Does this mean that bunk beds are too dangerous and that I 
  232. X> shouldn't ever sleep in one???
  233. X
  234. XI'll be more explicit (and just as strong).  Let's say sleeping is a
  235. Xzero (epsilon?) on the risk scale, and flying in a commercial aircraft
  236. Xis 1, and driving a car, oh, I'd guess about a 4, and parachuting maybe
  237. Xa 6, and SCUBA diving must be maybe a 7 or 8 then, comparable (?) with
  238. Xclimbing Fourteeners.  Based on my experience with it, I'd rank hang
  239. Xgliding at around a 12 or 15.  Don't risk your life.
  240. X
  241. XOne thing I discovered is that being under a "kite" feels very different
  242. Xfrom how you might guess while watching someone fly.  Not nearly as
  243. Xcomfortable (until airborne); very exposed.  Some people are naturals at
  244. Xit; some (like me) are not.  If you are the former, and you are lucky,
  245. Xand it appeals to you, you'll go do it anyway, no matter what I or Dave
  246. Xsay about it; good luck to you.
  247. X
  248. XBut, if you are the latter, you'll likely injure yourself seriously
  249. Xtrying to learn, because there isn't much margin for error outside a
  250. Xsimulator.  Look, I was gung-ho, being trained by a "professional"
  251. Xtraining school, determined to overcome inexperience, ignored warnings
  252. Xfrom concerned friends, was certain I could do it safely, paid close
  253. Xattention to instructions, studied the subject intensely, and when I
  254. Xcrashed, I'd been in the air about five seconds, was about ten feet off
  255. Xthe ground, and was amazed that I'd actually broken anything.  A very
  256. Xsobering experience.
  257. X
  258. XOn the way to the hospital, the trainer doing the driving informed me
  259. Xthat someone was seriously injured in their classes about once a month.
  260. X
  261. XGee, Dave, I guess I must be "out on a limb", incapable of giving advice
  262. Xon the subject, because I survived the crash.  :-)
  263. X
  264. XAlan
  265. X/* ---------- */
  266. X/***** hpcnof:fsd.rec / hpfcde!anny /  2:28 pm  Dec 31, 1985*/
  267. XWARNING:  Severe Base Note  D  r   i    f      t
  268. X
  269. X<. . . and driving a car, oh, I'd guess about a 4, and parachuting maybe
  270. X<a 6, and SCUBA diving must be maybe a 7 or 8 then, . . .
  271. X
  272. XCome on Alan!  SCUBA diving more dangerous than parachuting?  Maybe if your
  273. Xparachuting off a jump tower versus SCUBA diving alone on the Great Barrier
  274. XReef at night carring shark bait making wounded fish sounds. . . ;-)
  275. X
  276. XAfter all, the FIRST time you parachute, you have to jump out of a PLANE! (/.\)
  277. XIn the SKY!  You can SCUBA dive in a pool or a shallow lake or inlet.
  278. XIf something goes wrong in the water, your buddy's there to help.  If 
  279. Xsomething goes wrong in the sky, so long . . .
  280. X
  281. XJust defending what I consider to be a fun and safe sport!
  282. X
  283. XAnny (low altitude (4' or less) sports for me!) Randel
  284. X/* ---------- */
  285. X/***** hpcnof:fsd.rec / hpfcla!ajs /  9:27 am  Jan  2, 1986*/
  286. X> Come on Alan!  SCUBA diving more dangerous than parachuting?
  287. X
  288. XForgive me, I was just guessing, to make a point.  I don't know the
  289. Xactual statistics, but you're probably right -- if you measure accidents
  290. Xper hour.  On the other hand, if you measure accidents per jump or dive,
  291. Xit wouldn't surprise me if the rates were similar.  Lotsa people go
  292. Xdiving without enough training, but skydiving requires decent training
  293. Xand the accident rate is surprisingly low.
  294. X
  295. XAlan "pick your poison" Silverstein
  296. X/* ---------- */
  297. X/***** hpcnof:fsd.rec / hpfcdc!donn /  9:32 am  Jan  3, 1986*/
  298. XThe problem with SCUBA diving is the fact that "fly by nites" can
  299. Xafford to get into the business.  A reputable dive shop will not
  300. Xlet you rent a tank unless you have a NAUI card (or ==) (and they'll hold
  301. Xit while you have the tanks).  However there are always some who
  302. Xwill not do this, and some clown tries diving without essentially
  303. Xany training ("Gee, I can swim, so I can dive.") and gets into
  304. Xtrouble.  It's much tougher to be a "fly by night" (or anytime)
  305. Xwhen you need an airplane and a pilot's license.  Actually, the
  306. Xaccident rate for people with any significant training *and* who
  307. Xare doing something more-or-less reasonable is not bad.  (Diving
  308. Xbelow 150ft (or maybe less) is like starting a jump at 50000 feet:
  309. Xit might work, but good luck unless you know what you're doing. 
  310. XThe problem is that there isn't much reason to start at 50000 feet,
  311. Xbut there's a lot of interesting and valuable stuff below 150.)
  312. X
  313. XI like to dive (tropical saltwater only, so I don't do it much),
  314. Xand since one of the graduation exercises is diving while someone
  315. Xis *trying* to make you screw up (albeit in a pool where there's
  316. Xsomeone to fish you out), you learn to handle problems.  If you're
  317. Xgutsy, try the NAUI *instructors* class: the graduation from that
  318. Xis a open-water dive with known defective equipment!
  319. X
  320. XDonn
  321. X/* ---------- */
  322. END_OF_test/test.notes
  323. if test 13582 -ne `wc -c <test/test.notes`; then
  324.     echo shar: \"test/test.notes\" unpacked with wrong size!?
  325. fi
  326. # end of overwriting check
  327. fi
  328. echo shar: Extracting \"utils/arepdaemon.c\" \(13412 characters\)
  329. if test -f utils/arepdaemon.c ; then 
  330.   echo shar: Will not over-write existing file \"utils/arepdaemon.c\"
  331. else
  332. sed "s/^X//" >utils/arepdaemon.c <<'END_OF_utils/arepdaemon.c'
  333. X/**            arepdaemon.c            **/
  334. X
  335. X/** (C) Copyright 1986 Dave Taylor            **/
  336. X
  337. X/** Keep track of mail as it arrives, and respond by sending a 'recording'
  338. X    file to the sender as new mail is received.
  339. X
  340. X    Note: the user program that interacts with this program is the
  341. X    'autoreply' program and that should be consulted for further
  342. X    usage information.
  343. X
  344. X    This program is part of the 'autoreply' system, and is designed
  345. X    to run every hour and check all mailboxes listed in the file 
  346. X    "/etc/autoreply.data", where the data is in the form:
  347. X
  348. X    username    replyfile    current-mailfile-size
  349. X
  350. X    To avoid a flood of autoreplies, this program will NOT reply to mail 
  351. X    that contains header "X-Mailer: fastmail".  Further, each time the 
  352. X    program responds to mail, the 'mailfile size' entry is updated in
  353. X    the file /etc/autoreply.data to allow the system to be brought 
  354. X    down and rebooted without any loss of data or duplicate messages.
  355. X
  356. X    This daemon also uses a lock semaphore file, /usr/spool/uucp/LCK..arep,
  357. X    to ensure that more than one copy of itself is never running.  For this
  358. X    reason, it is recommended that this daemon be started up each morning
  359. X    from cron, since it will either start since it's needed or simply see
  360. X    that the file is there and disappear.
  361. X
  362. X    Since this particular program is the main daemon answering any
  363. X    number of different users, it must be run with uid root.
  364. X
  365. X    (C) 1985, Dave Taylor, HP Colorado Networks Operation
  366. X**/
  367. X
  368. X#include <stdio.h>
  369. X
  370. X#ifdef BSD
  371. X# include <sys/time.h>
  372. X#else
  373. X# include <time.h>
  374. X#endif
  375. X
  376. X#include <sys/types.h>
  377. X#include <sys/stat.h>
  378. X
  379. X#include "defs.h"
  380. X
  381. Xstatic char ident[] = { WHAT_STRING };
  382. X
  383. X#define arep_lock_file    "/usr/spool/uucp/LCK..arep"
  384. X
  385. X#define autoreply_file    "/etc/autoreply.data"
  386. X#define fastmail    "/usr/local/bin/fastmail"
  387. X
  388. X#define logfile        "/etc/autoreply.log"    /* first choice   */
  389. X#define logfile2    "/tmp/autoreply.log"    /* second choice  */
  390. X
  391. X#define BEGINNING    0        /* see fseek(3S) for info */
  392. X#define SLEEP_TIME    3600        /* run once an hour       */
  393. X#define MAX_PEOPLE    20        /* max number in program  */
  394. X
  395. X#define EXISTS        00        /* lock file exists??     */
  396. X#define MODE        0777        /* lockfile creation mode */
  397. X
  398. X#define remove_return(s)    if (strlen(s) > 0) { \
  399. X                      if (s[strlen(s)-1] == '\n') \
  400. X                    s[strlen(s)-1] = '\0'; \
  401. X                        }
  402. X
  403. Xstruct replyrec {
  404. X    char     username[NLEN];        /* login name of user */
  405. X    char    mailfile[SLEN];        /* name of mail file  */
  406. X    char    replyfile[SLEN];    /* name of reply file */
  407. X    long    mailsize;        /* mail file size     */
  408. X    int     in_list;        /* for new replies    */
  409. X      } reply_table[MAX_PEOPLE];
  410. X
  411. XFILE  *logfd;                /* logfile (log action)   */
  412. Xlong  autoreply_size = 0L;        /* size of autoreply file */
  413. Xint   active = 0;            /* # of people 'enrolled' */
  414. X
  415. XFILE  *open_logfile();            /* forward declaration    */
  416. X
  417. Xlong  bytes();                /*       ditto           */
  418. X
  419. Xmain()
  420. X{
  421. X    long size;
  422. X    int  person, data_changed;
  423. X
  424. X    if (! lock())
  425. X      exit(0);    /* already running! */
  426. X
  427. X    while (1) {
  428. X
  429. X      logfd = open_logfile();    /* open the log */
  430. X
  431. X      /* 1. check to see if autoreply table has changed.. */
  432. X
  433. X      if ((size = bytes(autoreply_file)) != autoreply_size) {
  434. X        read_autoreply_file(); 
  435. X        autoreply_size = size;
  436. X      }
  437. X
  438. X      /* 2. now for each active person... */
  439. X    
  440. X      data_changed = 0;
  441. X
  442. X      for (person = 0; person < active; person++) {
  443. X        if ((size = bytes(reply_table[person].mailfile)) != 
  444. X        reply_table[person].mailsize) {
  445. X          if (size > reply_table[person].mailsize)
  446. X            read_newmail(person);
  447. X          /* else mail removed - resync */
  448. X          reply_table[person].mailsize = size;
  449. X          data_changed++;
  450. X        }
  451. X      }
  452. X
  453. X      /* 3. if data changed, update autoreply file */
  454. X
  455. X      if (data_changed)
  456. X        update_autoreply_file();
  457. X
  458. X      close_logfile();        /* close the logfile again */
  459. X
  460. X      /* 4. Go to sleep...  */
  461. X
  462. X      sleep(SLEEP_TIME);
  463. X    }
  464. X}
  465. X
  466. Xint
  467. Xread_autoreply_file()
  468. X{
  469. X    /** We're here because the autoreply file has changed size!!  It
  470. X        could either be because someone has been added or because
  471. X        someone has been removed...since the list will always be in
  472. X        order (nice, eh?) we should have a pretty easy time of it...
  473. X    **/
  474. X
  475. X    FILE *file;
  476. X    char username[SLEN],     replyfile[SLEN];
  477. X    int  person;
  478. X     long size;
  479. X    
  480. X    log("Autoreply data file has changed!  Reading...");
  481. X
  482. X    if ((file = fopen(autoreply_file,"r")) == NULL) {
  483. X      log("No-one is using autoreply...");
  484. X      return(0);
  485. X    }
  486. X    
  487. X    for (person = 0; person < active; person++)
  488. X      reply_table[person].in_list = 0;
  489. X    
  490. X    while (fscanf(file, "%s %s %dl", username, replyfile, &size) != EOF) {
  491. X      /* check to see if this person is already in the list */
  492. X      if ((person = in_list(username)) != -1) {
  493. X        reply_table[person].in_list = 1;
  494. X        reply_table[person].mailsize = size;     /* sync */
  495. X      }
  496. X      else {     /* if not, add them */
  497. X        if (active == MAX_PEOPLE) {
  498. X          unlock();
  499. X          exit(log("Couldn't add %s - already at max people!", 
  500. X                 username));
  501. X        }
  502. X        log("adding %s to the active list", username);
  503. X        strcpy(reply_table[active].username, username);
  504. X        sprintf(reply_table[active].mailfile, "/usr/mail/%s", username);
  505. X        strcpy(reply_table[active].replyfile, replyfile);
  506. X        reply_table[active].mailsize = size;
  507. X        reply_table[active].in_list = 1;    /* obviously! */
  508. X        active++;
  509. X      }
  510. X    }
  511. X
  512. X    /** now check to see if anyone has been removed... **/
  513. X
  514. X    for (person = 0; person < active; person++)
  515. X      if (reply_table[person].in_list == 0) {
  516. X         log("removing %s from the active list", 
  517. X          reply_table[person].username);
  518. X        strcpy(reply_table[person].username, 
  519. X           reply_table[active-1].username);
  520. X        strcpy(reply_table[person].mailfile, 
  521. X           reply_table[active-1].mailfile);
  522. X        strcpy(reply_table[person].replyfile, 
  523. X           reply_table[active-1].replyfile);
  524. X        reply_table[person].mailsize = reply_table[active-1].mailsize;
  525. X        active--;
  526. X      }
  527. X}
  528. X
  529. Xupdate_autoreply_file()
  530. X{
  531. X    /** update the entries in the autoreply file... **/
  532. X
  533. X    FILE *file;
  534. X    register int person;
  535. X
  536. X    if ((file = fopen(autoreply_file,"w")) == NULL) {
  537. X          log("Couldn't update autoreply file!");
  538. X      return;
  539. X    }
  540. X
  541. X    for (person = 0; person < active; person++)
  542. X      fprintf(file, "%s %s %ld\n",
  543. X          reply_table[person].username,
  544. X          reply_table[person].replyfile,
  545. X          reply_table[person].mailsize);
  546. X
  547. X    fclose(file);
  548. X
  549. X    printf("updated autoreply file\n");
  550. X    autoreply_size = bytes(autoreply_file);
  551. X}
  552. X
  553. Xint
  554. Xin_list(name)
  555. Xchar *name;
  556. X{
  557. X    /** search the current active reply list for the specified username.
  558. X        return the index if found, or '-1' if not. **/
  559. X
  560. X    register int index;
  561. X
  562. X    for (index = 0; index < active; index++)
  563. X      if (strcmp(name, reply_table[index].username) == 0)
  564. X        return(index);
  565. X    
  566. X    return(-1);
  567. X}
  568. X
  569. Xread_newmail(person)
  570. Xint person;
  571. X{
  572. X    /** Read the new mail for the specified person. **/
  573. X
  574. X    
  575. X    FILE *mailfile;
  576. X    char from_whom[LONG_SLEN], subject[SLEN];
  577. X    int  sendit;
  578. X
  579. X    log("New mail for %s", reply_table[person].username);
  580. X
  581. X        if ((mailfile = fopen(reply_table[person].mailfile,"r")) == NULL)
  582. X           return(log("can't open mailfile for user %s", 
  583. X            reply_table[person].username));
  584. X
  585. X        if (fseek(mailfile, reply_table[person].mailsize, BEGINNING) == -1)
  586. X           return(log("couldn't seek to %ld in mail file!", 
  587. X                   reply_table[person].mailsize));
  588. X
  589. X    while (get_return(mailfile, person, from_whom, subject, &sendit) != -1)
  590. X      if (sendit)
  591. X        reply_to_mail(person, from_whom, subject);
  592. X
  593. X    return;
  594. X}
  595. X
  596. Xint
  597. Xget_return(file, person, from, subject, sendit)
  598. XFILE *file;
  599. Xint  person, *sendit;
  600. Xchar *from, *subject;
  601. X{
  602. X    /** Reads the new message and return the from and subject lines.
  603. X        sendit is set to true iff it isn't a machine generated msg
  604. X    **/
  605. X    
  606. X    char name1[SLEN], name2[SLEN], lastname[SLEN];
  607. X    char buffer[LONG_SLEN], hold_return[NLEN];
  608. X    int done = 0, in_header = 0;
  609. X
  610. X    from[0] = '\0';
  611. X    *sendit = 1;
  612. X
  613. X    while (! done) {
  614. X
  615. X      if (fgets(buffer, LONG_SLEN, file) == NULL)
  616. X    return(-1);
  617. X
  618. X      if (first_word(buffer, "From ")) {
  619. X    in_header++;
  620. X    sscanf(buffer, "%*s %s", hold_return);
  621. X      }
  622. X      else if (in_header) {
  623. X        if (first_word(buffer, ">From")) {
  624. X      sscanf(buffer,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s", name1, name2);
  625. X      add_site(from, name2, lastname);
  626. X        }
  627. X        else if (first_word(buffer,"Subject:")) {
  628. X      remove_return(buffer);
  629. X      strcpy(subject, (char *) (buffer + 8));
  630. X        }
  631. X        else if (first_word(buffer,"X-Mailer: fastmail"))
  632. X      *sendit = 0;
  633. X        else if (strlen(buffer) == 1)
  634. X      done = 1;
  635. X      }
  636. X    }
  637. X
  638. X    if (from[0] == '\0')
  639. X      strcpy(from, hold_return); /* default address! */
  640. X    else
  641. X      add_site(from, name1, lastname);    /* get the user name too! */
  642. X
  643. X    return(0);
  644. X}
  645. X
  646. Xadd_site(buffer, site, lastsite)
  647. Xchar *buffer, *site, *lastsite;
  648. X{
  649. X    /** add site to buffer, unless site is 'uucp', or the same as 
  650. X        lastsite.   If not, set lastsite to site.
  651. X    **/
  652. X
  653. X    char local_buffer[LONG_SLEN], *strip_parens();
  654. X
  655. X    if (strcmp(site, "uucp") != 0)
  656. X      if (strcmp(site, lastsite) != 0) {
  657. X          if (buffer[0] == '\0')
  658. X            strcpy(buffer, strip_parens(site));         /* first in list! */
  659. X          else {
  660. X            sprintf(local_buffer,"%s!%s", buffer, strip_parens(site));
  661. X            strcpy(buffer, local_buffer);
  662. X          }
  663. X          strcpy(lastsite, strip_parens(site)); /* don't want THIS twice! */
  664. X       }
  665. X}
  666. X
  667. Xremove_first_word(string)
  668. Xchar *string;
  669. X{    /** removes first word of string, ie up to first non-white space
  670. X        following a white space! **/
  671. X
  672. X    register int loc;
  673. X
  674. X    for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  675. X        ;
  676. X
  677. X    while (string[loc] == ' ' || string[loc] == '\t')
  678. X      loc++;
  679. X    
  680. X    move_left(string, loc);
  681. X}
  682. X
  683. Xmove_left(string, chars)
  684. Xchar string[];
  685. Xint  chars;
  686. X{
  687. X    /** moves string chars characters to the left DESTRUCTIVELY **/
  688. X
  689. X    register int i;
  690. X
  691. X    chars--; /* index starting at zero! */
  692. X
  693. X    for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  694. X      string[i-chars] = string[i];
  695. X
  696. X    string[i-chars] = '\0';
  697. X}
  698. X
  699. Xreply_to_mail(person, from, subject)
  700. Xint   person;
  701. Xchar *from, *subject;
  702. X{
  703. X    /** Respond to the message from the specified person with the
  704. X        specified subject... **/
  705. X    
  706. X    char buffer[SLEN];
  707. X
  708. X    if (strlen(subject) == 0)
  709. X      strcpy(subject, "Auto-reply Mail");
  710. X    else if (! first_word(subject,"Auto-reply")) {
  711. X      sprintf(buffer, "Auto-reply to:%s", subject);
  712. X      strcpy(subject, buffer);
  713. X    }
  714. X
  715. X    log("auto-replying to '%s'", from);
  716. X
  717. X    mail(from, subject, reply_table[person].replyfile, person);
  718. X}    
  719. X
  720. Xreverse(string)
  721. Xchar *string;
  722. X{
  723. X    /** reverse string... pretty trivial routine, actually! **/
  724. X
  725. X    char buffer[SLEN];
  726. X    register int i, j = 0;
  727. X
  728. X    for (i = strlen(string)-1; i >= 0; i--)
  729. X      buffer[j++] = string[i];
  730. X
  731. X    buffer[j] = '\0';
  732. X
  733. X    strcpy(string, buffer);
  734. X}
  735. X
  736. Xlong
  737. Xbytes(name)
  738. Xchar *name;
  739. X{
  740. X    /** return the number of bytes in the specified file.  This
  741. X        is to check to see if new mail has arrived....  **/
  742. X
  743. X    int ok = 1;
  744. X    extern int errno;    /* system error number! */
  745. X    struct stat buffer;
  746. X
  747. X    if (stat(name, &buffer) != 0)
  748. X      if (errno != 2) {
  749. X       unlock();
  750. X       exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
  751. X      }
  752. X      else
  753. X        ok = 0;
  754. X    
  755. X    return(ok ? buffer.st_size : 0);
  756. X}
  757. X
  758. Xmail(to, subject, filename, person)
  759. Xchar *to, *subject, *filename;
  760. Xint   person;
  761. X{
  762. X    /** Mail 'file' to the user from person... **/
  763. X    
  764. X    char buffer[VERY_LONG_STRING];
  765. X
  766. X    sprintf(buffer, "%s -f '%s [autoreply]' -s '%s' %s %s",
  767. X        fastmail, reply_table[person].username,
  768. X            subject, filename, to);
  769. X    
  770. X    system(buffer);
  771. X}
  772. X
  773. Xlog(message, arg)
  774. Xchar *message;
  775. Xchar *arg;
  776. X{
  777. X    /** Put log entry into log file.  Use the format:
  778. X          date-time: <message>
  779. X    **/
  780. X
  781. X    struct tm *localtime(), *thetime;
  782. X    long      time(), clock;
  783. X    char      buffer[SLEN];
  784. X
  785. X    /** first off, get the time and date **/
  786. X
  787. X    clock = time((long *) 0);       /* seconds since ???   */
  788. X    thetime = localtime(&clock);    /* and NOW the time... */
  789. X
  790. X    /** then put the message out! **/
  791. X
  792. X    sprintf(buffer, message, arg);
  793. X
  794. X    fprintf(logfd,"%d/%d-%d:%02d: %s\n", 
  795. X        thetime->tm_mon+1, thetime->tm_mday,
  796. X            thetime->tm_hour,  thetime->tm_min,
  797. X            buffer);
  798. X}
  799. X
  800. XFILE *open_logfile()
  801. X{
  802. X    /** open the logfile.  returns a valid file descriptor **/
  803. X
  804. X    FILE *fd;
  805. X
  806. X    if ((fd = fopen(logfile, "a")) == 0)
  807. X      if ((fd = fopen(logfile2, "a")) == 0) {
  808. X        unlock();
  809. X        exit(1);    /* give up! */
  810. X      }
  811. X
  812. X    return( (FILE *) fd);
  813. X}
  814. X
  815. Xclose_logfile()
  816. X{
  817. X    /** Close the logfile until needed again. **/
  818. X
  819. X    fclose(logfd);
  820. X}
  821. X
  822. Xchar *strip_parens(string)
  823. Xchar *string;
  824. X{
  825. X    /** Return string with all parenthesized information removed.
  826. X        This is a non-destructive algorithm... **/
  827. X
  828. X    static char  buffer[LONG_SLEN];
  829. X    register int i, depth = 0, buffer_index = 0;
  830. X
  831. X    for (i=0; i < strlen(string); i++) {
  832. X      if (string[i] == '(')
  833. X        depth++;
  834. X      else if (string[i] == ')') 
  835. X        depth--;
  836. X      else if (depth == 0)
  837. X        buffer[buffer_index++] = string[i];
  838. X    }
  839. X    
  840. X    buffer[buffer_index] = '\0';
  841. X
  842. X    return( (char *) buffer);
  843. X}
  844. X
  845. X/*** LOCK and UNLOCK - ensure only one copy of this daemon running at any
  846. X     given time by using a file existance semaphore (wonderful stuff!) ***/
  847. X
  848. Xlock()
  849. X{
  850. X    /** Try to create the lock file.  If it's there, or we can't
  851. X        create it for some stupid reason, return zero, otherwise,
  852. X        a non-zero return code indicates success in locking this
  853. X        process in. **/
  854. X
  855. X    if (access(arep_lock_file, EXISTS) == 0)
  856. X      return(0);     /* file already exists!! */
  857. X
  858. X    if (creat(arep_lock_file, MODE) == -1)
  859. X      return(0);    /* can't create file!!   */
  860. X
  861. X    return(1);
  862. X}
  863. X
  864. Xunlock()
  865. X{
  866. X    /** remove lock file if it's there! **/
  867. X
  868. X    (void) unlink(arep_lock_file);
  869. X}
  870. END_OF_utils/arepdaemon.c
  871. if test 13412 -ne `wc -c <utils/arepdaemon.c`; then
  872.     echo shar: \"utils/arepdaemon.c\" unpacked with wrong size!?
  873. fi
  874. # end of overwriting check
  875. fi
  876. echo shar: Extracting \"utils/newalias.c\" \(13123 characters\)
  877. if test -f utils/newalias.c ; then 
  878.   echo shar: Will not over-write existing file \"utils/newalias.c\"
  879. else
  880. sed "s/^X//" >utils/newalias.c <<'END_OF_utils/newalias.c'
  881. X/**        newalias.c        **/
  882. X
  883. X/** (C) Copyright 1986 Dave Taylor      **/
  884. X
  885. X/** Install a new set of aliases for the 'Elm' mailer. 
  886. X
  887. X    If invoked with a specific filename, it assumes that
  888. X  it is working with an individual users alias tables, and
  889. X  generates the .alias.hash and .alias.data files in their
  890. X  home directory.
  891. X    If, however, it is invoked with no arguments, then
  892. X  it assumes that the user is updating the system alias
  893. X  file and uses the defaults for everything.
  894. X
  895. X  The format for the input file is;
  896. X    alias1, alias2, ... : username : address
  897. Xor  alias1, alias2, ... : groupname: member, member, member, ...
  898. X                                     member, member, member, ...
  899. X
  900. X  "-q" flag added: 6/17/86
  901. X**/
  902. X
  903. X#ifdef BSD
  904. X#  include <sys/file.h>
  905. X#else
  906. X#  include <fcntl.h>
  907. X#endif
  908. X
  909. X#include <stdio.h>
  910. X#include "defs.h"        /* ELM system definitions */
  911. X
  912. Xstatic char ident[] = { WHAT_STRING };
  913. X
  914. X#ifndef TAB
  915. X# define TAB         '\t'    /* TAB character!         */
  916. X#endif
  917. X    
  918. X#define alias_hash    ".alias_hash"
  919. X#define alias_data    ".alias_data"
  920. X#define alias_text    ".alias_text"
  921. X
  922. X#define group(string)        (strpbrk(string,", ") != NULL)
  923. X
  924. Xstruct alias_rec
  925. Xshash_table[MAX_SALIASES];    /* the actual hash table     */
  926. X
  927. Xstruct alias_rec
  928. Xuhash_table[MAX_UALIASES];    /* the actual hash table     */
  929. X
  930. Xint  hash_table_loaded=0;    /* is system table actually loaded? */
  931. X
  932. Xint  buff_loaded;        /* for file input overlap... */
  933. Xint  error= 0;            /* if errors, don't save!    */
  934. Xint  system=0;            /* system file updating?     */
  935. Xint  count=0;            /* how many aliases so far?  */
  936. Xlong offset = 0L;        /* data file line offset!    */
  937. X
  938. Xmain(argc, argv)
  939. Xint argc;
  940. Xchar *argv[];
  941. X{
  942. X    FILE *in, *data;
  943. X    char inputname[SLEN], hashname[SLEN], dataname[SLEN];
  944. X    char home[SLEN], buffer[LONG_STRING];
  945. X    int  hash, count = 0, owner, quiet = 0;
  946. X
  947. X    if (argc != 1)
  948. X      if (strcmp(argv[1], "-q") == 0)
  949. X        quiet++;
  950. X      else
  951. X        exit(printf("Usage: %s\n", argv[0]));
  952. X
  953. X    owner = getuid();
  954. X
  955. X    if (owner == 0 && ! quiet) {    /* being run by root! */
  956. X      printf("Would you like to update the system aliases? (y/n)");
  957. X      gets(buffer, 2);
  958. X      if (buffer[0] == 'y' || buffer[0] == 'Y') {
  959. X        printf("Updating the system alias file...\n");
  960. X
  961. X        sprintf(inputname, "%s/%s", mailhome, alias_text);
  962. X        sprintf(hashname, "%s/%s", mailhome, alias_hash);
  963. X        sprintf(dataname, "%s/%s", mailhome, alias_data);
  964. X        system++;
  965. X        init_table(shash_table, MAX_SALIASES); 
  966. X      }
  967. X      else 
  968. X        printf("Updating your personal alias file...\n");
  969. X    }
  970. X    
  971. X    if (! system) {
  972. X      if (strcpy(home, getenv("HOME")) == NULL)
  973. X        exit(printf("Confused: No HOME variable in environment!\n"));
  974. X
  975. X      sprintf(inputname, "%s/%s", home, alias_text);
  976. X      sprintf(hashname,  "%s/%s", home, alias_hash); 
  977. X      sprintf(dataname,  "%s/%s", home, alias_data); 
  978. X
  979. X      init_table(uhash_table, MAX_UALIASES); 
  980. X
  981. X      read_in_system(shash_table, sizeof shash_table);
  982. X    }
  983. X
  984. X    if ((in = fopen(inputname,"r")) == NULL)
  985. X      exit(printf("Couldn't open %s for input!\n", inputname));
  986. X
  987. X    if ((hash = open(hashname, O_WRONLY | O_CREAT, 0644)) == -1)
  988. X      exit(printf("Couldn't open %s for output!\n", hashname));
  989. X
  990. X    if ((data = fopen(dataname,"w")) == NULL)
  991. X      exit(printf("Couldn't open %s for output!\n", dataname));
  992. X
  993. X    buff_loaded = 0;     /* file buffer empty right now! */
  994. X
  995. X    while (get_alias(in, buffer) != -1) {
  996. X      if (system)
  997. X        put_alias(data, buffer, shash_table, MAX_SALIASES);    
  998. X      else
  999. X        put_alias(data, buffer, uhash_table, MAX_UALIASES);    
  1000. X      count++;
  1001. X    }
  1002. X
  1003. X    if (error) {
  1004. X      printf("\n** Not saving tables!  Please fix and re-run %s!\n",
  1005. X         argv[0]);
  1006. X      exit(1);
  1007. X    }
  1008. X    else {
  1009. X      if (system)
  1010. X        write(hash, shash_table, sizeof shash_table);
  1011. X      else
  1012. X        write(hash, uhash_table, sizeof uhash_table);
  1013. X
  1014. X      close(hash);
  1015. X      fclose(data);
  1016. X      close(in);
  1017. X    
  1018. X      printf("Processed %d aliases\n", count);
  1019. X      exit(0);
  1020. X    }
  1021. X}
  1022. X
  1023. Xint
  1024. Xget_alias(file, buffer)
  1025. XFILE *file;
  1026. Xchar *buffer;
  1027. X{
  1028. X    /* load buffer with the next complete alias from the file.
  1029. X       (this can include reading in multiple lines and appending
  1030. X       them all together!)  Returns EOF after last entry in file.
  1031. X    
  1032. X    Lines that start with '#' are assumed to be comments and are
  1033. X     ignored.  White space as the first field of a line is taken
  1034. X    to indicate that this line is a continuation of the previous. */
  1035. X
  1036. X    static char mybuffer[SLEN];
  1037. X    int    done = 0, first_read = 1;
  1038. X
  1039. X    /** get the first line of the entry... **/
  1040. X
  1041. X    buffer[0] = '\0';            /* zero out line */
  1042. X
  1043. X    do {
  1044. X      if (get_line(file, mybuffer, first_read) == -1) 
  1045. X        return(-1);
  1046. X      first_read = 0;
  1047. X      if (mybuffer[0] != '#')
  1048. X        strcpy(buffer, mybuffer);
  1049. X    } while (strlen(buffer) == 0);    
  1050. X
  1051. X    /** now read in the rest (if there is any!) **/
  1052. X
  1053. X    do {
  1054. X      if (get_line(file, mybuffer, first_read) == -1) {
  1055. X        buff_loaded = 0;    /* force a read next pass! */
  1056. X        return(0);    /* okay. let's just hand 'buffer' back! */
  1057. X      }
  1058. X      done = (mybuffer[0] != ' ' && mybuffer[0] != TAB);
  1059. X      if (mybuffer[0] != '#' && ! done)
  1060. X        strcat(buffer, mybuffer);
  1061. X      done = (done && mybuffer[0] != '#');
  1062. X    } while (! done);
  1063. X    
  1064. X    return(0);    /* no sweat! */
  1065. X}
  1066. X
  1067. Xput_alias(data, buffer, table, size)
  1068. XFILE *data;
  1069. Xchar *buffer;
  1070. Xstruct alias_rec table[];
  1071. Xint  size;
  1072. X{
  1073. X    /** break buffer down into three pieces: aliases, comment, and address.
  1074. X        Make the appropriate entries in the table (size) 
  1075. X    **/
  1076. X
  1077. X    char aliases[LONG_STRING], address[LONG_STRING];
  1078. X    char comment[LONG_STRING];
  1079. X    int  first, last, i = 0, j = 0;
  1080. X
  1081. X    remove_all(' ', TAB, buffer);
  1082. X
  1083. X    for (i=0; buffer[i] != ':' && i < LONG_STRING; i++)
  1084. X      aliases[i] = buffer[i];
  1085. X    aliases[i] = '\0';
  1086. X
  1087. X    for (i=strlen(buffer)-1; buffer[i] != ':' && i > 0; i--)
  1088. X      address[j++] = buffer[i];
  1089. X    address[j] = '\0';
  1090. X
  1091. X    comment[0] = '\0';    /* default to nothing at all... */
  1092. X
  1093. X    if ((first=strlen(aliases)+1) < (last=(strlen(buffer) - j))) {
  1094. X      extract_comment(comment, buffer, first, last); 
  1095. X    }
  1096. X
  1097. X    reverse(address);
  1098. X
  1099. X    add_to_table(data, aliases, comment, address, table, size);
  1100. X}
  1101. X
  1102. Xint
  1103. Xget_line(file, buffer, first_line)
  1104. XFILE *file;
  1105. Xchar *buffer;
  1106. Xint  first_line;
  1107. X{
  1108. X    /** read line from file.  If first_line and buff_loaded, 
  1109. X        then just return! **/
  1110. X    int stat;
  1111. X
  1112. X    if (first_line && buff_loaded) {
  1113. X      buff_loaded = 1;
  1114. X      return;
  1115. X    }
  1116. X
  1117. X    buff_loaded = 1;    /* we're going to get SOMETHING in the buffer */
  1118. X
  1119. X    stat = fgets(buffer, SLEN, file) == NULL ? -1 : 0;
  1120. X
  1121. X    if (stat != -1)
  1122. X      no_ret(buffer);
  1123. X
  1124. X    return(stat);
  1125. X}
  1126. X
  1127. Xreverse(string)
  1128. Xchar *string;
  1129. X{
  1130. X    /** reverse the order of the characters in string... 
  1131. X        uses a bubble-sort type of algorithm!                 **/
  1132. X    
  1133. X    register int f, l;
  1134. X    char     c;
  1135. X    
  1136. X    f = 0;
  1137. X    l = strlen(string) - 1;
  1138. X    
  1139. X    while (f < l) {
  1140. X      c = string[f];
  1141. X       string[f] = string[l];
  1142. X      string[l] = c;
  1143. X      f++;
  1144. X      l--;
  1145. X    }
  1146. X}
  1147. X
  1148. Xadd_to_table(data, aliases, comment, address, table, size)
  1149. XFILE *data;
  1150. Xchar *aliases, *comment, *address;
  1151. Xstruct alias_rec table[];
  1152. Xint  size;
  1153. X{
  1154. X    /** add address + comment to datafile, incrementing offset count 
  1155. X        (bytes), then for each alias in the aliases string, add to the
  1156. X        hash table, with the associated pointer value! **/
  1157. X
  1158. X    static char buf[SLEN], *word;
  1159. X    long additive = 1L;
  1160. X
  1161. X    word = buf;    /* use the allocated space! */
  1162. X
  1163. X    if (group(address)) {
  1164. X      check_group(address, aliases);
  1165. X      if (error) return;    /* don't do work if we aren't to save it! */
  1166. X      fprintf(data, "!%s\n", address);
  1167. X      additive = 2L;
  1168. X    }
  1169. X    else {
  1170. X      if (error) return;    /* don't do work if we aren't to save it! */
  1171. X      if (strlen(comment) > 0) {
  1172. X        fprintf(data, "%s (%s)\n", address, comment);
  1173. X        additive = (long) (strlen(comment) + 4);
  1174. X      }
  1175. X      else
  1176. X        fprintf(data, "%s\n", address, comment);
  1177. X    }
  1178. X
  1179. X    while ((word = (char *) strtok(aliases,", ")) != NULL) {
  1180. X      add_to_hash_table(word, offset, table, size);
  1181. X      aliases = NULL;    /* let's get ALL entries via 'strtok' */
  1182. X      count++;
  1183. X    }
  1184. X
  1185. X    if ( system ? count > MAX_SALIASES-35 : count > MAX_UALIASES-21) {
  1186. X      printf("** Too many aliases in file! **\n");
  1187. X      error++;
  1188. X    }
  1189. X
  1190. X    offset = (offset + (long) strlen(address) + additive);
  1191. X}    
  1192. X
  1193. Xremove_all(c1, c2, string)
  1194. Xchar c1, c2, *string;
  1195. X{
  1196. X    /* Remove all occurances of character 'c1' or 'c2' from the string.
  1197. X       Hacked (literally) to NOT remove ANY characters from within the
  1198. X       colon fields.  This will only be used if the line contains TWO
  1199. X       colons (and comments with colons in them are the kiss of death!)
  1200. X     */
  1201. X
  1202. X    char buffer[LONG_STRING];
  1203. X    register int i = 0, j = 0, first_colon = -1, last_colon = -1;
  1204. X    
  1205. X    for (i = 0; string[i] != '\0' && i < LONG_STRING; i++) {
  1206. X      if (string[i] != c1 && string[i] != c2)
  1207. X        buffer[j++] = string[i];
  1208. X
  1209. X      if (first_colon == -1 && string[i] == ':') {
  1210. X        first_colon = i;
  1211. X        for (last_colon=strlen(string);string[last_colon] != ':'; 
  1212. X        last_colon--) ;
  1213. X      }
  1214. X      else if (i > first_colon && i < last_colon)
  1215. X       if (string[i] == c1 || string[i] == c2)
  1216. X         buffer[j++] = string[i];
  1217. X    }
  1218. X    
  1219. X    buffer[j] = '\0';
  1220. X    strcpy(string, buffer);
  1221. X}
  1222. X
  1223. Xadd_to_hash_table(word, offset, table, size)
  1224. Xchar *word;
  1225. Xlong  offset;
  1226. Xstruct alias_rec table[];
  1227. Xint   size;
  1228. X{
  1229. X    /** add word and offset to current hash table. **/
  1230. X    register int loc;
  1231. X    
  1232. X    if (strlen(word) > 20)
  1233. X      exit(printf("Bad alias name: %s.  Too long.\n", word));
  1234. X
  1235. X    loc = hash_it(word, size);
  1236. X
  1237. X    while (table[loc].name[0] != '\0' && strcmp(table[loc].name, word) != 0)
  1238. X      loc = loc + 1 % size; 
  1239. X
  1240. X    if (table[loc].name[0] == '\0') {
  1241. X      strcpy(table[loc].name, word);
  1242. X      table[loc].byte = offset;
  1243. X    }
  1244. X    else 
  1245. X      printf("** Duplicate alias '%s' in file.  Multiples ignored.\n",
  1246. X             word);
  1247. X}
  1248. X
  1249. Xint
  1250. Xhash_it(string, table_size)
  1251. Xchar *string;
  1252. X{
  1253. X    /** compute the hash function of the string, returning
  1254. X        it (mod table_size) **/
  1255. X
  1256. X    register int i, sum = 0;
  1257. X    
  1258. X    for (i=0; string[i] != '\0'; i++)
  1259. X      sum += (int) string[i];
  1260. X
  1261. X    return(sum % table_size);
  1262. X}
  1263. X
  1264. Xinit_table(table, size)
  1265. Xstruct alias_rec table[];
  1266. Xint size;
  1267. X{
  1268. X    /** initialize hash table! **/
  1269. X
  1270. X    register int i;
  1271. X
  1272. X    for (i=0; i < size; i++)
  1273. X      table[i].name[0] = '\0';
  1274. X}
  1275. X
  1276. Xread_in_system(table, size)
  1277. Xstruct alias_rec table[];
  1278. Xint size;
  1279. X{
  1280. X    /** read in the system hash table...to check for group aliases
  1281. X        from the user alias file (to ensure that there are no names
  1282. X        in the user group files that are not purely contained within
  1283. X        either alias table) **/
  1284. X    
  1285. X    int  fd;
  1286. X    char fname[SLEN];
  1287. X
  1288. X    sprintf(fname, "%s/%s", mailhome, alias_hash);
  1289. X
  1290. X    if ((fd = open(fname, O_RDONLY)) == -1)
  1291. X      return;    /* no sweat: flag 'hash_table_loaded' not set! */
  1292. X
  1293. X    (void) read(fd, table, size);
  1294. X    close(fd);
  1295. X    hash_table_loaded++;
  1296. X}
  1297. X    
  1298. Xcheck_group(names, groupname)
  1299. Xchar *names, *groupname;
  1300. X{
  1301. X    /** one by one make sure each name in the group is defined
  1302. X        in either the system alias file or the user alias file.
  1303. X        This search is linearly dependent, so all group aliases
  1304. X        in the source file should appear LAST, after all the user
  1305. X        aliases! **/
  1306. X
  1307. X    char *word, *bufptr, buffer[LONG_STRING];
  1308. X
  1309. X    strcpy(buffer, names);
  1310. X    bufptr = (char *) buffer;
  1311. X
  1312. X    while ((word = (char *) strtok(bufptr,", ")) != NULL) {
  1313. X      if (! can_find(word)) 
  1314. X        if (! valid_name(word)) {
  1315. X          error++;
  1316. X          printf("** Alias %s in group %s is bad!\n", word, groupname);
  1317. X        }
  1318. X      bufptr = NULL;
  1319. X    }
  1320. X}
  1321. X
  1322. Xint
  1323. Xcan_find(name)
  1324. Xchar *name;
  1325. X{    
  1326. X    /** find name in either hash table...use 'system' variable to
  1327. X        determine if we should look in both or just system....    **/
  1328. X
  1329. X    register int loc;
  1330. X    
  1331. X    if (strlen(name) > 20) {
  1332. X      error++;
  1333. X      printf("** Bad alias name: %s.  Too long.\n", name);
  1334. X      return(1);    /* fake out: don't want 2 error messages! */
  1335. X    }
  1336. X
  1337. X    /** system alias table... **/
  1338. X    if (hash_table_loaded || system) {
  1339. X      loc = hash_it(name, MAX_SALIASES);
  1340. X
  1341. X      while (strcmp(name, shash_table[loc].name) != 0 && 
  1342. X                 shash_table[loc].name[0] != '\0')
  1343. X        loc = (loc + 1) % MAX_SALIASES; 
  1344. X  
  1345. X      if (strcmp(name, shash_table[loc].name) == 0)
  1346. X        return(1);    /* found it! */
  1347. X    }
  1348. X
  1349. X    if (! system) {    /* okay! Let's check the user alias file! */
  1350. X      loc = hash_it(name, MAX_UALIASES);
  1351. X
  1352. X      while (strcmp(name, uhash_table[loc].name) != 0 && 
  1353. X                 uhash_table[loc].name[0] != '\0')
  1354. X        loc = (loc + 1) % MAX_UALIASES; 
  1355. X
  1356. X      if (strcmp(name, uhash_table[loc].name) == 0)
  1357. X        return(1);    /* found it! */
  1358. X    }
  1359. X
  1360. X    return(0);
  1361. X}
  1362. X
  1363. Xextract_comment(comment, buffer, first, last)
  1364. Xchar *comment, *buffer;
  1365. Xint first, last;
  1366. X{
  1367. X    /** Buffer contains a comment, located between the first and last
  1368. X        values.  Copy that into 'comment', but remove leading and
  1369. X        trailing white space.  Note also that it doesn't copy past
  1370. X        a comma, so `unpublishable' comments can be of the form;
  1371. X        dave: Dave Taylor, HP Labs : taylor@hplabs
  1372. X        and the output will be "taylor@hplabs (Dave Taylor)".
  1373. X    **/
  1374. X
  1375. X    register int loc = 0; 
  1376. X
  1377. X    /** first off, skip the LEADING white space... **/
  1378. X
  1379. X    while (buffer[first] == ' ') first++;
  1380. X    
  1381. X    /** now let's backup the 'last' value until we hit a non-space **/
  1382. X
  1383. X    last -= 2;    /* starts at ch AFTER colon.. */
  1384. X    while (buffer[last] == ' ') last--;
  1385. X
  1386. X    /** now a final check to make sure we're still talking about a 
  1387. X        reasonable string (rather than a "joe :: joe@dec" type string) **/
  1388. X
  1389. X    if (first < last) {
  1390. X      /* one more check - let's find the comma, if present... */
  1391. X      for (loc=first; loc < last; loc++)
  1392. X        if (buffer[loc] == ',') {
  1393. X          last = loc-1;
  1394. X          break;
  1395. X      }
  1396. X      loc = 0;
  1397. X      while (first <= last)
  1398. X        comment[loc++] = buffer[first++];
  1399. X      comment[loc] = '\0';
  1400. X    }
  1401. X}
  1402. END_OF_utils/newalias.c
  1403. if test 13123 -ne `wc -c <utils/newalias.c`; then
  1404.     echo shar: \"utils/newalias.c\" unpacked with wrong size!?
  1405. fi
  1406. # end of overwriting check
  1407. fi
  1408. echo shar: End of archive 13 \(of 19\).
  1409. cp /dev/null ark13isdone
  1410. DONE=true
  1411. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1412.     if test ! -f ark${I}isdone ; then
  1413.     echo shar: You still need to run archive ${I}.
  1414.     DONE=false
  1415.     fi
  1416. done
  1417. if test "$DONE" = "true" ; then
  1418.     echo You have unpacked all 19 archives.
  1419.     echo "See the Instructions file"
  1420.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1421. fi
  1422. ##  End of shell archive.
  1423. exit 0
  1424.