home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / remind / src / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-31  |  16.5 KB  |  616 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  INIT.C                                                     */
  4. /*                                                             */
  5. /*  Initialize remind; perform certain tasks between           */
  6. /*  iterations in calendar mode; do certain checks after end   */
  7. /*  in normal mode.                                            */
  8. /*                                                             */
  9. /*  This file is part of REMIND.                               */
  10. /*  Copyright (C) 1992, 1993 by David F. Skoll.                */
  11. /*                                                             */
  12. /***************************************************************/
  13. #define L_IN_INIT 1
  14. #include "config.h"
  15. #include <stdio.h>
  16. #include <string.h>
  17. #ifdef HAVE_STDLIB_H
  18. #include <stdlib.h>
  19. #endif
  20. #ifdef HAVE_MALLOC_H
  21. #include <malloc.h>
  22. #endif
  23. #ifdef UNIX
  24. #include <sys/types.h>
  25. #include <pwd.h>
  26. #ifdef HAVE_UNISTD
  27. #include <unistd.h>
  28. #endif
  29. #endif
  30. #include <ctype.h>
  31. #include "types.h"
  32. #include "protos.h"
  33. #include "expr.h"
  34. #include "err.h"
  35. #include "version.h"
  36. #include "globals.h"
  37.  
  38. /***************************************************************
  39.  *
  40.  *  Command line options recognized:
  41.  *
  42.  *  -n       = Output next trigger date of each reminder in
  43.  *             simple calendar format.
  44.  *  -r       = Disallow RUN mode
  45.  *  -c[n]    = Produce a calendar for n months (default = 1)
  46.  *  -w[n,n,n] = Specify output device width, padding and spacing
  47.  *  -s[n]    = Produce calendar in "simple calendar" format
  48.  *  -p[n]    = Produce calendar in format compatible with rem2ps
  49.  *  -v       = Verbose mode
  50.  *  -o       = Ignore ONCE directives
  51.  *  -a       = Don't issue timed reminders which will be queued
  52.  *  -q       = Don't queue timed reminders
  53.  *  -t       = Trigger all reminders (infinite delta)
  54.  *  -h       = Hush mode
  55.  *  -f       = Do not fork
  56.  *  -dchars  = Debugging mode:  Chars are:
  57.  *             e = Echo input lines
  58.  *             x = Display expression evaluation
  59.  *             t = Display trigger dates
  60.  *             v = Dump variables at end
  61.  *             l = Display entire line in error messages
  62.  *  -e       = Send messages normally sent to stderr to stdout instead
  63.  *  -z[n]    = Daemon mode waking up every n (def 5) minutes.
  64.  *  -bn      = Time format for cal (0, 1, or 2)
  65.  *  -xn      = Max. number of iterations for SATISFY
  66.  *  -uname   = Run as user 'name' - only valid when run by root.  If run
  67.  *             by non-root, changes environment but not effective uid.
  68.  *  -kcmd    = Run 'cmd' for MSG-type reminders instead of printing to stdout
  69.  *  -iVAR=EXPR = Initialize and preserve VAR.
  70.  *  -m       = Start calendar with Monday instead of Sunday.
  71.  *  A minus sign alone indicates to take input from stdin
  72.  *
  73.  **************************************************************/
  74.  
  75. /* For parsing an integer */
  76. #define PARSENUM(var, s)   \
  77.    var = 0;                \
  78.    while (isdigit(*(s))) { \
  79.       var *= 10;           \
  80.       var += *(s) - '0';   \
  81.       s++;                 \
  82.    }
  83.  
  84. #ifdef UNIX
  85. PRIVATE void ChgUser ARGS((char *uname));
  86. #endif
  87.  
  88. PRIVATE void InitializeVar ARGS ((char *str));
  89.  
  90. static char *BadDate = "Illegal date on command line\n";
  91.  
  92. /***************************************************************/
  93. /*                                                             */
  94. /*  InitRemind                                                 */
  95. /*                                                             */
  96. /*  Initialize the system - called only once at beginning!     */
  97. /*                                                             */
  98. /***************************************************************/
  99. #ifdef HAVE_PROTOS
  100. PUBLIC void InitRemind(int argc, char *argv[])
  101. #else
  102. void InitRemind(argc, argv)
  103. int argc;
  104. char *argv[];
  105. #endif
  106. {
  107.    char *arg;
  108.    int i;
  109.    int y, m, d, rep;
  110.    Token tok;
  111.  
  112.    y = NO_YR;
  113.    m = NO_MON;
  114.    d = NO_DAY;
  115.    rep = NO_REP;
  116.  
  117.    RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
  118.    if (RealToday < 0) {
  119.       fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
  120.       exit(1);
  121.    }
  122.    JulianToday = RealToday;
  123.    FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
  124.  
  125. #if !defined(HAVE_QUEUED)
  126.    DontFork = 1;
  127.    DontQueue = 1;
  128.    NumQueued = 0;
  129.    DontIssueAts = 0;
  130.    Daemon = 0;
  131. #elif defined(_MSC_VER) || defined(__BORLANDC__)
  132.    DontFork = 1;
  133. #elif defined(__OS2__) && defined (__MSDOS__)
  134.    if (DOSMODE)
  135.      DontFork = 1;
  136. #endif
  137.  
  138.    /* Parse the command-line options */
  139.    i = 1;
  140.    while (i < argc) {
  141.       arg = argv[i];
  142.       if (*arg != '-') break; /* Exit the loop if it's not an option */
  143.       i++;
  144.       arg++;
  145.       if (!*arg) {
  146.          UseStdin = 1;
  147.      IgnoreOnce = 1;
  148.      i--;
  149.      break;
  150.       }
  151.       while (*arg) {
  152.          switch(*arg++) {
  153.  
  154.             case 'i':
  155.         case 'I':
  156.            InitializeVar(arg);
  157.            while(*arg) arg++;
  158.            break;
  159.        
  160.         case 'n':
  161.         case 'N':
  162.            NextMode = 1;
  163. #ifdef HAVE_QUEUED
  164.            DontQueue = 1;
  165. #endif
  166.            break;
  167.  
  168.         case 'r':
  169.         case 'R':
  170.            RunDisabled = 1;
  171.            break;
  172.  
  173.         case 'm':
  174.         case 'M':
  175.            MondayFirst = 1;
  176.            break;
  177.  
  178.         case 'o':
  179.         case 'O':
  180.            IgnoreOnce = 1;
  181.            break;
  182.  
  183.         case 't':
  184.         case 'T':
  185.            InfiniteDelta = 1;
  186.            break;
  187.  
  188.         case 'e':
  189.         case 'E':
  190.            ErrFp = stdout;
  191.            break;
  192.  
  193.         case 'h':
  194.         case 'H':
  195.            Hush = 1;
  196.            break;
  197.  
  198.         case 'g':
  199.         case 'G':
  200.            SortByDate = SORT_ASCEND;
  201.            SortByTime = SORT_ASCEND;
  202.            SortByPrio = SORT_ASCEND;
  203.            if (*arg) {
  204.               if (*arg == 'D' || *arg == 'd')
  205.              SortByDate = SORT_DESCEND;
  206.           arg++;
  207.                }
  208.            if (*arg) {
  209.               if (*arg == 'D' || *arg == 'd')
  210.              SortByTime = SORT_DESCEND;
  211.           arg++;
  212.                }
  213.            if (*arg) {
  214.               if (*arg == 'D' || *arg == 'd')
  215.              SortByPrio = SORT_DESCEND;
  216.           arg++;
  217.                }
  218.            break;
  219.  
  220. #if defined(UNIX) && defined(WANT_U_OPTION)
  221.         case 'u':
  222.         case 'U':
  223.            ChgUser(arg);
  224.            while (*arg) arg++;
  225.            break;
  226. #endif           
  227.  
  228. #ifdef HAVE_QUEUED
  229.         case 'z':
  230.         case 'Z':
  231.            DontFork = 1;
  232.            PARSENUM(Daemon, arg);
  233.            if (Daemon<5) Daemon=5;
  234.            else if (Daemon>60) Daemon=60;
  235.            break;
  236.  
  237.         case 'a':
  238.         case 'A':
  239.            DontIssueAts = 1;
  240.            break;
  241.  
  242.         case 'q':
  243.         case 'Q':
  244.            DontQueue = 1;
  245.            break;
  246.  
  247.         case 'f':
  248.         case 'F':
  249.            DontFork = 1;
  250.            break;
  251. #endif
  252.         case 'c':
  253.         case 'C':
  254.            DoCalendar = 1;
  255.            if (*arg == '+') {
  256.               arg++;
  257.               PARSENUM(CalWeeks, arg);
  258.           if (!CalWeeks) CalWeeks = 1;
  259.                } else {
  260.                  PARSENUM(CalMonths, arg);
  261.               if (!CalMonths) CalMonths = 1;
  262.                }
  263.            break;
  264.  
  265.         case 's':
  266.         case 'S':
  267.            DoSimpleCalendar = 1;
  268.            if (*arg == '+') {
  269.               arg++;
  270.               PARSENUM(CalWeeks, arg);
  271.           if (!CalWeeks) CalWeeks = 1;
  272.                } else {
  273.                  PARSENUM(CalMonths, arg);
  274.               if (!CalMonths) CalMonths = 1;
  275.                }
  276.            break;
  277.  
  278.         case 'p':
  279.         case 'P':
  280.            DoSimpleCalendar = 1;
  281.            PsCal = 1;
  282.            PARSENUM(CalMonths, arg);
  283.            if (!CalMonths) CalMonths = 1;
  284.            break;
  285.  
  286.         case 'w':
  287.         case 'W':
  288.            if (*arg != ',') {
  289.               PARSENUM(CalWidth, arg);
  290.               if (CalWidth < 80) CalWidth = 80;
  291.            }
  292.            if (*arg == ',') {
  293.               arg++;
  294.           if (*arg != ',') {
  295.                 PARSENUM(CalLines, arg);
  296.              if (CalLines > 20) CalLines = 20;
  297.           }
  298.           if (*arg == ',') {
  299.              arg++;
  300.              PARSENUM(CalPad, arg);
  301.              if (CalPad > 20) CalPad = 20;
  302.           }
  303.            }
  304.            break;
  305.  
  306.         case 'd':
  307.         case 'D':
  308.            while (*arg) {
  309.               switch(*arg++) {
  310.              case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
  311.              case 'x': case 'X': DebugFlag |= DB_PRTEXPR;   break;
  312.              case 't': case 'T': DebugFlag |= DB_PRTTRIG;   break;
  313.              case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
  314.              case 'l': case 'L': DebugFlag |= DB_PRTLINE;   break;
  315.              default:
  316.                 fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
  317.           }
  318.                }
  319.            break;
  320.  
  321.         case 'v':
  322.         case 'V':
  323.            DebugFlag |= DB_PRTLINE;
  324.            ShowAllErrors = 1;
  325.            break;
  326.  
  327.         case 'b':
  328.         case 'B':
  329.            PARSENUM(ScFormat, arg);
  330.            if (ScFormat<0 || ScFormat>2) ScFormat=SC_AMPM;
  331.            break;
  332.  
  333.         case 'x':
  334.         case 'X':
  335.            PARSENUM(MaxSatIter, arg);
  336.            if (MaxSatIter < 10) MaxSatIter=10;
  337.            break;
  338.  
  339.         case 'k':
  340.         case 'K':
  341.            MsgCommand = arg;
  342.            while (*arg) arg++;  /* Chew up remaining chars in this arg */
  343.            break;
  344.  
  345.         default:
  346.            fprintf(ErrFp, ErrMsg[M_BAD_OPTION], *(arg-1));
  347.      }
  348.  
  349.       }
  350.    }
  351.  
  352.    /* Get the filename. */
  353.    if (i >= argc) {
  354.       Usage();
  355.       exit(1);
  356.    }
  357.    InitialFile = argv[i++];
  358.  
  359.    /* Get the date, if any */
  360.    if (i < argc) {
  361.       while (i < argc) {
  362.          arg = argv[i++];
  363.          FindToken(arg, &tok);
  364.      switch (tok.type) {
  365.         case T_Month:
  366.            if (m != NO_MON) Usage();
  367.            else m = tok.val;
  368.            break;
  369.  
  370.         case T_Day:
  371.            if (d != NO_DAY) Usage();
  372.            else d = tok.val;
  373.            break;
  374.  
  375.         case T_Year:
  376.            if (y != NO_YR) Usage();
  377.            else y = tok.val;
  378.            break;
  379.  
  380.         case T_Rep:
  381.            rep = tok.val;
  382.            break;
  383.  
  384.         default: Usage();
  385.          }
  386.       }
  387.  
  388.       if (rep > 0) {
  389.          Iterations = rep;
  390.      DontQueue = 1;
  391.      Daemon = 0;
  392.       }
  393.  
  394. /* Must supply date in the form:  day, mon, yr OR mon, yr */
  395.       if (m == NO_MON || y == NO_YR) {
  396.          if (rep == NO_REP) Usage();
  397.      else if (m != NO_MON || y != NO_YR) Usage();
  398.      else {
  399.         m = CurMon;
  400.         y = CurYear;
  401.         if (d == NO_DAY) d = CurDay;
  402.          }
  403.       }
  404.       if (d == NO_DAY) d=1;
  405.       if (d > DaysInMonth(m, y)) {
  406.          fprintf(ErrFp, BadDate);
  407.      Usage();
  408.       }
  409.       JulianToday = Julian(y, m, d);
  410.       if (JulianToday == -1) {
  411.          fprintf(ErrFp, BadDate);
  412.      Usage();
  413.       }
  414.       CurYear = y;
  415.       CurMon = m;
  416.       CurDay = d;
  417.       if (JulianToday != RealToday) IgnoreOnce = 1;
  418.  
  419.    }
  420. /* Figure out the offset from UTC */
  421.    if (CalculateUTC)
  422.       (void) CalcMinsFromUTC(JulianToday, SystemTime()/60,
  423.                  &MinsFromUTC, NULL);
  424. }
  425.  
  426. /***************************************************************/
  427. /*                                                             */
  428. /*  Usage                                                      */
  429. /*                                                             */
  430. /*  Print the usage info.                                      */
  431. /*                                                             */
  432. /***************************************************************/
  433. #ifndef L_USAGE_OVERRIDE
  434. #ifdef HAVE_PROTOS
  435. PUBLIC void Usage(void)
  436. #else
  437. void Usage()
  438. #endif /* HAVE_PROTOS */
  439. {
  440.    fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992, 1993 by David F. Skoll\n", VERSION, L_LANGNAME);
  441. #ifdef BETA
  442.    fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
  443. #endif
  444.    fprintf(ErrFp, "Usage: remind [options] filename [date] [*rep]\n");
  445.    fprintf(ErrFp, "Options:\n");
  446.    fprintf(ErrFp, " -n     Output next occurrence of reminders in simple format\n");
  447.    fprintf(ErrFp, " -r     Disable RUN directives\n");
  448.    fprintf(ErrFp, " -c[n]  Produce a calendar for n (default 1) months\n");
  449.    fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
  450.    fprintf(ErrFp, " -w[n[,p[,s]]]  Specify width, padding and spacing of calendar\n");
  451.    fprintf(ErrFp, " -s[+][n] Produce 'simple calendar' for n (1) months (weeks)\n");
  452.    fprintf(ErrFp, " -p[n]  Same as -s, but input compatible with rem2ps\n");
  453.    fprintf(ErrFp, " -v     Verbose mode\n");
  454.    fprintf(ErrFp, " -o     Ignore ONCE directives\n");
  455.    fprintf(ErrFp, " -t     Trigger all future reminders regardless of delta\n");
  456.    fprintf(ErrFp, " -h     'Hush' mode - be very quiet\n");
  457. #ifdef HAVE_QUEUED
  458.    fprintf(ErrFp, " -a     Don't trigger timed reminders immediately - just queue them\n");
  459.    fprintf(ErrFp, " -q     Don't queue timed reminders\n");
  460.    fprintf(ErrFp, " -f     Trigger timed reminders by staying in foreground\n");
  461.    fprintf(ErrFp, " -z[n]  Enter daemon mode, waking every n (5) minutes.\n");
  462. #endif
  463.    fprintf(ErrFp, " -d...  Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
  464.    fprintf(ErrFp, " -e     Divert messages normally sent to stderr to stdout\n");
  465.    fprintf(ErrFp, " -b[n]  Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
  466.    fprintf(ErrFp, " -x[n]  Iteration limit for SATISFY clause (def=150)\n");
  467.    fprintf(ErrFp, " -kcmd  Run 'cmd' for MSG-type reminders\n");
  468.    fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
  469.    fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
  470.    fprintf(ErrFp, " -m     Start calendar with Monday rather than Sunday\n");
  471.    exit(1);
  472. }
  473. #endif /* L_USAGE_OVERRIDE */
  474. /***************************************************************/
  475. /*                                                             */
  476. /*  ChgUser                                                    */
  477. /*                                                             */
  478. /*  Run as a specified user.  Can only be used if Remind is    */
  479. /*  started by root.  This changes the real and effective uid, */
  480. /*  the real and effective gid, and sets the HOME, SHELL and   */
  481. /*  USER environment variables.                                */
  482. /*                                                             */
  483. /***************************************************************/
  484. #if defined(UNIX) && defined(WANT_U_OPTION)
  485. #ifdef HAVE_PROTOS
  486. PRIVATE void ChgUser(char *user)
  487. #else
  488. static void ChgUser(user)
  489. char *user;
  490. #endif /* HAVE_PROTOS */
  491. {
  492. #ifdef SYSV
  493.    /* uid_t myuid; This seems to mess up on XENIX, so forget it... */ 
  494.   int myuid;
  495. #else
  496.    int myuid;
  497. #endif
  498.  
  499.    struct passwd *pwent;
  500.    static char *home, *shell, *username, *logname;
  501.  
  502.    myuid = getuid();
  503.  
  504.    pwent = getpwnam(user);
  505.  
  506.    if (!pwent) {
  507.       fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
  508.       exit(1);
  509.    }
  510.  
  511.    if (!myuid && setgid(pwent->pw_gid)) {
  512.       fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
  513.       exit(1);
  514.    }
  515.  
  516.    if (!myuid && setuid(pwent->pw_uid)) {
  517.       fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
  518.       exit(1);
  519.    }
  520.  
  521.    home = malloc(strlen(pwent->pw_dir) + 6);
  522.    if (!home) {
  523.       fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
  524.       exit(1);
  525.    }
  526.    sprintf(home, "HOME=%s", pwent->pw_dir);
  527.    putenv(home);
  528.  
  529.    shell = malloc(strlen(pwent->pw_shell) + 7);
  530.    if (!shell) {
  531.       fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
  532.       exit(1);
  533.    }
  534.    sprintf(shell, "SHELL=%s", pwent->pw_shell);
  535.    putenv(shell);
  536.  
  537.    if (pwent->pw_uid) {
  538.       username = malloc(strlen(pwent->pw_name) + 6);
  539.       if (!username) {
  540.          fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
  541.          exit(1);
  542.       }
  543.       sprintf(username, "USER=%s", pwent->pw_name);
  544.       putenv(username);
  545.       logname= malloc(strlen(pwent->pw_name) + 9);
  546.       if (!logname) {
  547.          fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
  548.          exit(1);
  549.       }
  550.       sprintf(logname, "LOGNAME=%s", pwent->pw_name);
  551.       putenv(logname);
  552.    }
  553. }
  554. #endif /* UNIX && WANT_U_OPTION */
  555.    
  556. /***************************************************************/
  557. /*                                                             */
  558. /*  InitializeVar                                              */
  559. /*                                                             */
  560. /*  Initialize and preserve a variable                         */
  561. /*                                                             */
  562. /***************************************************************/
  563. #ifdef HAVE_PROTOS
  564. PRIVATE void InitializeVar(char *str)
  565. #else
  566. static void InitializeVar(str)
  567. char *str;
  568. #endif
  569. {
  570.    char *varname, *expr;
  571.  
  572.    Value val;
  573.  
  574.    int r;
  575.  
  576.    /* Scan for an '=' sign */
  577.    varname = str;
  578.    while (*str && *str != '=') str++;
  579.    if (!*str) {
  580.       fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
  581.       return;
  582.    }
  583.    *str = 0;
  584.    if (!*varname) {
  585.       fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
  586.       return;
  587.    }
  588.    expr = str+1;
  589.    if (!*expr) {
  590.       fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EXPR]);
  591.       return;
  592.    }
  593.  
  594.    r=EvalExpr(&expr, &val);
  595.    if (r) {
  596.       fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
  597.       return;
  598.    }
  599.  
  600.    if (*varname == '$') {
  601.       r=SetSysVar(varname+1, &val);
  602.       if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
  603.       return;
  604.    }
  605.  
  606.    r=SetVar(varname, &val);
  607.    if (r) {
  608.       fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
  609.       return;
  610.    }
  611.    r=PreserveVar(varname);
  612.    if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
  613.    return;
  614. }
  615.  
  616.