Logo Search packages:      
Sourcecode: latd version File versions

latcp.cc

/******************************************************************************
    (c) 2000-2004 Patrick Caulfield                 patrick@debian.org
    (c) 2003 Dmitri Popov

    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
    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.
******************************************************************************/

// LAT Control Program (latcp)


#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <syslog.h>
#include <ctype.h>
#include <regex.h>
#include <stdlib.h>
#include <utmp.h>
#include <pwd.h>
#include <signal.h>
#include <limits.h>
#include <assert.h>

#include <list>
#include <queue>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <string>
#include <sstream>
#include <iostream>

#include "lat.h"
#include "latcp.h"
#include "utils.h"
#include "dn_endian.h"

static int latcp_socket;

static void make_upper(char *str);

int  read_reply(int fd, int &cmd, unsigned char *&cmdbuf, int &len);
bool send_msg(int fd, int cmd, char *buf, int len);
bool open_socket(bool);

// Command processing routines
void display(int argc, char *argv[]);
void add_service(int argc, char *argv[]);
void del_service(int argc, char *argv[]);
void set_multicast(int);
void set_retransmit(int);
void set_keepalive(int);
void set_responder(int onoff);
void shutdown();
void purge_services();
void start_latd(int argc, char *argv[]);
void set_rating(int argc, char *argv[]);
void set_ident(int argc, char *argv[]);
void set_server_groups(int argc, char *argv[]);
void set_user_groups(int argc, char *argv[]);
void set_node (char *);


// Misc utility routines
static void make_bitmap(char *bitmap, char *cmdline);


int usage(char *cmd)
{
    printf ("Usage: latcp      {option}\n");
    printf ("     where option is one of the following:\n");
    printf ("       -s [<latd args>]\n");
    printf ("       -h\n");
    printf ("       -A -a service [-i description] [-r rating] [-s] [-C command] [-u user] [-m max conn]\n");
    printf ("       -A -p tty -V learned_service [-R rem_port] [-H rem_node] [-Q] [-8]\n");
    printf ("       -D {-a service | -p tty}\n");
    printf ("       -C service command}\n");
    printf ("       -i description -a service\n");
    printf ("       -g list\n");
    printf ("       -G list\n");
    printf ("       -u list\n");
    printf ("       -U list\n");
    printf ("       -j\n");
    printf ("       -J\n");
    printf ("       -Y\n");
    printf ("       -x rating [-s] -a service\n");
    printf ("       -n node\n");
    printf ("       -r retransmit limit\n");
    printf ("       -m multicast timer (100ths/sec)\n");
    printf ("       -k keepalive timer (seconds)\n");
    printf ("       -d [ [-l [-v] [-n] ] ]\n");
    printf ("       -z \n");

    return 2;
}

int main(int argc, char *argv[])
{

// Parse the command.
// because the args vary so much for each command I just check argv[1]
// for the command switch and the command processors call getopt themselves

    if (argc == 1)
    {
      exit(usage(argv[0]));
    }

    if (argv[1][0] != '-')
    {
      exit(usage(argv[0]));
    }

    switch (argv[1][1])
    {
    case 'A':
      add_service(argc-1, &argv[1]);
      break;
    case 'D':
      del_service(argc-1, &argv[1]);
      break;
    case 'j':
      set_responder(1);
      break;
    case 'J':
      set_responder(0);
      break;
    case 'Y':
      purge_services();
      break;
    case 'n':
      set_node(argv[2]);
      break;
    case 'm':
      if (argv[2])
          set_multicast(atoi(argv[2]));
      else
          exit(usage(argv[0]));
      break;
    case 'r':
        if (argv[2])
            set_retransmit(atoi(argv[2]));
        else
            exit(usage(argv[0]));
        break;
    case 'k':
        if (argv[2])
            set_keepalive(atoi(argv[2]));
        else
            exit(usage(argv[0]));
        break;
    case 'd':
      display(argc-1, &argv[1]);
      break;
    case 'h':
      shutdown();
      break;
    case 's':
      start_latd(argc, argv);
      break;
    case 'x':
      set_rating(argc, argv);
      break;
    case 'i':
      set_ident(argc, argv);
      break;
    case 'z':
      printf("counters not yet done\n");
      break;
    case 'U':
      set_user_groups(argc, argv);
      break;
    case 'u':
      set_user_groups(argc, argv);
      break;
    case 'g':
      set_server_groups(argc, argv);
      break;
    case 'G':
      set_server_groups(argc, argv);
      break;
    default:
      exit(usage(argv[0]));
      break;
    }
}


