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

capiinit.c

/*
 * $Id: capiinit.c,v 1.17 2005/02/21 17:52:00 keil Exp $
 *
 * $Log: capiinit.c,v $
 * Revision 1.17  2005/02/21 17:52:00  keil
 * * have a seperate config directory for firmware
 * * have a seperate config directory for card tools
 *
 * Revision 1.16  2004/01/19 09:15:57  calle
 * Always use capifs, don't trust devfs.
 *
 * Revision 1.15  2004/01/16 15:27:12  calle
 * remove several warnings.
 *
 * Revision 1.14  2004/01/16 12:33:16  calle
 * Modifications to let ist run with patched 2.6 kernel.
 * Pure 2.6.0/2.6.1 is not working.
 *
 * Revision 1.13  2003/03/31 09:50:52  calle
 * Bugfix: fixed problems with activate and deactivate subcommands, when
 *         AVM B1 PCI V4 is used.
 *
 * Revision 1.12  2003/03/11 13:39:07  paul
 * Also search for firmware in /usr/share/isdn, which is more in line with LSB
 *
 * Revision 1.11  2003/01/14 13:47:15  calle
 * New Commands to only load modules, only initialize cards,
 * only reset cards, inititialize a single card or reset a single card.
 *
 * Revision 1.10  2002/10/25 13:50:44  calle
 * The protocol value was not tranfered to the patchinfo. Because of
 * this for example NI1 did not work ...
 *
 * Revision 1.9  2002/05/23 12:52:36  calle
 * - Uaah. Bugfix for c2 patchvalues.
 *
 * Revision 1.8  2001/04/18 10:21:42  calle
 * support for "AVM ISDN Controller C2" added.
 *
 * Revision 1.7  2000/08/31 08:23:35  calle
 * - produce an error message, if a driver could not be loaded.
 *
 * Revision 1.6  2000/07/24 14:15:10  calle
 * Bugfix: pci controllers were always by initialized first in multi
 *         controller environment.
 *
 * Revision 1.5  2000/07/24 08:38:04  calle
 * - Bugfix: devfs mount was never detected, because an extra / in path.
 *
 * Revision 1.4  2000/06/30 14:08:45  calle
 * - creat /dev/capi if not exist, and mount capifs if available and devfs
 *   not availabe or not mounted on /dev.
 * - better error messages
 *
 * Revision 1.3  2000/06/29 15:17:21  calle
 * Mount capifs on /dev/capi if available.
 *
 * Revision 1.2  2000/05/18 15:20:18  calle
 * Umount capifs on "stop".
 *
 * Revision 1.1  2000/03/17 16:19:43  calle
 * New command capiinit, this will replace avmcapictrl in the future, if
 * called as "capiinit start" ist will load all modules, add all cards
 * configured in "/etc/capi.conf" and load the firmware to all active
 * cards. When called as "capiinit stop", it will deinit all cards and
 * remove all modules. Sample config in capiinit/capi.conf.
 *
 */

#include <sys/types.h>
#include <sys/signal.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define _LINUX_LIST_H
#include <linux/b1lli.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <getopt.h>

#define MODPROBE  "/sbin/modprobe"
static char capidevnameold[] = "/dev/capi20";
static char capidevnamenew[] = "/dev/isdn/capi20";
static char *capidevname = capidevnameold;

static char *firmwarepath[] = {
      "/lib/firmware/isdn",
      "/usr/share/isdn",
      "/usr/lib/isdn",
      "/lib/isdn",
      0
};

/* ---------------- global variables --------------------------------- */

static int capifd = -1;

static int patchdebug = 0;    /* -d || -debug */
static int silent = 0;        /* -s || -silent */
char *configfilename = "/etc/capi.conf";

/* ---------------- utils -------------------------------------------- */

#define STRUCTALLOC(type)     (type *)malloc(sizeof(type))

static FILE *fopen_with_errmsg(const char *path, const char *mode)
{
      FILE *fp;
      if ((fp = fopen(path, mode)) == NULL) {
            int serrno = errno;
            fprintf(stderr, "ERROR: fopen(%s,%s) failed - %s (%d)\n",
                  path, mode, strerror(serrno), serrno);
      }
      return fp;
}

static char *skip_whitespace(char *s)
{
   while (*s && isspace(*s)) s++;
   return s;
}

static char *skip_nonwhitespace(char *s)
{
   while (*s && !isspace(*s)) s++;
   return s;
}

/* ---------------- load module -------------------------------------- */

static int is_module_loaded(char *module)
{
      static char *fn = "/proc/modules";
      char buf[4096];
      FILE *fp;
      char *s;

      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            s = skip_nonwhitespace(buf);
            if (s) {
               *s = 0;
               if (strcmp(module,buf) == 0) {
                  fclose(fp);
                  return 1;
               }
            }
      }
      fclose(fp);
      return 0;
}

static int load_module(char *module)
{
      char buf[1024];
      snprintf(buf, sizeof(buf), "%s %s", MODPROBE, module);
      return system(buf);
}

static int unload_module(char *module)
{
      char buf[1024];
        if (is_module_loaded(module)) {
            snprintf(buf, sizeof(buf), "%s -r %s", MODPROBE, module);
            return system(buf);
      }
      return 0;
}

/* ---------------- /proc/capi/controller ---------------------------- */

/*
1 b1pciv4    detected b1pciv4-e400     - - 0xe400 19 0xea003000 r4
2 c4         detected c4-d800          - - 0xd800 17 0xea001000
3 c4         detected c4-d800          - - 0xd800 17 0xea001000
4 c4         detected c4-d800          - - 0xd800 17 0xea001000
5 c4         detected c4-d800          - - 0xd800 17 0xea001000
*/

#define CARD_FREE 0
#define CARD_DETECTED   1
#define CARD_LOADING    2
#define CARD_RUNNING    3

00196 struct cardstatemap {
      char *name;
      int state;
} cardstatemap[] = {
{ "free",   CARD_FREE },
{ "detected",     CARD_DETECTED },
{ "loading",      CARD_LOADING },
{ "running",      CARD_RUNNING },
{ 0 }
};

static char *cardstate2str(int state)
{
      struct cardstatemap *p;
      for (p = cardstatemap; p->name; p++) {
            if (state == p->state)
                  return p->name;
      }
      return cardstatemap[0].name;
}

