isdn4k-utils/vbox/src/vboxd.c

1259 lines
33 KiB
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);
}