/*
 *  FILE: wristsavr.c
 *  AUTH: Michael John Radwin <mjr>
 *
 *  DESC: saves your wrists: periodically zwrites & xlocks screen to
 *        remind you to take a 2 minute break.
 *
 *  DATE: Wed Dec  4 21:45:14 EST 1996
 *   $Id: wristsavr.c,v 1.3 1996/12/05 17:03:32 mjr Exp mjr $ 
 *
 * signal handling, daemonizing, and cmdline options code ripped off
 * from mws's stb project 
 */

#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static const char *USAGE = "usage: wristsavr [-hb] [-m mins]\n\
    -h        Display usage information.\n\
    -b        Bully mode.  If xlock terminates before two minutes,\n\
              xlock the screen again.\n\
    -m mins   wait mins minutes between wristsavr notices (defualt 45)\n\
\n";

static const char *OPTS = "hbm:";
static const char *rcsid = "$Id: wristsavr.c,v 1.3 1996/12/05 17:03:32 mjr Exp mjr $";

static unsigned g_seconds = 0;
static int g_bully = 0;

static void daemonize()
{
  pid_t ppgid = getpgid(getppid());

  if(fork() != (pid_t) 0)
    _exit(0);

  (void) setpgid(0, ppgid);

  (void) close(STDIN_FILENO);
  (void) close(STDOUT_FILENO);
  (void) close(STDERR_FILENO);
}

static void interrupt(int sig)
{
    printf("exiting...\n");
    _exit(sig);
}

static void parse(int argc, char *argv[])
{
    extern char *optarg;
    extern int optind;

    register int c;

    while (optind < argc) {
	while ((c = getopt(argc, argv, OPTS)) != (int) EOF) {
	    switch(c) {
	    case 'b': 
		g_bully = 1; 
		break;

	    case 'h': 
		fprintf(stdout, USAGE);
		exit(0);
		/*NOTREACHED*/
       
	    case 'm': 
		if ((g_seconds = atoi(optarg) * 60) <= 0) {
		    fprintf(stderr, "wristsavr: option -m takes a positive integer\n");
		    exit(2);
		}
		break;          

	    default:
		fprintf(stderr, USAGE);
		exit(2);
	    }
	}

	if (optind < argc) {
	    fprintf(stderr, USAGE);
	    exit(2);
	}
    }
}

int main(int argc, char *argv[])
{
    struct sigaction act;
    char *login;
    char zwbuf[255];
    time_t t;

    parse(argc, argv);

    if ((login = getlogin()) == NULL) {
	perror("getlogin");
	return 1;
    }

    if (g_seconds == 0) g_seconds = 2700;    /* 45 mins */

    daemonize();

    (void) sigemptyset(&act.sa_mask);
    act.sa_handler = interrupt;
    act.sa_flags = 0;

    (void) sigaction(SIGINT, &act, (struct sigaction *) NULL);
    (void) sigaction(SIGHUP, &act, (struct sigaction *) NULL);
    (void) sigaction(SIGTERM, &act, (struct sigaction *) NULL);
    (void) sigaction(SIGQUIT, &act, (struct sigaction *) NULL);

    sprintf(zwbuf, "zwrite %s -m 'wrist savr daemon started: delay %d, bully %s.'",
	    login, (g_seconds / 60), (g_bully) ? "on" : "off");
    (void) system(zwbuf);

    sprintf(zwbuf, "zwrite %s -m 'wrist savr...'", login);
    for(;;) {
	(void) sleep(g_seconds);
	(void) system(zwbuf);
	(void) sleep(15);               /* time to react before xlock */

	do {
	    t = time(NULL);
	    (void) system("xlock");
	} while (g_bully && (time(NULL) - t) < 120);
    }

    /*NOTREACHED*/
}