static int str2cardstate(char *s)
{
      struct cardstatemap *p;
      for (p = cardstatemap; p->name; p++) {
            if (strcmp(p->name, s) == 0)
                  return p->state;
      }
      return cardstatemap[0].state;
}

00227 struct contrprocinfo {
      struct contrprocinfo *next;
      int                   contr;
      char                  driver[32];
      int                   state;
      char                  name[32];
      char                  driverinfo[32];
};

static void free_contrprocinfo(struct contrprocinfo **pp)
{
      struct contrprocinfo *p;
      while (*pp) {
            p = *pp;
            *pp = p->next;
            free(p);
      }
}

static struct contrprocinfo *load_contrprocinfo(int *lastcontrp)
{
      static char *fn = "/proc/capi/controller";
      struct contrprocinfo *list, *p, **pp;
      char buf[4096];
      FILE *fp;
      int line = 0;

      if (lastcontrp)
            *lastcontrp = 0;
      list = 0;
      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            char *s, *tmp, *target;
            line++;
            if ((p = STRUCTALLOC(struct contrprocinfo)) == 0) {
                  fprintf(stderr, "ERROR: %s:%d: malloc failed\n", fn, line);
                  goto error;
            }
            memset(p, 0, sizeof(*p));
            s = buf;
            /* contr */
            tmp = s;
            p->contr = strtol(s, &tmp, 10);
            if (tmp == s) goto parseerror;
            /* driver */
            target = skip_whitespace(tmp);
            s = skip_nonwhitespace(target);
            if (!*s) goto parseerror;
            *s++ = 0;
            snprintf(p->driver, sizeof(p->driver), "%s", target);
            /* state */
            target = skip_whitespace(s);
            s = skip_nonwhitespace(target);
            if (!*s) goto parseerror;
            *s++ = 0;
            p->state = str2cardstate(target);
            /* name */
            target = skip_whitespace(s);
            s = skip_nonwhitespace(target);
            if (!*s) goto parseerror;
            *s++ = 0;
            snprintf(p->name, sizeof(p->name), "%s", target);
            /* driverinfo */
            target = skip_whitespace(s);
            while (*s && *s != '\n') s++;
            if (*s) *s = 0;
            snprintf(p->driverinfo, sizeof(p->driverinfo), "%s", target);

            for (pp = &list; *pp; pp = &(*pp)->next) ;
            *pp = p;
            if (lastcontrp && *lastcontrp < p->contr)
                  *lastcontrp = p->contr;
      }
      fclose(fp);
      return list;
parseerror:
      fprintf(stderr, "ERROR: %s:%d: parse error\n", fn, line);
error:
      fclose(fp);
      free_contrprocinfo(&list);
      return 0;
}

static struct contrprocinfo *
find_contrprocinfo(struct contrprocinfo *cpinfo, int contr)
{
      struct contrprocinfo *p;
      for (p = cpinfo; p; p = p->next)
            if (p->contr == contr)
                  break;
      return p;
}

static void show_contrprocinfo(struct contrprocinfo *cpinfo, char *cardname)
{
      struct contrprocinfo *p;
      for (p = cpinfo; p; p = p->next) {
            if (cardname && strcmp(cardname, p->name) != 0)
                  continue;
            printf("%d %-10s %-8s %-16s %s\n", 
                  p->contr, p->driver, cardstate2str(p->state),
                  p->name, p->driverinfo);
      }
}

/* ---------------- /proc/capi/driver -------------------------------- */

/*
b1pci                            0  1.20 
b1pciv4                          1 0.0
c4                               4  1.4 
*/

static int driver_loaded(char *driver)
{
      static char *fn = "/proc/capi/driver";
      char buf[4096];
      FILE *fp;

      if (strcmp(driver, "b1pciv4") == 0)
            driver = "b1pci";

      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            char *s = buf;
            while (*s && !isspace(*s)) s++;
            *s = 0;
            if (strcmp(buf, driver) == 0) {
                  fclose(fp);
                  return 1;
            }
      }
      fclose(fp);
      return 0;
}

static int load_driver(char *driver)
{
      if (strcmp(driver, "b1pciv4") == 0)
            driver = "b1pci";
      if (strcmp(driver, "c2") == 0)
            driver = "c4";
      return load_module(driver);
}

static int unload_driver(char *driver)
{
      if (strcmp(driver, "b1pciv4") == 0)
            driver = "b1pci";
      if (strcmp(driver, "c2") == 0)
            driver = "c4";
      return unload_module(driver);
}

/* ---------------- /proc/filesystems -------------------------------- */

static int filesystem_available(char *fstype)
{
      static char *fn = "/proc/filesystems";
      char buf[4096];
      FILE *fp;

      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            char *t, *s;
            buf[strlen(buf)-1] = 0;
            t = skip_whitespace(buf);
            s = skip_nonwhitespace(t);
            if (*s) {
                  t = skip_whitespace(s);
                  s = skip_nonwhitespace(t);
            }
            if (strcmp(t, fstype) == 0) {
                  fclose(fp);
                  return 1;
            }
      }
      fclose(fp);
      return 0;
}

static int load_filesystem(char *fstype)
{
      return load_module(fstype);
}

static int unload_filesystem(char *fstype)
{
      return unload_module(fstype);
}

/* ---------------- /proc/mounts ------------------------------------- */

/*
/dev/root / ext2 rw 0 0
proc /proc proc rw 0 0
/dev/hda1 /boot ext2 rw 0 0
/dev/hda7 /src ext2 rw 0 0
devpts /dev/pts devpts rw 0 0
*/

static char *mounted(char *fstype)
{
      static char *fn = "/proc/mounts";
      static char mpret[PATH_MAX];
      char buf[4096];
      FILE *fp;
      char *mp,*ftype;

      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            char *t, *s;
            buf[strlen(buf)-1] = 0;
            s = skip_whitespace(buf);
            t = skip_nonwhitespace(s);
            mp = skip_whitespace(t);
            t = skip_nonwhitespace(mp);
            if (!*t) 
                  continue;
            *t++ = 0;
            strncpy(mpret, mp, sizeof(mpret)-1);
            mpret[sizeof(mpret)-1] = 0;
            ftype = skip_whitespace(t);
            t = skip_nonwhitespace(ftype);
            if (!*t)
                  continue;
            *t++ = 0;
            if (strcmp(ftype, fstype) == 0) {
                  fclose(fp);
                  return mpret;
            }
      }
      fclose(fp);
      return 0;
}

