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

mailleds.c



































/* 
 *  mailleds - Check for new mail, blinking keyboard leds when it arrives
 *  Copyright (C) 1996 Benjamin Osheroff 
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 *
 *  Author: Benjamin Osheroff (mtr@ratbert.bagel.org)
 *  106 Meernaa Ave.
 *  Fairfax, CA 94930
 *
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <time.h>
#include <paths.h>
#include <pwd.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/kd.h>
#include <utmp.h>

/*#ifdef X_SUPPORT
#include <X11/X.h>
#include <X11/Xlib.h>
#endif*/

#include "config.h"
#include "mailleds.h"

sig_atomic_t exit_now = 0;
char opt_a, opt_h, opt_q, opt_l, opt_t, opt_u, opt_x, *opt_m;
char *pid_filename;
char *username;
int kbd_leds = 0x0;
int port_leds = 0x0;
int opt_maildir = 0;

int interval_on = BLINK_TIME_ON;
int interval_off = BLINK_TIME_OFF;
int interval_between = TIME_BETWEEN_COUNTS;

/* array of open file descriptors of ttys whose leds must be flashed */
int ct[MAX_CONSOLES];

/* X Display whose leds must be flashed */
#ifdef X_SUPPORT
/*Display *dpy;*/
int ttyfd_X = 0; /*descr of tty for -x */
#endif

/* array of X leds that are to be flashed */
int x_leds[3];
int uid, euid, pid;

void usage(void)
{
      fprintf(stderr, "usage: mailleds [ -afhkqtx ] [ -m filename ] [ -l [cns] ] [ -d dpy ]\n");
      fprintf(stderr, "Options:\n");
      fprintf(stderr, "-a, --answering-machine  : blink number of messages on led\n");
      fprintf(stderr, "-h, --help               : brings up this help screen\n");
      fprintf(stderr, "-k, --kill               : kills a running mailleds daemon\n");
      fprintf(stderr, "-q, --quiet              : die quietly if another mailleds process exists\n");
      fprintf(stderr, "-t, --ttys               : specifies that mailleds should flash the vt's leds.\n");
      fprintf(stderr, "                           (This is the default if -d is not specified but keyboard LEDs are.)\n");
      fprintf(stderr, "-M, --maildir            : specifies that the mailbox is a maildir\n");
      fprintf(stderr, "--version                : displays version number\n");
      fprintf(stderr, "-u, --user <user>        : runs mailleds as if you were <user>.  You must be root to specify this.\n");
      fprintf(stderr, "-l, --leds [cnsp<number>]\n");
      fprintf(stderr, "                         : c, n, and s are keyboard LEDs mailleds will blink.\n");
#ifdef PARALLEL_SUPPORT
      fprintf(stderr, "                         : p<number> corresponds to LEDs hooked up to a port.\n");
#endif
      fprintf(stderr, "-i, --interval <msec>    : set blink-time-on and blink-time-off to 50000 milli-\n");
      fprintf(stderr, "                           seconds and time-between-counts to <msec> ms.\n");
#ifdef X_SUPPORT
      fprintf(stderr, "-x                       : flash the leds on X display.\n");
#endif
      fprintf(stderr, "-m, --mailbox filename   : use 'filename' as a mailbox file\n");

}

static struct option long_options[] =
{
      {"message-count", 0, 0, 'a'},
      {"leds", 1, 0, 'l'},
      {"help", 0, 0, 'h'},
      {"display", 0, 0, 'd'},
      {"kill", 0, 0, 'k'},
      {"quiet", 0, 0, 'q'},
      {"version", 0, 0, 'v'},
      {"mailbox", 1, 0, 'm'},
      {"ttys", 0, 0, 't'},
      {"user", 1, 0, 'u'},
      {"interval", 1, 0, 'i'},
      {"maildir",0,0,'M'},
      {0, 0, 0, 0}
};