// Display latd characteristics or learned services
void display(int argc, char *argv[])
{
    char verboseflag[1] = {'\0'};
    signed char opt;
    bool show_services = false;
    bool show_nodes = false;

    if (!open_socket(false)) return;

    while ((opt=getopt(argc,argv,"lvn")) != EOF)
    {
      switch(opt)
      {
      case 'l':
          show_services=true;
          break;

      case 'v':
          verboseflag[0] = 1;
          break;

      case 'n':
          show_nodes = true;
          break;

      default:
          fprintf(stderr, "only -v, -n or -l valid with -d flag\n");
          exit(2);
      }
    }

     if (show_nodes)
     {
      send_msg(latcp_socket, LATCP_SHOWNODES, verboseflag, 1);
         unsigned char *result;
         int len;
         int cmd;
         if (!read_reply(latcp_socket, cmd, result, len))
       {
             std::cout << result;

             delete[] result;
       }
         return;
     }

    if (show_services)
    {
      send_msg(latcp_socket, LATCP_SHOWSERVICE, verboseflag, 1);
    }
    else
    {
      send_msg(latcp_socket, LATCP_SHOWCHAR, verboseflag, 1);
    }

    unsigned char *result = NULL;
    int len;
    int cmd;

    if (!read_reply(latcp_socket, cmd, result, len))
    {
          std::cout << result;

          delete[] result;
    }
}


// Change the rating of a service
void set_rating(int argc, char *argv[])
{
    int new_rating = 0;
    bool static_rating = false;
    char service[256];
    signed char opt;

    if (!open_socket(false)) return;

    while ((opt=getopt(argc,argv,"x:sa:")) != EOF)
    {
      switch(opt)
      {
      case 'x':
          new_rating = atoi(optarg);
          break;

      case 's':
          static_rating = true;
          break;

      case 'a':
          strcpy(service, optarg);
          make_upper(service);
          break;

      default:
          fprintf(stderr, "only valid with -a and -x flags\n");
          exit(2);
      }
    }

    if (!new_rating)
    {
      fprintf(stderr, "Invalid rating\n");
      exit(2);
    }

    make_upper(service);

    char message[520];
    int ptr = 2;
    message[0] = (int)static_rating;
    message[1] = new_rating;
    add_string((unsigned char*)message, &ptr, (unsigned char*)service);
    send_msg(latcp_socket, LATCP_SETRATING, message, ptr);

    // Wait for ACK or error
    unsigned char *result = NULL;
    int len;
    int cmd;

    exit (read_reply(latcp_socket, cmd, result, len));

}


// Change the ident of a service
void set_ident(int argc, char *argv[])
{
    char service[256];
    char ident[256];
    signed char opt;

    if (!open_socket(false)) return;

    while ((opt=getopt(argc,argv,"i:a:")) != EOF)
    {
      switch(opt)
      {
      case 'a':
          strcpy(service, optarg);
          make_upper(service);
          break;
      case 'i':
          strcpy(ident, optarg);
          break;

      default:
          fprintf(stderr, "must have both -i and -a flags\n");
          exit(2);
      }
    }

    make_upper(service);

    char message[1024];
    int ptr = 0;
    add_string((unsigned char*)message, &ptr, (unsigned char*)service);
    add_string((unsigned char*)message, &ptr, (unsigned char*)ident);
    send_msg(latcp_socket, LATCP_SETIDENT, message, ptr);

    // Wait for ACK or error
    unsigned char *result = NULL;
    int len;
    int cmd;
    exit(read_reply(latcp_socket, cmd, result, len));
}