/* ---------------- /etc/capi.conf ----------------------------------- */

/*
# card            file  proto io    irq   mem   cardnr      options
b1isa       b1.t4 DSS1  0x150 7     -     -     P2P
*/

#define DP_ERROR  -1
#define DP_NONE         0
#define DP_1TR6         0
#define DP_DSS1         0
#define DP_CT1          1
#define DP_VN3          2
#define DP_NI1          3     /* need SPID,SPID2,DN,DN2 */
#define DP_AUSTEL 4
#define DP_5ESS         5     /* need SPID,SPID2,DN,DN2 */

static struct pmap {
  char *name;
  int   protocol;
} pmap[] = {
  { "-", DP_NONE },
  { "none", DP_NONE },
  { "DSS1", DP_DSS1 },
  { "1TR6", DP_1TR6 },
  { "CT1", DP_CT1 },
  { "VN3", DP_VN3 },
  { "AUSTEL", DP_AUSTEL },
  { "5ESS", DP_5ESS },
  { "NI1", DP_NI1 },
  { 0 },
};

static int dchan_protocol(char *pname)
{
   struct pmap *p;
   for (p=pmap; p->name; p++) {
      if (strcasecmp(pname, p->name) == 0)
       return p->protocol;
   }
   return DP_ERROR;
}

00510 struct patchinfo {
      int protocol;
      int p2p;
      char *dn1;
      char *spid1;
      char *dn2;
      char *spid2;
};

00519 struct capicard {
      struct capicard  *next;
      int               found;
      int               line;
      char             *driver;
      char             *firmware;
      char             *protoname;
      int           proto;
      int           ioaddr;
      int           irq;
      unsigned long       memaddr;
      int               cardnr;
      char             *optionstring;
      struct patchinfo  patchinfo;
};

static void free_config(struct capicard **pp)
{
      struct capicard *p;
      while (*pp) {
            p = *pp;
            *pp = p->next;
            if (p->driver) free(p->driver);
            if (p->firmware) free(p->firmware);
            if (p->protoname) free(p->protoname);
            if (p->optionstring) free(p->optionstring);
            if (p->patchinfo.dn1) free(p->patchinfo.dn1);
            if (p->patchinfo.spid1) free(p->patchinfo.spid1);
            if (p->patchinfo.dn2) free(p->patchinfo.dn2);
            if (p->patchinfo.spid2) free(p->patchinfo.spid2);
            free(p);
      }
}

static int parse_cardoptions(char *opts, struct patchinfo *infop)
{
      char buf[4096];
      char *s, *option, *p;
      char save;

      strncpy(buf, opts, sizeof(buf)-1);
      buf[sizeof(buf)-1] = 0;

      s = buf;
      while (*s) {
            s = skip_whitespace(s);
            option = s;
            s = skip_nonwhitespace(option);
            save = *s;
            *s = 0;
            if (*option == 0 || *option == '#')
                  break;
            if (strcasecmp(option, "p2p") == 0) {
                  infop->p2p = 1;
                  *s = save;
                  if (*s) s++;
                  continue;
            }
            if ((p = strchr(option, ':')) != 0) {     /* DN:SPID */
                  char *dn, *spid;
                  *p = 0;
                  dn = strdup(option);
                  spid = strdup(p+1);
                  *p = ':';
                  if (infop->dn1 == 0) {
                        infop->dn1 = dn;
                        infop->spid1 = spid;
                  } else {
                        if (infop->dn2) free(infop->dn2);
                        if (infop->spid2) free(infop->spid2);
                        infop->dn2 = dn;
                        infop->spid2 = spid;
                  }
                  *s = save;
                  if (*s) s++;
                  continue;
            }

            fprintf(stderr, "ERROR: cardoptions: unknown option \"%s\"\n", option);
            *s = save;
            return -1;
      }
      return 0;
}

struct capicard *load_config(char *fn)
{
      struct capicard *list, *p, **pp;
      char buf[4096];
      char *s, *t, *tmp;
      FILE *fp;
      int line = 0;

      list = 0;
      if ((fp = fopen_with_errmsg(fn, "r")) == NULL)
            return 0;
      while (fgets(buf,sizeof(buf),fp)) {
            line++;

            buf[strlen(buf)-1] = 0;
            if ((p = STRUCTALLOC(struct capicard)) == 0) {
                  fprintf(stderr, "ERROR: %s:%d: malloc failed\n", fn, line);
                  goto error;
            }
            memset(p, 0, sizeof(*p));
            p->line = line;
            s = skip_whitespace(buf);
            if (*s == 0 || *s == '#')
                  continue;

            /* driver */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            p->driver = strdup(t);
            if (!p->driver) goto nomem;
            s = skip_whitespace(s);

            /* firmware */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            p->firmware = strdup(t);
            if (!p->firmware) goto nomem;
            s = skip_whitespace(s);

            /* proto */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            p->protoname = strdup(t);
            if (!p->protoname) goto nomem;
            p->proto = dchan_protocol(t);
            p->patchinfo.protocol = p->proto;
            s = skip_whitespace(s);

            /* ioaddr */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            if (strcmp(t, "-") == 0 || strcmp(t, "none") == 0) {
                  p->ioaddr = 0;
            } else {
                  tmp = t;
                  p->ioaddr = strtol(t, &tmp, 0);
                  if (*tmp) {
                        fprintf(stderr, "ERROR: %s:%d: illegal ioaddr \"%s\"\n",
                              fn, line, t);
                        goto error;
                  }
            }
            s = skip_whitespace(s);

            /* irq */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            if (strcmp(t, "-") == 0 || strcmp(t, "none") == 0) {
                  p->irq = 0;
            } else {
                  tmp = t;
                  p->irq = strtol(t, &tmp, 0);
                  if (*tmp) {
                        fprintf(stderr, "ERROR: %s:%d: illegal irq \"%s\"\n",
                              fn, line, t);
                        goto error;
                  }
            }
            s = skip_whitespace(s);

            /* memaddr */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            if (strcmp(t, "-") == 0 || strcmp(t, "none") == 0) {
                  p->memaddr = 0;
            } else {
                  tmp = t;
                  p->memaddr = strtoul(t, &tmp, 0);
                  if (*tmp) {
                        fprintf(stderr, "ERROR: %s:%d: illegal memaddr \"%s\"\n",
                              fn, line, t);
                        goto error;
                  }
            }
            s = skip_whitespace(s);

            /* cardnr */
            t = s;
            s = skip_nonwhitespace(t);
            if (*s) *s++ = 0;
            if (strcmp(t, "-") == 0 || strcmp(t, "none") == 0) {
                  p->cardnr = 0;
            } else {
                  tmp = t;
                  p->cardnr = strtol(t, &tmp, 0);
                  if (*tmp) {
                        fprintf(stderr, "ERROR: %s:%d: illegal cardnr \"%s\"\n",
                              fn, line, t);
                        goto error;
                  }
            }
            s = skip_whitespace(s);

            /* options */
            p->optionstring = strdup(s);
            if (!p->optionstring) goto nomem;

            if (parse_cardoptions(p->optionstring, &p->patchinfo) < 0) {
                  fprintf(stderr, "ERROR: %s:%d: illegal options \"%s\"\n",
                              fn, line, p->optionstring);
                  goto error;
            }

            /* append it to the list */
            for (pp = &list; *pp; pp = &(*pp)->next) ;
            *pp = p;
      }
      fclose(fp);
      return list;
nomem:
      fprintf(stderr, "ERROR: %s:%d: no memory\n", fn, line);
error:
      fclose(fp);
      free_config(&list);
      return 0;
}