void parse_argv(argc, argv)
int argc;
char *argv[];
{
      int other_process_pid;
      int index = 0;
      char opt;
      char *program;
      struct passwd *pass_info;
      kbd_leds = 0x00;
      port_leds = 0x00;

      /* first, parse the name given. */

      program = rindex(*argv, '/');
      if (program == NULL) {
            program = *argv;
      } else
            program++;

      if (strcmp(program, "xmailleds") == 0)
            opt_x = 1;

      while (1) {
            opt = getopt_long(argc, argv, "Mahkqxtl:m:d:u:i:", long_options, &index);
            if (opt == -1)
                  break;

            switch (opt) {
            case 'a':
                  opt_a = 1;
                  break;

            case 'h':
                  usage();
                  exit(0);    /* printing help was succesful */
                  break;

            case 'k':
                  set_pidfilename();
                  other_process_pid = get_pid_from_file(pid_filename);
                  if (other_process_pid) {
                        if (kill(other_process_pid, SIGTERM)) {
                              perror("mailleds");
                              exit(-2);
                        }
                        fprintf(stderr, "mailleds: process %d killed sucessfully\n", other_process_pid);
                        exit(0);
                  } else {
                        fprintf(stderr, "mailleds: no process running for %s\n", username);
                        exit(1);
                  }
                  break;

            case 'q':
                  opt_q = 1;
                  break;

            case 'v':
                  fprintf(stderr, "mailleds version %s\n", VERSION);
                  exit(0);
                  break;

            case 'm':
                  opt_m = strdup(optarg);
                  break;

            case 't':
                  opt_t = 1;
                  break;

            case 'x':
                  opt_x = 1;
                  break;
                  
            case 'M':
                  opt_maildir = 1;
                  break;
                  
            case 'i':
                  interval_on             = 50000;
                  interval_off            = 50000;
                  interval_between  = atoi(optarg);
                  break;

            case 'u':
                  if (uid != 0) {
                        fprintf(stderr, "mailleds: only root can specify -u\n");
                        exit(-1);
                  }
                  /* here we effectively become the user in -u */
                  free(username);
                  username = strdup(optarg);
                  pass_info = getpwnam(username);
                  uid = pass_info->pw_uid;
                  opt_u = 1;
                  break;

            case 'l':
                  while (*optarg && *optarg != ' ') {
                        switch (*optarg) {
                        case 'n':
                              kbd_leds |= LED_NUM;
                              break;

                        case 'c':
                              kbd_leds |= LED_CAP;
                              break;

                        case 's':
                              kbd_leds |= LED_SCR;
                              break;

#ifdef PARALLEL_SUPPORT
                        case 'p':
                              switch (*++optarg) {
                              case '1':
                                    port_leds |= PORT_LED_1;
                                    break;
                              case '2':
                                    port_leds |= PORT_LED_2;
                                    break;
                              case '3':
                                    port_leds |= PORT_LED_3;
                                    break;
                              case '4':
                                    port_leds |= PORT_LED_4;
                                    break;
                              case '5':
                                    port_leds |= PORT_LED_5;
                                    break;
                              case '6':
                                    port_leds |= PORT_LED_6;
                                    break;
                              case '7':
                                    port_leds |= PORT_LED_7;
                                    break;
                              case '8':
                                    port_leds |= PORT_LED_8;
                                    break;
                              default:
                                    fprintf(stderr, "mailleds: no such led p%c", *optarg);
                                    exit(-1);
                              }
                              break;
#endif                        /* PARALLEL_SUPPORT */
                        default:
                              fprintf(stderr, "mailleds: Unknown LED '%c'\n", *optarg);
                              exit(-1);
                        }
                        optarg++;
                  }
                  break;

            case '?':
                  usage();
                  exit(-1);
                  break;

            case ':':
                  usage();
                  exit(-1);
                  break;
            }
      }

      /* default behavior */
      if (!opt_t && !opt_x && !port_leds)
            opt_t = 1;

      if (!opt_m)
            opt_m = get_mailfile();

      if (!kbd_leds && (opt_x || opt_t))
            kbd_leds = DEF_KBD_LEDS;

      if (kbd_leds && !opt_x && !opt_t)
            opt_t = 1;

      if (!kbd_leds && !port_leds) {
            kbd_leds = DEF_KBD_LEDS;
            port_leds = DEF_PORT_LEDS;
      }
#ifdef X_SUPPORT
      if (opt_x)
            get_X_leds_from_kbd_leds(kbd_leds);
#endif

}

void fatal_error_signal(int sig)
{
      exit_now = 1;
}

void exit_cleanly()
{
      setreuid(uid, euid);
      unlink(pid_filename);
      exit(0);
}

