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

vboxd.c

/*
** $Id: vboxd.c,v 1.5 1998/04/28 08:34:52 paul Exp $
**
** Copyright (C) 1996, 1997 Michael 'Ghandi' Herold
*/

#include "config.h"

#if TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#   if HAVE_SYS_TIME_H
#      include <sys/time.h>
#   else
#      include <time.h>
#   endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <fnmatch.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
#include <getopt.h>
#include <utime.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "vboxd.h"
#include "libvbox.h"
#include "streamio.h"

/** Variables *************************************************************/

static streamio_t *accesslist = NULL;
static char       *vbasename  = NULL;

static char *client_hostaddr    = NULL;
static char *client_hostname    = NULL;
static char *client_user        = NULL;
static char *client_spool       = NULL;
static char *client_home        = NULL;
static char *server_vboxdrc     = NULL;
static int   client_access      = VBOXD_ACC_NOTHING;    /* Default no access */
static int   client_1st_timeout = 30;
static int   client_2nd_timeout = 600;

/** Prototypes ************************************************************/

static void leave_program(int);
static void start_connection(void);
static void message(char *, ...);
static int  wildmat(char *, char *);
static int  check_client_access_login(char *, char *, char *, char *);
static int  check_client_access_start(char *, char *);
static int  get_next_command(char *, int, int);
static void handle_client_input(void);
static void handle_commands(char *);
static void usage(void);
static void version(void);
static void exit_on_signal(int);

/** Server prototypes *****************************************************/

static void srv_help(int, char **);
static void srv_quit(int, char **);
static void srv_list(int, char **);
static void srv_noop(int, char **);
static void srv_count(int, char **);
static void srv_login(int, char **);
static void srv_header(int, char **);
static void srv_message(int, char **);
static void srv_toggle(int, char **);
static void srv_delete(int, char **);
static void srv_statusctrl(int, char **);
static void srv_createctrl(int, char **);
static void srv_removectrl(int, char **);

/** Structures ************************************************************/

static struct servercmds commands[] =
{
      { "help"      , srv_help       },
      { "quit"      , srv_quit       },
      { "list"      , srv_list       },
      { "noop"      , srv_noop       },
      { "count"     , srv_count      },
   { "login"     , srv_login      },
      { "header"    , srv_header     },
      { "message"   , srv_message    },
      { "toggle"    , srv_toggle     },
      { "delete"    , srv_delete     },
      { "statusctrl", srv_statusctrl },
      { "createctrl", srv_createctrl },
      { "removectrl", srv_removectrl },
      { NULL        , NULL           }
};

static struct option arguments[] =
{
      { "version"       , no_argument                 , NULL, 'v' },
      { "help"                , no_argument                 , NULL, 'h' },
      { "timeout"       , required_argument     , NULL, 't' },
      { "file"       , required_argument  , NULL, 'f' },
      { NULL                  , 0                                 , NULL, 0   }
};

/**************************************************************************/
/** The magic main...                                                    **/
/**************************************************************************/

