Logo Search packages:      
Sourcecode: zephyr version File versions  Download package

zleave.c

/* This file is part of the Project Athena Zephyr Notification System.
 * It contains code for the "zleave" command.
 *
 *      Created by:     David Jedlinsky
 *
 *      $Id: zleave.c,v 1.25 1999/08/13 00:19:39 danw Exp $
 *
 *      Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
 *      For copying and distribution information, see the file
 *      "mit-copyright.h". 
 */

#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>

#include <com_err.h>

#ifndef lint
static char rcsid_zlocate_c[] = "$Id: zleave.c,v 1.25 1999/08/13 00:19:39 danw Exp $";
#endif /* lint */

/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of California at Berkeley. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific written prior permission. This software
 * is provided ``as is'' without express or implied warranty.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#define MESSAGE_CLASS "MESSAGE"
#define INSTANCE "LEAVE"
/*
 * zleave [[+]hhmm [ -m "Reminder Message" ]]
 *  or
 * zleave can[cel]
 *
 * Reminds you when you have to leave.
 * Leave prompts for input and goes away if you hit return.
 * Messages are sent through Zephyr.  Subscriptions are handled automagically.
 * It nags you like a mother hen.
 */
char origlogin[20];
char tempfile[40];
char *getlogin();
char *whenleave;
char *reminder_message = NULL;
char buff[100];
int use_zephyr=1, oldpid;

void usage(), doalarm(), bother(), delay();

main(argc, argv)
char **argv;
{
      time_t now;
      long when, diff, hours, minutes;
      char *cp;
      FILE *fp;
      struct tm *nv;
      int gethm();
      int port, c;
      ZSubscription_t sub;
      
      if (ZInitialize() != ZERR_NONE) {
            fprintf(stderr,"No Zephyr! Will write directly to terminal.\n");
            use_zephyr = 0;
      }
      (void) sprintf(tempfile, "/tmp/zleave.%d", (int) getuid());

      if (use_zephyr) {
            if ((port = ZGetWGPort()) == -1) {
                  fprintf(stderr,
                        "Can't find WindowGram subscription port.\n");
                  fprintf(stderr,"Will write directly to terminal.\n");
                  use_zephyr = 0;
            } else {
                  sub.zsub_class = MESSAGE_CLASS;
                  sub.zsub_classinst = INSTANCE;
                  sub.zsub_recipient = ZGetSender();
                  if (ZSubscribeToSansDefaults(&sub,1,(u_short)port)
                      != ZERR_NONE) {
                        fprintf(stderr,
                              "Subscription error!  Writing to your terminal...\n");
                        use_zephyr = 0;
                  } 
            }
      }     
      if (!use_zephyr) {
          if ((cp = getlogin()) == NULL) {
            fputs("leave: You are not logged in.\n", stderr);
            exit(1);
          }
          (void) strcpy(origlogin, cp);
      }

      c = 1;
      while ((c<argc) && (! reminder_message))
          if (!strcmp(argv[c++],"-m")) {
            if (argv[c])
                reminder_message = argv[c];
            else
                usage();
          }

      if (!reminder_message)
          reminder_message = "";

      if (argc < 2) {
            printf("When do you have to leave? ");
            (void) fflush(stdout);
            buff[read(0, buff, sizeof buff)] = 0;
            cp = buff;
      } else
            cp = argv[1];
      if (*cp == '\n')
            exit(0);
      if (*cp == '+') {
            cp++;
            if (!gethm(cp, &hours, &minutes))
                  usage();
            if (minutes < 0 || minutes > 59)
                  usage();
            diff = 60*hours+minutes;
            doalarm(diff);
            exit(0);
      }
      if (!strcmp(cp, "cancel") || !strcmp(cp, "can")) {
            if (!(fp = fopen(tempfile,"r"))) {
                printf("No zleave is currently running.\n");
                exit(0);
            }
            if (fscanf(fp, "%d", &oldpid) != 1) {
                  printf("The zleave pid file is corrupted.\n");
                  (void) fclose(fp);
                  exit(0);
            }
            (void) fclose(fp);
            if (kill(oldpid,9))
                printf("No zleave is currently running.\n");
            (void) unlink(tempfile);
            exit(0);
      }
      if (!gethm(cp, &hours, &minutes))
            usage();
      if (hours > 12)
            hours -= 12;
      if (hours == 12)
            hours = 0;

      if (hours < 0 || hours > 12 || minutes < 0 || minutes > 59)
            usage();

      (void) time(&now);
      nv = localtime(&now);
      when = 60*hours+minutes;
      if (nv->tm_hour > 12)
            nv->tm_hour -= 12;      /* do am/pm bit */
      now = 60 * nv->tm_hour + nv->tm_min;
      diff = when - now;
      while (diff < 0)
            diff += 12*60;
      if (diff > 11*60) {
            fprintf(stderr, "That time has already passed!\n");
            exit(1);
      }

      doalarm(diff);
      exit(0);
}

