isdn4k-utils/vbox/src/libvbox.c

565 lines
16 KiB
C

/*
** $Id: libvbox.c,v 1.12 2001/03/01 14:59:16 paul Exp $
**
** Copyright (C) 1996, 1997 Michael 'Ghandi' Herold
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "libvbox.h"
/** Variables ************************************************************/
char *compressions[] =
{
"?", "?", "ADPCM-2", "ADPCM-3", "ADPCM-4", "ALAW", "ULAW"
};
static char vboxd_message[VBOXD_MAX_LINE + 1];
int vboxd_r_fd = -1;
int vboxd_w_fd = -1;
/**************************************************************************/
/** vboxd_connect(): Connect to the vbox message server. After connect **/
/** the function reads the server startup message! **/
/**************************************************************************/
/** machine String with the hostname or the ip address. **/
/** port Port number to connect. **/
/** <return> 0 on success; < 0 on error. **/
/**************************************************************************/
int vboxd_connect(char *machine, int port)
{
struct sockaddr_in sockp;
struct hostent *hostp;
struct hostent defaulthost;
struct in_addr defaultaddr;
char defaultname[256];
char *defaultlist[1];
char **p;
int c;
int s;
if (isdigit(*machine))
{
defaultlist[0] = NULL;
if (inet_aton(machine, &defaultaddr) != 0)
{
xstrncpy(defaultname, machine, 255);
defaulthost.h_name = (char *)defaultname;
defaulthost.h_addr_list = defaultlist;
defaulthost.h_addr = (char *)&defaultaddr;
defaulthost.h_length = sizeof(struct in_addr);
defaulthost.h_addrtype = AF_INET;
defaulthost.h_aliases = 0;
hostp = &defaulthost;
}
else hostp = gethostbyname(machine);
}
else hostp = gethostbyname(machine);
if (!hostp) return(VBOXC_ERR_UNKNOWNHOST);
memset((char *)&sockp, '\0', sizeof(struct sockaddr_in));
sockp.sin_family = hostp->h_addrtype;
sockp.sin_port = htons(port);
c = -1;
s = -1;
errno = 0;
for (p = hostp->h_addr_list; ((p) && (*p)); p++)
{
s = socket(hostp->h_addrtype, SOCK_STREAM, 0);
if (s < 0) return(VBOXC_ERR_NOSOCKET);
memcpy((char *)&sockp.sin_addr, *p, hostp->h_length);
c = connect(s, (struct sockaddr *)&sockp, sizeof(struct sockaddr_in));
if (c == 0) break;
close(s);
}
if (c < 0) return(VBOXC_ERR_NOCONNECT);
vboxd_r_fd = s;
vboxd_w_fd = dup(vboxd_r_fd);
if ((vboxd_w_fd < 0) || (vboxd_r_fd < 0))
{
vboxd_disconnect();
return(VBOXC_ERR_NOFILEIO);
}
if (!vboxd_get_message())
{
vboxd_disconnect();
return(VBOXC_ERR_GETMESSAGE);
}
if (!vboxd_test_response(VBOXD_VAL_SERVEROK))
{
vboxd_disconnect();
return(VBOXC_ERR_GETMESSAGE);
}
return(VBOXC_ERR_OK);
}
/**************************************************************************/
/** vboxd_disconnect(): Sends "quit" and disconnect from the server. **/
/**************************************************************************/
void vboxd_disconnect(void)
{
if (vboxd_w_fd) vboxd_put_message("quit");
if (vboxd_r_fd != -1) close_and_mone(vboxd_r_fd);
if (vboxd_w_fd != -1) close_and_mone(vboxd_w_fd);
}
/**************************************************************************/
/** vboxd_login(): Login to the vboxd server. **/
/**************************************************************************/
/** username Username to login. **/
/** password Password to login. **/
/** <return> 0 on success; < 0 on error. **/
/**************************************************************************/
int vboxd_login(char *username, char *password)
{
vboxd_put_message("login %s %s", username, password);
if (vboxd_get_message())
{
if (vboxd_test_response(VBOXD_VAL_LOGINOK)) return(VBOXC_ERR_OK);
}
return(VBOXC_ERR_LOGIN);
}
/**************************************************************************/
/** vboxd_put_message(): Puts a message to the server. **/
/**************************************************************************/
void vboxd_put_message(char *fmt, ...)
{
va_list arg;
char msgline[VBOXD_MAX_LINE + 1];
va_start(arg, fmt);
vnprintstring(msgline, VBOXD_MAX_LINE, fmt, arg);
va_end(arg);
write(vboxd_w_fd, msgline, strlen(msgline));
write(vboxd_w_fd, "\r\n", 2);
}
/**************************************************************************/
/** vboxd_get_message(): Try to get a message from the server. The func- **/
/** tion us a timeout of VBOXD_GET_MSG_TIMEOUT sec- **/
/** ends to get the message. **/
/**************************************************************************/
/** <return> Pointer to the message or NULL on error. **/
/**************************************************************************/
char *vboxd_get_message(void)
{
struct timeval timeval;
fd_set rmask;
char *stop;
int p;
int c;
int rc;
*vboxd_message = '\0';
p = 0;
c = 0;
while (TRUE)
{
VBOX_ONE_FD_MASK(&rmask, vboxd_r_fd);
timeval.tv_sec = VBOXD_GET_MSG_TIMEOUT;
timeval.tv_usec = 0;
rc = select((vboxd_r_fd + 1), &rmask, NULL, NULL, &timeval);
if (rc <= 0)
{
if ((rc < 0) && (errno == EINTR)) continue;
break;
}
if (!FD_ISSET(vboxd_r_fd, &rmask)) break;
rc = read(vboxd_r_fd, &c, 1);
if (rc <= 0)
{
if ((rc < 0) && (errno == EINTR)) continue;
break;
}
if (c == '\n')
{
if ((stop = rindex(vboxd_message, '\r'))) *stop = '\0';
return(vboxd_message);
}
vboxd_message[p + 0] = c;
vboxd_message[p + 1] = '\0';
if (p++ >= VBOXD_MAX_LINE) break;
}
return(NULL);
}
/**************************************************************************/
/** vboxd_test_response(): Test response of a vboxd message. **/
/**************************************************************************/
/** response Needed response code to check. **/
/** <return> TRUE (1) on success, FALSE (0) on error. **/
/**************************************************************************/
int vboxd_test_response(char *response)
{
if (strlen(vboxd_message) > (strlen(response) + 1))
{
if (strncmp(response, vboxd_message, strlen(response)) == 0)
{
if (vboxd_message[strlen(response)] == ' ') returnok();
}
}
returnerror();
}
/*************************************************************************/
/** get_message_ptime(): Returns the vbox message length in seconds. **/
/** The length is calculated from the size & the **/
/** compression mode. **/
/*************************************************************************/
/** compression Compression mode of the sample. **/
/** size Size of the sample. **/
/** <return> Sample length in seconds. **/
/*************************************************************************/
int get_message_ptime(int compression, int size)
{
if ((compression >= 2) && (compression <= 4))
{
size = ((size * 8) / compression);
}
return((size / KERNEL_SAMPLE_FREQ));
}
/*************************************************************************/
/** get_nr_messages(): Returns number of files in directory <path>. If **/
/** <countnew> is set only files with modification **/
/** time greater 0 are counted. Theres no check if **/
/** the files is a vbox message! **/
/*************************************************************************/
/** path Directory with files to count. **/
/** countnew 0 to count all or 1 to count only new files. **/
/** <return> Number of files found. **/
/*************************************************************************/
int get_nr_messages(char *path, int countnew)
{
struct dirent *entry;
struct stat status;
char temp[PATH_MAX + 1];
DIR *dir;
int messages;
messages = 0;
if ((dir = opendir(path)))
{
while ((entry = readdir(dir)))
{
if (countnew)
{
if (strcmp(entry->d_name, "." ) == 0) continue;
if (strcmp(entry->d_name, "..") == 0) continue;
xstrncpy(temp, path , PATH_MAX);
xstrncat(temp, "/" , PATH_MAX);
xstrncat(temp, entry->d_name, PATH_MAX);
if (stat(temp, &status) == 0)
{
if (status.st_mtime > 0) messages++;
}
}
else messages++;
}
closedir(dir);
}
return(messages);
}
/*************************************************************************/
/** ctrl_create(): Creates a vbox control file. The file is created **/
/** with the permissions -rw-rw-rw-. **/
/*************************************************************************/
/** path Path to the spool directory of the current user. **/
/** file Name of the control file to create. **/
/** <return> FALSE (0) on error; TRUE (1) on success. **/
/*************************************************************************/
int ctrl_create(char *path, char *file)
{
char location[PATH_MAX + 1];
int fd;
xstrncpy(location, path, PATH_MAX);
xstrncat(location, "/" , PATH_MAX);
xstrncat(location, file, PATH_MAX);
if (strncmp(file, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
{
if ((fd = open(location, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != -1)
{
chmod(location, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
chmod(location, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
close(fd);
returnok();
}
}
returnerror();
}
/*************************************************************************/
/** ctrl_remove(): Removes a vbox control file. **/
/*************************************************************************/
/** path Path to the spool directory of the current user. **/
/** file Name of the control file to remove. **/
/** <return> FALSE (0) on error; TRUE (1) on success. **/
/*************************************************************************/
int ctrl_remove(char *path, char *file)
{
char location[PATH_MAX + 1];
int loop;
xstrncpy(location, path, PATH_MAX);
xstrncat(location, "/" , PATH_MAX);
xstrncat(location, file, PATH_MAX);
if (strncmp(file, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
{
loop = 5;
while (loop > 0)
{
unlink(location);
unlink(location);
if (!ctrl_ishere(path, file)) returnok();
xpause(1000);
loop--;
}
}
returnerror();
}
/*************************************************************************/
/** ctrl_ishere(): Checks if a control file exists. **/
/*************************************************************************/
/** path Path to the spool directory of the current user. **/
/** file Name of the control file to check. **/
/** <return> FALSE (0) doesn't exist; TRUE (1) exists. **/
/*************************************************************************/
int ctrl_ishere(char *path, char *file)
{
char location[PATH_MAX + 1];
xstrncpy(location, path, PATH_MAX);
xstrncat(location, "/" , PATH_MAX);
xstrncat(location, file, PATH_MAX);
if (strncmp(file, CTRL_NAME_MAGIC, strlen(CTRL_NAME_MAGIC)) == 0)
{
if (access(location, F_OK) == 0) returnok();
}
returnerror();
}
/*************************************************************************/
/** xstrncpy(): Copys one string to another. **/
/*************************************************************************/
/** dest Pointer to the destination. **/
/** source Pointer to the source. **/
/** max Max length of destination. **/
/*************************************************************************/
void xstrncpy(char *dest, char *source, int max)
{
strncpy(dest, source, max);
dest[max] = '\0';
}
/*************************************************************************/
/** xstrncat(): Cats one string to another. **/
/*************************************************************************/
/** dest Pointer to the destination. **/
/** source Pointer to the source. **/
/** max Max length of destination. **/
/*************************************************************************/
void xstrncat(char *dest, char *source, int max)
{
if ((max - strlen(dest)) > 0) strncat(dest, source, max - strlen(dest));
dest[max] = '\0';
}
/*************************************************************************/
/** xpause(): Waits some miliseconds. **/
/*************************************************************************/
/** ms Miliseconds to wait. **/
/*************************************************************************/
void xpause(unsigned long ms)
{
usleep(ms * 1000);
}
/*************************************************************************/
/** xstrtol(): Converts a string to a long number, using a default on **/
/** error. **/
/*************************************************************************/
/** str String to convert to long. **/
/** use Default value if string can't converted. **/
/** <return> Converted string value on success; default on error. **/
/*************************************************************************/
long xstrtol(char *str, long use)
{
char *stop;
long line;
line = strtol(str, &stop, 10);
if ((line < 0) || (*stop != 0)) line = use;
return(line);
}
/*************************************************************************/
/** xstrtoul(): Converts a string to a unsigned long number, using a **/
/** default on error. **/
/*************************************************************************/
/** str String to convert to unsigned long. **/
/** use Default value if string can't converted. **/
/** <return> Converted string value on success; default on error. **/
/*************************************************************************/
unsigned long xstrtoul(char *str, unsigned long use)
{
char *stop;
unsigned long line;
line = strtoul(str, &stop, 10);
if ((line < 0) || (*stop != 0)) line = use;
return(line);
}
/*************************************************************************/
/** header_put(): Writes the vbox audio header. **/
/*************************************************************************/
/** fd File descriptor used to write. **/
/** header Pointer to a filled vbox audio header. **/
/** <return> 0 on error; 1 on success. **/
/*************************************************************************/
int header_put(int fd, vaheader_t *header)
{
if (write(fd, header, sizeof(vaheader_t)) != sizeof(vaheader_t))
{
returnerror();
}
returnok();
}
/*************************************************************************/
/** header_get(): Reads a vbox audio header. **/
/*************************************************************************/
/** fd File descriptor used to read. **/
/** header Pointer to a vbox audio header. **/
/** <return> 0 on error; 1 on success. **/
/*************************************************************************/
int header_get(int fd, vaheader_t *header)
{
vaheader_t dummy;
if (read(fd, &dummy, VAH_MAX_MAGIC) == VAH_MAX_MAGIC)
{
if (strncmp(dummy.magic, VAH_MAGIC, VAH_MAX_MAGIC) == 0)
{
if (lseek(fd, 0, SEEK_SET) == 0)
{
if (read(fd, header, sizeof(vaheader_t)) == sizeof(vaheader_t))
{
returnok();
}
}
}
}
returnerror();
}