home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume18 / xalarm30 / part03 < prev    next >
Encoding:
Text File  |  1992-07-07  |  50.2 KB  |  1,716 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!darwin.sura.net!mips!msi!dcmartin
  3. From: Simon Marshall <S.Marshall@sequent.cc.hull.ac.uk>
  4. Subject: v18i004: Xalarm 3.04, Part03/05
  5. Message-ID: <1992Jul8.154413.20488@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. References: <csx-18i002-xalarm-3.04@uunet.UU.NET>
  10. Date: Wed, 8 Jul 1992 15:44:13 GMT
  11. Approved: dcmartin@msi.com
  12. Lines: 1702
  13.  
  14. Submitted-by: Simon Marshall <S.Marshall@sequent.cc.hull.ac.uk>
  15. Posting-number: Volume 18, Issue 4
  16. Archive-name: xalarm-3.04/part03
  17.  
  18. # this is part.03 (part 3 of a multipart archive)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file README continued
  21. #
  22. if test ! -r _shar_seq_.tmp; then
  23.     echo 'Please unpack part 1 first!'
  24.     exit 1
  25. fi
  26. (read Scheck
  27.  if test "$Scheck" != 3; then
  28.     echo Please unpack part "$Scheck" next!
  29.     exit 1
  30.  else
  31.     exit 0
  32.  fi
  33. ) < _shar_seq_.tmp || exit 1
  34. if test ! -f _shar_wnt_.tmp; then
  35.     echo 'x - still skipping README'
  36. else
  37. echo 'x - continuing file README'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'README' &&
  39. X  warnings times, and the message xalarm will display when the alarm is
  40. X  triggered.
  41. X
  42. X  This form is suitable for inclusion as a menu option under a window manager.
  43. X
  44. X  You can make xalarm read alarm times, dates, and the messages to display from
  45. X  a file, either as a one-off or periodically using an xalarm daemon.  The
  46. X  alarms will only be set on the dates specified in the file.  This way you can
  47. X  have an appointments file.
  48. X
  49. X  This form is suitable for inclusion in an X start up or initialisation
  50. X  script.
  51. X
  52. X  To help you, xalarm shows the current time, and the alarm also displays the
  53. X  time since the alarm triggered.  Even if you end an X session before xalarm
  54. X  has finished, xalarm will save its alarm.  It will then be re-started (if the
  55. X  time has not passed) next time you invoke xalarm.
  56. X
  57. X  xalarm allows you to snooze the alarm after it is triggered, to give you an
  58. X  opportunity to carry on and be late anyway.  It can also pester you after it
  59. X  has triggered.  Even after you have set the alarm and confirmed it, you can
  60. X  reset the alarm as long as you know the xalarm process number; xalarm can
  61. X  list other xalarm pids.
  62. X
  63. X  xalarm makes maximum use of resources, as well as having a number of command
  64. X  line options, and these can be used to control most of the appearance of
  65. X  xalarm and (just about) all of its behaviour.
  66. X
  67. X  The current xalarm options include:
  68. X    -daemon +days|daily|weekly
  69. X    -file +days|date|today|tomorrow|weekly
  70. X    -date +days|date|today|tomorrow|week
  71. X    -time +time|time|now|noon
  72. X    -warn time[,time...]                -nowarn
  73. X    -confirm                    -noconfirm
  74. X    -warnwords number                -nowarnwords
  75. X    -list
  76. X    -reset pid|all
  77. X    -kill pid|all
  78. X    -pester time                    -nopester
  79. X    -snooze time
  80. X    -alarmaudio bell|beep|quiet|shell_script
  81. X    -warningaudio bell|beep|quiet|shell_script
  82. X    -quiet                        -volume    percent
  83. X    -help                        -version
  84. X
  85. X  Also supplied is xmemo, a front end to xalarm.  By default, make tries to
  86. X  create xfortune and xyow (front ends to xmemo).  Note that they require the
  87. X  fortune and yow programs respectively, they don't come with this.
  88. X
  89. X  See the file INSTALL and PROBLEMS for help with installation and problems.
  90. X
  91. X
  92. THE END
  93. ~~~~~~~
  94. X
  95. X  Xalarm uses Xt & Xaw stuff only, and may well be a useful aid to someone
  96. X  trying to learn X, as I was/am.
  97. X
  98. X  You may have problems with X function names if using R3 or earlier;
  99. X  application contexts are used, but this should not take much changing - using
  100. X  #defines may do most of the job.
  101. X
  102. X  Written in an attempt to learn X Windows in as short a time as possible; it
  103. X  may be written badly, but makes as much use of resources as possible.  I
  104. X  don't think it is (but I wouldn't, would I?) and I have found it is very
  105. X  useful for me now I'm to be responsible for giving lectures...
  106. X
  107. X    Simon.
  108. _______________________________________________________________________________
  109. X    Simon Marshall, Dept. Computer Science, University of Hull, HU6 7RX, UK
  110. X    S.Marshall@Hull.ac.UK
  111. SHAR_EOF
  112. echo 'File README is complete' &&
  113. chmod 0644 README ||
  114. echo 'restore of README failed'
  115. Wc_c="`wc -c < 'README'`"
  116. test 4281 -eq "$Wc_c" ||
  117.     echo 'README: original size 4281, current size' "$Wc_c"
  118. rm -f _shar_wnt_.tmp
  119. fi
  120. # ============= XAlarm.ad ==============
  121. if test -f 'XAlarm.ad' -a X"$1" != X"-c"; then
  122.     echo 'x - skipping XAlarm.ad (File already exists)'
  123.     rm -f _shar_wnt_.tmp
  124. else
  125. > _shar_wnt_.tmp
  126. echo 'x - extracting XAlarm.ad (Text)'
  127. sed 's/^X//' << 'SHAR_EOF' > 'XAlarm.ad' &&
  128. ! We can't surround this by "#ifdef COLOR ... #endif" and have it in
  129. ! .../lib/X11/app-defaults/XAlarm because stuff in there is not pre-processed
  130. ! with cpp like wot xrdb does.  Now why is that...?
  131. ! If you want colour, you have to stick this in your ~/.xresources file (where
  132. ! you can surround it with #ifdefs).
  133. ! #ifdef COLOR
  134. ! XAlarm*background:            LightYellow
  135. ! XAlarm*foreground:            IndianRed
  136. ! XAlarm*Command.background:        IndianRed
  137. ! XAlarm*Command.foreground:        LightYellow
  138. ! #endif
  139. X
  140. XXAlarm.confirm:                True
  141. XXAlarm.warnings:            5,15
  142. XXAlarm.warningwords:            0
  143. XXAlarm.pester:                0
  144. XXAlarm.snooze:                0
  145. XXAlarm.volume:                50
  146. XXAlarm.alarmaudio:            bell
  147. XXAlarm.warningaudio:            bell
  148. X
  149. XXAlarm*background:            White
  150. XXAlarm*foreground:            Black
  151. XXAlarm*font:                -*-times-bold-r-*-*-14-*-*-*-p-*-iso8859-1
  152. XXAlarm*allowShellResize:        True
  153. XXAlarm*resizable:            True
  154. X
  155. XXAlarm*top:                ChainTop
  156. XXAlarm*bottom:                ChainTop
  157. XXAlarm*left:                ChainLeft
  158. XXAlarm*right:                ChainLeft
  159. X
  160. XXAlarm*Command.background:        Black
  161. XXAlarm*Command.foreground:        White
  162. XXAlarm*Command.ShapeStyle:        rectangle
  163. XXAlarm*Command.cursor:            hand2
  164. XXAlarm*Label.justify:            left
  165. XXAlarm*Label.cursor:            question_arrow
  166. XXAlarm*Text.cursor:            pencil
  167. X
  168. XXAlarm*quit.label:            Quit
  169. XXAlarm*reset.label:            Reset
  170. X
  171. XXAlarm.Alarm!.alarm.background:                Black
  172. XXAlarm.Alarm!.alarm.message.cursor:            gumby
  173. XXAlarm.Alarm!.alarm.message.label:            Alarm Call!!!
  174. XXAlarm.Alarm!.alarm.message.font:            -*-times-bold-i-*-*-34-*-*-*-p-*-iso8859-1
  175. XXAlarm.Alarm!.alarm.message.internalWidth:        10
  176. XXAlarm.Alarm!.alarm.message.internalHeight:        5
  177. XXAlarm.Alarm!.alarm.message.bottom:            ChainBottom
  178. X
  179. XXAlarm.Alarm!.alarm.buttons.snooze.label:        Snooze
  180. XXAlarm.Alarm!.alarm.buttons.snooze1.label:        +1 min
  181. XXAlarm.Alarm!.alarm.buttons.snooze5.label:        +5 mins
  182. XXAlarm.Alarm!.alarm.buttons.snooze15.label:        +15 mins
  183. XXAlarm.Alarm!.alarm.buttons.snooze.fromHoriz:        quit
  184. XXAlarm.Alarm!.alarm.buttons.snooze1.fromHoriz:        snooze
  185. XXAlarm.Alarm!.alarm.buttons.snooze5.fromHoriz:        snooze1
  186. XXAlarm.Alarm!.alarm.buttons.snooze15.fromHoriz:        snooze5
  187. XXAlarm.Alarm!.alarm.buttons.snoozetime.fromHoriz:    snooze15
  188. XXAlarm.Alarm!.alarm.message.fromVert:            buttons
  189. X
  190. XXAlarm.When?.when.background:            Black
  191. XXAlarm.When?.when.defaultDistance:        0
  192. X
  193. XXAlarm.When?.when.time.background:        Black
  194. XXAlarm.When?.when.time.ok.label:        Enter time
  195. XXAlarm.When?.when.time.value.translations:    #override <Key>Return: EnteredTime()
  196. X
  197. XXAlarm.When?.when.date.background:        Black
  198. XXAlarm.When?.when.date.ok.label:        Enter date
  199. XXAlarm.When?.when.date.value.translations:    #override <Key>Return: EnteredDate()
  200. X
  201. XXAlarm.When?.when.warnings.background:        Black
  202. XXAlarm.When?.when.warnings.ok.label:        Enter warnings
  203. XXAlarm.When?.when.warnings.value.translations:    #override <Key>Return: EnteredWarnings()
  204. X
  205. XXAlarm.When?.when.confirm.background:        Black
  206. XXAlarm.When?.when.confirm.value*font:        -*-times-bold-i-*-*-14-*-*-*-p-*-iso8859-1
  207. XXAlarm.When?.when.confirm.ok.label:        Confirm time
  208. XXAlarm.When?.when.confirm.cancel.label:        Re-edit
  209. XXAlarm.When?.when.confirm.save.label:        Save
  210. XXAlarm.When?.when.confirm.value.translations:    #override <Key>Return: Confirmed()
  211. X
  212. XXAlarm.When?*edittime.label:        Time
  213. XXAlarm.When?*editdate.label:        Date
  214. XXAlarm.When?*editwarnings.label:    Warnings
  215. X
  216. XXAlarm.When?*value*font:        9x15bold
  217. XXAlarm.When?*value.bottom:        ChainBottom
  218. XXAlarm.When?*value.right:        ChainRight
  219. XXAlarm.When?*Command.top:        ChainBottom
  220. XXAlarm.When?*Command.bottom:        ChainBottom
  221. X
  222. XXAlarm.Warning!.warning.background:        Black
  223. XXAlarm.Warning!.warning.dismiss.label:        Dismiss
  224. XXAlarm.Warning!.warning.message.fromHoriz:    dismiss
  225. XXAlarm.Warning!.warning.message.cursor:        clock
  226. XXAlarm.Warning!.warning.reset.fromHoriz:    message
  227. XXAlarm.Warning!.warning.quit.fromHoriz:        reset
  228. SHAR_EOF
  229. chmod 0644 XAlarm.ad ||
  230. echo 'restore of XAlarm.ad failed'
  231. Wc_c="`wc -c < 'XAlarm.ad'`"
  232. test 3684 -eq "$Wc_c" ||
  233.     echo 'XAlarm.ad: original size 3684, current size' "$Wc_c"
  234. rm -f _shar_wnt_.tmp
  235. fi
  236. # ============= XAlarm.ad+ ==============
  237. if test -f 'XAlarm.ad+' -a X"$1" != X"-c"; then
  238.     echo 'x - skipping XAlarm.ad+ (File already exists)'
  239.     rm -f _shar_wnt_.tmp
  240. else
  241. > _shar_wnt_.tmp
  242. echo 'x - extracting XAlarm.ad+ (Text)'
  243. sed 's/^X//' << 'SHAR_EOF' > 'XAlarm.ad+' &&
  244. ! We can't surround this by "#ifdef COLOR ... #endif" and have it in
  245. ! .../lib/X11/app-defaults/XAlarm because stuff in there is not pre-processed
  246. ! with cpp like wot xrdb does.  Now why is that...?
  247. X
  248. ! If you want colour, you have to stick this in your ~/.xresources file (where
  249. ! you can surround it with #ifdefs).
  250. X
  251. #ifdef COLOR
  252. XXAlarm*background:            LightYellow
  253. XXAlarm*foreground:            IndianRed
  254. XXAlarm*Command.background:        IndianRed
  255. XXAlarm*Command.foreground:        LightYellow
  256. #endif
  257. X
  258. ! If you want a smaller button box in the alarm window, uncomment & try these
  259. ! for size in your ~/.xresources file:
  260. X
  261. !XAlarm.Alarm!.alarm.buttons.snooze1.fromVert:        quit
  262. ! This will vary depending on the button labels & font...
  263. !XAlarm.Alarm!.alarm.buttons.snooze1.horizDistance:    -93
  264. !XAlarm.Alarm!.alarm.buttons.snooze5.fromVert:        quit
  265. !XAlarm.Alarm!.alarm.buttons.snooze15.fromVert:        quit
  266. !XAlarm.Alarm!.alarm.buttons.snoozetime.fromHoriz:    snooze
  267. X
  268. ! If you want the button box next to the alarm window, uncomment & try this:
  269. X
  270. !XAlarm.Alarm!.alarm.message.fromHoriz:            buttons
  271. ! This will vary depending on the button labels & font...
  272. !XAlarm.Alarm!.alarm.message.vertDistance:        -33
  273. SHAR_EOF
  274. chmod 0644 XAlarm.ad+ ||
  275. echo 'restore of XAlarm.ad+ failed'
  276. Wc_c="`wc -c < 'XAlarm.ad+'`"
  277. test 1165 -eq "$Wc_c" ||
  278.     echo 'XAlarm.ad+: original size 1165, current size' "$Wc_c"
  279. rm -f _shar_wnt_.tmp
  280. fi
  281. # ============= alarm.c ==============
  282. if test -f 'alarm.c' -a X"$1" != X"-c"; then
  283.     echo 'x - skipping alarm.c (File already exists)'
  284.     rm -f _shar_wnt_.tmp
  285. else
  286. > _shar_wnt_.tmp
  287. echo 'x - extracting alarm.c (Text)'
  288. sed 's/^X//' << 'SHAR_EOF' > 'alarm.c' &&
  289. /*
  290. X      Copyright (c) 1991, 1992 by Simon Marshall, University of Hull, UK
  291. X
  292. X           If you still end up late, don't blame me!
  293. X                       
  294. X  Permission to use, copy, modify, distribute, and sell this software and its
  295. X       documentation for any purpose and without fee is hereby granted,
  296. X    provided that the above copyright notice appear in all copies and that
  297. X    both that copyright notice and this permission notice appear in
  298. X               supporting documentation.
  299. X                       
  300. X  This software is provided AS IS with no warranties of any kind.  The author
  301. X    shall have no liability with respect to the infringement of copyrights,
  302. X     trade secrets or any patents by this file or any part thereof.  In no
  303. X      event will the author be liable for any lost revenue or profits or
  304. X          other special, indirect and consequential damages.
  305. */
  306. X
  307. /* 
  308. X * The stuff needed for the alarm call widget to appear on the screen, 
  309. X * and the stuff for snoozing it.
  310. X */
  311. X
  312. X
  313. #include "xalarm.h"
  314. #include <X11/Xaw/Label.h>
  315. #include <X11/Xaw/Command.h>
  316. #include <X11/Xaw/Form.h>
  317. X
  318. X
  319. #define        NAMEFORMAT    "%s: %s@%s"
  320. #define        REALNAMEFORMAT    " (%s)"
  321. #define        TIMEFORMAT    " (%d:%02d)"
  322. X
  323. X
  324. X
  325. void        CreateAlarmWidget(), WakeUp(), ShowClickToZero(), ShowSnoozeValue();
  326. SIGRET        ResetAlarm();
  327. static void    SnoozeAmount(), Snooze(), TimeTracker();
  328. extern void    PopupAndAsk(), AddTimeOuts(), SetWMName(), SetGeometry(),
  329. X        EnsureNotGrownOffScreen(), Audio(), QuitWarning(), Quit();
  330. extern unsigned long DateToMilliSeconds();
  331. extern long    TimeToMilliSeconds();
  332. extern XtIntervalId ResetTracker();
  333. extern String    getenv(), UserName(), MachineName();
  334. extern time_t    time();
  335. extern struct tm *localtime();
  336. X
  337. X
  338. X
  339. extern AlarmData        xalarm;
  340. X
  341. X
  342. X
  343. /* 
  344. X * Create the widget that holds the alarm itself.
  345. X */
  346. X
  347. void CreateAlarmWidget (alarmmessage)
  348. X  String   alarmmessage;
  349. {
  350. X    Widget       alarm, alarmbox, message, buttonbox,
  351. X          quit, snooze, snooze1, snooze5, snooze15, snoozetime;
  352. X    static char   snoozetimetranslations [] =
  353. X              "<EnterWindow>:    highlight() ShowClickToZero() \n\
  354. X               <LeaveWindow>:    ShowSnoozeValue() unhighlight()";
  355. X
  356. X    alarm = XtVaCreatePopupShell ("Alarm!", transientShellWidgetClass, xalarm.toplevel,
  357. X                  NULL);
  358. X
  359. X    alarmbox = XtVaCreateManagedWidget ("alarm", formWidgetClass, alarm, NULL);
  360. X
  361. X    buttonbox = XtVaCreateManagedWidget ("buttons", formWidgetClass, alarmbox, NULL);
  362. X
  363. X    CreateManagedButton (quit, "quit", buttonbox, Quit, NULL);
  364. X    CreateManagedButton (snooze, "snooze", buttonbox, Snooze, NULL);
  365. X    CreateManagedButton (snooze1, "snooze1", buttonbox, SnoozeAmount, 1);
  366. X    CreateManagedButton (snooze5, "snooze5", buttonbox, SnoozeAmount, 5);
  367. X    CreateManagedButton (snooze15, "snooze15" ,buttonbox, SnoozeAmount, 15);
  368. X    CreateManagedButton (snoozetime, "snoozetime", buttonbox, SnoozeAmount, 0);
  369. X
  370. X    if (NONNIL (String, alarmmessage))
  371. X    message = XtVaCreateManagedWidget ("message", labelWidgetClass, alarmbox, XtNlabel,
  372. X                       (XtArgVal) (xalarm.messagestr = alarmmessage),
  373. X                       NULL);
  374. X    else {
  375. X    message = XtVaCreateManagedWidget ("message", labelWidgetClass, alarmbox, NULL);
  376. X    XtVaGetValues (message, XtNlabel, &xalarm.messagestr, NULL);
  377. X    }
  378. X
  379. X    XtOverrideTranslations (snoozetime,
  380. X                XtParseTranslationTable (snoozetimetranslations));
  381. X
  382. X    xalarm.alarmwidget = alarm;
  383. X    xalarm.snoozetimebutton = snoozetime;
  384. X    xalarm.messagewidget = message;
  385. }
  386. X
  387. X
  388. X
  389. /* 
  390. X * This is for the snoozetime button which doubles as the label showing how 
  391. X * much time the snooze is selected for.
  392. X */
  393. X
  394. void ShowClickToZero ()
  395. {
  396. X    XtVaSetValues (xalarm.snoozetimebutton, XtNlabel, (XtArgVal) "Zero time", NULL);
  397. X    EnsureNotGrownOffScreen (xalarm.alarmwidget);
  398. }
  399. X  
  400. X
  401. X
  402. void ShowSnoozeValue ()
  403. {  
  404. X    char   buf[TEXT];
  405. X
  406. X    MAKETIMESTRING (buf, (int) (xalarm.timeout / MSECSIN1MIN));
  407. X    XtVaSetValues (xalarm.snoozetimebutton, XtNlabel, (XtArgVal) buf, NULL);
  408. X    EnsureNotGrownOffScreen (xalarm.alarmwidget);
  409. }
  410. X
  411. X
  412. X
  413. /* 
  414. X * Add to the amount that is currently the amount to snooze by.
  415. X */
  416. X
  417. static void SnoozeAmount (widget, clientdata, calldata)
  418. X  Widget      widget;
  419. X  XtPointer   clientdata, calldata;
  420. {
  421. X    int   mins = (int) clientdata;
  422. X
  423. X    if (mins == 0) {
  424. X    xalarm.timeout = xalarm.dateout = 0;
  425. X    ShowClickToZero ();
  426. X    } else {
  427. X    xalarm.timeout += (mins*MSECSIN1MIN);
  428. X    ShowSnoozeValue ();
  429. X    }
  430. }
  431. X
  432. X
  433. X
  434. /* 
  435. X * Time to sleep.  Add the time outs & disappear.
  436. X */
  437. X
  438. static void Snooze (widget, clientdata, calldata)
  439. X  Widget      widget;
  440. X  XtPointer   clientdata, calldata;
  441. {
  442. X    AddTimeOuts ();
  443. X    if (ISVALID (xalarm.pesterid)) {
  444. X    XtRemoveTimeOut (xalarm.pesterid);
  445. X    xalarm.pesterid = INVALID;
  446. X    }
  447. X    if (ISVALID (xalarm.alarmid)) {
  448. X    XtRemoveTimeOut (xalarm.alarmid);
  449. X    xalarm.alarmid = INVALID;
  450. X    }
  451. X
  452. X    XtPopdown (xalarm.alarmwidget);
  453. }
  454. X
  455. X
  456. X
  457. /* 
  458. X * Time to wake up.
  459. X */
  460. X
  461. void WakeUp (clientdata, id)
  462. X  XtPointer      clientdata;
  463. X  XtIntervalId      id;
  464. {
  465. X    xalarm.timeout = xalarm.dateout = 0;
  466. X    xalarm.saveonshutdown = False;
  467. X    SnoozeAmount ((Widget) NULL, (XtPointer) xalarm.snooze, (XtPointer) NULL);
  468. X
  469. X    if (ISNONID (xalarm.alarmid))
  470. X    TimeTracker ((XtPointer) xalarm.alarmwidget, (XtIntervalId) NULL);
  471. X    SetGeometry (xalarm.alarmwidget);
  472. X    XtPopup (xalarm.alarmwidget, XtGrabNone);
  473. X    XFlush (XtDisplay (xalarm.alarmwidget));
  474. X    Audio (xalarm.alarmaudio);
  475. X
  476. X    if (xalarm.pester > 0) {
  477. X    XRaiseWindow (XtDisplay (xalarm.alarmwidget), XtWindow (xalarm.alarmwidget));
  478. X    xalarm.pesterid =
  479. X        XtAppAddTimeOut (xalarm.appcon, TIMEOUT (xalarm.pester * MSECSIN1MIN),
  480. X                 (XtTimerCallbackProc) WakeUp, (XtPointer) NULL);
  481. X    }
  482. X
  483. X    if (ISWIDGET (xalarm.warningwidget))
  484. X    QuitWarning ((Widget) NULL,
  485. X             (XtPointer) (XtParent (XtParent (xalarm.warningwidget))),
  486. X             (XtPointer) NULL);
  487. }
  488. X
  489. X
  490. X
  491. /* 
  492. X * Track the time for this widget.  Puts a clock in the WM name,
  493. X * along with the user's name etc.
  494. X */
  495. X
  496. static void TimeTracker (clientdata, id)
  497. X  XtPointer      clientdata;
  498. X  XtIntervalId      id;
  499. {
  500. X    String      user = UserName(), host = MachineName(), name = getenv ("NAME");
  501. X    char      wmname[TEXT];
  502. X    time_t      now;
  503. X    struct tm     *clock;
  504. X
  505. X    (void) time (&now);
  506. X    clock = localtime (&now);
  507. X    now -= (time_t) xalarm.offtime;
  508. X
  509. X    (void) sprintf (wmname, NAMEFORMAT, xalarm.proggie, user, host);
  510. X    if (NONNIL (String, name))
  511. X    (void) sprintf (ENDOF (wmname), REALNAMEFORMAT, name);
  512. X    if (now >= 60) {
  513. X    (void) strcat (wmname, " +");
  514. X    MAKETIMESTRING (ENDOF (wmname), now / SECSIN1MIN);
  515. X    }
  516. X    (void) sprintf (ENDOF (wmname), TIMEFORMAT, clock->tm_hour, clock->tm_min);
  517. X
  518. X    SetWMName ((Widget) clientdata, wmname);
  519. X
  520. X    xalarm.alarmid = ResetTracker (TimeTracker, clientdata, (int) (xalarm.offtime % 60));
  521. }
  522. X
  523. X
  524. X
  525. /* 
  526. X * Let's popup to reset our alarm.
  527. X */
  528. X
  529. SIGRET ResetAlarm (sig, code, scp, addr)
  530. X  int               sig, code;
  531. X  struct sigcontext  *scp;
  532. X  char              *addr;
  533. {
  534. X    unsigned long   timeout = SUMTIMEOUTS (xalarm.dateout, xalarm.timeout);
  535. X    time_t         now;
  536. X    int         i;
  537. X
  538. X    now = time ((time_t *) NULL);
  539. X    timeout -= (now - xalarm.settime);
  540. X
  541. X    for (i=0; i<xalarm.numwarnings; i++)
  542. X    if (timeout  > xalarm.warnings[i])
  543. X        XtRemoveTimeOut (xalarm.timeoutid[i]);
  544. X    XtRemoveTimeOut (xalarm.timeoutid[xalarm.numwarnings]);
  545. X
  546. X    if (ISVALID (xalarm.pesterid)) {
  547. X    XtRemoveTimeOut (xalarm.pesterid);
  548. X    xalarm.pesterid = INVALID;
  549. X    }
  550. X
  551. X    xalarm.dateout = DateToMilliSeconds (xalarm.datestr);
  552. X    xalarm.timeout = TimeToMilliSeconds (xalarm.timestr);
  553. X
  554. X    PopupAndAsk ();
  555. }
  556. SHAR_EOF
  557. chmod 0644 alarm.c ||
  558. echo 'restore of alarm.c failed'
  559. Wc_c="`wc -c < 'alarm.c'`"
  560. test 7396 -eq "$Wc_c" ||
  561.     echo 'alarm.c: original size 7396, current size' "$Wc_c"
  562. rm -f _shar_wnt_.tmp
  563. fi
  564. # ============= config.1st ==============
  565. if test -f 'config.1st' -a X"$1" != X"-c"; then
  566.     echo 'x - skipping config.1st (File already exists)'
  567.     rm -f _shar_wnt_.tmp
  568. else
  569. > _shar_wnt_.tmp
  570. echo 'x - extracting config.1st (Text)'
  571. sed 's/^X//' << 'SHAR_EOF' > 'config.1st' &&
  572. #!/bin/sh
  573. X
  574. # Just try to find out the full path names for kill, ps, grep & colrm which
  575. # are used within fns.c to do process listing.
  576. X
  577. echo -n '
  578. I need to find the path of a few things on your system.  If I guess wrongly,
  579. say so at the end, and I will try again.  If I do not know where they reside, I
  580. will ask you.  Default answers are in brackets.  If you do not know where they
  581. are on your system, first try "which <command>" (or equivalent) in a shell, or
  582. ask your local System Guru or Manager.
  583. X
  584. + If you do not have "kill", "ps", "grep" or "colrm" (or equivalent), do not
  585. X  panic, xalarm only uses them when it is attempting to list the process ids of
  586. X  other xalarms.  If you do not have these commands, just hit RETURN.
  587. X
  588. X  You can make xalarm, but you will not be able to use the -reset, -kill or
  589. X  -list options.
  590. X
  591. X  I need to know because xalarm should use full path names.
  592. X
  593. + If you do not have "fortune" or "yow", you cannot have the X equivalent since
  594. X  they are just front ends to them!  But do not panic, they are not necessary
  595. X  for xalarm, so if you do not have them just hit RETURN when asked for their
  596. X  whereabouts.
  597. X
  598. Hit RETURN when ready...'
  599. read dummy
  600. echo " "
  601. X
  602. if test "$1" = "-quick"; then
  603. X    mode=-quick
  604. X    shift
  605. else
  606. X    mode=
  607. fi
  608. X
  609. kill=`./fullpath $mode kill`
  610. ps=`./fullpath $mode ps`
  611. grep=`./fullpath $mode grep`
  612. colrm=`./fullpath $mode colrm`
  613. X
  614. echo '/*
  615. X * Get xalarm pids:
  616. X *     list user processes | filter for xalarm | pid #s only | filter us out
  617. X *
  618. X * Where "us" is where the xalarm pid# running this will go.
  619. X *
  620. X * Normally we use ps(1), grep(1), colrm(1) and grep(1) again, respectively.
  621. X * Typically:
  622. X *    "/bin/ps -cx | /bin/grep -w xalarm | /usr/ucb/colrm 7 | /bin/grep -v %d"
  623. X */
  624. X
  625. #define    GETXALARMPIDS    \
  626. X    "'$ps' -cx | '$grep' -w xalarm | '$colrm' 7 | '$grep' -v %d"
  627. X
  628. /*
  629. X * Full path of kill(1), typically "/bin/kill".
  630. X */
  631. X
  632. #define    KILLPATH    "'$kill'"
  633. ' > fns.h
  634. X
  635. echo "+ Created fns.h using these."
  636. echo " "
  637. X
  638. for program in $*; do
  639. X    progpath=`./fullpath $mode $program`
  640. X    if test -f "$progpath"; then
  641. X        echo '#!/bin/sh
  642. exec xmemo -name x'$program' ${1+"$@"} "`'$progpath'`"' > x$program
  643. X        echo "+ Created x$program using this."
  644. X    else
  645. X        echo '#!/bin/sh
  646. exec xmemo -name x'$program' "Sorry, x'$program' is unavailable - no '$program'!"' > x$program
  647. X        echo "+ Created x$program with an apologetic message."
  648. X    fi
  649. X    chmod +x x$program
  650. done
  651. X
  652. echo -n "
  653. Are these OK? [y] "
  654. read ans
  655. case $ans in
  656. X    ""|"y"*|"Y"*)    touch .config
  657. X            echo "
  658. Thank you.
  659. ";;
  660. X    *)        ./config.1st $*;;
  661. esac
  662. SHAR_EOF
  663. chmod 0755 config.1st ||
  664. echo 'restore of config.1st failed'
  665. Wc_c="`wc -c < 'config.1st'`"
  666. test 2498 -eq "$Wc_c" ||
  667.     echo 'config.1st: original size 2498, current size' "$Wc_c"
  668. rm -f _shar_wnt_.tmp
  669. fi
  670. # ============= dates.c ==============
  671. if test -f 'dates.c' -a X"$1" != X"-c"; then
  672.     echo 'x - skipping dates.c (File already exists)'
  673.     rm -f _shar_wnt_.tmp
  674. else
  675. > _shar_wnt_.tmp
  676. echo 'x - extracting dates.c (Text)'
  677. sed 's/^X//' << 'SHAR_EOF' > 'dates.c' &&
  678. /*
  679. X      Copyright (c) 1991, 1992 by Simon Marshall, University of Hull, UK
  680. X
  681. X           If you still end up late, don't blame me!
  682. X                       
  683. X  Permission to use, copy, modify, distribute, and sell this software and its
  684. X       documentation for any purpose and without fee is hereby granted,
  685. X    provided that the above copyright notice appear in all copies and that
  686. X    both that copyright notice and this permission notice appear in
  687. X               supporting documentation.
  688. X                       
  689. X  This software is provided AS IS with no warranties of any kind.  The author
  690. X    shall have no liability with respect to the infringement of copyrights,
  691. X     trade secrets or any patents by this file or any part thereof.  In no
  692. X      event will the author be liable for any lost revenue or profits or
  693. X          other special, indirect and consequential damages.
  694. */
  695. X
  696. /* 
  697. X * Parse dates.
  698. X */
  699. X
  700. X
  701. X
  702. #include "xalarm.h"
  703. #include "dates.h"
  704. X
  705. X
  706. Boolean        AppointmentWithin();
  707. unsigned long    DateToMilliSeconds();
  708. int        DaysTo();
  709. static int    DaysBetween(), DaysBeforeDate();
  710. static Boolean    ParseDateString();
  711. extern Boolean    ParseTimeString(), IsInteger();
  712. extern String    NextWord();
  713. extern long    TimeToMilliSeconds();
  714. extern time_t    time();
  715. extern struct tm *localtime();
  716. X
  717. X
  718. X
  719. extern AlarmData xalarm;
  720. X
  721. X
  722. X
  723. /* 
  724. X * Is the number of days before the date within the number of days given.
  725. X */
  726. X
  727. Boolean AppointmentWithin (withindays, line, timestr, datestr, chpos)
  728. X  String   line, *timestr, *datestr;
  729. X  int        withindays, *chpos;
  730. {
  731. X    String         date, word;
  732. X    Boolean         dummy;
  733. X    unsigned long   dateout;
  734. X    long         timeout;
  735. X    int         days, dayofweek, dayofmonth, month, year, hrs, mins;
  736. X
  737. X    if ((*line == '\n') or (*line == '#') or (*line == '!') or (*line == '\0'))
  738. X    return (False);
  739. X
  740. X    /* 
  741. X     * Get the date.
  742. X     */
  743. X    date = XtMalloc (TEXT);
  744. X    date[0] = '\0';
  745. X    while (strcmp (word = NextWord (line, chpos), "-"))
  746. X    if (*word == '\0')
  747. X        break;
  748. X    else if (date[0] == '\0')
  749. X        (void) strcpy (date, word);
  750. X    else
  751. X        (void) sprintf (ENDOF (date), " %s", word);
  752. X
  753. X    if (date[0] == '\0')
  754. X    *datestr = XtNewString ("today");
  755. X    else
  756. X    *datestr = XtNewString (date);
  757. X
  758. X    if (not ParseDateString (*datestr, &days, &dayofweek, &dayofmonth, &month, &year)) {
  759. X    (void) fprintf (stderr, "%s%s", xalarm.errormessage, line);
  760. X    return (False);
  761. X    }
  762. X
  763. X    /*
  764. X     * Get the time.
  765. X     * There might not be a time there, so we ignore any errors.
  766. X     */
  767. X    if (*word == '\0')
  768. X    *timestr = XtNewString ("+0");
  769. X    else {
  770. X    *timestr = NextWord (line, chpos);
  771. X    if (not ParseTimeString (*timestr, &hrs, &mins, &dummy)) {
  772. X        if (*timestr[0] != '\0')
  773. X        do
  774. X            (*chpos)--;
  775. X        while (line[*chpos] != ' ');
  776. X        *timestr = XtNewString ("+0");
  777. X    }
  778. X    }
  779. X    
  780. X    dateout = DateToMilliSeconds (*datestr);
  781. X    timeout = TimeToMilliSeconds (*timestr);
  782. X
  783. X    if (ISVALID (dateout)) {
  784. X    /* 
  785. X     * We can't just see if the sum is positive 'cos dateout is unsigned...
  786. X     */
  787. X    days = (int) (dateout / MSECSIN1DAY);
  788. X    return (((days > 0) and (days <= withindays)) or
  789. X        ((days == 0) and (timeout >= 0)));
  790. X    } else {
  791. X    /* 
  792. X     * We don't report errors if the alarm is just too far ahead or gone...
  793. X     */
  794. X    (void) DateToMilliSeconds (*datestr);
  795. X    if (not (ERRORIS (TOOFARAHEAD) or ERRORIS (DATEPASSED) or ERRORIS (TIMEPASSED)))
  796. X        (void) fprintf (stderr, "%s%s", xalarm.errormessage, line);
  797. X    return (False);
  798. X    }
  799. }
  800. X
  801. X
  802. X
  803. /* 
  804. X * Returns the number of milliseconds to the date given in datestr.
  805. X */
  806. X
  807. unsigned long DateToMilliSeconds (datestr)
  808. X  String   datestr;
  809. {
  810. X    char   baddate[TEXT];
  811. X    int    days, dayofweek, dayofmonth, month, year;
  812. X
  813. X    if (*datestr == '\0')
  814. X    return ((unsigned long) 0);
  815. X    else if (not ParseDateString (datestr, &days, &dayofweek, &dayofmonth, &month, &year))
  816. X    return ((unsigned long) INVALID);
  817. X
  818. X    if (ISINVALID (days))
  819. X    days = DaysBeforeDate (dayofweek, dayofmonth, month, year);
  820. X
  821. X    if (((days > 0) and (days <= MAXDAYS)) or
  822. X    ((days == 0) and (ISINVALID (xalarm.timeout) or (xalarm.timeout >= 0))))
  823. X    return ((unsigned long) days * MSECSIN1DAY);
  824. X    else {
  825. X    if ((days == 0) and (ISVALID (xalarm.timeout)) and (xalarm.timeout < 0)) {
  826. X        ADDERROR (TIMEPASSED, (String) NULL);
  827. X    } else if (days < 0) {
  828. X        (void) sprintf (baddate, "%d days", days);
  829. X        ADDERROR (DATEPASSED, baddate);
  830. X    } else {
  831. X        (void) sprintf (baddate, "+%d days", days);
  832. X        ADDERROR (TOOFARAHEAD, baddate);
  833. X    }
  834. X    return ((unsigned long) INVALID);
  835. X    }
  836. }
  837. X
  838. X
  839. X
  840. /* 
  841. X * Parse that string.  I did this one myself!
  842. X * Works in whole days only.
  843. X */
  844. X
  845. static Boolean ParseDateString (str, days, dayofweek, dayofmonth, month, year)
  846. X  String   str;
  847. X  int       *days, *dayofweek, *dayofmonth, *month, *year;
  848. {
  849. X    static int       daysin[] = {DAYSINMONTHS};
  850. X    static char   strings[][4] = {WEEKDAYS, MONTHS, TODAY, DAILY, TOMORROW, WEEK, WEEKLY,
  851. X                  "!!!", "!!!"};
  852. X    String       word, monthstr = (String) NULL;
  853. X    time_t       now;
  854. X    struct tm      *today;
  855. X    int       thisyear, num, i, chpos = 0;
  856. X    
  857. X    RESETERROR ();
  858. X    
  859. X    *days = *dayofweek = *dayofmonth = *month = *year = -1;
  860. X
  861. X    (void) time (&now);
  862. X    today = localtime (&now);
  863. X
  864. X    if ((*str == '+') and (IsInteger (str)))
  865. X    *days = atoi (str);
  866. X    else
  867. X    while (strcmp (word = NextWord (str, &chpos), "")) {
  868. X        i = 0;
  869. X        while ((not (STREQUAL (word, strings[i]))) and (i < XtNumber (strings)))
  870. X        i++;
  871. X
  872. X        if (i == 19)                /* TODAY. */
  873. X        *days = 0;
  874. X        else if (i == 20)                /* DAILY. */
  875. X        *days = 1;
  876. X        else if (i == 21)                /* TOMORROW. */
  877. X        if (*days < 0)
  878. X            *days = 1;
  879. X        else
  880. X            (*days)++;
  881. X        else if ((i == 22) or (i == 23))        /* WEEK or WEEKLY. */
  882. X        if (*days < 0)
  883. X            *days = 7;
  884. X        else
  885. X            (*days) += 7;
  886. X        else if (i < 7)                /* Weekday. */
  887. X        if (*dayofweek < 0)
  888. X            *dayofweek = i;
  889. X        else {
  890. X            ADDERROR (ANOTHERWEEKDAY, word);
  891. X            return (False);
  892. X        }
  893. X        else if (i < 19)                /* Month. */
  894. X        if (*month < 0) {
  895. X            *month = i-7;
  896. X            monthstr = word;
  897. X        } else {
  898. X            ADDERROR (ANOTHERMONTH, word);
  899. X            return (False);
  900. X        }
  901. X        else if (((num = atoi (word)) <= 0) or (not IsInteger (word))) {
  902. X            ADDERROR (UNRECOGNISED, word);
  903. X            return (False);
  904. X        }
  905. X        /*
  906. X         * Otherwise assume it's a year or a month day.
  907. X         */
  908. X        else if (num > 90)
  909. X            if (*year < 0)
  910. X            *year = num;
  911. X            else {
  912. X            ADDERROR (ANOTHERYEAR, word);
  913. X            return (False);
  914. X            }
  915. X        else
  916. X            if (*dayofmonth < 0)
  917. X            *dayofmonth = num;
  918. X            else {
  919. X            ADDERROR (ANOTHERMONTH, word);
  920. X            return (False);
  921. X            }
  922. X    }
  923. X    
  924. X    /* 
  925. X     * Have we been given a day + day of week, like "week tues"?
  926. X     */
  927. X    if ((*days > 0) and (*dayofweek >= 0))
  928. X    (*days) += ((*dayofweek + 7) - today->tm_wday) % 7;
  929. X
  930. X    /* 
  931. X     * Check that the day of month is OK for this month.
  932. X     */
  933. X    if ((*month >= 0) and (*dayofmonth > 0)) {
  934. X    if ((thisyear = *year) < 0)
  935. X        thisyear = today->tm_year + 1900;
  936. X    daysin[1] = DAYSINFEB (thisyear);
  937. X    if (*dayofmonth > daysin[*month]) {
  938. X        ADDERROR (WRONGDAYSMONTH, monthstr);
  939. X        return (False);
  940. X    }
  941. X    }
  942. X    
  943. X    return (True);
  944. }
  945. X
  946. X
  947. X
  948. /* 
  949. X * Calculates the number of *whole* days before the date given by the args.
  950. X */
  951. X
  952. static int DaysBeforeDate (dayofweek, dayofmonth, month, year)
  953. X  int        dayofweek, dayofmonth, month, year;
  954. {
  955. X    static int      daysin[] = {DAYSINMONTHS};
  956. X    struct tm      today, *date;
  957. X    time_t      now;
  958. X
  959. X    (void) time (&now);
  960. X    date = localtime (&now);
  961. X    today.tm_yday = date->tm_yday;
  962. X    today.tm_year = date->tm_year;
  963. X
  964. X    if (year > 99)
  965. X    year = year - 1900;
  966. X
  967. X    if (dayofweek < 0) {
  968. X    /* 
  969. X     * If no day of week is given, just use the day/month/year date.
  970. X     * Cycle through the month/year.
  971. X     */
  972. X    if (dayofmonth >= 0)        date->tm_mday = dayofmonth;
  973. X    if (month >= 0)            date->tm_mon = month;
  974. X    if (year >= 0)            date->tm_year = year;
  975. X    while ((year < 0) and (date->tm_year < (2500-1900)) and
  976. X           (DaysBetween (&today, date) < 0))
  977. X        if (month < 0)
  978. X        date->tm_mon = (date->tm_mon + 1) % 12;
  979. X        else
  980. X        date->tm_year++;
  981. X    } else
  982. X    /* 
  983. X     * We assume Buck Rodgers will have something better than xalarm...
  984. X     * Cycle through dates until we find it.
  985. X     */
  986. X    while ((date->tm_year < (2500-1900)) and 
  987. X           (((dayofweek >= 0) and    (dayofweek != date->tm_wday)) or
  988. X        ((dayofmonth >= 0) and    (dayofmonth != date->tm_mday)) or
  989. X        ((month >= 0) and    (month != date->tm_mon)) or
  990. X        ((year >= 0) and    (year != date->tm_year)))) {
  991. X        /* 
  992. X         * Just add one to the week day & month day...
  993. X         */
  994. X        date->tm_wday = (date->tm_wday + 1) % 7;
  995. X        date->tm_mday++;
  996. X        daysin[1] = DAYSINFEB (date->tm_year + 1900);
  997. X        if (date->tm_mday > daysin[date->tm_mon]) {
  998. X        date->tm_mday = 1;
  999. X        date->tm_mon++;
  1000. X        if (date->tm_mon > 11) {
  1001. X            date->tm_mon = 0;
  1002. X            date->tm_year++;
  1003. X        }
  1004. X        }
  1005. X    }
  1006. X
  1007. X    return (DaysBetween (&today, date));
  1008. }
  1009. X
  1010. X
  1011. X
  1012. /* 
  1013. X * Why oh why don't all systems have timelocal()?
  1014. X */
  1015. X
  1016. static int DaysBetween (today, date)
  1017. X  struct tm  *today, *date;
  1018. {
  1019. X    static int      daysin[] = {DAYSINMONTHS};
  1020. X    int      i, dayofyear = date->tm_mday-1, daysbetween = 0;
  1021. X
  1022. X    for (i=0; i<date->tm_mon; i++)
  1023. X    if (i == 1)
  1024. X        dayofyear += DAYSINFEB (date->tm_year + 1900);
  1025. X    else
  1026. X        dayofyear += daysin[i];
  1027. X
  1028. X    if (date->tm_year == today->tm_year)
  1029. X    return (dayofyear - today->tm_yday);
  1030. X    else {
  1031. X    for (i = 1 + MIN (date->tm_year, today->tm_year);
  1032. X         i < MAX (date->tm_year, today->tm_year); i++)
  1033. X        daysbetween += DAYSINYEAR (i + 1900);
  1034. X
  1035. X    daysbetween += (date->tm_year > today->tm_year) ?
  1036. X            dayofyear + (DAYSINYEAR (today->tm_year+1900) - today->tm_yday) :
  1037. X            today->tm_yday + (DAYSINYEAR (date->tm_year+1900) - dayofyear);
  1038. X
  1039. X    return ((date->tm_year > today->tm_year) ? daysbetween : -daysbetween);
  1040. X    }
  1041. }
  1042. X
  1043. X
  1044. X
  1045. /* 
  1046. X * Returns the number of days before the date given.  WEEK is special.
  1047. X * WEEK means until the end of the current week.
  1048. X */
  1049. X
  1050. int DaysTo (datestr, inst)
  1051. X  String     datestr;
  1052. X  Instance   inst;
  1053. {
  1054. X    time_t         abstime;
  1055. X    struct tm        *now;
  1056. X    unsigned long   millisecs;
  1057. X
  1058. X    (void) time (&abstime);
  1059. X    now = localtime (&abstime);
  1060. X
  1061. X    if (STREQUAL (datestr, WEEK))
  1062. X    if (inst == Daemon)
  1063. X        return (DAEMONWEEKLY);
  1064. X    else
  1065. X        return (7 - now->tm_wday);
  1066. X    else
  1067. X    if (ISVALID (millisecs = DateToMilliSeconds (datestr)))
  1068. X        return ((int) (millisecs / MSECSIN1DAY));
  1069. X    else
  1070. X        return (INVALID);
  1071. }
  1072. SHAR_EOF
  1073. chmod 0644 dates.c ||
  1074. echo 'restore of dates.c failed'
  1075. Wc_c="`wc -c < 'dates.c'`"
  1076. test 10134 -eq "$Wc_c" ||
  1077.     echo 'dates.c: original size 10134, current size' "$Wc_c"
  1078. rm -f _shar_wnt_.tmp
  1079. fi
  1080. # ============= dates.h ==============
  1081. if test -f 'dates.h' -a X"$1" != X"-c"; then
  1082.     echo 'x - skipping dates.h (File already exists)'
  1083.     rm -f _shar_wnt_.tmp
  1084. else
  1085. > _shar_wnt_.tmp
  1086. echo 'x - extracting dates.h (Text)'
  1087. sed 's/^X//' << 'SHAR_EOF' > 'dates.h' &&
  1088. /*
  1089. X      Copyright (c) 1991, 1992 by Simon Marshall, University of Hull, UK
  1090. X
  1091. X           If you still end up late, don't blame me!
  1092. X                       
  1093. X  Permission to use, copy, modify, distribute, and sell this software and its
  1094. X       documentation for any purpose and without fee is hereby granted,
  1095. X    provided that the above copyright notice appear in all copies and that
  1096. X    both that copyright notice and this permission notice appear in
  1097. X               supporting documentation.
  1098. X                       
  1099. X  This software is provided AS IS with no warranties of any kind.  The author
  1100. X    shall have no liability with respect to the infringement of copyrights,
  1101. X     trade secrets or any patents by this file or any part thereof.  In no
  1102. X      event will the author be liable for any lost revenue or profits or
  1103. X          other special, indirect and consequential damages.
  1104. */
  1105. X
  1106. /* 
  1107. X * Various stuff to do with dates & times.
  1108. X * 
  1109. X * Maximum allowed days based on a 32-bit unsigned long, ie. 2^32 / 24*60*60*1000.
  1110. X */
  1111. X
  1112. #define        MAXDAYS        (49)
  1113. X
  1114. /*
  1115. X * Change these if you want a different notation/language.  Keep it to 
  1116. X * 3 chars each, lower case only.
  1117. X */
  1118. X
  1119. #define        WEEKDAYS    "sun", "mon", "tue", "wed", "thu", "fri", "sat"
  1120. #define        MONTHS        "jan", "feb", "mar", "apr", "may", "jun", \
  1121. X                "jul", "aug", "sep", "oct", "nov", "dec"
  1122. #define        DAYSINMONTHS    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1123. #define        TODAY        "tod"
  1124. #define        DAILY        "dai"
  1125. #define        TOMORROW    "tom"
  1126. #define        WEEK        "wee"
  1127. #define        WEEKLY        "wee"
  1128. #define        NOW        "now"
  1129. #define        NOON        "noo"
  1130. X
  1131. /* 
  1132. X * Error messages.
  1133. X */
  1134. X
  1135. #define        DATEPASSED    "The date has passed."
  1136. #define        TOOFARAHEAD    "Too far ahead, I'm afraid."
  1137. #define        ANOTHERWEEKDAY    "Another weekday?"
  1138. #define        ANOTHERMONTH    "Another month?"
  1139. #define        ANOTHERYEAR    "Another year?"
  1140. #define        WRONGDAYSMONTH    "Wrong days in month?"
  1141. #define        WRONGNUMDIGITS    "Wrong number of digits."
  1142. #define        TIMEPASSED    "The time has passed today."
  1143. #define        EXPECTEDAMPM    "Expected am/pm."
  1144. #define        BADHOURS    "Bad number of hours."
  1145. #define        BADMINUTES    "Bad number of minutes."
  1146. #define        UNRECOGNISED    "Don't recognise this."
  1147. SHAR_EOF
  1148. chmod 0644 dates.h ||
  1149. echo 'restore of dates.h failed'
  1150. Wc_c="`wc -c < 'dates.h'`"
  1151. test 2064 -eq "$Wc_c" ||
  1152.     echo 'dates.h: original size 2064, current size' "$Wc_c"
  1153. rm -f _shar_wnt_.tmp
  1154. fi
  1155. # ============= file.c ==============
  1156. if test -f 'file.c' -a X"$1" != X"-c"; then
  1157.     echo 'x - skipping file.c (File already exists)'
  1158.     rm -f _shar_wnt_.tmp
  1159. else
  1160. > _shar_wnt_.tmp
  1161. echo 'x - extracting file.c (Text)'
  1162. sed 's/^X//' << 'SHAR_EOF' > 'file.c' &&
  1163. /*
  1164. X      Copyright (c) 1991, 1992 by Simon Marshall, University of Hull, UK
  1165. X
  1166. X           If you still end up late, don't blame me!
  1167. X                       
  1168. X  Permission to use, copy, modify, distribute, and sell this software and its
  1169. X       documentation for any purpose and without fee is hereby granted,
  1170. X    provided that the above copyright notice appear in all copies and that
  1171. X    both that copyright notice and this permission notice appear in
  1172. X               supporting documentation.
  1173. X                       
  1174. X  This software is provided AS IS with no warranties of any kind.  The author
  1175. X    shall have no liability with respect to the infringement of copyrights,
  1176. X     trade secrets or any patents by this file or any part thereof.  In no
  1177. X      event will the author be liable for any lost revenue or profits or
  1178. X          other special, indirect and consequential damages.
  1179. */
  1180. X
  1181. /* 
  1182. X * Deal with the appointments alarm file.
  1183. X */
  1184. X
  1185. X
  1186. #include "xalarm.h"
  1187. #include "dates.h"
  1188. X
  1189. #include <X11/Xaw/Dialog.h>
  1190. X
  1191. /* 
  1192. X * We use fcntl() to lock files, or we can use flock() or lockf():
  1193. X */
  1194. X
  1195. #if defined (USEFLOCK)
  1196. #include <sys/file.h>
  1197. #elif defined (USELOCKF)
  1198. #include <unistd.h>
  1199. #elif not defined (SEEK_SET)
  1200. #define SEEK_SET 0
  1201. #endif
  1202. X
  1203. X
  1204. #define        ALARMFILEFORMAT        "\n%s %s %2d - %s\t%s\n"
  1205. #define        DIALOGVALUE(widget)    (XtNewString (XawDialogGetValueString (widget)))
  1206. #define        UPCASE(ch)        (((ch) >= 'a') and ((ch) <= 'z') ? \
  1207. X                     ((ch) - 'a' + 'A') : (ch))
  1208. X
  1209. X
  1210. void        SaveAlarmSettings(), AlarmDying(), RestartDiedAlarms();
  1211. int        ParseAlarmFile();
  1212. static Boolean    SaveAlarm();
  1213. static void    RenameFile();
  1214. extern Boolean    AppointmentWithin();
  1215. extern long    TimeToMilliSeconds();
  1216. extern unsigned long DateToMilliSeconds();
  1217. extern String    ReplaceNewlines(), HomeDirectory(), DisplayName(), getenv();
  1218. extern void    DoAlarm(), EditedText(), MakeConfirmMessage(), EnsureNotGrownOffScreen();
  1219. extern FORKRET    fork();
  1220. extern time_t    time();
  1221. extern struct tm *localtime();
  1222. X
  1223. X
  1224. X
  1225. extern AlarmData    xalarm;
  1226. X
  1227. X
  1228. X
  1229. /* 
  1230. X * Parse each line of the alarm file, if it's around.  If the 
  1231. X * appointment is within that given, fork and do the alarm.  Returns
  1232. X * number forked.
  1233. X */
  1234. X
  1235. int ParseAlarmFile (days, argv, argc)
  1236. X  String  *argv;
  1237. X  int        days, argc;
  1238. {
  1239. X    FILE     *file;
  1240. X    String    timestr, datestr, alarmfilepath = getenv ("XALARMFILEPATH"),
  1241. X          home = HomeDirectory ();
  1242. X    Boolean   failed = True;
  1243. X    char      alarmpath[TEXT], filename[TEXT], line[TEXT];
  1244. X    int       newargc, endofdate, start, finish = 0, kids = 0;
  1245. X    
  1246. X    (void) sprintf (alarmpath, "%s/.xalarms", HomeDirectory ());
  1247. X    if (NONNIL (String, alarmfilepath))
  1248. X    (void) sprintf (ENDOF (alarmpath), ":%s", alarmfilepath);
  1249. X
  1250. X    do {
  1251. X    /* 
  1252. X     * Try each file in the path list.
  1253. X     */
  1254. X    start = finish;
  1255. X    while ((alarmpath[finish] != '\0') and (alarmpath[finish] != ':'))
  1256. X        finish++;
  1257. X
  1258. X    if (alarmpath[start] == '/') {
  1259. X        (void) strncpy (filename, alarmpath+start, finish-start);
  1260. X        filename[finish-start] = '\0';
  1261. X    } else {
  1262. X        (void) sprintf (filename, "%s/", home);
  1263. X        (void) strncpy (ENDOF (filename), alarmpath+start, finish-start);
  1264. X        filename[finish-start + strlen (home)+1] = '\0';
  1265. X    }
  1266. X
  1267. X    if (NONNIL (FILE *, (file = fopen (filename, "r")))) {
  1268. X        /* 
  1269. X         * Deal with this file.
  1270. X         */
  1271. X        failed = False;
  1272. X
  1273. X        while (NONNIL (String, fgets (line, TEXT, file))) {
  1274. X        endofdate = 0;
  1275. X        if (AppointmentWithin (days, line, ×tr, &datestr, &endofdate)) {
  1276. X            while (isspace (line[endofdate]))
  1277. X            endofdate++;
  1278. X            
  1279. X            newargc = argc;
  1280. X            argv[newargc++] = XtNewString ("-time");
  1281. X            argv[newargc++] = timestr;
  1282. X            argv[newargc++] = XtNewString ("-date");
  1283. X            argv[newargc++] = datestr;
  1284. X            
  1285. X            if (line[endofdate] != '\0') {
  1286. X            line[strlen (line) - 1] = '\0';
  1287. X            argv[newargc++] = line+endofdate;
  1288. X            }
  1289. X
  1290. X            switch ((int) fork ()) {
  1291. X             case -1:
  1292. X            perror ("xalarm");
  1293. X            exit (-1);
  1294. X             case 0:
  1295. X            DoAlarm (argv, newargc);
  1296. X             default:
  1297. X            kids++;
  1298. X            }
  1299. X        }
  1300. X        }
  1301. X    }
  1302. X    
  1303. X    while (alarmpath[finish] == ':')
  1304. X        finish++;
  1305. X    } while (alarmpath[finish] != '\0');
  1306. X
  1307. X    if (failed)
  1308. X    fprintf (stderr, "Failed to open any of these alarm files:\n%s\n", alarmpath);
  1309. X
  1310. X    return (kids);
  1311. }
  1312. X
  1313. X
  1314. X
  1315. /* 
  1316. X * Save the alarm settings in the alarm file.
  1317. X */
  1318. X
  1319. void SaveAlarmSettings (widget, clientdata, calldata)
  1320. X  Widget      widget;
  1321. X  XtPointer   clientdata, calldata;
  1322. {
  1323. X    String   message = DIALOGVALUE (xalarm.confirmwidget);
  1324. X    char     buf[TEXT], filename[TEXT];
  1325. X    
  1326. X    if (*message != '\0')
  1327. X    XtVaSetValues (xalarm.messagewidget, XtNlabel,
  1328. X               (XtArgVal) (xalarm.messagestr = message), NULL);
  1329. X    
  1330. X    MakeConfirmMessage (buf);
  1331. X    (void) sprintf (filename, "%s/%s", HomeDirectory (), XALARMFILE);
  1332. X    if (not SaveAlarm (filename))
  1333. X    (void) sprintf (ENDOF (buf), "\nCouldn't open %s", filename);
  1334. X    else {
  1335. X    (void) sprintf (ENDOF (buf), "\nSaved in %s", filename);
  1336. X    EditedText ((Widget) NULL, (XtPointer) NULL, (XtPointer) False);
  1337. X    }
  1338. X
  1339. X    XtVaSetValues (xalarm.confirmwidget, XtNlabel, (XtArgVal) buf, NULL);
  1340. X    EnsureNotGrownOffScreen (XtParent (XtParent (xalarm.confirmwidget)));
  1341. }
  1342. X
  1343. X
  1344. X
  1345. /* 
  1346. X * Save the alarm in the alarm-died file.  Can be resurrected later.
  1347. X */
  1348. X
  1349. void AlarmDying (display)
  1350. X  Display  *display;
  1351. {
  1352. X    char   filename[TEXT];
  1353. X
  1354. X    if (xalarm.saveonshutdown) {
  1355. X    (void) sprintf (filename, "%s/%s.died", HomeDirectory (), XALARMFILE);
  1356. X    if (not SaveAlarm (filename))
  1357. X        (void) fprintf (stderr, "xalarm: Couldn't open %s\n", filename);
  1358. X    }
  1359. X
  1360. X    exit (0);
  1361. }
  1362. X
  1363. X
  1364. X
  1365. /* 
  1366. X * Save the current alarm.
  1367. X */
  1368. X
  1369. static Boolean SaveAlarm (filename)
  1370. X  String   filename;
  1371. {
  1372. X    FILE       *file;
  1373. X    static char    days[][4] = {WEEKDAYS}, months[][4] = {MONTHS};
  1374. #if not (defined (USEFLOCK) or defined (USELOCKF))
  1375. X    struct flock   lock;
  1376. #endif
  1377. X    time_t        now;
  1378. X    struct tm       *alarmtime;
  1379. X
  1380. X    (void) umask (63);
  1381. X    if (NONNIL (FILE *, (file = fopen (filename, "a")))) {
  1382. #if defined (USEFLOCK)
  1383. X    flock (fileno (file), LOCK_EX);
  1384. #elif defined (USELOCKF)
  1385. X    lockf (fileno (file), F_LOCK, (long) 0);
  1386. #else
  1387. X    lock.l_type = F_WRLCK;
  1388. X    lock.l_whence = SEEK_SET;
  1389. X    lock.l_start = lock.l_len = (long) 0;
  1390. X    fcntl (fileno (file), F_SETFL, O_SYNC);
  1391. X    fcntl (fileno (file), F_SETLKW, &lock);
  1392. #endif
  1393. X
  1394. X    (void) time (&now);
  1395. X    now += ((TimeToMilliSeconds (xalarm.timestr) +
  1396. X         DateToMilliSeconds (xalarm.datestr)) / MSECSIN1SEC);
  1397. X    alarmtime = localtime (&now);
  1398. X
  1399. X    days[alarmtime->tm_wday][0] = UPCASE (days[alarmtime->tm_wday][0]);
  1400. X    months[alarmtime->tm_mon][0] = UPCASE (months[alarmtime->tm_mon][0]);
  1401. X
  1402. #if defined (USELSEEK)
  1403. X    lseek (fileno (file), (off_t) 0, L_XTND);
  1404. #else
  1405. X    fseek (file, (long) 0, 2);
  1406. #endif
  1407. X
  1408. X    (void) fprintf (file, ALARMFILEFORMAT, days[alarmtime->tm_wday],
  1409. X            months[alarmtime->tm_mon], alarmtime->tm_mday,
  1410. X            xalarm.timestr, ReplaceNewlines (xalarm.messagestr));
  1411. X
  1412. X    fflush (file);
  1413. #if defined (USEFLOCK)
  1414. X    flock (fileno (file), LOCK_UN);
  1415. #elif defined (USELOCKF)
  1416. X    lockf (fileno (file), F_ULOCK, (long) 0);
  1417. #else
  1418. X    lock.l_type = F_UNLCK;
  1419. X    fcntl (fileno (file), F_SETLK, &lock);
  1420. #endif
  1421. X    fclose (file);
  1422. X    }
  1423. X
  1424. X    return (NONNIL (FILE *, file));
  1425. }
  1426. X
  1427. X
  1428. X
  1429. /* 
  1430. X * Check to see if there are any old alarms, then restart them.
  1431. X */
  1432. X
  1433. void RestartDiedAlarms (argv, argc)
  1434. X  String  *argv;
  1435. X  int        argc;
  1436. {
  1437. X    Display  *display;
  1438. X    char      diedfilename[TEXT], livefilename[TEXT], tmp[TEXT];
  1439. X    int       kids;
  1440. X    
  1441. X    (void) sprintf (diedfilename, "%s/%s.died", HomeDirectory (), XALARMFILE);
  1442. X    if (access (diedfilename, R_OK) == 0)
  1443. X    if (NIL (Display *, (display = XOpenDisplay (DisplayName (argv, argc)))))
  1444. X        (void) fprintf (stderr, "xalarm: Can't open display to restart alarms.\n");
  1445. X    else {
  1446. X        /* Save the current alarm file. */
  1447. X        (void) sprintf (livefilename, "%s/%s", HomeDirectory (), XALARMFILE);
  1448. X        (void) sprintf (tmp, "%s/%s.%05d", HomeDirectory (), XALARMFILE, getpid ());
  1449. X        if (access (livefilename, R_OK) == 0)
  1450. X        RenameFile (livefilename, tmp);
  1451. X        RenameFile (diedfilename, livefilename);
  1452. X        
  1453. X        /* Parse this file as if it were the alarm file. */
  1454. X        xalarm.saveonshutdown = True;
  1455. X        kids = ParseAlarmFile (MAXDAYS, argv, argc);
  1456. X        while (kids-- > 0)
  1457. X        (void) wait ((int *) NULL);
  1458. X        (void) unlink (livefilename);
  1459. X        
  1460. X        /* Restore the alarm file. */
  1461. X        if (access (tmp, R_OK) == 0)
  1462. X        RenameFile (tmp, livefilename);
  1463. X        XCloseDisplay (display);
  1464. X    }
  1465. }
  1466. X
  1467. X
  1468. X
  1469. /* 
  1470. X * Rename the file.
  1471. X */
  1472. X
  1473. static void RenameFile (from, to)
  1474. X  String   from, to;
  1475. {
  1476. #if defined (USERENAME)
  1477. X    (void) rename (from, to);
  1478. #else
  1479. X    (void) unlink (to);
  1480. X    (void) link (from, to);
  1481. X    (void) unlink (from);
  1482. #endif
  1483. }
  1484. SHAR_EOF
  1485. chmod 0644 file.c ||
  1486. echo 'restore of file.c failed'
  1487. Wc_c="`wc -c < 'file.c'`"
  1488. test 8441 -eq "$Wc_c" ||
  1489.     echo 'file.c: original size 8441, current size' "$Wc_c"
  1490. rm -f _shar_wnt_.tmp
  1491. fi
  1492. # ============= fns.c ==============
  1493. if test -f 'fns.c' -a X"$1" != X"-c"; then
  1494.     echo 'x - skipping fns.c (File already exists)'
  1495.     rm -f _shar_wnt_.tmp
  1496. else
  1497. > _shar_wnt_.tmp
  1498. echo 'x - extracting fns.c (Text)'
  1499. sed 's/^X//' << 'SHAR_EOF' > 'fns.c' &&
  1500. /*
  1501. X      Copyright (c) 1991, 1992 by Simon Marshall, University of Hull, UK
  1502. X
  1503. X           If you still end up late, don't blame me!
  1504. X                       
  1505. X  Permission to use, copy, modify, distribute, and sell this software and its
  1506. X       documentation for any purpose and without fee is hereby granted,
  1507. X    provided that the above copyright notice appear in all copies and that
  1508. X    both that copyright notice and this permission notice appear in
  1509. X               supporting documentation.
  1510. X                       
  1511. X  This software is provided AS IS with no warranties of any kind.  The author
  1512. X    shall have no liability with respect to the infringement of copyrights,
  1513. X     trade secrets or any patents by this file or any part thereof.  In no
  1514. X      event will the author be liable for any lost revenue or profits or
  1515. X          other special, indirect and consequential damages.
  1516. */
  1517. X
  1518. /* 
  1519. X * Just a few bits and bobs.
  1520. X */
  1521. X
  1522. X
  1523. #include "xalarm.h"
  1524. #include "fns.h"
  1525. X
  1526. #if defined (USEGETPWUID)
  1527. #include <pwd.h>
  1528. #else
  1529. extern String    getenv();
  1530. #endif
  1531. X
  1532. #if defined (USEUNAME)
  1533. #include <sys/utsname.h>
  1534. #endif
  1535. X
  1536. X
  1537. #define        FILEOPTION1    "-file"
  1538. #define        FILEOPTION2    "-f"
  1539. #define        DAEMONOPTION1    "-daemon"
  1540. #define        DAEMONOPTION2    "-demon"
  1541. #define        RESTARTONLY1    "-restartonly"
  1542. #define        RESTARTONLY2    "-restart"
  1543. X
  1544. #define        COMMANDLIST    "echo xalarms: `%s`"
  1545. #define        COMMANDRESET    "%s -USR1 `%s`"
  1546. #define        COMMANDKILL    "%s -USR2 `%s`"
  1547. #define        DOWNCASE(ch)    (((ch) >= 'A') and ((ch) <= 'Z') ? \
  1548. X                 ((ch) - 'A' + 'a') : (ch))
  1549. X
  1550. X
  1551. X
  1552. String        Concat(), ReplaceNewlines(), NextWord(), DisplayName(),
  1553. X        UserName(), HomeDirectory(), MachineName();
  1554. Boolean        IsInteger();
  1555. Instance    PreParseArgList();
  1556. XXtIntervalId    ResetTracker();
  1557. SIGRET        KillAlarm();
  1558. void        Initialise(), AddTimeOuts(), SetWMName(), StartDaemon(),
  1559. X        SetGeometry(), EnsureNotGrownOffScreen(), Audio(), Quit();
  1560. static void    CentreWidgetUnderPointer(), ParseGeometry();
  1561. static SIGRET    KillDaemon();
  1562. extern void    DoAlarm(), Warning(), WakeUp(), PopupAndAsk();
  1563. extern FORKRET    fork();
  1564. extern int    ParseAlarmFile(), DaysTo();
  1565. extern long    TimeToMilliSeconds();
  1566. extern unsigned long DateToMilliSeconds();
  1567. extern time_t    time();
  1568. extern struct tm *localtime();
  1569. X
  1570. X
  1571. X
  1572. extern AlarmData   xalarm;
  1573. X
  1574. X
  1575. /* 
  1576. X * Just give a bit of help etc.
  1577. X * Fork off a child otherwise.
  1578. X */
  1579. X
  1580. void Initialise (proggie, data)
  1581. X  String     proggie;
  1582. X  ApplData  *data;
  1583. {
  1584. X    char   getpids[TEXT], command[TEXT];
  1585. X
  1586. X    if (NIL (String, data->proggie))
  1587. X    data->proggie = proggie;
  1588. X
  1589. X    if (data->version)
  1590. X    (void) printf ("%s: using xalarm version %s\n", data->proggie, XALARMVERSION);
  1591. X
  1592. X    if (data->help) {
  1593. X    (void) printf ("Usage: %s [options] [text]\n\n", data->proggie);
  1594. X    (void) printf ("Default values for these resources/options are used by %s,\n\t",
  1595. X               data->proggie);
  1596. X    (void) printf ("but may be over-ruled.\n");
  1597. X    (void) printf ("Usual X options, plus:\n\t");
  1598. X    (void) printf ("-file +days|date\tSet alarms up to date from alarm file(s).\n\t");
  1599. X    (void) printf ("-daemon +days|date\tStart a daemon to look at alarm file(s).\n\t");
  1600. X    (void) printf ("-date +days|date\tDate at which to trigger %s.\n\t",
  1601. X               data->proggie+1);
  1602. X    (void) printf ("-time +time|time\tTime at which to trigger %s.\n\t",
  1603. X               data->proggie+1);
  1604. X    (void) printf ("-[no]confirm\t\t[Don't] ask for confirmation.\n\t");
  1605. X    (void) printf ("-warn time[,time...]\tTimes before %s for warnings.\n\t",
  1606. X               data->proggie+1);
  1607. X    (void) printf ("-warnwords number\tWords from %s message in warning.\n\t",
  1608. X               data->proggie+1);
  1609. X    (void) printf ("-list\t\t\tList xalarm process numbers (pids).\n\t");
  1610. X    (void) printf ("-reset pid|all\t\tReset xalarm process number pid/all xalarms.\n\t");
  1611. X    (void) printf ("-kill pid|all\t\tKill xalarm process number pid/all xalarms.\n\t");
  1612. X    (void) printf ("-restart\t\tOnly try to restart previous alarms.\n\t");
  1613. X    (void) printf ("-alarmaudio method\tWhat noise to make on the alarm.\n\t");
  1614. X    (void) printf ("-warningaudio method\tWhat noise to make on warnings.\n\t");
  1615. X    (void) printf ("-volume percentage\tPercentage volume for the terminal bell.\n\t");
  1616. X    (void) printf ("-quiet\t\t\tDon't make a sound.\n\t");
  1617. X    (void) printf ("-pester time\t\tTime after which %s re-triggers.\n\t",
  1618. X               data->proggie+1);
  1619. X    (void) printf ("-snooze time\t\tSet initial alarm snooze time value.\n\t");
  1620. X    (void) printf ("-nowarn\t\t\tNo warnings.\n\t");
  1621. X    (void) printf ("-nowarnwords\t\tNo words from %s message in warning.\n\t",
  1622. X               data->proggie+1);
  1623. X    (void) printf ("-nopester\t\tDon't persecute after %s triggers.\n",
  1624. X               data->proggie+1);
  1625. X    }
  1626. X
  1627. X    if (data->list) {
  1628. X    (void) sprintf (getpids, GETXALARMPIDS, getpid ());
  1629. X    (void) sprintf (command, COMMANDLIST, getpids);
  1630. X    if (system (command) != 0)
  1631. X        perror (data->proggie);
  1632. X    }
  1633. X
  1634. X    if (NONNIL (String, data->reset))
  1635. X    if (not STREQUAL (data->reset, ALL)) {
  1636. X        if (kill (atoi (data->reset), SIGUSR1) == -1)
  1637. X        perror (data->proggie);
  1638. X    } else {
  1639. X        (void) sprintf (getpids, GETXALARMPIDS, getpid ());
  1640. X        (void) sprintf (command, COMMANDRESET, KILLPATH, getpids);
  1641. X        if (system (command) != 0)
  1642. X        perror (data->proggie);
  1643. X    }
  1644. X
  1645. X    if (NONNIL (String, data->kill))
  1646. X    if (not STREQUAL (data->kill, ALL)) {
  1647. X        if (kill (atoi (data->kill), SIGUSR2) == -1)
  1648. X        perror (data->proggie);
  1649. X    } else {
  1650. X        (void) sprintf (getpids, GETXALARMPIDS, getpid ());
  1651. X        (void) sprintf (command, COMMANDKILL, KILLPATH, getpids);
  1652. X        if (system (command) != 0)
  1653. X        perror (data->proggie);
  1654. X    }
  1655. X
  1656. X    if ((data->list) or (data->version) or (data->help) or
  1657. X    (NONNIL (String, data->kill)) or (NONNIL (String, data->reset)))
  1658. X    exit (0);
  1659. X
  1660. X    /* 
  1661. X     * Fork & exit the parent.  If the fork fails, carry on anyway.
  1662. X     * Is this OK?  Should we sleep a bit first?
  1663. X     */
  1664. X
  1665. X    switch ((int) fork ()) {
  1666. X     case -1:
  1667. X    perror (data->proggie);
  1668. X     case 0:
  1669. X    break;
  1670. X     default:
  1671. X    exit (0);
  1672. X    }
  1673. }
  1674. X
  1675. X
  1676. X
  1677. /* 
  1678. X * Check to see if we're to do the appointments thing, and copy out 
  1679. X * the arg list, then clear the original to prevent others snooping.
  1680. X */
  1681. X
  1682. Instance PreParseArgList (argv, argc, days, args)
  1683. X  String  *argv, **args;
  1684. X  int       *argc, *days;
  1685. {
  1686. X    String     ch;
  1687. X    Instance   instance = Alarm;
  1688. X    int        last = *argc, i;
  1689. X
  1690. X    *args = (String *) XtCalloc (*argc+4, sizeof (String *));
  1691. X    (*args)[0] = XtNewString (argv[0]);
  1692. X    *argc = 1;
  1693. X
  1694. X    for (i=1; i<last; i++)
  1695. X    if ((STREQUAL (argv[i], RESTARTONLY1)) or (STREQUAL (argv[i], RESTARTONLY2)))
  1696. X        instance = RestartOnly;
  1697. X    else if ((STREQUAL (argv[i], FILEOPTION1)) or
  1698. X         (STREQUAL (argv[i], FILEOPTION2))) {
  1699. X        if (++i == last) {
  1700. X        (void) fprintf (stderr, "No file date to parse alarm file with.\n");
  1701. X        exit (-1);
  1702. X        } else if (ISINVALID (*days = DaysTo (argv[i], instance = File))) {
  1703. X        (void) fprintf (stderr, "Can't use file date: %s", xalarm.errormessage);
  1704. SHAR_EOF
  1705. true || echo 'restore of fns.c failed'
  1706. fi
  1707. echo 'End of  part 3'
  1708. echo 'File fns.c is continued in part 4'
  1709. echo 4 > _shar_seq_.tmp
  1710. exit 0
  1711. -- 
  1712. --
  1713. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1714. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1715. Sunnyvale, California 94086            at&t: 408/522-9236
  1716.