int main(int argc, char **argv)
{
      int opts;

      client_hostaddr    = NULL;
      client_hostname    = NULL;
      client_user        = NULL;
      client_spool       = NULL;
      client_1st_timeout = 20;
      client_2nd_timeout = 600;
      client_access      = VBOXD_ACC_NOTHING;
      server_vboxdrc     = VBOXDRC;

      if (!(vbasename = rindex(argv[0], '/')))
            vbasename = argv[0];
      else
            vbasename++;

      while ((opts = getopt_long(argc, argv, "vhf:t:", arguments, (int *)0)) != EOF)
      {
            switch (opts)
            {
                  case 't':
                        client_2nd_timeout = xstrtol(optarg, 600);
                        break;

                  case 'f':
                        server_vboxdrc = optarg;
                        break;

                  case 'v':
                        version();
                        break;

                  case 'h':
                  default:
                        usage();
                        break;
            }
      }

      /*
       * Install signal handlers.
       */

      signal(SIGPIPE, SIG_IGN);
      signal(SIGINT , exit_on_signal);
      signal(SIGHUP , exit_on_signal);
      signal(SIGTERM, exit_on_signal);

      openlog("vboxd", LOG_CONS|LOG_PID, LOG_DAEMON); 

      /*
       * Read the access list into memory. If we can't get it, we exit with
       * error.
       */

      if (!(accesslist = streamio_open(server_vboxdrc)))
      {
            syslog(LOG_ERR, "can't read access list (%s).", strerror(errno));

            message("%s Can't read access list (%s). Goodbye!\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));

            leave_program(1);
      }

      /*
       * Get remote host information and check if the remote host is in the
       * access list (no user or password check is done now).
       */

      start_connection();

      message("%s vbox message server %s (%s) is ready (timeouts %d/%d secs).\r\n", VBOXD_VAL_SERVEROK, VERSION, VERDATE, client_1st_timeout, client_2nd_timeout);

      /*
       * Handle the incomming commands.
       */

      handle_client_input();

      leave_program(0);
      return 0;
}

/**************************************************************************/
/** leave_program(): Frees all resources and exist.                      **/
/**************************************************************************/

static void leave_program(int status)
{
      syslog(LOG_INFO, "connection closed.");

      if (client_hostaddr) free(client_hostaddr);
      if (client_hostname) free(client_hostname);
      if (client_spool   ) free(client_spool   );
      if (client_user    ) free(client_user    );

      streamio_close(accesslist);

      message("%s .\r\n", VBOXD_VAL_SERVERQUIT);
      fflush(stdout);

      closelog();

      exit(status);
}

/**************************************************************************/
/** version(): Prints package version                                    **/
/**************************************************************************/

static void version(void)
{
      fprintf(stderr, "\n");
      fprintf(stderr, "%s version %s (%s)\n", vbasename, VERSION, VERDATE);
      fprintf(stderr, "\n");

      exit(1);
}

/**************************************************************************/
/** usage(): Prints usage message.                                       **/
/**************************************************************************/

static void usage(void)
{
      fprintf(stderr, "\n");
      fprintf(stderr, "Usage: %s [ OPTION ] [ ... ]\n", vbasename);
      fprintf(stderr, "\n");
      fprintf(stderr, "-f, --file FILE      Overwrites \"%s\".\n", VBOXDRC);
   fprintf(stderr, "-t, --timeout SECS   Close connection after SECS idle time (default 600).\n");
      fprintf(stderr, "-v, --version        Displays program version.\n");
      fprintf(stderr, "-h, --help           Displays this message.\n");
      fprintf(stderr, "\n");

      exit(1);
}

/**************************************************************************/
/** exit_on_signal(): Exit program on signal.                            **/
/**************************************************************************/

static void exit_on_signal(int s)
{
      syslog(LOG_INFO, "server dies on signal %d.", s);

      message("%s Server dies on signal %d.\r\n", VBOXD_VAL_TEMPERROR, s);

      leave_program(s);
}

/**************************************************************************/
/** handle_client_input(): Handle clients input.                         **/
/**************************************************************************/

static void handle_client_input(void)
{
      char line[VBOXD_LEN_CMDLINE + 1];
      int  rc;

      while (TRUE)
      {
            fflush(stdout);

            rc = get_next_command(line, VBOXD_LEN_CMDLINE, client_1st_timeout);

            switch (rc)
            {
                  case VBOXD_ERR_TIMEOUT:
                        message("%s Timeout after %d seconds, closing connection.\r\n", VBOXD_VAL_TEMPERROR, client_1st_timeout);
                        leave_program(1);
                        break;

                  case VBOXD_ERR_TOOLONG:
                        syslog(LOG_WARNING, "line too long.");
                        message("%s Line too long.\r\n", VBOXD_VAL_BADCOMMAND);
                        break;

                  case VBOXD_ERR_EOF:
                        syslog(LOG_WARNING, "receive EOF - pipe broken.");
                        message("%s Receive EOF - I think the pipe is broken.\r\n", VBOXD_VAL_TEMPERROR);
                        leave_program(1);
                        break;

                  case VBOXD_ERR_OK:
                        handle_commands(line);
                        break;
            }
      }
}

/**************************************************************************/
/** handle_commands(): Handles incomming commands.                       **/
/**************************************************************************/

static void handle_commands(char *line)
{
      char *av[VBOXD_LEN_ARGLIST];
      int   ac;
      char *arg;
      int   cc;

      /*
       * Parse command line and fill the internal argument structure. The
       * first argument is allways the command.
       */

      av[0] = strtok(line, "\t ");

      if (!av[0])
      {
            message("%s No command given.\r\n", VBOXD_VAL_BADCOMMAND);

            return;
      }

      ac = 1;
      cc = 0;

      while ((arg = strtok(NULL, "\t ")) && (ac < VBOXD_LEN_ARGLIST))
      {
            av[ac++] = arg;
      }

      /*
       * Check if the command is in the command list. If found we call the
       * command with the internal argument list as parameters.
       */

      while (commands[cc].name)
      {
            if (strcasecmp(commands[cc].name, av[0]) == 0)
            {
                  if (commands[cc].func)
                  {
                        client_1st_timeout = client_2nd_timeout;

                        commands[cc].func(ac, av);

                        return;
                  }
            }

            cc++;
      }

      /*
       * If the command was not found in the command list we print a error
       * message (nothing else is done).
       */

      syslog(LOG_INFO, "unknown command \"%s\" requested.", av[0]);

      message("%s Unknown (or not yet implemented) command \"%s\".\r\n", VBOXD_VAL_BADCOMMAND, av[0]);
}

/**************************************************************************/
/** get_next_command(): Wait for clients next command.                   **/
/**************************************************************************/

static int get_next_command(char *line, int linelen, int timeout)
{
      struct timeval timeval;
      fd_set         rmask;
      char          *stop;
      int            p;
      int            c;
      int            rc;

      *line = '\0';

      p = 0;
      c = 0;

      while (TRUE)
      {
            VBOX_ONE_FD_MASK(&rmask, STDIN_FILENO);

            timeval.tv_sec  = timeout;
            timeval.tv_usec = 0;

            rc = select((STDIN_FILENO + 1), &rmask, NULL, NULL, &timeval);

            if (rc < 0)
            {
                  if (errno == EINTR) continue;

                  syslog(LOG_ERR, "can't select (%s).", strerror(errno));

                  message("%s can't select (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));

                  return(VBOXD_ERR_TIMEOUT);
            }

            if ((rc == 0) || (!FD_ISSET(STDIN_FILENO, &rmask))) return(VBOXD_ERR_TIMEOUT);

            rc = read(STDIN_FILENO, &c, 1);

            if (rc == 0) return(VBOXD_ERR_EOF);

            if (rc < 0)
            {
                  syslog(LOG_ERR, "can't read (%s).", strerror(errno));

         message("%s can't read (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));

                  return(VBOXD_ERR_TIMEOUT);
            }

            if (c == '\n')
            {
                  if ((stop = rindex(line, '\r'))) *stop = '\0';

                  return(VBOXD_ERR_OK);
            }

            line[p + 0] = c;
            line[p + 1] = '\0';

            if (p++ >= linelen) return(VBOXD_ERR_TOOLONG);
      }

      return(VBOXD_ERR_TIMEOUT);
}

/**************************************************************************/
/** start_connection(): Starts the connection to the client.             **/
/**************************************************************************/

static void start_connection(void)
{
      struct hostent     *hostptr;
      struct sockaddr_in  sockptr;
      int                 socklen;

      socklen = sizeof(sockptr);

      if (getpeername(STDIN_FILENO, (struct sockaddr *)&sockptr, &socklen) < 0)
      {
            syslog(LOG_ERR, "can't get peername (%s).", strerror(errno));

            message("%s I can't get your name (%s). Goodbye!\r\n", VBOXD_VAL_ACCESSDENIED, strerror(errno));

            leave_program(1);
      }

      if (sockptr.sin_family != AF_INET)
      {
            syslog(LOG_ERR, "bad address family.");

            message("%s Bad address family. Goodbye!\r\n", VBOXD_VAL_ACCESSDENIED);

            leave_program(1);
      }

      client_hostaddr = strdup(inet_ntoa(sockptr.sin_addr));

      hostptr = gethostbyaddr((char *)&sockptr.sin_addr, sizeof(sockptr.sin_addr), AF_INET);

      if (!hostptr)
            client_hostname = strdup(inet_ntoa(sockptr.sin_addr));
      else
            client_hostname = strdup(hostptr->h_name);

      if ((!client_hostaddr) || (!client_hostname))
      {
            syslog(LOG_ERR, "out of memory (%s).", strerror(errno));

            message("%s Out of memory (%s). Goodbye!\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));

            leave_program(1);
      }

      client_access = VBOXD_ACC_NOTHING;

      if (!check_client_access_start(client_hostname, client_hostaddr))
      {
            syslog(LOG_INFO, "host %s not in access list.", client_hostname);

            message("%s You are not in my access list. Goodbye!\r\n", VBOXD_VAL_ACCESSDENIED);

            leave_program(1);
      }
}

/**************************************************************************/
/** check_client_access_start(): Checks if the client can login as       **/
/**                              unknown user (server startup).          **/
/**************************************************************************/

static int check_client_access_start(char *name, char *addr)
{
   char  line[VBOXD_LEN_ACCESSLINE + 1];
   char *list[3];
   char *p;
   int   i;

   accesslist = streamio_reopen(accesslist);

   while (streamio_gets(line, VBOXD_LEN_ACCESSLINE, accesslist))
   {
            if ((line[0] != 'L') || (line[1] != ':')) continue;

      /*
       * Split the current line into seperate fields.
       */

      for (list[0] = line, i = 0, p = line; ((*p) && (i < 3)); p++)
      {
         if (*p == ':')
         {
            *p = '\0';

            list[++i] = (p + 1);
         }
      }

            if (i != 2) continue;

            /*
             * Check if the hostname or the hosts ip address matchs the current
             * pattern.
             */

            if ((name) || (addr))
            {
                  if (!wildmat(name, list[1]))
                  {
                        if (!wildmat(addr, list[1])) continue;
                  }
            }

            /*
             * Check if the client has access to count new messages. If true,
             * the "login" is correct.
             */

            if ((strcasecmp(list[2], "yes")) == 0 || (strcasecmp(list[2], "y") == 0))
            {
                  client_access |= VBOXD_ACC_COUNT;

                  returnok();
            }
      }

      returnerror();
}

/**************************************************************************/
/** check_client_access_login(): Checks if the client can login as user. **/
/**************************************************************************/

static int check_client_access_login(char *name, char *addr, char *user, char *pass)
{
      char  temp[PATH_MAX + 1];
      char  line[VBOXD_LEN_ACCESSLINE + 1];
      char *list[7];
      char *p;
      int   i;

      accesslist = streamio_reopen(accesslist);

      if (client_spool) free(client_spool);
      if (client_user ) free(client_user );

      client_spool  = NULL;
      client_home   = NULL;
      client_user   = NULL;
      client_access = VBOXD_ACC_COUNT;

      while (streamio_gets(line, VBOXD_LEN_ACCESSLINE, accesslist))
      {
            /*
             * Split the current line into seperate fields.
             */

            if ((line[0] != 'A') || (line[1] != ':')) continue;

            for (list[0] = line, i = 0, p = line; ((*p) && (i < 6)); p++)
            {
                  if (*p == ':')
                  {
                        *p = '\0';

                        list[++i] = (p + 1);
                  }
            }

            if (i != 6) continue;

            /*
             * Check if the hostname or the hosts ip address matchs the current
             * pattern.
             */

            if (!wildmat(name, list[1]))
            {
                  if (!wildmat(addr, list[1])) continue;
            }

            /*
             * Check if the user and the password are correct. If the password
             * field contains '!' or '-' user is unable to login.
             */

            if (strcmp(user, list[3]) != 0) continue;

            if (*list[4])
            {
                  if (!pass) continue;

                  if (strcmp(list[4], "-" ) == 0) continue;
                  if (strcmp(list[4], "!" ) == 0) continue;
                  if (strcmp(list[4], pass) != 0) continue;
            }

            /*
             * Save name and spool directory. If memory allocation fails we return
             * an error so the complete check will fail!
             */

            client_user  = strdup(list[3]);
            client_home  = strdup(list[5]);
            client_spool = strdup(list[6]);

            if ((client_home) && (client_spool))
            {
                  if (*client_spool != '/')
                  {
                        xstrncpy(temp, client_home , PATH_MAX);
                        xstrncat(temp, "/"         , PATH_MAX);
                        xstrncat(temp, client_spool, PATH_MAX);

                        free(client_spool);

                        client_spool = strdup(temp);
                  }
            }

            if ((!client_user) || (!client_spool) || (!client_home))
            {
                  if (client_spool) free(client_spool);
                  if (client_user ) free(client_user );
                  if (client_home ) free(client_home );

                  returnerror();
            }

            /*
             * Check users access: '*' for all, 'R' for read access and 'W' for
             * write access.
             */

            if (strcmp(list[2], "*") == 0)
            {
                  client_access = (VBOXD_ACC_COUNT|VBOXD_ACC_READ|VBOXD_ACC_WRITE);
            }

            if (index(list[2], 'R')) client_access |= VBOXD_ACC_READ;
            if (index(list[2], 'W')) client_access |= VBOXD_ACC_WRITE;

            returnok();
      }

      returnerror();
}

/**************************************************************************/
/** wildmat(): Matchs pattern.                                           **/
/**************************************************************************/

static int wildmat(char *text, char *pattern)
{
      if ((text) && (pattern))
      {
            if (fnmatch(pattern, text, FNM_PERIOD) == 0) returnok();
      }

      returnerror();
}

/**************************************************************************/
/** message(): Prints message to stdout.                                 **/
/**************************************************************************/

static void message(char *fmt, ...)
{
      va_list arg;

      va_start(arg, fmt);
      vfprintf(stdout, fmt, arg);
   va_end(arg);
}

/**************************************************************************/
/**                                                                      **/
/**                                                                      **/
/**                     S E R V E R   C O M M A N D S                    **/
/**                                                                      **/
/**                                                                      **/
/**************************************************************************/
/** login      <username> [password]                                     **/
/** delete     <message>                                                 **/
/** toggle     <message>                                                 **/
/** message    <message>                                                 **/
/** header     <message>                                                 **/
/** statusctrl <control>                                                 **/
/** count                                                                **/
/** noop                                                                 **/
/** list                                                                 **/
/** help                                                                 **/
/** quit                                                                 **/
/**************************************************************************/

/**************************************************************************/
/** srv_noop(): Does nothing.                                   [server] **/
/**************************************************************************/

static void srv_noop(int argc, char **argv)
{
}

/**************************************************************************/
/** srv_header(): Gets a vbox message header.                   [server] **/
/**************************************************************************/

static void srv_header(int argc, char **argv)
{
      vaheader_t  header;
      int         fd;
      char       *msgname;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_READ)))
      {
            message("%s Access denied (no read access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <message>\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;
      
      if ((fd = open(msgname, O_RDONLY)) != -1)
      {
            if (header_get(fd, &header))
            {
                  message("%s %d\r\n", VBOXD_VAL_HEADER, sizeof(vaheader_t));
                  pullmsg(stdout);

                  write(STDOUT_FILENO, (char *)&header, sizeof(vaheader_t));

                  message("%s .\r\n", VBOXD_VAL_HEADER);
                  pullmsg(stdout);
            }
            else message("%s Not a vbox message.\r\n", VBOXD_VAL_BADMESSAGE);
      }
      else message("%s Can't open message (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));
}

/**************************************************************************/
/** srv_message(): Gets a vbox message.                         [server] **/
/**************************************************************************/

static void srv_message(int argc, char **argv)
{
      struct stat  status;
      vaheader_t   header;
      char        *block;
      char        *msgname;
      int          fd;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_READ)))
      {
            message("%s Access denied (no read access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <message>\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;
      
      if ((fd = open(msgname, O_RDONLY)) != -1)
      {
            if (fstat(fd, &status) == 0)
            {
                  if (header_get(fd, &header))
                  {
                        if (lseek(fd, 0, SEEK_SET) == 0)
                        {
                              if ((block = malloc(status.st_size)))
                              {
                                    if (read(fd, block, status.st_size) == status.st_size)
                                    {
                                          message("%s %d\r\n", VBOXD_VAL_MESSAGE, status.st_size);
                     pullmsg(stdout);

                                          write(STDOUT_FILENO, block, status.st_size);

                                          message("%s .\r\n", VBOXD_VAL_MESSAGE);
                                          pullmsg(stdout);

                                          free(block);
                                    }
                                    else message("%s Can't read message (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));
                              }
                              else message("%s Not enough memory (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));
                        }
                        else message("%s Can't seek back (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));
                  }
                  else message("%s Not a vbox message.\r\n", VBOXD_VAL_BADMESSAGE);
            }
            else message("%s Can't get message status (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));

            close(fd);
      }
      else message("%s Can't open message (%s).\r\n", VBOXD_VAL_TEMPERROR, strerror(errno));
}

/**************************************************************************/
/** srv_list(): List available messages.                        [server] **/
/**************************************************************************/

static void srv_list(int argc, char **argv)
{
      struct stat    status;
      struct dirent *tmp;
      vaheader_t     header;
      DIR           *dir;
      int            fd;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_READ)))
      {
            message("%s Access denied (no read access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (!(dir = opendir(".")))
      {
            message("%s Access denied (can't open directory).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      while ((tmp = readdir(dir)))
      {
            if (strcmp(tmp->d_name, "." ) == 0) continue;
            if (strcmp(tmp->d_name, "..") == 0) continue;

            if ((fd = open(tmp->d_name, O_RDONLY)) != -1)
            {
                  if (fstat(fd, &status) == 0)
                  {
                        if (header_get(fd, &header))
                        {
                              message("%s +\r\n"    , VBOXD_VAL_LIST);
                              message("%s F %s\r\n" , VBOXD_VAL_LIST, tmp->d_name);
                              message("%s T %lu\r\n", VBOXD_VAL_LIST, ntohl(header.time));
                              message("%s M %lu\r\n", VBOXD_VAL_LIST, status.st_mtime);
                              message("%s C %d\r\n" , VBOXD_VAL_LIST, ntohl(header.compression));
                              message("%s S %d\r\n" , VBOXD_VAL_LIST, status.st_size);
                              message("%s N %s\r\n" , VBOXD_VAL_LIST, header.name);
                              message("%s I %s\r\n" , VBOXD_VAL_LIST, header.callerid);
                              message("%s P %s\r\n" , VBOXD_VAL_LIST, header.phone);
                              message("%s L %s\r\n" , VBOXD_VAL_LIST, header.location);
                        }
                  }

                  close(fd);
            }
      }

      message("%s .\r\n", VBOXD_VAL_LIST);

      closedir(dir);
}

/**************************************************************************/
/** srv_login(): Login as user.                                 [server] **/
/**************************************************************************/

static void srv_login(int argc, char **argv)
{
      char *user = NULL;
      char *pass = NULL;
      int   r;

      if (argc >= 2) user = argv[1];
      if (argc >= 3) pass = argv[2];

      r = check_client_access_login(client_hostname, client_hostaddr, user, pass);

      if (r)
      {
            message("%s Welcome %s; messagebox is %s (", VBOXD_VAL_LOGINOK, client_user, client_spool);

            if (client_access & VBOXD_ACC_READ ) message("r");
            if (client_access & VBOXD_ACC_WRITE) message("w");

            message(").\r\n");
      }
      else message("%s Access denied.\r\n", VBOXD_VAL_ACCESSDENIED);
}

/**************************************************************************/
/** srv_help(): Prints the help message.                        [server] **/
/**************************************************************************/

static void srv_help(int argc, char **argv)
{
   message("%s Commands require special access:\r\n"                                , VBOXD_VAL_HELP);
   message("%s \r\n"                                                                , VBOXD_VAL_HELP);
      message("%s LIST                               List all messages.\r\n"           , VBOXD_VAL_HELP);
      message("%s COUNT                              Count new messages.\r\n"          , VBOXD_VAL_HELP);
   message("%s DELETE     <message>               Delete a message.\r\n"            , VBOXD_VAL_HELP);
      message("%s MESSAGE    <message>               Get a message.\r\n"               , VBOXD_VAL_HELP);
   message("%s HEADER     <message>               Get a message header.\r\n"        , VBOXD_VAL_HELP);
   message("%s TOGGLE     <message>               Toggle message new flag.\r\n"     , VBOXD_VAL_HELP);
   message("%s STATUSCTRL <control>               Check if control exists.\r\n"     , VBOXD_VAL_HELP);
   message("%s CREATECTRL <control>               Create a control file.\r\n"       , VBOXD_VAL_HELP);
   message("%s REMOVECTRL <control>               Remove a control file.\r\n"       , VBOXD_VAL_HELP);
   message("%s \r\n"                                                                , VBOXD_VAL_HELP);
   message("%s Commands available for all clients:\r\n"                             , VBOXD_VAL_HELP);
   message("%s \r\n"                                                                , VBOXD_VAL_HELP);
      message("%s LOGIN      <username> [password]   Login as user (gives access).\r\n", VBOXD_VAL_HELP);
      message("%s NOOP                               Does nothing.\r\n"                , VBOXD_VAL_HELP);
      message("%s HELP                               Display command list.\r\n"        , VBOXD_VAL_HELP);
      message("%s QUIT                               Quit.\r\n"                        , VBOXD_VAL_HELP);
      message("%s .\r\n"                                                               , VBOXD_VAL_HELP);
}

/**************************************************************************/
/** srv_count(): Counts new messages.                           [server] **/
/**************************************************************************/

static void srv_count(int argc, char **argv)
{
      struct stat    status;
      struct dirent *tmp;
      time_t         newest;
      int            mcount;
      DIR           *dir;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_READ)))
      {
            message("%s Access denied (no read access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (!(dir = opendir(".")))
      {
            message("%s Access denied (can't open directory).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      newest = 0;
      mcount = 0;

      while ((tmp = readdir(dir)))
      {
            if (strcmp(tmp->d_name, "." ) == 0) continue;
            if (strcmp(tmp->d_name, "..") == 0) continue;

            if (stat(tmp->d_name, &status) == 0)
            {
                  if (status.st_mtime > 0)
                  {
                        mcount++;

                        if (status.st_mtime > newest) newest = status.st_mtime;
                  }
            }
      }

      closedir(dir);

      message("%s %d %ld\r\n", VBOXD_VAL_COUNT, mcount, newest);
}

/**************************************************************************/
/** srv_toggle(): Toggle message new flag.                      [server] **/
/**************************************************************************/

static void srv_toggle(int argc, char **argv)
{
      struct utimbuf  utimeb;
      struct stat     status;
      char           *msgname;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_WRITE)))
      {
            message("%s Access denied (no write access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <message>.\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;

      if (stat(msgname, &status) == 0)
      {
            utimeb.actime  = status.st_atime;
            utimeb.modtime = (status.st_mtime > 0 ? 0 : status.st_ctime);
                  
            if (utime(msgname, &utimeb) != 0)
            {
                  message("%s Can't set new modification time.\r\n", VBOXD_VAL_TEMPERROR);
            }
            else message("%s %lu\r\n", VBOXD_VAL_TOGGLE, utimeb.modtime);
      }
      else message("%s: Can't get file status.\r\n", VBOXD_VAL_TEMPERROR);
}

/**************************************************************************/
/** srv_delete(): Delete a message.                             [server] **/
/**************************************************************************/

static void srv_delete(int argc, char **argv)
{
      char *msgname;

      if ((!client_spool) || (!client_user) || (!(client_access & VBOXD_ACC_WRITE)))
      {
            message("%s Access denied (no write access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (chdir(client_spool) != 0)
      {
            message("%s Access denied (messagebox unaccessable).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <message>.\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;

      if (unlink(msgname) != 0)
      {
            message("%s: Can't delete message.\r\n", VBOXD_VAL_TEMPERROR);
      }
      else message("%s .\r\n", VBOXD_VAL_DELETEOK);
}

/**************************************************************************/
/** srv_statusctrl(): Check if control file exists.             [server] **/
/**************************************************************************/

static void srv_statusctrl(int argc, char **argv)
{
      char *msgname;

      if ((!client_home) || (!client_user) || (!(client_access & VBOXD_ACC_READ)))
      {
            message("%s Access denied (no read access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <control>.\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;

      if (strncmp(msgname, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
      {
            message("%s %d\r\n", VBOXD_VAL_STATUSCTRLOK, ctrl_ishere(client_home, msgname));
      }
      else message("%s bad control name.\r\n", VBOXD_VAL_BADARGS);
}

/**************************************************************************/
/** srv_createctrl(): Create control file.                      [server] **/
/**************************************************************************/

static void srv_createctrl(int argc, char **argv)
{
      char *msgname;

      if ((!client_home) || (!client_user) || (!(client_access & VBOXD_ACC_WRITE)))
      {
            message("%s Access denied (no write access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <control>.\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;

      if (strncmp(msgname, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
      {
            message("%s %d\r\n", VBOXD_VAL_CREATECTRLOK, ctrl_create(client_home, msgname));
      }
      else message("%s bad control name.\r\n", VBOXD_VAL_BADARGS);
}

/**************************************************************************/
/** srv_removectrl(): Remove control file.                      [server] **/
/**************************************************************************/

static void srv_removectrl(int argc, char **argv)
{
      char *msgname;

      if ((!client_home) || (!client_user) || (!(client_access & VBOXD_ACC_WRITE)))
      {
            message("%s Access denied (no write access).\r\n", VBOXD_VAL_ACCESSDENIED);

            return;
      }

      if (argc != 2)
      {
            message("%s usage: %s <control>.\r\n", VBOXD_VAL_BADARGS, argv[0]);

            return;
      }

      if (!(msgname = rindex(argv[1], '/')))
      {
            msgname = argv[1];
      }
      else msgname++;

      if (strncmp(msgname, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
      {
            message("%s %d\r\n", VBOXD_VAL_REMOVECTRLOK, ctrl_remove(client_home, msgname));
      }
      else message("%s bad control name.\r\n", VBOXD_VAL_BADARGS);
}

/**************************************************************************/
/** srv_quit(): Quits the connection.                           [server] **/
/**************************************************************************/

static void srv_quit(int argc, char **argv)
{
      leave_program(0);
}

Generated by  Doxygen 1.6.0   Back to index