void exit_fatal(const char *reason)
{
      setreuid(uid, euid);
      unlink(pid_filename);
      fprintf(stderr, "mailleds: %s\n", reason);
      exit(1);
}

void set_up_signals()
{
      signal(SIGINT, fatal_error_signal);
      signal(SIGTERM, fatal_error_signal);
}

time_t
get_time_of(filename)
char *filename;
{
      static struct stat i;
      if (stat(filename, &i))
            return (rand());  /* If unable to stat, this forces the mailfile check / wait functions to kick in. */
      return (i.st_ctime);
}

void stat_error(filename)
char *filename;
{
      char *msg;
      msg = (char *) xmalloc(strlen("mailleds: ") + strlen(filename) + 1);
      sprintf(msg, "mailleds: %s", filename);
      perror(msg);
      exit_fatal("File access error");
}

int main(argc, argv)
int argc;
char *argv[];
{
      FILE *mailbox;
      time_t newmod;
      struct passwd *uinfo;

      int mail = 0;
      time_t lastmod = 0;

      uid = getuid();
      euid = geteuid();
      if (!opt_u) {
            uinfo = getpwuid(uid);
            username = strdup(uinfo->pw_name);
      }
      /* don't need to know pid to know pid filename */
      parse_argv(argc, argv);
      set_pidfilename();

      /*if (!opt_x)*/
            pid_check();

#ifndef DEBUG
      switch (fork()) {
      case -1:          /* Cannot fork */
            perror("fork");
            exit(1);
      case 0:           /* Son process */
            break;
      default:          /* Father process */
            exit(0);
      }
#endif

      /* set umask for pidfile */
      umask(022);
      
      /*if (!opt_x) {*/
            pid = getpid();
            write_pidfile();
            detach_from_tty();
      /*}*/
#ifdef PARALLEL_SUPPORT
      if (port_leds) {
            if ((ioperm(LPT_PORT, 1, 1)) == -1) {
                  fprintf(stderr, "unable to set permissions on port 0x%x\n",
                        LPT_PORT);
                  perror("mailleds");
                  exit(1);
            }
      }
#endif

      setreuid(euid, uid);    /* set userid to REAL userid. (security issues) */
      set_up_signals();
      while (!exit_now) {
            newmod = get_time_of(opt_m);
            if (lastmod != newmod) {
                  /*
                  mailbox = open_mailbox_file(opt_m);
                  mail = count_mail(mailbox);
                  lastmod = newmod;
                  fclose(mailbox);
                  */
                  if(!opt_maildir) {
                        mailbox = open_mailbox_file(opt_m);
                        mail = count_mail(mailbox);
                        lastmod = newmod;
                        fclose(mailbox);
                  } else {
                        mail = count_maildir(opt_m);
                  }
            }
            if (kbd_leds) {
                  if (opt_t)
                        make_tty_array();

#ifdef X_SUPPORT
                  if (!ttyfd_X && opt_x) {
                        setreuid(uid, euid);    /* set uid to root because we run this prog suid root */
                        /*dpy = XOpenDisplay(opt_d);
                        if (dpy == (Display *) NULL)
                              exit_fatal("Cannot open Display");
                        XCloseDisplay(dpy);*/
                        
                        /*open tty for -x (to blink on all tty)*/
                        if((ttyfd_X = open("/dev/tty0", O_RDWR)) < 0)
                              exit_fatal("Cannot open /dev/tty0: open(\"dev/tty0\", O_RDWR)");
                        setreuid(euid, uid);    /* remove root. (security issues) */
                  }
#endif
                  if (!port_leds && opt_t && *ct == -1 && !opt_u)       /* we never exit with port_leds */
                        exit_fatal("Couldn't locate your login tty");
            }
            if (mail) {
                  if (!opt_x)
                        setreuid(uid, euid);
                  if (opt_a) {
                        blink_x(interval_on, interval_off, mail);
                        usleep(interval_between);
                  } else {
                        blink_once(interval_on, interval_off);
                        usleep(interval_between);
                  }
                  if (!opt_x)
                        setreuid(euid, uid);
            } else {
                  sleep(INTERVAL_BETWEEN_CHECKS);
            }
      }
      exit_cleanly();
}

Generated by  Doxygen 1.6.0   Back to index