void set_server_groups(int argc, char *argv[])
{
    signed char opt;
    int  cmd;
    char groups[256];

    while ((opt=getopt(argc,argv,"G:g:")) != EOF)
    {
      switch(opt)
      {
      case 'G':
          cmd = LATCP_SETSERVERGROUPS;
          strcpy(groups, optarg);
          break;

      case 'g':
          cmd = LATCP_UNSETSERVERGROUPS;
          strcpy(groups, optarg);
          break;

      default:
          fprintf(stderr, "Just G or g please\n");
          exit(2);
      }
    }

    if (!open_socket(false)) return;

    char bitmap[32]; // 256 bits
    make_bitmap(bitmap, groups);

    send_msg(latcp_socket, cmd, bitmap, 32);

    // Wait for ACK or error
    unsigned char *result = NULL;
    int len;
    exit(read_reply(latcp_socket, cmd, result, len));

}

void set_user_groups(int argc, char *argv[])
{
    signed char opt;
    int  cmd;
    char groups[256];

    while ((opt=getopt(argc,argv,"u:U:")) != EOF)
    {
      switch(opt)
      {
      case 'U':
          cmd = LATCP_SETUSERGROUPS;
          strcpy(groups, optarg);
          break;

      case 'u':
          cmd = LATCP_UNSETUSERGROUPS;
          strcpy(groups, optarg);
          break;

      default:
          fprintf(stderr, "Just U or u please\n");
          exit(2);
      }
    }

    if (!open_socket(false)) return;

    char bitmap[32]; // 256 bits
    make_bitmap(bitmap, groups);

    send_msg(latcp_socket, cmd, bitmap, 32);

    // Wait for ACK or error
    unsigned char *result = NULL;
    int len;
    exit(read_reply(latcp_socket, cmd, result, len));

}

// Enable/Disable the service responder
void set_responder(int onoff)
{
    if (!open_socket(false)) return;

    char flag[1];
    flag[0] = onoff;
    send_msg(latcp_socket, LATCP_SETRESPONDER, flag, 1);
}

// Shutdown latd
void shutdown()
{
    if (!open_socket(false)) return;

    char dummy[1];
    send_msg(latcp_socket, LATCP_SHUTDOWN, dummy, 0);
}

// Purge learned services
void purge_services()
{
    if (!open_socket(false)) return;

    char dummy[1];
    send_msg(latcp_socket, LATCP_PURGE, dummy, 0);
}

void set_multicast(int newtime)
{
    if (newtime < 10 || newtime > 180)
    {
      fprintf(stderr, "invalid multicast time\n");
      return;
    }
    if (!open_socket(false)) return;

    send_msg(latcp_socket, LATCP_SETMULTICAST, (char *)&newtime, sizeof(int));
}

void set_retransmit(int newlim)
{
    if (newlim < 4 || newlim > 120)
    {
        fprintf(stderr, "invalid retransmit limit\n");
        return;
    }
    if (!open_socket(false)) return;

    send_msg(latcp_socket, LATCP_SETRETRANS, (char *)&newlim, sizeof(int));
}

void set_keepalive(int newtime)
{
    if (newtime < 10 || newtime > 180)
    {
      fprintf(stderr, "invalid keepalive timer\n");
      return;
    }
    if (!open_socket(false)) return;

    send_msg(latcp_socket, LATCP_SETKEEPALIVE, (char *)&newtime, sizeof(int));
}

void set_node(char *name)
{
    if (!open_socket(false)) return;

    make_upper(name);

    char message[520];
    int ptr = 0;
    add_string((unsigned char*)message, &ptr, (unsigned char*)name);

    send_msg(latcp_socket, LATCP_SETNODENAME, message, ptr);
    return;
}

