home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************/
- /* */
- /* INIT.C */
- /* */
- /* Initialize remind; perform certain tasks between */
- /* iterations in calendar mode; do certain checks after end */
- /* in normal mode. */
- /* */
- /* This file is part of REMIND. */
- /* Copyright (C) 1992, 1993 by David F. Skoll. */
- /* */
- /***************************************************************/
- #define L_IN_INIT 1
- #include "config.h"
- #include <stdio.h>
- #include <string.h>
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #ifdef HAVE_MALLOC_H
- #include <malloc.h>
- #endif
- #ifdef UNIX
- #include <sys/types.h>
- #include <pwd.h>
- #ifdef HAVE_UNISTD
- #include <unistd.h>
- #endif
- #endif
- #include <ctype.h>
- #include "types.h"
- #include "protos.h"
- #include "expr.h"
- #include "err.h"
- #include "version.h"
- #include "globals.h"
-
- /***************************************************************
- *
- * Command line options recognized:
- *
- * -n = Output next trigger date of each reminder in
- * simple calendar format.
- * -r = Disallow RUN mode
- * -c[n] = Produce a calendar for n months (default = 1)
- * -w[n,n,n] = Specify output device width, padding and spacing
- * -s[n] = Produce calendar in "simple calendar" format
- * -p[n] = Produce calendar in format compatible with rem2ps
- * -v = Verbose mode
- * -o = Ignore ONCE directives
- * -a = Don't issue timed reminders which will be queued
- * -q = Don't queue timed reminders
- * -t = Trigger all reminders (infinite delta)
- * -h = Hush mode
- * -f = Do not fork
- * -dchars = Debugging mode: Chars are:
- * e = Echo input lines
- * x = Display expression evaluation
- * t = Display trigger dates
- * v = Dump variables at end
- * l = Display entire line in error messages
- * -e = Send messages normally sent to stderr to stdout instead
- * -z[n] = Daemon mode waking up every n (def 5) minutes.
- * -bn = Time format for cal (0, 1, or 2)
- * -xn = Max. number of iterations for SATISFY
- * -uname = Run as user 'name' - only valid when run by root. If run
- * by non-root, changes environment but not effective uid.
- * -kcmd = Run 'cmd' for MSG-type reminders instead of printing to stdout
- * -iVAR=EXPR = Initialize and preserve VAR.
- * -m = Start calendar with Monday instead of Sunday.
- * A minus sign alone indicates to take input from stdin
- *
- **************************************************************/
-
- /* For parsing an integer */
- #define PARSENUM(var, s) \
- var = 0; \
- while (isdigit(*(s))) { \
- var *= 10; \
- var += *(s) - '0'; \
- s++; \
- }
-
- #ifdef UNIX
- PRIVATE void ChgUser ARGS((char *uname));
- #endif
-
- PRIVATE void InitializeVar ARGS ((char *str));
-
- static char *BadDate = "Illegal date on command line\n";
-
- /***************************************************************/
- /* */
- /* InitRemind */
- /* */
- /* Initialize the system - called only once at beginning! */
- /* */
- /***************************************************************/
- #ifdef HAVE_PROTOS
- PUBLIC void InitRemind(int argc, char *argv[])
- #else
- void InitRemind(argc, argv)
- int argc;
- char *argv[];
- #endif
- {
- char *arg;
- int i;
- int y, m, d, rep;
- Token tok;
-
- y = NO_YR;
- m = NO_MON;
- d = NO_DAY;
- rep = NO_REP;
-
- RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
- if (RealToday < 0) {
- fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
- exit(1);
- }
- JulianToday = RealToday;
- FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
-
- #if !defined(HAVE_QUEUED)
- DontFork = 1;
- DontQueue = 1;
- NumQueued = 0;
- DontIssueAts = 0;
- Daemon = 0;
- #elif defined(_MSC_VER) || defined(__BORLANDC__)
- DontFork = 1;
- #elif defined(__OS2__) && defined (__MSDOS__)
- if (DOSMODE)
- DontFork = 1;
- #endif
-
- /* Parse the command-line options */
- i = 1;
- while (i < argc) {
- arg = argv[i];
- if (*arg != '-') break; /* Exit the loop if it's not an option */
- i++;
- arg++;
- if (!*arg) {
- UseStdin = 1;
- IgnoreOnce = 1;
- i--;
- break;
- }
- while (*arg) {
- switch(*arg++) {
-
- case 'i':
- case 'I':
- InitializeVar(arg);
- while(*arg) arg++;
- break;
-
- case 'n':
- case 'N':
- NextMode = 1;
- #ifdef HAVE_QUEUED
- DontQueue = 1;
- #endif
- break;
-
- case 'r':
- case 'R':
- RunDisabled = 1;
- break;
-
- case 'm':
- case 'M':
- MondayFirst = 1;
- break;
-
- case 'o':
- case 'O':
- IgnoreOnce = 1;
- break;
-
- case 't':
- case 'T':
- InfiniteDelta = 1;
- break;
-
- case 'e':
- case 'E':
- ErrFp = stdout;
- break;
-
- case 'h':
- case 'H':
- Hush = 1;
- break;
-
- case 'g':
- case 'G':
- SortByDate = SORT_ASCEND;
- SortByTime = SORT_ASCEND;
- SortByPrio = SORT_ASCEND;
- if (*arg) {
- if (*arg == 'D' || *arg == 'd')
- SortByDate = SORT_DESCEND;
- arg++;
- }
- if (*arg) {
- if (*arg == 'D' || *arg == 'd')
- SortByTime = SORT_DESCEND;
- arg++;
- }
- if (*arg) {
- if (*arg == 'D' || *arg == 'd')
- SortByPrio = SORT_DESCEND;
- arg++;
- }
- break;
-
- #if defined(UNIX) && defined(WANT_U_OPTION)
- case 'u':
- case 'U':
- ChgUser(arg);
- while (*arg) arg++;
- break;
- #endif
-
- #ifdef HAVE_QUEUED
- case 'z':
- case 'Z':
- DontFork = 1;
- PARSENUM(Daemon, arg);
- if (Daemon<5) Daemon=5;
- else if (Daemon>60) Daemon=60;
- break;
-
- case 'a':
- case 'A':
- DontIssueAts = 1;
- break;
-
- case 'q':
- case 'Q':
- DontQueue = 1;
- break;
-
- case 'f':
- case 'F':
- DontFork = 1;
- break;
- #endif
- case 'c':
- case 'C':
- DoCalendar = 1;
- if (*arg == '+') {
- arg++;
- PARSENUM(CalWeeks, arg);
- if (!CalWeeks) CalWeeks = 1;
- } else {
- PARSENUM(CalMonths, arg);
- if (!CalMonths) CalMonths = 1;
- }
- break;
-
- case 's':
- case 'S':
- DoSimpleCalendar = 1;
- if (*arg == '+') {
- arg++;
- PARSENUM(CalWeeks, arg);
- if (!CalWeeks) CalWeeks = 1;
- } else {
- PARSENUM(CalMonths, arg);
- if (!CalMonths) CalMonths = 1;
- }
- break;
-
- case 'p':
- case 'P':
- DoSimpleCalendar = 1;
- PsCal = 1;
- PARSENUM(CalMonths, arg);
- if (!CalMonths) CalMonths = 1;
- break;
-
- case 'w':
- case 'W':
- if (*arg != ',') {
- PARSENUM(CalWidth, arg);
- if (CalWidth < 80) CalWidth = 80;
- }
- if (*arg == ',') {
- arg++;
- if (*arg != ',') {
- PARSENUM(CalLines, arg);
- if (CalLines > 20) CalLines = 20;
- }
- if (*arg == ',') {
- arg++;
- PARSENUM(CalPad, arg);
- if (CalPad > 20) CalPad = 20;
- }
- }
- break;
-
- case 'd':
- case 'D':
- while (*arg) {
- switch(*arg++) {
- case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
- case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
- case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
- case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
- case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
- default:
- fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
- }
- }
- break;
-
- case 'v':
- case 'V':
- DebugFlag |= DB_PRTLINE;
- ShowAllErrors = 1;
- break;
-
- case 'b':
- case 'B':
- PARSENUM(ScFormat, arg);
- if (ScFormat<0 || ScFormat>2) ScFormat=SC_AMPM;
- break;
-
- case 'x':
- case 'X':
- PARSENUM(MaxSatIter, arg);
- if (MaxSatIter < 10) MaxSatIter=10;
- break;
-
- case 'k':
- case 'K':
- MsgCommand = arg;
- while (*arg) arg++; /* Chew up remaining chars in this arg */
- break;
-
- default:
- fprintf(ErrFp, ErrMsg[M_BAD_OPTION], *(arg-1));
- }
-
- }
- }
-
- /* Get the filename. */
- if (i >= argc) {
- Usage();
- exit(1);
- }
- InitialFile = argv[i++];
-
- /* Get the date, if any */
- if (i < argc) {
- while (i < argc) {
- arg = argv[i++];
- FindToken(arg, &tok);
- switch (tok.type) {
- case T_Month:
- if (m != NO_MON) Usage();
- else m = tok.val;
- break;
-
- case T_Day:
- if (d != NO_DAY) Usage();
- else d = tok.val;
- break;
-
- case T_Year:
- if (y != NO_YR) Usage();
- else y = tok.val;
- break;
-
- case T_Rep:
- rep = tok.val;
- break;
-
- default: Usage();
- }
- }
-
- if (rep > 0) {
- Iterations = rep;
- DontQueue = 1;
- Daemon = 0;
- }
-
- /* Must supply date in the form: day, mon, yr OR mon, yr */
- if (m == NO_MON || y == NO_YR) {
- if (rep == NO_REP) Usage();
- else if (m != NO_MON || y != NO_YR) Usage();
- else {
- m = CurMon;
- y = CurYear;
- if (d == NO_DAY) d = CurDay;
- }
- }
- if (d == NO_DAY) d=1;
- if (d > DaysInMonth(m, y)) {
- fprintf(ErrFp, BadDate);
- Usage();
- }
- JulianToday = Julian(y, m, d);
- if (JulianToday == -1) {
- fprintf(ErrFp, BadDate);
- Usage();
- }
- CurYear = y;
- CurMon = m;
- CurDay = d;
- if (JulianToday != RealToday) IgnoreOnce = 1;
-
- }
- /* Figure out the offset from UTC */
- if (CalculateUTC)
- (void) CalcMinsFromUTC(JulianToday, SystemTime()/60,
- &MinsFromUTC, NULL);
- }
-
- /***************************************************************/
- /* */
- /* Usage */
- /* */
- /* Print the usage info. */
- /* */
- /***************************************************************/
- #ifndef L_USAGE_OVERRIDE
- #ifdef HAVE_PROTOS
- PUBLIC void Usage(void)
- #else
- void Usage()
- #endif /* HAVE_PROTOS */
- {
- fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992, 1993 by David F. Skoll\n", VERSION, L_LANGNAME);
- #ifdef BETA
- fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
- #endif
- fprintf(ErrFp, "Usage: remind [options] filename [date] [*rep]\n");
- fprintf(ErrFp, "Options:\n");
- fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
- fprintf(ErrFp, " -r Disable RUN directives\n");
- fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n");
- fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
- fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
- fprintf(ErrFp, " -s[+][n] Produce 'simple calendar' for n (1) months (weeks)\n");
- fprintf(ErrFp, " -p[n] Same as -s, but input compatible with rem2ps\n");
- fprintf(ErrFp, " -v Verbose mode\n");
- fprintf(ErrFp, " -o Ignore ONCE directives\n");
- fprintf(ErrFp, " -t Trigger all future reminders regardless of delta\n");
- fprintf(ErrFp, " -h 'Hush' mode - be very quiet\n");
- #ifdef HAVE_QUEUED
- fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\n");
- fprintf(ErrFp, " -q Don't queue timed reminders\n");
- fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
- fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (5) minutes.\n");
- #endif
- fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
- fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
- fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
- fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
- fprintf(ErrFp, " -kcmd Run 'cmd' for MSG-type reminders\n");
- fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
- fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
- fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
- exit(1);
- }
- #endif /* L_USAGE_OVERRIDE */
- /***************************************************************/
- /* */
- /* ChgUser */
- /* */
- /* Run as a specified user. Can only be used if Remind is */
- /* started by root. This changes the real and effective uid, */
- /* the real and effective gid, and sets the HOME, SHELL and */
- /* USER environment variables. */
- /* */
- /***************************************************************/
- #if defined(UNIX) && defined(WANT_U_OPTION)
- #ifdef HAVE_PROTOS
- PRIVATE void ChgUser(char *user)
- #else
- static void ChgUser(user)
- char *user;
- #endif /* HAVE_PROTOS */
- {
- #ifdef SYSV
- /* uid_t myuid; This seems to mess up on XENIX, so forget it... */
- int myuid;
- #else
- int myuid;
- #endif
-
- struct passwd *pwent;
- static char *home, *shell, *username, *logname;
-
- myuid = getuid();
-
- pwent = getpwnam(user);
-
- if (!pwent) {
- fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
- exit(1);
- }
-
- if (!myuid && setgid(pwent->pw_gid)) {
- fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
- exit(1);
- }
-
- if (!myuid && setuid(pwent->pw_uid)) {
- fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
- exit(1);
- }
-
- home = malloc(strlen(pwent->pw_dir) + 6);
- if (!home) {
- fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
- exit(1);
- }
- sprintf(home, "HOME=%s", pwent->pw_dir);
- putenv(home);
-
- shell = malloc(strlen(pwent->pw_shell) + 7);
- if (!shell) {
- fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
- exit(1);
- }
- sprintf(shell, "SHELL=%s", pwent->pw_shell);
- putenv(shell);
-
- if (pwent->pw_uid) {
- username = malloc(strlen(pwent->pw_name) + 6);
- if (!username) {
- fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
- exit(1);
- }
- sprintf(username, "USER=%s", pwent->pw_name);
- putenv(username);
- logname= malloc(strlen(pwent->pw_name) + 9);
- if (!logname) {
- fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
- exit(1);
- }
- sprintf(logname, "LOGNAME=%s", pwent->pw_name);
- putenv(logname);
- }
- }
- #endif /* UNIX && WANT_U_OPTION */
-
- /***************************************************************/
- /* */
- /* InitializeVar */
- /* */
- /* Initialize and preserve a variable */
- /* */
- /***************************************************************/
- #ifdef HAVE_PROTOS
- PRIVATE void InitializeVar(char *str)
- #else
- static void InitializeVar(str)
- char *str;
- #endif
- {
- char *varname, *expr;
-
- Value val;
-
- int r;
-
- /* Scan for an '=' sign */
- varname = str;
- while (*str && *str != '=') str++;
- if (!*str) {
- fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
- return;
- }
- *str = 0;
- if (!*varname) {
- fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
- return;
- }
- expr = str+1;
- if (!*expr) {
- fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EXPR]);
- return;
- }
-
- r=EvalExpr(&expr, &val);
- if (r) {
- fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
- return;
- }
-
- if (*varname == '$') {
- r=SetSysVar(varname+1, &val);
- if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
- return;
- }
-
- r=SetVar(varname, &val);
- if (r) {
- fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
- return;
- }
- r=PreserveVar(varname);
- if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
- return;
- }
-
-