void
usage()
{
      fprintf(stderr, "usage: zleave [[+]hhmm [-m \"Reminder Message\"]]\n\
\tor: zleave can[cel]\n");
      exit(1);
}

int
gethm(cp, hp, mp)
register char *cp;
int *hp, *mp;
{
      register char c;
      register int tod;

      tod = 0;
      while ((c = *cp++) != '\0') {
            if (!isdigit(c))
                  return(0);
            tod = tod * 10 + (c - '0');
      }
      *hp = tod / 100;
      *mp = tod % 100;
      return(1);
}

void
doalarm(nmins)
long nmins;
{
      time_t daytime;
      char *msg1, *msg2, *msg3, *msg4;
      register int i;
      long slp1, slp2, slp3, slp4;
      long seconds, gseconds;
      FILE *fp;
#ifdef _POSIX_VERSION
      struct sigaction sa;
#endif

      seconds = 60 * nmins;
      if (seconds <= 0)
            seconds = 1;
      gseconds = seconds;

      msg1 = "You have to leave in 5 minutes";
      if (seconds <= 60*5) {
            slp1 = 0;
      } else {
            slp1 = seconds - 60*5;
            seconds = 60*5;
      }

      msg2 = "Just one more minute!";
      if (seconds <= 60) {
            slp2 = 0;
      } else {
            slp2 = seconds - 60;
            seconds = 60;
      }

      msg3 = "Time to leave!";
      slp3 = seconds;

      msg4 = "You're going to be late!";
      slp4 = 60L;

      (void) time(&daytime);
      daytime += gseconds;
      whenleave = ctime(&daytime);

      if (fp = fopen(tempfile,"r")) {
            if (fscanf(fp, "%d", &oldpid) == 1)
                  if (!kill(oldpid,9))
                        printf("Old zleave process killed.\n");
            (void) fclose(fp);
      }
      printf("Alarm set for %s", whenleave);

/* Subscribe to MESSAGE.LEAVE here */

      switch(fork()) {
          case -1:
            perror("fork");
            exit(-1);
            break;
          case 0:
            break;
          default:
            exit(0);
            break;
      }
      if (!(fp = fopen(tempfile, "w")))
        fprintf(stderr, "Cannot open pid file.\n");
      else {
            fprintf(fp, "%d\n", getpid());
            if (fclose(fp) == EOF)
                  (void) perror("fclose on pid file");
      }

#ifdef _POSIX_VERSION
      sigemptyset(&sa.sa_mask);
      sa.sa_flags = 0;
      sa.sa_handler = SIG_IGN;
      sigaction(SIGINT, &sa, (struct sigaction *)0);
      sigaction(SIGQUIT, &sa, (struct sigaction *)0);
      sigaction(SIGTERM, &sa, (struct sigaction *)0);
      sigaction(SIGTTOU, &sa, (struct sigaction *)0);
#else
      (void) signal(SIGINT, SIG_IGN);
      (void) signal(SIGQUIT, SIG_IGN);
      (void) signal(SIGTERM, SIG_IGN);
      (void) signal(SIGTTOU, SIG_IGN);
#endif

      if (slp1)
            bother(slp1, msg1);
      if (slp2)
            bother(slp2, msg2);
      bother(slp3, msg3);
      for (i = 0; i < 10; i++)
            bother(slp4, msg4);

      bother(0L, "That was the last time I'll tell you. Bye.");
      (void) unlink(tempfile);
      exit(0);
}