static void mark_unfound(struct capicard *cards) 
{
      struct capicard *card = cards;
      for (card = cards; card; card = card->next)
            card->found = 0;
}

static struct capicard *find_config(struct capicard *cards, char *driver)
{
      struct capicard *card;

      for (card = cards; card; card = card->next) {
            if (card->found)
                  continue;
            if (strcmp(card->driver,driver) == 0)
                  break;
      }
      if (card) {
            card->found = 1;
            return card;
      }

      if (strcmp(driver, "b1pci") == 0) {
            for (card = cards; card; card = card->next) {
                  if (card->found)
                        continue;
                  if (strcmp(card->driver, "b1pciv4") == 0)
                        break;
            }
      } else if (strcmp(driver, "b1pciv4") == 0) {
            for (card = cards; card; card = card->next) {
                  if (card->found)
                        continue;
                  if (strcmp(card->driver, "b1pci") == 0)
                        break;
            }
      } else if (strcmp(driver, "c4") == 0) {
            for (card = cards; card; card = card->next) {
                  if (card->found)
                        continue;
                  if (strcmp(card->driver, "c2") == 0)
                        break;
            }
      } else if (strcmp(driver, "c2") == 0) {
            for (card = cards; card; card = card->next) {
                  if (card->found)
                        continue;
                  if (strcmp(card->driver, "c4") == 0)
                        break;
            }
      }

      if (card) card->found = 1;
      return card;
}

static void show_confighead(void)
{
      printf("%s\t%-12s\t%s", "driver", "firmware", "proto");
      printf("\tio");
      printf("\tirq");
      printf("\tmem");
      printf("\tcardnr");
      printf("\toptions");
      printf("\n");
}

static void show_configone(struct capicard *p)
{
      printf("%s\t%-12s\t%s", p->driver, p->firmware, p->protoname);
      if (p->ioaddr) printf("\t0x%x", p->ioaddr);
      else printf("\t-");
      if (p->irq) printf("\t%d", p->irq);
      else printf("\t-");
      if (p->memaddr) printf("\t0x%lx", p->memaddr);
      else printf("\t-");
      if (p->cardnr) printf("\t%d", p->cardnr);
      else printf("\t-");
      printf("\t%s", p->optionstring);
      printf("\n");
}

static void show_config(struct capicard *cards)
{
      struct capicard *p;
      show_confighead();
      for (p = cards; p; p = p->next)
            show_configone(p);
}

/* ---------------- add card ----------------------------------------- */

static int add_card(struct capicard *card)
{
      capi_manufacturer_cmd ioctl_s;
      kcapi_carddef carddef;

      memset(&carddef, 0, sizeof(carddef));
      strncpy(carddef.driver, card->driver, sizeof(carddef.driver)-1);
      carddef.port = card->ioaddr;
      carddef.irq = card->irq;
      carddef.irq = card->irq;
      carddef.membase = card->memaddr;
      carddef.cardnr = card->cardnr;
      ioctl_s.cmd = KCAPI_CMD_ADDCARD;
      ioctl_s.data = &carddef;
      if (ioctl(capifd, CAPI_MANUFACTURER_CMD, &ioctl_s) >= 0)
            return 0;
      fprintf(stderr, "ERROR: add_card(%s) failed - %s (%d)\n",
                        card->driver, strerror(errno), errno);
      fprintf(stderr, "\n!! CHECK THE KERNEL MESSAGES BEFORE SENDING MAIL !!\n\n");
      return -1;
}

/* ---------------- patchvalues for AVM active cards ----------------- */

static char patcharea[8192];
static int  patchlen = 0;

static char *getpatchdata(void)
{
      return patcharea;
}

static int getpatchlen(void)
{
      return patchlen;
}

static void clearpatcharea(void)
{
      patchlen = 0;
}

static void addpatchvalue(char *name, char *value, int len)
{
   int nlen = strlen(name);
   if (patchlen + nlen + len + 2 >= sizeof(patcharea)) {
      fprintf(stderr, "ERROR: addpatchvalue: patcharea overflow (%s)\n" , name);
      return;
   }
   patcharea[patchlen++] = ':';
   memcpy(&patcharea[patchlen], name, nlen);
   patchlen += nlen;
   patcharea[patchlen++] = 0;
   memcpy(&patcharea[patchlen], value, len);
   patchlen += len;
   patcharea[patchlen++] = 0;
   patcharea[patchlen+1] = 0;
}

static void addpatchstring(char *name, char *value)
{
      addpatchvalue(name, value, strlen(value));
}