void add_service(int argc, char *argv[])
{
    char name[255] = {'\0'};
    char ident[255] = {'\0'};
    char remport[255] = {'\0'};
    char localport[255] = {'\0'};
    char remnode[255] = {'\0'};
    char remservice[255] = {'\0'};
    char password[255] = {'\0'};
    char command[1024] = {'\0'};
    signed char opt;
    bool got_service=false;
    bool got_port=false;
    bool static_rating=false;
    int  rating = 0;
    int  queued = 0;
    int  clean = 0;
    int  max_connections = 0;
    uid_t target_uid = 0;
    gid_t target_gid = 0;
    struct passwd *target_user;

    opterr = 0;
    while ((opt=getopt(argc,argv,"a:i:p:H:R:V:r:w:sQ8C:m:u:")) != EOF)
    {
      switch(opt)
      {
      case 'a':
          got_service=true;
          strcpy(name, optarg);
          make_upper(name);
          break;

      case 'i':
          got_service=true;
          strcpy(ident, optarg);
          break;

      case 'w':
          strcpy(password, optarg);
          break;

      case 'p':
          got_port=true;
          strcpy(localport, optarg);
          if (strncmp(localport, LAT_DIRECTORY, strlen(LAT_DIRECTORY)) != 0)
          {
            fprintf(stderr, "Local port name must start " LAT_DIRECTORY "\n");
            return;
          }
          break;

      case 'H':
          got_port=true;
          strcpy(remnode, optarg);
          make_upper(remnode);
          break;

      case 'R':
          got_port=true;
          strcpy(remport, optarg);
          make_upper(remport);
          break;

      case 'V':
          got_port=true;
          strcpy(remservice, optarg);
          make_upper(remservice);
          break;

      case 'Q':
          got_port=true;
          queued = 1;
          break;

      case 's':
          static_rating = true;
          break;

      case '8':
          clean = true;
          break;

      case 'C':
          strcpy(command, optarg);
          break;

      case 'u':
          target_user = getpwnam(optarg);
          if (target_user == NULL)
          {
            fprintf(stderr, "Unknown username '%s'\n", optarg);
            exit(99);
          }
          target_uid = target_user->pw_uid;
          target_gid = target_user->pw_gid;
          break;

      case 'm':
          max_connections = atoi(optarg);
          break;

      case 'r':
          rating = atoi(optarg);
          break;

      default:
          fprintf(stderr, "No more service switches defined yet\n");
          exit(2);
      }
    }

    if (!open_socket(false)) return;

    // Variables for ACK message
    unsigned char *result = NULL;
    int len;
    int cmd;

    if (got_service)
    {
      if (name[0] == '\0')
      {
          fprintf(stderr, "No name for new service\n");
          exit(2);
      }

      char message[520];
      int ptr = 2;
      message[0] = (int)static_rating;
      message[1] = rating;
      add_string((unsigned char*)message, &ptr, (unsigned char*)name);
      add_string((unsigned char*)message, &ptr, (unsigned char*)ident);
      message[ptr++] = max_connections;
      memcpy(message+ptr, &target_uid, sizeof(uid_t)); ptr += sizeof(uid_t);
      memcpy(message+ptr, &target_gid, sizeof(uid_t)); ptr += sizeof(gid_t);
      add_string((unsigned char*)message, &ptr, (unsigned char*)command);

      send_msg(latcp_socket, LATCP_ADDSERVICE, message, ptr);

      // Wait for ACK or error
      exit(read_reply(latcp_socket, cmd, result, len));
    }

    if (got_port)
    {
      char message[520];
      int ptr = 0;
      add_string((unsigned char*)message, &ptr, (unsigned char*)remservice);
      add_string((unsigned char*)message, &ptr, (unsigned char*)remport);
      add_string((unsigned char*)message, &ptr, (unsigned char*)localport);
      add_string((unsigned char*)message, &ptr, (unsigned char*)remnode);
      message[ptr++] = queued;
      message[ptr++] = clean;
      add_string((unsigned char*)message, &ptr, (unsigned char*)password);
      send_msg(latcp_socket, LATCP_ADDPORT, message, ptr);

      // Wait for ACK or error
      exit(read_reply(latcp_socket, cmd, result, len));
    }

    fprintf(stderr, "Sorry, did you want me to do something??\n");
}

void del_service(int argc, char *argv[])
{
    char name[255] = {'\0'};
    signed char opt;
    bool got_service = false;
    bool got_port = false;
    opterr = 0;

    while ((opt=getopt(argc,argv,"a:p:")) != EOF)
    {
      switch(opt)
      {
      case 'a':
          got_service = true;
          strcpy(name, optarg);
          make_upper(name);
          break;

      case 'p':
          got_port = true;
          strcpy(name, optarg);
          break;

      default:
          fprintf(stderr, "No more service switches defined yet\n");
          exit(2);
      }
    }

    if ((got_port && got_service) ||
      (!got_port && !got_service))
    {
      fprintf(stderr, "Either -a or -p can be specified but not both\n");
      return;
    }


    if (!open_socket(false)) return;

    char message[520];
    int ptr = 0;
    add_string((unsigned char*)message, &ptr, (unsigned char*)name);
    if (got_service)
      send_msg(latcp_socket, LATCP_REMSERVICE, message, ptr);
    else
      send_msg(latcp_socket, LATCP_REMPORT, message, ptr);

    unsigned char *result = NULL;
    int len;
    int cmd;
    exit(read_reply(latcp_socket, cmd, result, len));
}