void
bother(slp, msg)
long slp;
char *msg;
{
      ZNotice_t notice;
      ZNotice_t retnotice;
      int retval;
      char *real_message;

      delay(slp);

      if (use_zephyr) {
          real_message = (char *) malloc(strlen(msg) +
                                 strlen(reminder_message) + 3);
          if (real_message == NULL) {
            fprintf (stderr, "zleave: out of memory\n");
            exit (1);
          }
          sprintf(real_message,"%c%s\n%s",'\0',msg,reminder_message);

          (void) memset((char *)&notice, 0, sizeof(notice));
          notice.z_kind = ACKED;
          notice.z_port = 0;
          notice.z_class = MESSAGE_CLASS;
          notice.z_class_inst = INSTANCE;
          notice.z_recipient = ZGetSender();
          notice.z_opcode = "";
          notice.z_sender = (char *) 0;
          notice.z_default_format = "\n$2";
          notice.z_message = real_message;
          /* +3: initial null, newline, final null */
          notice.z_message_len = strlen(msg)+strlen(reminder_message)+3;
          
          if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
              printf("\7\7\7%s\n%s", msg, reminder_message);
              use_zephyr = 0;
          } else
          if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
                            ZCompareUIDPred, 
                            (char *)&notice.z_uid)) != ZERR_NONE) {
            fprintf(stderr,
                  "zleave: %s while waiting for acknowledgement\n", 
                  error_message(retval));
            use_zephyr = 0;
          } else
          if (retnotice.z_kind == SERVNAK) {
            fprintf(stderr,
                  "zleave: authorization failure while sending\n");
            use_zephyr = 0;
          } else
          if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
            fprintf(stderr, "zleave: Detected server failure while receiving acknowledgement\n");
            use_zephyr = 0;
          } else
          if (strcmp(retnotice.z_message, ZSRVACK_SENT)) {
            /* it wasn't sent */
            exit(0);
          }
          if (!use_zephyr)
            exit(1);
          ZFreeNotice(&retnotice);
          free(real_message);
      } else
#ifdef __STDC__
      printf("\a\a\a%s\n%s", msg, reminder_message);
#else
      printf("\7\7\7%s\n%s", msg, reminder_message);
#endif
}

/*
 * delay is like sleep but does it in 100 sec pieces and
 * knows what zero means.
 */
void
delay(secs)
long secs;
{
      long n;
      register char *l;

      while (secs > 0) {
            n = 100;
            if (secs < n)
                  n = secs;
            secs -= n;
            if (n > 0)
                  sleep((unsigned) n);
            if (!use_zephyr) {
                l = getlogin();
                if (l == NULL)
                  exit(0);
                if (strcmp(origlogin, l) != 0)
                  exit(0);
            }
      }
}

#ifndef HAVE_GETLOGIN
char *getlogin() {
#include <utmp.h>

      static struct utmp ubuf;
      int ufd;

      ufd = open("/etc/utmp",0);
      seek(ufd, ttyn(0)*sizeof(ubuf), 0);
      read(ufd, &ubuf, sizeof(ubuf));
      ubuf.ut_name[sizeof(ubuf.ut_name)] = 0;
      return(&ubuf.ut_name);
}
#endif

Generated by  Doxygen 1.6.0   Back to index