static void addpatchbyte(char *name, unsigned char value)
{
      char buf[16];
      sprintf(buf, "\\x%02x", value);
      addpatchvalue(name, buf, strlen(buf));
}

static void addpatchvalues(struct patchinfo *p)
{
      int p2p = p->p2p;
      addpatchstring("WATCHDOG", "1");
      addpatchbyte("AutoFrame", 1);
      switch (p->protocol) {
                  case DP_CT1: 
                  addpatchbyte("PROTOCOL", 1);
                  break;
                  case DP_VN3: 
                  addpatchbyte("PROTOCOL", 2);
                  break;
                  case DP_NI1: 
                  p2p = 0;
                  addpatchbyte("PROTOCOL", 3);
                  if (p->dn1 && p->spid1) {
                              addpatchstring("DN", p->dn1);
                              addpatchstring("SPID", p->spid1);
                  }
                  if (p->dn2 && p->spid2) {
                              addpatchstring("DN2", p->dn2);
                              addpatchstring("SPID2", p->spid2);
                  }
                  break;
                  case DP_AUSTEL: 
                  addpatchbyte("PROTOCOL", 4);
                  break;
                  case DP_5ESS: 
                  p2p = 0;
                  addpatchbyte("PROTOCOL", 5);
                  if (p->dn1 && p->spid1) {
                              addpatchstring("DN", p->dn1);
                              addpatchstring("SPID", p->spid1);
                  }
                  if (p->dn2 && p->spid2) {
                              addpatchstring("DN2", p->dn2);
                              addpatchstring("SPID2", p->spid2);
                  }
                  break;
      }
      if (p2p) {
            addpatchbyte("P2P", 1);
            addpatchbyte("TEI", 0);
      }
}

static void savepatcharea(char *dir, int contr)
{
      char fn[PATH_MAX];
      int fd;
      snprintf(fn, sizeof(fn), "%s/capicontr%d.pvals", dir, contr);
      if (access(fn, 0)) unlink(fn);
      if ((fd = open(fn, O_WRONLY|O_CREAT, 0600)) < 0) {
            fprintf(stderr, "creation of %s failed - %s (%d)\n",
                  fn, strerror(errno), errno);
            return;
      }
      if (write(fd, patcharea, patchlen) != patchlen) {
            fprintf(stderr, "write to %s failed - %s (%d)\n",
                  fn, strerror(errno), errno);
            close(fd);
            return;
      }
      close(fd);
      printf("controller %d: patchvalues written to %s\n",
                  contr, fn);
}

/* ---------------- firmware load ------------------------------------ */

static char *locate_firmware(struct capicard *card)
{
      static char fn[PATH_MAX];
      char **path;

      if (card->firmware[0] == '/') {
            snprintf(fn, sizeof(fn), "%s", card->firmware);
            return fn;
      }
      for (path = firmwarepath; *path; path++) {
            snprintf(fn, sizeof(fn), "%s/%s", path[0], card->firmware);
            if (access(fn, R_OK) == 0)
                  return fn;
      }
      return 0;
}

static char signalinfo[PATH_MAX+64];

static void sigdummy(int sig)
{
      fprintf(stderr, "ERROR: %s\n", signalinfo);
}

static struct capicard *load_firmware(int contr, struct capicard *card)
{
      capi_manufacturer_cmd ioctl_s;
      avmb1_loadandconfigdef ldef;
      struct capicard *next = card->next;
      char *fn, *type;
      struct stat st;
      int codefd;

      clearpatcharea();
      if (strcmp(card->driver, "c4") == 0) {
            struct capicard *cp;
            int i;
            for (i=0,cp=card; i < 4; i++) {
                  addpatchbyte("CtlrNr", i);
                  addpatchvalues(&cp->patchinfo);
                  if (cp->next && strcmp(cp->next->driver, "c4") == 0)
                        cp = cp->next;
            }
            next = cp->next;
      } else if (strcmp(card->driver, "c2") == 0) {
            struct capicard *cp;
            int i;
            for (i=0,cp=card; i < 2; i++) {
                  addpatchbyte("CtlrNr", i);
                  addpatchvalues(&cp->patchinfo);
                  if (cp->next && strcmp(cp->next->driver, "c2") == 0)
                        cp = cp->next;
            }
            next = cp->next;
      } else {
            addpatchvalues(&card->patchinfo);
      }

      if ((fn = locate_firmware(card)) == 0) {
            fprintf(stderr, "ERROR: controller %d: firmware file \"%s\" not found\n",
                        contr, card->firmware);
            return next;
      }
      if (stat(fn, &st)) {
            fprintf(stderr, "ERROR: controller %d: stat failed for firmware file %s - %s (%d)\n",
                        contr, fn, strerror(errno), errno);
            return next;
      }
      switch (st.st_mode & S_IFMT) {
            case S_IFREG:  type = 0; break;
            case S_IFSOCK: type = "socket"; break;
            case S_IFLNK:  type = "symbolic link"; break;
            case S_IFBLK:  type = "block device"; break;
            case S_IFDIR:  type = "directory"; break;
            case S_IFCHR:  type = "character device"; break;
            case S_IFIFO:  type = "named pipe"; break;
            default:       type = "unknown file type"; break;
      }
      if (type != 0) {
            fprintf(stderr, "ERROR: controller %d: firmware file \"%s\" is a %s\n",
                        contr, fn, type);
            return next;
      }

      if ((codefd = open(fn, O_RDONLY)) < 0) {
            fprintf(stderr, "ERROR: controller %d: failed to open firmware file \"%s\" - %s (%d)\n",
                        contr, fn, strerror(errno), errno);
            return next;
      }