// Start latd & run startup script.
void start_latd(int argc, char *argv[])
{
    if (getuid() != 0)
    {
      fprintf(stderr, "You must be root to start latd\n");
      return;
    }

    // If we can connect to LATD than it's already running
    if (open_socket(true))
    {
      fprintf(stderr, "LAT is already running\n");
      return;
    }

    // Look for latd in well-known places
    struct stat st;
    char *latd_bin = NULL;
    char *latd_path = NULL;

    // Look for latd in the same place as latcp
    char *name = (char *)malloc(strlen(argv[0])+1);
    char *path = (char *)malloc(strlen(argv[0])+1);
    strcpy(name, argv[0]);

    char *slash = rindex(name, '/');
    if (slash)
    {
      *slash='\0';
      strcpy(path, name);
      strcat(name, "/latd");
      if (!stat(name, &st))
      {
          latd_bin = name;
          latd_path = path;
      }
    }
    // Otherwise look in some well-known places
    else if (!stat("/usr/sbin/latd", &st))
    {
      latd_bin = "/usr/sbin/latd";
      latd_path = "/usr/sbin";
    }
    else if (!stat("/usr/local/sbin/latd", &st))
    {
      latd_bin = "/usr/local/sbin/latd";
      latd_path = "/usr/local/sbin";
    }

    // Did we find it?
    if (latd_bin)
    {
      char *newargv[argc+1];
      char *newenv[4];
      int   i;
      char  latcp_bin[PATH_MAX];
      char  latcp_env[PATH_MAX+7];

// This is VERY Linux specific and needs /proc mounted.
// we get the full path of the current executable by doing a readlink.
// /proc/<pid>/exe

#ifdef __linux__
      char  latcp_proc[PATH_MAX];

      sprintf(latcp_proc, "/proc/%d/exe", getpid());
      if ( (i=readlink(latcp_proc, latcp_bin, sizeof(latcp_bin))) == -1)
      {
          fprintf(stderr, "readlink in /proc failed. Make sure the the proc filesystem is mounted on /proc\n");
          exit(2);
      }
#endif
      sprintf(latcp_env, "LATCP=%s", latcp_bin);

      newargv[0] = latd_bin;
      newargv[1] = NULL;
      newenv[0] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin";
      newenv[1] = "LATCP_STARTED=true"; // Tell latd it was started by us.
      newenv[2] = latcp_env;
      newenv[3] = NULL;

      switch(fork())
      {
      case 1: //Error
          perror("fork failed");
          return;
      case 0: // Child
          // Start latd with our args (after the "-s")
          for (i=2; i<argc; i++)
            newargv[i-1] = argv[i];
          newargv[i-1] = NULL;

          execve(latd_bin, newargv, newenv);
          perror("exec of latd failed");
          break;

      default: //Parent
          {
            // Wait for latd to start up
            int count = 0;
            while (!open_socket(true) && count < 10)
            {
                sleep(1);
                count++;
            }
            if (count >= 10)
            {
                fprintf(stderr, "latd did not start\n");
                exit(2);
            }


            // Run startup script if there is one.
            if (!stat("/etc/latd.conf", &st))
            {
                pid_t shell_pid;
                switch ( (shell_pid=fork()) )
                {
                case 0: // Child
                  newargv[0] = "/bin/sh";
                  newargv[1] = "/etc/latd.conf";
                  newargv[2] = NULL;
                  execve("/bin/sh", newargv, newenv);
                  perror("exec of /bin/sh failed");
                  exit(0);

                case -1:
                  perror("Fork failed");
                  exit(0);

                default: // Parent. Wait for child to finish
                  waitpid(shell_pid, NULL, 0);
                }
            }
            // OK, latd has started and we have run the startup script.
            // Now "unlock" latd. ie tell it we have finished initialisation
            char dummy[1];
            send_msg(latcp_socket, LATCP_UNLOCK, dummy, 0);
          }
          break;
      }
    }
    else
    {
      fprintf(stderr, "cannot find latd\n");
      return;
    }
}