      ldef.contr = contr;
      ldef.t4file.len = st.st_size;
      ldef.t4file.data = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, codefd, 0);
      if (ldef.t4file.data == (unsigned char *) -1) {
            fprintf(stderr, "ERROR: controller %d: mmap of firmware failed - %s (%d)\n",
                        contr, strerror(errno), errno);
            return next;
      }

      ldef.t4config.len = getpatchlen();
      ldef.t4config.data = getpatchdata();

      if (patchdebug)
            savepatcharea("/tmp", contr);

      ioctl_s.cmd = AVMB1_LOAD_AND_CONFIG;
      ioctl_s.data = &ldef;
      snprintf(signalinfo, sizeof(signalinfo), 
            "controller %d: timeout while loading \"%s\"", contr, fn);
      signal(SIGALRM, sigdummy);
      alarm(10);
      if (ioctl(capifd, CAPI_MANUFACTURER_CMD, &ioctl_s) < 0) {
            if (errno != EINTR) {
                  fprintf(stderr, "ERROR: controller %d: firmware load failed - %s (%d)\n", contr, strerror(errno), errno);
                  fprintf(stderr, "\n!! CHECK THE KERNEL MESSAGES BEFORE SENDING MAIL !!\n\n");
            }
            alarm(0);
            signal(SIGALRM, SIG_DFL);
            return next;
      }
      alarm(0);
      signal(SIGALRM, SIG_DFL);
      munmap(ldef.t4file.data, ldef.t4file.len);
      close(codefd);
      return next;
}

int reset_controller(int contr)
{
      capi_manufacturer_cmd ioctl_s;
      avmb1_resetdef rdef;

      rdef.contr = contr;
      ioctl_s.cmd = AVMB1_RESETCARD;
      ioctl_s.data = &rdef;
      if (ioctl(capifd, CAPI_MANUFACTURER_CMD, &ioctl_s) < 0)
            return -1;
      return 0;
}

int remove_controller(int contr)
{
      capi_manufacturer_cmd ioctl_s;
      avmb1_resetdef rdef;

      rdef.contr = contr;
      ioctl_s.cmd = AVMB1_REMOVECARD;
      ioctl_s.data = &rdef;
      if (ioctl(capifd, CAPI_MANUFACTURER_CMD, &ioctl_s) < 0)
            return -1;
      return 0;
}

/* ---------------- prechecks ---------------------------------------- */

static int check_superuser(void)
{
      if (getuid() != 0) {
            fprintf(stderr, "ERROR: you must be super user\n");
            return -1;
      }
      return 0;
}

static int check_procfs(void)
{
      if (access("/proc/self", 0) < 0) {
            fprintf(stderr, "ERROR: proc filesystem not mounted\n");
            return -1;
      }
      return 0;
}

static int check_for_kernelcapi(void)
{
      if (access("/proc/capi/applications", 0) == 0)
            return 0;
      load_module("kernelcapi");
      if (access("/proc/capi/applications", 0) == 0)
            return 0;
      fprintf(stderr, "ERROR: cannot load module kernelcapi\n");
      return -1;
}

static int check_for_capi(void)
{
      if (access("/proc/capi/capi20", 0) == 0)
            return 0;
      load_module("capi");
      if (access("/proc/capi/capi20", 0) == 0)
            return 0;
      fprintf(stderr, "ERROR: cannot load module capi20\n");
      return -1;
}

static int check_for_devcapi(void)
{
      int fd;
      capidevname = capidevnameold;
      if ((fd = open(capidevname, O_RDWR)) < 0 && errno == ENOENT) {
            capidevname = capidevnamenew;
            fd = open(capidevname, O_RDWR);
      }
      if (fd < 0) {
            fprintf(stderr, "ERROR: cannot open %s nor %s - %s (%d)\n",
                  capidevnameold, capidevnamenew, strerror(errno), errno);
            return -1;
      }
      close(fd);
      return 0;
}

static int check_for_capifs(void)
{
      if (filesystem_available("capifs"))
            return 0;
      load_filesystem("capifs");
      if (filesystem_available("capifs")) 
            return 0;
#ifdef WITH_DEVFS
      if (filesystem_available("devfs"))
            return 0;
#endif
      load_filesystem("capifs");
      if (filesystem_available("capifs")) 
            return 0;
      fprintf(stderr, "WARNING: filesystem capifs not available\n");
      return -1;
}

static int checkdir(char *dir)
{
      struct stat st;
      if (stat(dir, &st) < 0)
            return -1;
      if (S_ISDIR(st.st_mode))
            return 0;
      return -1;
}

static int check_for_capifs_mounted(void)
{
      char *mp;
#ifdef WITH_DEVFS
      if (filesystem_available("devfs")) {
            if ((mp = mounted("devfs")) != 0 && strcmp(mp, "/dev") == 0)
                  return 0;
      }
#endif
      if (filesystem_available("capifs")) {
            if ((mp = mounted("capifs")) != 0 && strcmp(mp, "/dev/capi") == 0)
                  return 0;
            if (checkdir("/dev/capi") < 0) {
                  unlink("/dev/capi");
                  if (mkdir("/dev/capi", 0755) < 0) {
                        fprintf(stderr, "ERROR: mkdir(/dev/capi) failed - %s (%d)\n",
                              strerror(errno), errno);
                        return -1;
                  }
            }
            system("mount -t capifs -omode=0666 capifs /dev/capi");
            if ((mp = mounted("capifs")) != 0 && strcmp(mp, "/dev/capi") == 0)
                  return 0;
            fprintf(stderr, "ERROR: cound't mount capifs on /dev/capi\n");
            return -1;
      }
      return -1;
}
static int prestartcheck(void)
{
      if (check_superuser() < 0) return -1;
      if (check_procfs() < 0) return -1;
      if (check_for_kernelcapi() < 0) return -1;
      if (check_for_capi() < 0) return -1;
      if (check_for_devcapi() < 0) return -1;
      if (check_for_capifs() < 0) return 0; /* only warning */
      if (check_for_capifs_mounted() < 0) return -1;
      return 0;
}

static int prestopcheck(void)
{
      if (check_superuser() < 0) return -1;
      if (check_procfs() < 0) return -1;
      if (check_for_kernelcapi() < 0) return -1;
      if (check_for_capi() < 0) return -1;
      if (check_for_devcapi() < 0) return -1;
      return 0;
}

/* ------------------------------------------------------------------- */

static int is_card_of_driver(char *cardname, struct contrprocinfo *p)
{
      if (strcmp(cardname, p->driver) == 0)
            return 1;
      if (   strcmp(cardname, "b1pci") == 0
          && strcmp(p->driver, "b1pciv4") == 0)
            return 1;
      if (strcmp(cardname, p->name) == 0)
         return 1;
      return 0;
}

static int card_exists(const char * driver, int ioaddr)
{
      static char buf[64];
      struct contrprocinfo *cp, *cpinfo;

      snprintf (buf, sizeof (buf), "%s-%x", driver, ioaddr);
      buf[sizeof (buf) - 1] = (char) 0;
      for (cp = cpinfo = load_contrprocinfo(0); cp; cp = cp->next) {
            if (strcmp (cp->name, buf) == 0)
                  break;
      }
      free_contrprocinfo (&cpinfo);
      return cp != 0;
}


int main_start(int activate, char *cardname, int number)
{
      struct capicard *cards, *card;
      struct contrprocinfo *cpinfo, *p;
      int contr, lastcontr;
      int ret = 0;
      char cname[32];

      if (prestartcheck() < 0)
            return -1;

      cname[0] = 0;

      /* could not fail, tested by check_for_capi() */
      capifd = open(capidevname, O_RDWR);

      cards = load_config(configfilename);
      for (card = cards; card; card = card->next) {
            if (!driver_loaded(card->driver))
                  load_driver(card->driver);
                if (!driver_loaded(card->driver)) {
                  fprintf(stderr,"ERROR: failed to load driver %s\n",
                                       card->driver);
                  continue;
            }
            if (card->ioaddr && !card_exists(card->driver, card->ioaddr)) 
                  add_card(card);
      }

      mark_unfound(cards); 
      if (activate) {
            int act;
            act = 0;
            cpinfo = load_contrprocinfo(&lastcontr);
            for (contr = 1; contr <= lastcontr; contr++) {
                  struct capicard *thiscard;
                  cpinfo = load_contrprocinfo(0);
                  p = find_contrprocinfo(cpinfo, contr);
                  thiscard = find_config(cards, p->driver);
                  if (cardname) {
                        if (number == 0) {
                              if (strcmp(cardname, p->name) != 0) {
                                    free_contrprocinfo(&cpinfo);
                                    continue;
                              }
                        } else if (is_card_of_driver(cardname, p)) {
                              if (++act != number) {
                                    free_contrprocinfo(&cpinfo);
                                    continue;
                              }
                        } else {
                              free_contrprocinfo(&cpinfo);
                              continue;
                        }
                        strncpy(cname, p->name, sizeof(cname));
                  }
                  if (p->state ==   CARD_LOADING)
                        reset_controller(contr);
                  if (p->state == CARD_DETECTED) {
                        if (thiscard) {
                              card = load_firmware(contr, thiscard);
                        } else {
                              fprintf(stderr,"ERROR: missing config entry for controller %d driver %s name %s\n",
                                    p->contr, p->driver, p->name);
                        }
                  }
                  free_contrprocinfo(&cpinfo);
            }
            mark_unfound(cards); 
            act = 0;
            cpinfo = load_contrprocinfo(&lastcontr);
            for (contr = 1; contr <= lastcontr; contr++) {
                  struct capicard *thiscard;
                  cpinfo = load_contrprocinfo(0);
                  p = find_contrprocinfo(cpinfo, contr);
                  thiscard = find_config(cards, p->driver);
                  if (cardname && cname[0]) {
                        if (strcmp(cname, p->name) != 0) {
                              free_contrprocinfo(&cpinfo);
                              continue;
                        }
                  }
                  if (p->state == CARD_DETECTED && thiscard) {
                        fprintf(stderr,"ERROR: failed to load firmware for controller %d driver %s name %s\n",
                                    p->contr, p->driver, p->name);
                        ret = 3;
                  }
                  free_contrprocinfo(&cpinfo);
            }
      }

      if (cardname && cname[0] == 0) {
            fprintf(stderr,"ERROR: card \"%s\"  not found\n", cardname);
            ret = 4;
      }

      if (!silent) {
            cpinfo = load_contrprocinfo(0);
            show_contrprocinfo(cpinfo, cardname ? cname: "");
            free_contrprocinfo(&cpinfo);
      }

      free_config(&cards);
      close(capifd);

      return ret;
}

/* ------------------------------------------------------------------- */

int main_stop(int unload, char *cardname, int number)
{
      struct capicard *cards, *card;
      struct contrprocinfo *cpinfo, *p;
      int contr, lastcontr;
      char *mp;
      int act;
      char cname[32];

      if (prestopcheck() < 0)
            return -1;

      cname[0] = 0;

      /* could not fail, tested by check_for_capi() */
      capifd = open(capidevname, O_RDWR);

      act = 0;
      cpinfo = load_contrprocinfo(&lastcontr);
      if (cardname) {
            for (contr = 1; contr <= lastcontr; contr++) {
                  cpinfo = load_contrprocinfo(0);
                  p = find_contrprocinfo(cpinfo, contr);
                  if (number == 0) {
                        if (strcmp(cardname, p->name) != 0) {
                              free_contrprocinfo(&cpinfo);
                              continue;
                        }
                  } else if (is_card_of_driver(cardname, p)) {
                        if (++act != number) {
                              free_contrprocinfo(&cpinfo);
                              continue;
                        }
                  } else {
                        free_contrprocinfo(&cpinfo);
                        continue;
                  }
                  strncpy(cname, p->name, sizeof(cname));
                  if (p && p->state != CARD_DETECTED)
                        reset_controller(contr);
                  free_contrprocinfo(&cpinfo);
            }
      } else {
            for (contr = lastcontr; contr > 0; contr--) {
                  cpinfo = load_contrprocinfo(0);
                  p = find_contrprocinfo(cpinfo, contr);
                  if (p && p->state != CARD_DETECTED)
                        reset_controller(contr);
                  free_contrprocinfo(&cpinfo);
            }
      }
      if (unload) {
            cpinfo = load_contrprocinfo(&lastcontr);
            for (contr = lastcontr; contr > 0; contr--) {
                  cpinfo = load_contrprocinfo(0);
                  p = find_contrprocinfo(cpinfo, contr);
                  if (p)
                        remove_controller(contr);
                  free_contrprocinfo(&cpinfo);
            }
      }

      if (unload && !cardname) {
            cards = load_config(configfilename);
            for (card = cards; card; card = card->next) {
                  if (driver_loaded(card->driver))
                        unload_driver(card->driver);
            }
            for (card = cards; card; card = card->next) {
                  if (driver_loaded(card->driver))
                        unload_driver(card->driver);
            }
      }

      if (!silent) {
            cpinfo = load_contrprocinfo(0);
            show_contrprocinfo(cpinfo, cardname ? cname: 0);
            free_contrprocinfo(&cpinfo);
      }
      close(capifd);

      if (unload && !cardname) {
            unload_module("capi");
            unload_module("capidrv");
            unload_module("kernelcapi");
            unload_module("capiutil");
            if ((mp = mounted("capifs")) != 0 && strcmp(mp, "/dev/capi") == 0)
                  system("umount /dev/capi");
            if (filesystem_available("capifs"))
                  unload_filesystem("capifs");
      }
      if (cardname && cname[0] == 0) {
            fprintf(stderr,"ERROR: card \"%s\"  not found\n", cardname);
            return 4;
      }
      return 0;
}