bool send_msg(int fd, int cmd, char *buf, int len)
{
    unsigned char outhead[3];

    outhead[0] = cmd;
    outhead[1] = len/256;
    outhead[2] = len%256;
    if (write(fd, outhead, 3) != 3) return false;
    if (write(fd, buf, len) != len) return false;

    return true;
}


// Return 0 for success and -1 for failure
int read_reply(int fd, int &cmd, unsigned char *&cmdbuf, int &len)
{
    unsigned char head[3];

    // Get the message header (cmd & length)
    if (read(fd, head, sizeof(head)) != 3)
      return -1; // Bad header

    len = head[1] * 256 + head[2];
    cmd = head[0];
    cmdbuf = new unsigned char[len];
    if (cmdbuf == NULL)
      return -1;

    // Read the message buffer
    if (read(fd, cmdbuf, len) != len)
    {
      return -1; // Bad message
    }

    if (cmd == LATCP_ERRORMSG)
    {
      fprintf(stderr, "%s\n", cmdbuf);
      return -1;
    }

    return 0;
}

bool open_socket(bool quiet)
{
    struct sockaddr_un sockaddr;

    latcp_socket = socket(PF_UNIX, SOCK_STREAM, 0);
    if (latcp_socket == -1)
    {
      if (!quiet) perror("Can't create socket");
      return false; /* arggh ! */
    }

    strcpy(sockaddr.sun_path, LATCP_SOCKNAME);
    sockaddr.sun_family = AF_UNIX;
    if (connect(latcp_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr)))
    {
      if (!quiet) perror("Can't connect to latd");
      close(latcp_socket);
      return false;
    }

    unsigned char *result = NULL;
    int len;
    int cmd;

    // Send our version
    send_msg(latcp_socket, LATCP_VERSION, VERSION, strlen(VERSION)+1);

    if (!read_reply(latcp_socket, cmd, result, len)) // Read version number back
      delete[] result;

    return true;
}

static void make_upper(char *str)
{
    unsigned int i;

    for (i=0; i<strlen(str); i++)
    {
      str[i] = toupper(str[i]);
    }
}

static inline void set_in_bitmap(char *bits, int entry)
{

    if (entry < 256)
    {
      unsigned int  intnum;
      unsigned int  bitnum;

      intnum = entry / 8;
      bitnum = entry % 8;
      bits[intnum] |= 1<<bitnum;
    }
}

static void make_bitmap(char *bitmap, char *cmdline)
{
    int   firstnum;
    int   secondnum;
    int   i;
    bool  finished = false;
    char  delimchar;
    char* delimiter;

    memset(bitmap, 0, 32);
    delimiter = strpbrk(cmdline, ",-");

    do
    {
      if (delimiter == NULL)
      {
          delimchar = ',';
      }
      else
      {
          delimchar = delimiter[0];
          delimiter[0] = '\0';
      }
      firstnum = atoi(cmdline);
      if (delimiter != NULL) delimiter[0] = delimchar;

      /* Found a comma -- mark the number preceding it as read */
      if ((delimchar == ',') || (delimiter == NULL))
      {
          set_in_bitmap(bitmap, firstnum);
      }

      /* Found a hyphen -- mark the range as read */
      if (delimchar == '-')
      {
          cmdline = delimiter+1;
          delimiter = strpbrk(cmdline, ",");

          if (delimiter != NULL)
          {
            delimchar = delimiter[0];
            delimiter[0] = '\0';
          }
          secondnum = atoi(cmdline);
          if (delimiter != NULL) delimiter[0] = delimchar;

          for (i=firstnum; i<=secondnum; i++)
          {
            set_in_bitmap(bitmap, i);
          }
      }
      if (delimiter == NULL) finished = true;

      cmdline = delimiter+1;
      if (delimiter != NULL) delimiter = strpbrk(cmdline, ",-");
    } while (!finished);
}

Generated by  Doxygen 1.6.0   Back to index