int main_show(void)
{
      struct capicard *cards;
      cards = load_config(configfilename);
      if (cards == 0) {
            fprintf(stderr,"ERROR: no cards configured in %s\n",
                        configfilename);
            return -1;
      }
      show_config(cards);
      return 0;
}

/* ------------------------------------------------------------------- */

int main_status(void)
{
      struct contrprocinfo *cpinfo;

      cpinfo = load_contrprocinfo(0);
      show_contrprocinfo(cpinfo, 0);
      free_contrprocinfo(&cpinfo);
      return 0;
}

/* ------------------------------------------------------------------- */

static void usage(void)
{
    fprintf(stderr, "Usage: capiinit [OPTION]\n");
    fprintf(stderr, "   or: capiinit [OPTION] start\n");
    fprintf(stderr, "       - load all modules and inititialize all cards\n");
    fprintf(stderr, "   or: capiinit [OPTION] stop\n");
    fprintf(stderr, "       - reset all cards and unload modules\n");
    fprintf(stderr, "   or: capiinit [OPTION] show\n");
    fprintf(stderr, "       - show current config\n");
    fprintf(stderr, "   or: capiinit [OPTION] status\n");
    fprintf(stderr, "       - show current status\n");
    fprintf(stderr, "   or: capiinit [OPTION] prepare\n");
    fprintf(stderr, "       - load all modules\n");
    fprintf(stderr, "   or: capiinit [OPTION] activate\n");
    fprintf(stderr, "       - inititialize all cards \n");
    fprintf(stderr, "   or: capiinit [OPTION] activate cardname\n");
    fprintf(stderr, "       - inititialize one cards (i.e.: c4-ec00) \n");
    fprintf(stderr, "   or: capiinit [OPTION] activate driver [cardnumber]\n");
    fprintf(stderr, "       - inititialize one card \n");
    fprintf(stderr, "   or: capiinit [OPTION] deactivate\n");
    fprintf(stderr, "       - reset all cards \n");
    fprintf(stderr, "   or: capiinit [OPTION] deactivate cardname\n");
    fprintf(stderr, "       - reset one card (i.e.: c4-ec00) \n");
    fprintf(stderr, "   or: capiinit [OPTION] deactivate driver [cardnumber]\n");
    fprintf(stderr, "       - reset one cards \n");
    fprintf(stderr, "   or: capiinit [OPTION] reload\n");
    fprintf(stderr, "       - reset all cards and initialize them again\n");
    fprintf(stderr, "Setup or unsetup CAPI2.0 Controllers\n");
    fprintf(stderr, "   -c, --config filename  (default %s)\n", configfilename);
    fprintf(stderr, "   -d, --debug            save patchvalues for debugging\n");
    fprintf(stderr, "   -s, --silent           don't show status\n");
}

int main(int ac, char *av[])
{
         int c;

         for (;;) {
            int option_index = 0;
            static struct option long_options[] = {
                  {"config", 1, 0, 'c'},
                  {"debug", 1, 0, 'd'},
                  {"silent", 1, 0, 's'},
                  {0, 0, 0, 0}
            };

            c = getopt_long (ac, av, "c:ds",
                        long_options, &option_index);
                  if (c == -1)
                        break;

            switch (c) {
                  case 0:
                        printf ("option %s",
                              long_options[option_index].name);
                        if (optarg)
                              printf (" with arg %s", optarg);
                        printf ("\n");
                        break;

                  case 'c':
                        configfilename = optarg;
                        break;
                  case 'd':
                        patchdebug = 1;
                        break;
                  case 's':
                        silent = 1;
                        break;
                  case '?':
                        usage();
                        return 1;
            }
      }

      if (optind == ac) {
            return main_start(1, 0, 0);
      } else if (optind+1 == ac) {
            if (strcmp(av[optind], "start") == 0) {
                  return main_start(1, 0, 0);
            } else if (strcmp(av[optind], "activate") == 0) {
                  return main_start(1, 0, 0);
            } else if (strcmp(av[optind], "prepare") == 0) {
                  return main_start(0, 0, 0);
            } else if (strcmp(av[optind], "stop") == 0) {
                  return main_stop(1, 0, 0);
            } else if (strcmp(av[optind], "deactivate") == 0) {
                  return main_stop(0, 0, 0);
            } else if (strcmp(av[optind], "show") == 0) {
                  return main_show();
            } else if (strcmp(av[optind], "status") == 0) {
                  return main_status();
            } else if (strcmp(av[optind], "reload") == 0) {
                  if (main_stop(0, 0, 0) == 0)
                     return main_start(1, 0, 0);
            }
      } else if (optind+2 == ac) {
            int number = strchr(av[optind+1], '-') == 0 ? 1 : 0;
            if (strcmp(av[optind], "activate") == 0)
                  return main_start(1, av[optind+1], number);
            else if (strcmp(av[optind], "deactivate") == 0)
                  return main_stop(0, av[optind+1], number);
      } else if (optind+3 == ac) {
            if (strcmp(av[optind], "activate") == 0)
                  return main_start(1, av[optind+1], atoi(av[optind+2]));
            else if (strcmp(av[optind], "deactivate") == 0)
                  return main_stop(0, av[optind+1], atoi(av[optind+2]));
      }
      usage();
      return 1;
}

Generated by  Doxygen 1.6.0   Back to index