1892 lines
44 KiB
C
1892 lines
44 KiB
C
/*
|
|
** $Id: vbox.c,v 1.10 2001/03/01 14:59:16 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 <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <netinet/in.h>
|
|
#include <ncurses.h>
|
|
#include <panel.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <netdb.h>
|
|
#include <signal.h>
|
|
#include <termios.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <pwd.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
|
|
#include "libvbox.h"
|
|
#include "vbox.h"
|
|
#include "streamio.h"
|
|
|
|
/** Variables *************************************************************/
|
|
|
|
static char loginname[VBOX_MAX_USERNAME + 1];
|
|
static char loginpass[VBOX_MAX_PASSWORD + 1];
|
|
|
|
static char *messagesmp = NULL;
|
|
static int messagesnr = 0;
|
|
static char *vbasename = NULL;
|
|
static char *vboxdname = NULL;
|
|
static char *playerbin = NULL;
|
|
static int vboxdport = -1;
|
|
static int usecolors = FALSE;
|
|
static int leaveloop = FALSE;
|
|
static int leavevbox = FALSE;
|
|
static int monocolor = FALSE;
|
|
static int ledstatus = TRUE;
|
|
static int rloadtime = 0;
|
|
static int messagenr = 0;
|
|
static int messageyp = 0;
|
|
static int sndvolume = 10;
|
|
static int newmessys = FALSE;
|
|
static int forcepass = FALSE;
|
|
|
|
static struct statusled statusleds[] =
|
|
{
|
|
{ 1, CTRL_NAME_STOP , 0, "" },
|
|
{ 5, CTRL_NAME_REJECT , 0, "" },
|
|
{ 7, CTRL_NAME_ANSWERNOW, 0, "" },
|
|
{ 9, CTRL_NAME_ANSWERALL, 0, "" },
|
|
{ 11, CTRL_NAME_AUDIO , 0, "" },
|
|
{ 13, CTRL_NAME_SUSPEND , 0, "" },
|
|
{ -1, NULL , 0, "" }
|
|
};
|
|
|
|
static struct colortable colortable[] =
|
|
{
|
|
{ NULL , 0, 0 , 0 , A_NORMAL, A_REVERSE },
|
|
{ "C_BACKGROUND" , 1, COLOR_WHITE , COLOR_BLACK, A_NORMAL, A_NORMAL },
|
|
{ "C_STATUSBAR" , 2, COLOR_WHITE , COLOR_BLUE , A_NORMAL, A_REVERSE },
|
|
{ "C_STATUSBAR_HL" , 3, COLOR_YELLOW, COLOR_BLUE , A_BOLD , A_REVERSE|A_BOLD },
|
|
{ "C_POWERLED_ON" , 4, COLOR_GREEN , COLOR_BLUE , A_NORMAL, A_REVERSE|A_BOLD },
|
|
{ "C_POWERLED_OFF" , 5, COLOR_RED , COLOR_BLUE , A_NORMAL, A_REVERSE },
|
|
{ "C_STATUSLED_ON" , 6, COLOR_YELLOW, COLOR_BLUE , A_BOLD , A_REVERSE|A_BOLD },
|
|
{ "C_STATUSLED_OFF", 7, COLOR_BLACK , COLOR_BLUE , A_NORMAL, A_REVERSE },
|
|
{ "C_LIST" , 8, COLOR_WHITE , COLOR_BLACK, A_NORMAL, A_NORMAL },
|
|
{ "C_LIST_SELECTED", 9, COLOR_WHITE , COLOR_RED , A_NORMAL, A_REVERSE },
|
|
{ "C_INFOTEXT" , 10, COLOR_GREEN , COLOR_BLACK, A_NORMAL, A_NORMAL },
|
|
{ "C_HELP" , 11, COLOR_WHITE , COLOR_BLUE , A_NORMAL, A_REVERSE },
|
|
{ "C_HELP_BORDER" , 12, COLOR_YELLOW, COLOR_BLUE , A_BOLD , A_REVERSE|A_BOLD },
|
|
{ "C_STATUS" , 13, COLOR_WHITE , COLOR_RED , A_NORMAL, A_REVERSE },
|
|
{ "C_STATUS_BORDER", 14, COLOR_YELLOW, COLOR_RED , A_BOLD , A_REVERSE|A_BOLD },
|
|
{ "C_INFO" , 15, COLOR_WHITE , COLOR_YELLOW, A_NORMAL, A_REVERSE },
|
|
{ "C_INFO_BORDER" , 16, COLOR_YELLOW, COLOR_YELLOW, A_BOLD , A_REVERSE|A_BOLD },
|
|
{ NULL , -1, 0 , 0 , 0 , 0 }
|
|
};
|
|
|
|
static char *colornames[] =
|
|
{
|
|
"BLACK", "RED", "GREEN", "BROWN", "BLUE", "MAGENTA", "CYAN", "GRAY",
|
|
"DARKGRAY", "LIGHTRED", "LIGHTGREEN", "YELLOW", "LIGHTBLUE", "LIGHTMAGENTA",
|
|
"LIGHTCYAN", "WHITE",
|
|
NULL
|
|
};
|
|
|
|
static struct option arguments[] =
|
|
{
|
|
{ "version" , no_argument , NULL, 'v' },
|
|
{ "help" , no_argument , NULL, 'h' },
|
|
{ "mono" , no_argument , NULL, 'o' },
|
|
{ "force" , no_argument , NULL, 'f' },
|
|
{ "noledstatus", no_argument , NULL, 's' },
|
|
{ "hostname" , required_argument , NULL, 'm' },
|
|
{ "reload" , required_argument , NULL, 'r' },
|
|
{ "port" , required_argument , NULL, 'p' },
|
|
{ "playcmd" , required_argument , NULL, 'c' },
|
|
{ NULL , 0 , NULL, 0 }
|
|
};
|
|
|
|
/** Prototypes ************************************************************/
|
|
|
|
static int message(char *, char *, ...);
|
|
static int sort_message_list(const void *, const void *);
|
|
static int count_new_messages(void);
|
|
static int delete_message(char *);
|
|
static int get_color_nr(char *);
|
|
static int load_message(int, int);
|
|
static int init_screen(void);
|
|
static void exit_screen(void);
|
|
static void draw_main_screen(void);
|
|
static void draw_status_bar(void);
|
|
static void draw_bottom_bar(void);
|
|
static void draw_ctrl_status(void);
|
|
static void draw_message_list(void);
|
|
static void draw_message_line(int, int, int);
|
|
static void clear_screen(void);
|
|
static void process_input(void);
|
|
static void get_message_list(void);
|
|
static void sig_handling_resize(int);
|
|
static void sig_handling_interrupt(int);
|
|
static void one_line_down(void);
|
|
static void one_line_up(void);
|
|
static void init_locale(void);
|
|
static void play_message(int);
|
|
static void toggle_new_flag(int);
|
|
static void toggle_delete_flag(int);
|
|
static void transfer_message_list(void);
|
|
static void delete_selected_messages(void);
|
|
static void parse_vboxrc(void);
|
|
static void parse_colors(char *, char *);
|
|
static void usage(void);
|
|
static void version(void);
|
|
static void help(void);
|
|
static void status(void);
|
|
static void statuscontrol(int);
|
|
static void set_window_background(WINDOW *, chtype);
|
|
static void messageinfo(int);
|
|
static chtype color(int);
|
|
|
|
/**************************************************************************/
|
|
/** The magic main... **/
|
|
/**************************************************************************/
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct servent *vboxdserv;
|
|
int dimension;
|
|
char *pass;
|
|
int opts;
|
|
|
|
if (!(vbasename = rindex(argv[0], '/')))
|
|
{
|
|
vbasename = argv[0];
|
|
}
|
|
else vbasename++;
|
|
|
|
init_locale();
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
signal(SIGINT , SIG_IGN);
|
|
|
|
vboxdname = "localhost";
|
|
vboxdport = -1;
|
|
rloadtime = 60;
|
|
monocolor = FALSE;
|
|
ledstatus = TRUE;
|
|
playerbin = PLAY;
|
|
forcepass = FALSE;
|
|
|
|
*loginname = '\0';
|
|
*loginpass = '\0';
|
|
|
|
parse_vboxrc();
|
|
|
|
while ((opts = getopt_long(argc, argv, "vhofsm:r:p:c:", arguments, (int *)0)) != EOF)
|
|
{
|
|
switch (opts)
|
|
{
|
|
case 'o':
|
|
monocolor = TRUE;
|
|
break;
|
|
|
|
case 'f':
|
|
forcepass = TRUE;
|
|
break;
|
|
|
|
case 's':
|
|
ledstatus = FALSE;
|
|
break;
|
|
|
|
case 'm':
|
|
vboxdname = optarg;
|
|
break;
|
|
|
|
case 'p':
|
|
vboxdport = xstrtol(optarg, -1);
|
|
break;
|
|
|
|
case 'r':
|
|
rloadtime = xstrtol(optarg, 60);
|
|
break;
|
|
|
|
case 'c':
|
|
playerbin = optarg;
|
|
break;
|
|
|
|
case 'h':
|
|
usage();
|
|
break;
|
|
|
|
case 'v':
|
|
version();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check if login and password are given. If not, we prompt for user
|
|
* input.
|
|
*/
|
|
|
|
if ((!*loginname) || (!*loginpass) || (forcepass))
|
|
{
|
|
printf("\n");
|
|
printf("Username: ");
|
|
fflush(stdout);
|
|
|
|
fgets(loginname, VBOX_MAX_USERNAME, stdin);
|
|
|
|
loginname[strlen(loginname) - 1] = '\0';
|
|
|
|
if ((pass = getpass("Password: ")))
|
|
{
|
|
xstrncpy(loginpass, pass, VBOX_MAX_PASSWORD);
|
|
|
|
memset(pass, '\0', strlen(pass));
|
|
}
|
|
else *loginpass = '\0';
|
|
|
|
printf("\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
if ((!loginname) || (!*loginname) || (!loginpass) || (!*loginpass))
|
|
{
|
|
fprintf(stderr, "%s: you must enter a login name and a password.\n", vbasename);
|
|
|
|
exit(5);
|
|
}
|
|
|
|
/*
|
|
* Connect to the server, login and get the list with all messages
|
|
* for the user.
|
|
*/
|
|
|
|
if (vboxdport == -1)
|
|
{
|
|
if (!(vboxdserv = getservbyname("vboxd", "tcp")))
|
|
{
|
|
fprintf(stderr, "%s: can't get service 'vboxd/tcp' - please read the manual.\n", vbasename);
|
|
|
|
exit(5);
|
|
}
|
|
|
|
vboxdport = ntohs(vboxdserv->s_port);
|
|
}
|
|
|
|
fprintf(stderr, "Connecting to '%s:%d'...\n", vboxdname, vboxdport);
|
|
|
|
if (vboxd_connect(vboxdname, vboxdport) != VBOXC_ERR_OK)
|
|
{
|
|
fprintf(stderr, "%s: can't connect to '%s:%d'.\n", vbasename, vboxdname, vboxdport);
|
|
|
|
exit(5);
|
|
}
|
|
|
|
if (vboxd_login(loginname, loginpass) != VBOXC_ERR_OK)
|
|
{
|
|
memset(loginpass, '\0', VBOX_MAX_PASSWORD);
|
|
|
|
fprintf(stderr, "%s: can't login as '%s'.\n", vbasename, loginname);
|
|
|
|
vboxd_disconnect();
|
|
exit(5);
|
|
}
|
|
|
|
memset(loginpass, '\0', VBOX_MAX_PASSWORD);
|
|
|
|
fprintf(stderr, "Transfering message list...\n");
|
|
|
|
get_message_list();
|
|
|
|
/*
|
|
* Do a endless loop: initialize ncurses, draw the screen, process user
|
|
* action & exit ncurses. This loop will only end if the variable leave-
|
|
* vbox is true.
|
|
*/
|
|
|
|
leavevbox = FALSE;
|
|
dimension = TRUE;
|
|
|
|
if (init_screen())
|
|
{
|
|
while (!leavevbox)
|
|
{
|
|
if ((LINES >= 24) && (COLS >= 80))
|
|
{
|
|
draw_main_screen();
|
|
process_input();
|
|
}
|
|
else
|
|
{
|
|
dimension = FALSE;
|
|
leavevbox = TRUE;
|
|
}
|
|
}
|
|
|
|
exit_screen();
|
|
}
|
|
else fprintf(stderr, "%s: can't initialize screen.\n", vbasename);
|
|
|
|
if (!dimension)
|
|
{
|
|
fprintf(stderr, "%s: screen dimensions too small - need 80x24 or greater.\n", vbasename);
|
|
}
|
|
|
|
vboxd_disconnect();
|
|
|
|
if (messagesmp) free(messagesmp);
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** usage(): Displays usage message. **/
|
|
/**************************************************************************/
|
|
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Usage: %s OPTION [ OPTION ] [ ... ]\n", vbasename);
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "-m, --hostname NAME Connect to host NAME (localhost).\n");
|
|
fprintf(stderr, "-p, --port PORT Connect to port PORT (vboxd/tcp).\n");
|
|
fprintf(stderr, "-c, --playcmd PROG Use PROG to play messages (%s).\n", playerbin);
|
|
fprintf(stderr, "-r, --reload SECS Reload message list all SECS seconds (%d).\n", rloadtime);
|
|
fprintf(stderr, "-o, --mono Force mono color (color if terminal have).\n");
|
|
fprintf(stderr, "-f, --force Force login prompt.\n");
|
|
fprintf(stderr, "-s, --noledstatus Don't get led status from server (get status).\n");
|
|
fprintf(stderr, "-v, --version Display program version.\n");
|
|
fprintf(stderr, "-h, --help Display usage message.\n");
|
|
fprintf(stderr, "\n");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** version(): Displays program version. **/
|
|
/**************************************************************************/
|
|
|
|
static void version(void)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "%s version %s (%s)\n", vbasename, VERSION, VERDATE);
|
|
fprintf(stderr, "\n");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** process_input(): Main input loop. **/
|
|
/**************************************************************************/
|
|
|
|
static void process_input(void)
|
|
{
|
|
int timerreload;
|
|
int timerstatus;
|
|
int c;
|
|
|
|
signal(SIGWINCH, sig_handling_resize);
|
|
signal(SIGINT , sig_handling_interrupt);
|
|
signal(SIGTERM , sig_handling_interrupt);
|
|
signal(SIGHUP , sig_handling_interrupt);
|
|
signal(SIGQUIT , SIG_IGN);
|
|
|
|
timerstatus = 0;
|
|
timerreload = 0;
|
|
messageyp = 4;
|
|
messagenr = 0;
|
|
leaveloop = FALSE;
|
|
|
|
noecho();
|
|
cbreak();
|
|
setscrreg(4, LINES - 3);
|
|
scrollok(stdscr, FALSE);
|
|
keypad(stdscr, TRUE);
|
|
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
|
|
while (!leaveloop)
|
|
{
|
|
timeout(1000);
|
|
curs_set(0);
|
|
move((LINES - 2), 0);
|
|
|
|
c = wgetch(stdscr);
|
|
|
|
if (c != ERR) timerreload = 0;
|
|
|
|
switch (c)
|
|
{
|
|
case 27:
|
|
c = wgetch(stdscr);
|
|
break;
|
|
|
|
case ERR:
|
|
if (++timerstatus > 30)
|
|
{
|
|
timerstatus = 0;
|
|
|
|
draw_ctrl_status();
|
|
}
|
|
if (++timerreload > rloadtime)
|
|
{
|
|
timerreload = 0;
|
|
|
|
transfer_message_list();
|
|
}
|
|
break;
|
|
|
|
case 'Q':
|
|
case 'q':
|
|
delete_selected_messages();
|
|
leavevbox = TRUE;
|
|
leaveloop = TRUE;
|
|
break;
|
|
|
|
case 'R':
|
|
case 'r':
|
|
transfer_message_list();
|
|
break;
|
|
|
|
case KEY_DOWN:
|
|
one_line_down();
|
|
break;
|
|
|
|
case KEY_UP:
|
|
one_line_up();
|
|
break;
|
|
|
|
case '+':
|
|
if (sndvolume < 1000)
|
|
{
|
|
sndvolume++;
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
break;
|
|
|
|
case '-':
|
|
if (sndvolume > 0)
|
|
{
|
|
sndvolume--;
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
break;
|
|
|
|
case 'D':
|
|
case 'd':
|
|
toggle_delete_flag(messagenr);
|
|
one_line_down();
|
|
break;
|
|
|
|
case 'T':
|
|
case 't':
|
|
case 'N':
|
|
case 'n':
|
|
toggle_new_flag(messagenr);
|
|
draw_bottom_bar();
|
|
one_line_down();
|
|
break;
|
|
|
|
case '\r':
|
|
case '\n':
|
|
play_message(messagenr);
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
draw_bottom_bar();
|
|
break;
|
|
|
|
case 'H':
|
|
case 'h':
|
|
help();
|
|
break;
|
|
|
|
case 'S':
|
|
case 's':
|
|
status();
|
|
break;
|
|
|
|
case 'I':
|
|
case 'i':
|
|
messageinfo(messagenr);
|
|
break;
|
|
|
|
default:
|
|
beep();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** status(): Displays status window. **/
|
|
/**************************************************************************/
|
|
|
|
static void status(void)
|
|
{
|
|
WINDOW *win;
|
|
PANEL *pan;
|
|
int c;
|
|
int noop;
|
|
int done;
|
|
int max;
|
|
int led;
|
|
int w;
|
|
int h;
|
|
char *b;
|
|
|
|
if (ledstatus)
|
|
{
|
|
led = 0;
|
|
|
|
while (statusleds[led].name) led++;
|
|
|
|
h = (4 + led);
|
|
w = 48;
|
|
b = " Press 'Q' to quit ";
|
|
|
|
if ((win = newwin(h, w, 1, 0)))
|
|
{
|
|
if ((pan = new_panel(win)))
|
|
{
|
|
set_window_background(win, color(13));
|
|
wattrset(win, color(14));
|
|
box(win, ACS_VLINE, ACS_HLINE);
|
|
|
|
mvwprintw(win, (h - 1), ((w - strlen(b)) / 2), "%s", b);
|
|
|
|
wattrset(win, color(13));
|
|
|
|
max = 0;
|
|
led = 0;
|
|
|
|
while (statusleds[led].name)
|
|
{
|
|
max = led;
|
|
|
|
mvwprintw(win, 0, statusleds[led].x, "%d", led);
|
|
mvwprintw(win, (2 + led), 3, "%d) %s '%s' control...", led, (statusleds[led].status ? "Remove" : "Create"), statusleds[led].name);
|
|
|
|
led++;
|
|
}
|
|
|
|
wmove(win, (h - 2), (w - 2));
|
|
update_panels();
|
|
wrefresh(win);
|
|
|
|
done = FALSE;
|
|
noop = 0;
|
|
|
|
cbreak();
|
|
noecho();
|
|
wtimeout(win, 1000);
|
|
|
|
while (!done)
|
|
{
|
|
switch ((c = wgetch(win)))
|
|
{
|
|
case ERR:
|
|
if (++noop > 30)
|
|
{
|
|
vboxd_put_message("NOOP");
|
|
|
|
noop = 0;
|
|
}
|
|
break;
|
|
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
c -= 48;
|
|
|
|
if ((c >= 0) && (c <= max))
|
|
{
|
|
statuscontrol(c);
|
|
|
|
done = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'Q':
|
|
case 'q':
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
del_panel(pan);
|
|
}
|
|
|
|
delwin(win);
|
|
}
|
|
}
|
|
else message("\r\n", "You must enable 'ledstatus' first!%s", " [RETURN]");
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** statuscontrol(): Removes or creates a control file. **/
|
|
/**************************************************************************/
|
|
|
|
static void statuscontrol(int nr)
|
|
{
|
|
char *resp;
|
|
char *todo;
|
|
char *answer;
|
|
int status;
|
|
|
|
status = statusleds[nr].status;
|
|
|
|
message("", "%s '%s'...", (status ? "Removing" : "Creating"), statusleds[nr].name);
|
|
|
|
if (status)
|
|
{
|
|
todo = "removectrl";
|
|
resp = VBOXD_VAL_REMOVECTRLOK;
|
|
}
|
|
else
|
|
{
|
|
todo = "createctrl";
|
|
resp = VBOXD_VAL_CREATECTRLOK;
|
|
}
|
|
|
|
vboxd_put_message("%s %s", todo, statusleds[nr].name);
|
|
|
|
if ((answer = vboxd_get_message()))
|
|
{
|
|
if (vboxd_test_response(resp))
|
|
{
|
|
if (answer[4] != '1') message("\r\n", "Can't %s '%s'! [RETURN]", (status ? "remove" : "create"), statusleds[nr].name);
|
|
|
|
draw_ctrl_status();
|
|
}
|
|
}
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** help(): Displays the help window. **/
|
|
/**************************************************************************/
|
|
|
|
static void help(void)
|
|
{
|
|
WINDOW *win;
|
|
PANEL *pan;
|
|
int h;
|
|
int w;
|
|
char *t;
|
|
char *b;
|
|
int n;
|
|
int done;
|
|
|
|
w = 37;
|
|
h = 12;
|
|
n = 0;
|
|
t = " HELP ";
|
|
b = " Press 'Q' to quit ";
|
|
|
|
if ((win = newwin(h, w, ((LINES - h) / 2), ((COLS - w) / 2))))
|
|
{
|
|
if ((pan = new_panel(win)))
|
|
{
|
|
set_window_background(win, color(11));
|
|
wattrset(win, color(12));
|
|
box(win, ACS_VLINE, ACS_HLINE);
|
|
|
|
mvwprintw(win, 0, ((w - strlen(t)) / 2), "%s", t);
|
|
mvwprintw(win, (h - 1), ((w - strlen(b)) / 2), "%s", b);
|
|
|
|
wattrset(win, color(11));
|
|
|
|
mvwprintw(win, 2, 3, "RETURN Play message");
|
|
mvwprintw(win, 3, 3, "R Reload message list");
|
|
mvwprintw(win, 4, 3, "N Toggle read/unread");
|
|
mvwprintw(win, 5, 3, "D Toggle delete/undelete");
|
|
mvwprintw(win, 6, 3, "S Status control");
|
|
mvwprintw(win, 7, 3, "I Message information");
|
|
mvwprintw(win, 8, 3, "+/- Volume +/-");
|
|
mvwprintw(win, 9, 3, "Q Quit vbox");
|
|
|
|
update_panels();
|
|
wrefresh(win);
|
|
move((LINES - 2), 0);
|
|
|
|
cbreak();
|
|
noecho();
|
|
wtimeout(win, 1000);
|
|
|
|
done = FALSE;
|
|
|
|
while (!done)
|
|
{
|
|
switch (wgetch(win))
|
|
{
|
|
case ERR:
|
|
if (++n > 30)
|
|
{
|
|
vboxd_put_message("NOOP");
|
|
|
|
n = 0;
|
|
}
|
|
break;
|
|
|
|
case 'Q':
|
|
case 'q':
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
del_panel(pan);
|
|
}
|
|
|
|
delwin(win);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** parse_vboxrc(): Reads and parse ~/.vboxrc. **/
|
|
/**************************************************************************/
|
|
|
|
void parse_vboxrc(void)
|
|
{
|
|
struct passwd *userpw;
|
|
streamio_t *vboxrc;
|
|
char rcname[PATH_MAX + 1];
|
|
char rcline[128 + 1];
|
|
char *cmd;
|
|
char *arg;
|
|
|
|
if ((userpw = getpwuid(getuid())))
|
|
{
|
|
xstrncpy(rcname, userpw->pw_dir, PATH_MAX);
|
|
xstrncat(rcname, "/.vboxrc" , PATH_MAX);
|
|
|
|
if ((vboxrc = streamio_open(rcname)))
|
|
{
|
|
while (streamio_gets(rcline, 128, vboxrc))
|
|
{
|
|
cmd = strtok(rcline, "\t ");
|
|
arg = strtok(NULL , "\t ");
|
|
|
|
if ((cmd) && (arg))
|
|
{
|
|
if (strncasecmp(cmd, "C_", 2) == 0)
|
|
{
|
|
parse_colors(cmd, arg);
|
|
}
|
|
else
|
|
{
|
|
if (strcasecmp(cmd, "USERNAME") == 0)
|
|
{
|
|
xstrncpy(loginname, arg, VBOX_MAX_USERNAME);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (strcasecmp(cmd, "PASSWORD") == 0)
|
|
{
|
|
xstrncpy(loginpass, arg, VBOX_MAX_PASSWORD);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (strcasecmp(cmd, "VOLUME") == 0)
|
|
{
|
|
sndvolume = atoi(arg);
|
|
|
|
if (sndvolume < 0 ) sndvolume = 0;
|
|
if (sndvolume > 999) sndvolume = 999;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
streamio_close(vboxrc);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** parse_colors(): Parse a colorname. **/
|
|
/**************************************************************************/
|
|
|
|
static void parse_colors(char *cmd, char *arg)
|
|
{
|
|
char *ctext;
|
|
char *cback;
|
|
int i;
|
|
|
|
ctext = arg;
|
|
|
|
if ((cback = index(ctext, ':'))) *cback++ = '\0';
|
|
|
|
i = 1;
|
|
|
|
while (colortable[i].pair > 0)
|
|
{
|
|
if (strcasecmp(colortable[i].name, cmd) == 0)
|
|
{
|
|
colortable[i].fg = get_color_nr(ctext);
|
|
colortable[i].bg = get_color_nr(cback);
|
|
|
|
colortable[i].cattr = (colortable[i].fg > 7 ? A_BOLD : A_NORMAL);
|
|
|
|
while (colortable[i].bg > 7) colortable[i].bg -= 8;
|
|
while (colortable[i].fg > 7) colortable[i].fg -= 8;
|
|
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** get_color_nr(): Returns the color number of a color in colortable. **/
|
|
/**************************************************************************/
|
|
|
|
static int get_color_nr(char *cname)
|
|
{
|
|
int i;
|
|
|
|
if ((cname) && (*cname))
|
|
{
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
if (strcasecmp(colornames[i], cname) == 0) return(i);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** delete_selected_messages(): Deletes all selected messages. **/
|
|
/**************************************************************************/
|
|
|
|
static void delete_selected_messages(void)
|
|
{
|
|
struct messageline *msgline;
|
|
int i;
|
|
int s;
|
|
|
|
if ((messagesmp) && (messagesnr > 0))
|
|
{
|
|
for (s = 0, i = 0; i < messagesnr; i++)
|
|
{
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * i));
|
|
|
|
if (msgline->delete) s++;
|
|
}
|
|
|
|
if (s > 0)
|
|
{
|
|
i = message("yn", "Really delete all marked messages (y/n)? ");
|
|
|
|
if (i == 'y')
|
|
{
|
|
for (i = 0; i < messagesnr; i++)
|
|
{
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * i));
|
|
|
|
if (msgline->delete)
|
|
{
|
|
message("", "Removing message #%d...", i);
|
|
|
|
if (!delete_message(msgline->messagename)) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** delete_message(): Deletes one message. **/
|
|
/**************************************************************************/
|
|
|
|
static int delete_message(char *name)
|
|
{
|
|
vboxd_put_message("delete %s", name);
|
|
|
|
if (vboxd_get_message())
|
|
{
|
|
if (vboxd_test_response(VBOXD_VAL_DELETEOK)) returnok();
|
|
|
|
message("\r\n", "Can't delete; invalid server response! %s", "[RETURN]");
|
|
}
|
|
else message("\r\n", "Can't delete; no server response! %s", "[RETURN]");
|
|
|
|
returnerror();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** toggle_new_flag(): Toggles the message new flag. **/
|
|
/**************************************************************************/
|
|
|
|
static void toggle_new_flag(int nr)
|
|
{
|
|
struct messageline *msgline;
|
|
char *answer;
|
|
|
|
if ((messagesmp) && (messagesnr > 0))
|
|
{
|
|
message("", "Toggle message new flag...");
|
|
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * nr));
|
|
|
|
vboxd_put_message("toggle %s", msgline->messagename);
|
|
|
|
if ((answer = vboxd_get_message()))
|
|
{
|
|
if (vboxd_test_response(VBOXD_VAL_TOGGLE))
|
|
{
|
|
msgline->mtime = xstrtoul(&answer[4], 0);
|
|
msgline->new = msgline->mtime > 0 ? TRUE : FALSE;
|
|
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
}
|
|
else message("\r\n", "Can't toggle; invalid server response! %s", "[RETURN]");
|
|
}
|
|
else message("\r\n", "Can't toggle; no answer from server! %s", "[RETURN]");
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** toggle_delete_flag(): Toggles the message delete flag. **/
|
|
/**************************************************************************/
|
|
|
|
static void toggle_delete_flag(int nr)
|
|
{
|
|
struct messageline *msgline;
|
|
|
|
if ((messagesmp) && (messagesnr > 0))
|
|
{
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * nr));
|
|
|
|
msgline->delete = msgline->delete ? FALSE : TRUE;
|
|
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** transfer_message_list(): Transfers the message list. **/
|
|
/**************************************************************************/
|
|
|
|
static void transfer_message_list(void)
|
|
{
|
|
message("", "Transfering message list...");
|
|
|
|
get_message_list();
|
|
|
|
if (newmessys)
|
|
{
|
|
draw_message_list();
|
|
messagenr = 0;
|
|
messageyp = 4;
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
}
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** color(): Returns the attributes for a given color. **/
|
|
/**************************************************************************/
|
|
|
|
static chtype color(int c)
|
|
{
|
|
if ((usecolors) && (!monocolor))
|
|
{
|
|
return(COLOR_PAIR(colortable[c].pair) | colortable[c].cattr);
|
|
}
|
|
else return(COLOR_PAIR(0) | colortable[c].mattr);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_main_screen(): Draw the hole main screen. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_main_screen(void)
|
|
{
|
|
clear_screen();
|
|
draw_bottom_bar();
|
|
draw_status_bar();
|
|
draw_message_list();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** clear_screen(): Clears screen and set background. **/
|
|
/**************************************************************************/
|
|
|
|
static void clear_screen(void)
|
|
{
|
|
set_window_background(stdscr, COLTAB(1));
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** init_screen(): Initialize the ncurses screen and the colors. **/
|
|
/**************************************************************************/
|
|
|
|
static int init_screen(void)
|
|
{
|
|
int i;
|
|
|
|
if (initscr())
|
|
{
|
|
if (start_color() != ERR)
|
|
{
|
|
if ((has_colors()) && (!monocolor))
|
|
{
|
|
if ((COLORS >= 8) && (COLOR_PAIRS >= 64))
|
|
{
|
|
i = 1;
|
|
|
|
while (colortable[i].pair > 0)
|
|
{
|
|
init_pair(colortable[i].pair, colortable[i].fg, colortable[i].bg);
|
|
|
|
i++;
|
|
}
|
|
|
|
usecolors = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
returnok();
|
|
}
|
|
|
|
returnerror();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** exit_screen(): Exit ncurses screen management. **/
|
|
/**************************************************************************/
|
|
|
|
static void exit_screen(void)
|
|
{
|
|
endwin();
|
|
printf("%c%c%c\n", 27, 'c', 12);
|
|
fflush(stdout);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** sig_handling_resize(): Signal handler for screen resizing. **/
|
|
/**************************************************************************/
|
|
|
|
static void sig_handling_resize(int s)
|
|
{
|
|
#ifdef HAVE_RESIZETERM
|
|
|
|
struct winsize win;
|
|
int newsizec;
|
|
int newsizel;
|
|
|
|
newsizel = LINES;
|
|
newsizec = COLS;
|
|
|
|
if (ioctl(0, TIOCGWINSZ, &win) == 0)
|
|
{
|
|
if (win.ws_row != 0) newsizel = win.ws_row;
|
|
if (win.ws_col != 0) newsizec = win.ws_col;
|
|
}
|
|
|
|
if (resizeterm(newsizel, newsizec) == ERR) leavevbox = TRUE;
|
|
|
|
#endif
|
|
|
|
leaveloop = TRUE;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** sig_handling_interrupt(): Signal handler for ctrl-c or other breaks. **/
|
|
/**************************************************************************/
|
|
|
|
static void sig_handling_interrupt(int s)
|
|
{
|
|
leaveloop = TRUE;
|
|
leavevbox = TRUE;
|
|
|
|
/*
|
|
* We *not* re-set the interrupt handler, so a 2nd control-c will
|
|
* break the program!
|
|
*/
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** get_message_list(): Get the list with all messages. The list replace **/
|
|
/** any old messages. If the function can't get the **/
|
|
/** new list, the old one is not touched. **/
|
|
/**************************************************************************/
|
|
|
|
static void get_message_list(void)
|
|
{
|
|
struct messageline *mrgline;
|
|
struct messageline *msgline;
|
|
char *newline;
|
|
char *tmpmessagesmp;
|
|
char *newmessagesmp;
|
|
int newmessagesnr;
|
|
int o;
|
|
int n;
|
|
|
|
newmessagesmp = NULL;
|
|
newmessagesnr = 0;
|
|
newmessys = FALSE;
|
|
|
|
vboxd_put_message("list");
|
|
|
|
while ((newline = vboxd_get_message()))
|
|
{
|
|
if ((!vboxd_test_response(VBOXD_VAL_LIST)) || (strlen(newline) < 5))
|
|
{
|
|
if (newmessagesmp) free(newmessagesmp);
|
|
|
|
return;
|
|
}
|
|
|
|
if (newline[4] == '.') break;
|
|
|
|
if (newline[4] == '+')
|
|
{
|
|
newmessagesnr++;
|
|
|
|
if ((tmpmessagesmp = realloc(newmessagesmp, (sizeof(struct messageline) * newmessagesnr))))
|
|
{
|
|
newmessagesmp = tmpmessagesmp;
|
|
|
|
msgline = (struct messageline *)(newmessagesmp + (sizeof(struct messageline) * (newmessagesnr - 1)));
|
|
|
|
msgline->ctime = 0;
|
|
msgline->mtime = 0;
|
|
msgline->compression = 0;
|
|
msgline->size = 0;
|
|
msgline->new = FALSE;
|
|
msgline->delete = FALSE;
|
|
|
|
strcpy(msgline->messagename, "");
|
|
strcpy(msgline->name , "");
|
|
strcpy(msgline->callerid , "");
|
|
strcpy(msgline->phone , "");
|
|
strcpy(msgline->location , "");
|
|
}
|
|
else newmessagesnr--;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (newmessagesnr > 0)
|
|
{
|
|
msgline = (struct messageline *)(newmessagesmp + (sizeof(struct messageline) * (newmessagesnr - 1)));
|
|
|
|
switch (newline[4])
|
|
{
|
|
case 'F':
|
|
xstrncpy(msgline->messagename, &newline[6], NAME_MAX);
|
|
break;
|
|
|
|
case 'N':
|
|
xstrncpy(msgline->name, &newline[6], VAH_MAX_NAME);
|
|
break;
|
|
|
|
case 'I':
|
|
xstrncpy(msgline->callerid, &newline[6], VAH_MAX_CALLERID);
|
|
break;
|
|
|
|
case 'P':
|
|
xstrncpy(msgline->phone, &newline[6], VAH_MAX_PHONE);
|
|
break;
|
|
|
|
case 'L':
|
|
xstrncpy(msgline->location, &newline[6], VAH_MAX_LOCATION);
|
|
break;
|
|
|
|
case 'T':
|
|
msgline->ctime = (time_t)xstrtoul(&newline[6], 0);
|
|
break;
|
|
|
|
case 'M':
|
|
msgline->mtime = (time_t)xstrtoul(&newline[6], 0);
|
|
msgline->new = msgline->mtime > 0 ? TRUE : FALSE;
|
|
break;
|
|
|
|
case 'C':
|
|
msgline->compression = (int)xstrtol(&newline[6], 6);
|
|
break;
|
|
|
|
case 'S':
|
|
msgline->size = (int)xstrtol(&newline[6], 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newmessagesnr > 0)
|
|
{
|
|
if (messagesmp)
|
|
{
|
|
if (messagesnr > 0)
|
|
{
|
|
/*
|
|
* Try to merge the old and the new message list, so no status
|
|
* flags are lost.
|
|
*/
|
|
|
|
for (n = 0; n < newmessagesnr; n++)
|
|
{
|
|
msgline = (struct messageline *)(newmessagesmp + (sizeof(struct messageline) * n));
|
|
|
|
for (o = 0; o < messagesnr; o++)
|
|
{
|
|
mrgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * o));
|
|
|
|
if (strcmp(mrgline->messagename, msgline->messagename) == 0)
|
|
{
|
|
msgline->delete = mrgline->delete;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(messagesmp);
|
|
}
|
|
|
|
if (newmessagesnr != messagesnr) newmessys = TRUE;
|
|
|
|
messagesmp = newmessagesmp;
|
|
messagesnr = newmessagesnr;
|
|
|
|
qsort(messagesmp, messagesnr, sizeof(struct messageline), sort_message_list);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** sort_message_list(): Sorts the message list. **/
|
|
/**************************************************************************/
|
|
|
|
static int sort_message_list(const void *a, const void *b)
|
|
{
|
|
struct messageline *linea = (struct messageline *)a;
|
|
struct messageline *lineb = (struct messageline *)b;
|
|
|
|
if (lineb->ctime == linea->ctime) return( 0);
|
|
if (lineb->ctime < linea->ctime) return(-1);
|
|
|
|
return(1);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** init_locale(): Starts and initialize the locale functions. **/
|
|
/**************************************************************************/
|
|
|
|
static void init_locale(void)
|
|
{
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** one_line_down(): Moves cursor in message list one line down. **/
|
|
/**************************************************************************/
|
|
|
|
static void one_line_down(void)
|
|
{
|
|
if ((messagesnr > 0) && (messagesmp) && (messagenr < (messagesnr - 1)))
|
|
{
|
|
draw_message_line(messageyp, messagenr, FALSE);
|
|
|
|
messagenr++;
|
|
|
|
if (messageyp >= (LINES - 3))
|
|
{
|
|
wrefresh(stdscr);
|
|
scrollok(stdscr, TRUE);
|
|
wscrl(stdscr, 1);
|
|
scrollok(stdscr, FALSE);
|
|
}
|
|
else messageyp++;
|
|
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
}
|
|
else beep();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** one_line_up(): Moves cursor in message list one line up. **/
|
|
/**************************************************************************/
|
|
|
|
static void one_line_up(void)
|
|
{
|
|
if ((messagesnr > 0) && (messagesmp) && (messagenr > 0))
|
|
{
|
|
draw_message_line(messageyp, messagenr, FALSE);
|
|
|
|
messagenr--;
|
|
|
|
if (messageyp <= 4)
|
|
{
|
|
wrefresh(stdscr);
|
|
scrollok(stdscr, TRUE);
|
|
wscrl(stdscr, -1);
|
|
scrollok(stdscr, FALSE);
|
|
}
|
|
else messageyp--;
|
|
|
|
draw_message_line(messageyp, messagenr, TRUE);
|
|
}
|
|
else beep();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_message_line(): Draws one message line. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_message_line(int y, int nr, int selected)
|
|
{
|
|
struct tm *msgtime;
|
|
char strtime[32];
|
|
struct messageline *msgline;
|
|
chtype msgattr;
|
|
int secs;
|
|
int mins;
|
|
|
|
if ((messagesmp) && (messagesnr >= nr))
|
|
{
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * nr));
|
|
msgattr = (selected ? COLTAB(9) : COLTAB(8));
|
|
|
|
attrset(msgattr);
|
|
mvhline(y, 0, ' ', COLS);
|
|
|
|
mvprintw(y, 1, "%s", msgline->mtime > 0 ? "+" : "");
|
|
mvprintw(y, 1, "%s", msgline->delete ? "-" : "");
|
|
|
|
strcpy(strtime, "??-???-???? ??:??:??");
|
|
|
|
if ((msgtime = localtime(&msgline->ctime)))
|
|
{
|
|
strftime(strtime, 30, "%d-%b-%Y %H:%M:%S", msgtime);
|
|
}
|
|
|
|
secs = get_message_ptime(msgline->compression, msgline->size);
|
|
mins = (secs / 60);
|
|
secs = (secs - (mins * 60));
|
|
|
|
mvprintw(y, 3, "%s", strtime);
|
|
mvprintw(y, 25, "%02d:%02d", mins, secs),
|
|
mvprintw(y, 32, "%s", msgline->name);
|
|
|
|
if ((strcmp(msgline->phone, "*** Unknown ***")) != 0 && (strcmp(msgline->phone, "<not supported>") != 0) && (strcmp(msgline->phone, "") != 0))
|
|
{
|
|
mvprintw(y, COLS - 3 - strlen(msgline->phone), "%s P", msgline->phone);
|
|
}
|
|
else mvprintw(y, COLS - 3 - strlen(msgline->callerid), "%s I", msgline->callerid);
|
|
|
|
move(LINES - 2, 0);
|
|
|
|
if (selected) wrefresh(stdscr);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_ctrl_status(): Gets and draws the control status leds. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_ctrl_status(void)
|
|
{
|
|
char *answer;
|
|
int i;
|
|
int x;
|
|
chtype statuschar;
|
|
chtype statusattr;
|
|
|
|
i = 0;
|
|
x = 0;
|
|
|
|
while (statusleds[i].name)
|
|
{
|
|
statuschar = '-';
|
|
statusattr = COLTAB(7);
|
|
|
|
if (ledstatus)
|
|
{
|
|
if (i == 0) message("", "Getting control status...");
|
|
|
|
vboxd_put_message("statusctrl %s", statusleds[i].name);
|
|
|
|
statusleds[i].status = TRUE;
|
|
|
|
if ((answer = vboxd_get_message()))
|
|
{
|
|
if (vboxd_test_response(VBOXD_VAL_STATUSCTRLOK))
|
|
{
|
|
statuschar = ACS_DIAMOND;
|
|
|
|
if (answer[4] == '1')
|
|
{
|
|
statusleds[i].status = TRUE;
|
|
statusattr = i ? COLTAB(6) : COLTAB(5);
|
|
}
|
|
else
|
|
{
|
|
statusleds[i].status = FALSE;
|
|
statusattr = i ? COLTAB(7) : COLTAB(4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
attrset(statusattr);
|
|
mvaddch(0, statusleds[i].x, statuschar);
|
|
|
|
x = statusleds[i].x;
|
|
|
|
i++;
|
|
}
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_status_bar(): Draws the top status bar. This function also get **/
|
|
/** the control status information. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_status_bar(void)
|
|
{
|
|
char *helpmsg = "HELP";
|
|
int i;
|
|
int x;
|
|
|
|
attrset(COLTAB(2));
|
|
|
|
mvhline(0, 0, ' ', COLS);
|
|
mvvline(0, 3, ACS_VLINE, 1);
|
|
mvvline(0, (COLS - strlen(helpmsg) - 7), ACS_VLINE, 1);
|
|
|
|
wattrset(stdscr, COLTAB(2));
|
|
mvprintw(0, COLS - strlen(helpmsg) - 5, "( ) %s", helpmsg);
|
|
wattrset(stdscr, COLTAB(3));
|
|
mvprintw(0, COLS - strlen(helpmsg) - 4, "H");
|
|
|
|
i = 0;
|
|
x = 0;
|
|
|
|
while (statusleds[i].name)
|
|
{
|
|
x = statusleds[i].x;
|
|
|
|
i++;
|
|
}
|
|
|
|
attrset(COLTAB(2));
|
|
mvaddch(0, (x + 2), ACS_VLINE);
|
|
printw(" %s %s", PACKAGE, VERSION);
|
|
|
|
draw_ctrl_status();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_message_list(): Draws the message list. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_message_list(void)
|
|
{
|
|
char phone[30];
|
|
int m;
|
|
int y;
|
|
|
|
printstring(phone, "%28.28s", "Number");
|
|
|
|
wattrset(stdscr, COLTAB(10));
|
|
mvprintw(2, 1, "* %-20.20s", "Incoming date");
|
|
mvprintw(2, 25, "%5.5s", "Len");
|
|
mvprintw(2, 32, "%-28.28s", "Name");
|
|
mvprintw(2, COLS - 1 - strlen(phone), "%s", phone);
|
|
|
|
mvhline(3, 1, ACS_HLINE, (COLS - 2));
|
|
|
|
y = 4;
|
|
m = 0;
|
|
|
|
while (m < messagesnr)
|
|
{
|
|
draw_message_line(y, m, FALSE);
|
|
|
|
y++;
|
|
m++;
|
|
|
|
if (y >= (LINES - 2)) break;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** play_message(): Play the selected message. **/
|
|
/**************************************************************************/
|
|
|
|
static void play_message(int msg)
|
|
{
|
|
struct messageline *msgline;
|
|
char msgname[sizeof("/tmp/vboxXXXXXX\0")];
|
|
char *command;
|
|
char *answer;
|
|
int size;
|
|
int have;
|
|
int fd;
|
|
|
|
if ((!messagesmp) || (messagesnr < 1)) return;
|
|
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * msg));
|
|
if (!msgline)
|
|
{
|
|
message("\r\n", "No message found! (can't happen?) %s", "[RETURN]");
|
|
return;
|
|
}
|
|
strcpy(msgname, "/tmp/vboxXXXXXX");
|
|
if ((fd = mkstemp(msgname)) == -1)
|
|
{
|
|
message("\r\n", "Can't open temporary file! %s", "[RETURN]");
|
|
return;
|
|
}
|
|
|
|
message("", "Searching message...");
|
|
|
|
vboxd_put_message("message %s", msgline->messagename);
|
|
|
|
if ((answer = vboxd_get_message()))
|
|
{
|
|
if (vboxd_test_response(VBOXD_VAL_MESSAGE))
|
|
{
|
|
if ((size = (int)xstrtol(&answer[4], 0)) > 0)
|
|
{
|
|
message("", "Transfering message (%d bytes)...", size);
|
|
|
|
if ((have = load_message(fd, size)) == size)
|
|
{
|
|
message("", "Searching end sequence...");
|
|
|
|
if ((answer = vboxd_get_message()))
|
|
{
|
|
if (!vboxd_test_response(VBOXD_VAL_MESSAGE))
|
|
{
|
|
message("\r\n", "Can't get end sequence (bad response)! %s", "[RETURN]");
|
|
}
|
|
}
|
|
else message("\r\n", "Can't get end sequence! %s", "[RETURN]");
|
|
|
|
close_and_mone(fd);
|
|
|
|
size = 100 + strlen(msgname) + strlen(playerbin);
|
|
|
|
if ((command = malloc(size)))
|
|
{
|
|
message("", "Playing message...");
|
|
|
|
printstring(command, "%s %s %d 1>/dev/null 2>/dev/null", playerbin, msgname, sndvolume);
|
|
system(command);
|
|
free(command);
|
|
|
|
if (msgline->new) toggle_new_flag(msg);
|
|
}
|
|
}
|
|
else message("\n\r", "Can only get %d of %d bytes! %s", have, size, "[RETURN]");
|
|
}
|
|
else message("\r\n", "Message size is zero! %s", "[RETURN]");
|
|
}
|
|
else message("\r\n", "Can't get init sequence (bad response)! %s", "[RETURN]");
|
|
}
|
|
else message("\r\n", "Can't get init sequence! %s", "[RETURN]");
|
|
|
|
if (fd != -1) close(fd);
|
|
|
|
unlink(msgname);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** load_message(): Loads the message from server. **/
|
|
/**************************************************************************/
|
|
|
|
static int load_message(int fd, int size)
|
|
{
|
|
struct timeval timeval;
|
|
fd_set rmask;
|
|
|
|
unsigned char temp[256];
|
|
int have;
|
|
int take;
|
|
int rc;
|
|
|
|
have = 0;
|
|
|
|
while (have < size)
|
|
{
|
|
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;
|
|
|
|
if ((take = (size - have)) > 255) take = 255;
|
|
|
|
rc = read(vboxd_r_fd, temp, take);
|
|
|
|
if (rc <= 0)
|
|
{
|
|
if ((rc < 0) && (errno == EINTR)) continue;
|
|
|
|
break;
|
|
}
|
|
|
|
have += rc;
|
|
|
|
write(fd, temp, rc);
|
|
}
|
|
|
|
return(have);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** message(): Prints a message into the bottom bar. The function can **/
|
|
/** also wait for a special keypress. While waiting, a NOOP **/
|
|
/** message is send all 10 seconds. **/
|
|
/**************************************************************************/
|
|
|
|
static int message(char *keys, char *fmt, ...)
|
|
{
|
|
char message[256];
|
|
va_list arg;
|
|
int k;
|
|
int timernoop;
|
|
int returnkey;
|
|
|
|
va_start(arg, fmt);
|
|
vnprintstring(message, 255, fmt, arg);
|
|
va_end(arg);
|
|
|
|
attrset(COLTAB(2));
|
|
mvhline(LINES - 1, 0, ' ', COLS);
|
|
mvprintw(LINES - 1, 1, "%s", message);
|
|
wrefresh(stdscr);
|
|
|
|
returnkey = -1;
|
|
|
|
if ((keys) && (*keys))
|
|
{
|
|
timeout(1000);
|
|
noecho();
|
|
cbreak();
|
|
beep();
|
|
refresh();
|
|
|
|
timernoop = 0;
|
|
|
|
while (returnkey == -1)
|
|
{
|
|
k = wgetch(stdscr);
|
|
|
|
if (k == ERR)
|
|
{
|
|
if (timernoop++ > 10)
|
|
{
|
|
vboxd_put_message("noop");
|
|
|
|
timernoop = 0;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (index(keys, k)) returnkey = k;
|
|
}
|
|
|
|
draw_bottom_bar();
|
|
}
|
|
|
|
return(returnkey);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** draw_bottom_bar(): Draws the bottom bar. **/
|
|
/**************************************************************************/
|
|
|
|
static void draw_bottom_bar(void)
|
|
{
|
|
struct passwd *pass;
|
|
char temp[32];
|
|
char svol[16];
|
|
|
|
attrset(COLTAB(2));
|
|
mvhline(LINES - 1, 0, ' ', COLS);
|
|
|
|
printstring(temp, "%d/%d", messagesnr, count_new_messages());
|
|
printstring(svol, "%d", sndvolume);
|
|
|
|
mvhline(LINES - 1, COLS - strlen(temp) - 3, ACS_VLINE, 1);
|
|
mvhline(LINES - 1, COLS - strlen(temp) - strlen(svol) - 6, ACS_VLINE, 1);
|
|
|
|
mvprintw(LINES - 1, COLS - strlen(temp) - 1, "%s", temp);
|
|
mvprintw(LINES - 1, COLS - strlen(temp) - strlen(svol) - 4, "%s", svol);
|
|
|
|
mvprintw(LINES - 1, 1, "%s", loginname);
|
|
|
|
if ((pass = getpwuid(getuid())))
|
|
{
|
|
mvprintw(LINES - 1, 2 + strlen(loginname), "[%s]", pass->pw_name);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** count_new_messages(): Counts new messages in the message list. **/
|
|
/**************************************************************************/
|
|
|
|
static int count_new_messages(void)
|
|
{
|
|
struct messageline *msgline;
|
|
int newmsgs;
|
|
int i;
|
|
|
|
newmsgs = 0;
|
|
|
|
if ((messagesmp) && (messagesnr > 0))
|
|
{
|
|
for (i = 0; i < messagesnr; i++)
|
|
{
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * i));
|
|
|
|
if (msgline->new) newmsgs++;
|
|
}
|
|
}
|
|
|
|
return(newmsgs);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/** set_window_background(): Clears a windows. **/
|
|
/**************************************************************************/
|
|
|
|
static void set_window_background(WINDOW *win, chtype col)
|
|
{
|
|
int y;
|
|
|
|
wattrset(win, col);
|
|
|
|
for (y = 0; y < (win->_maxy + 1); y++)
|
|
{
|
|
mvwhline(win, y, 0, ' ', (win->_maxx + 1));
|
|
}
|
|
}
|
|
|
|
static void messageinfo(int nr)
|
|
{
|
|
struct messageline *msgline;
|
|
WINDOW *win;
|
|
PANEL *pan;
|
|
int h;
|
|
int w;
|
|
char *t;
|
|
char *b;
|
|
int n;
|
|
int done;
|
|
|
|
if ((!messagesmp) || (messagesnr < nr)) return;
|
|
|
|
msgline = (struct messageline *)(messagesmp + (sizeof(struct messageline) * nr));
|
|
|
|
w = 51;
|
|
h = 15;
|
|
n = 0;
|
|
t = " INFO ";
|
|
b = " Press 'Q' to quit ";
|
|
|
|
if ((win = newwin(h, w, ((LINES - h) / 2), ((COLS - w) / 2))))
|
|
{
|
|
if ((pan = new_panel(win)))
|
|
{
|
|
set_window_background(win, color(15));
|
|
wattrset(win, color(16));
|
|
box(win, ACS_VLINE, ACS_HLINE);
|
|
|
|
mvwprintw(win, 0, ((w - strlen(t)) / 2), "%s", t);
|
|
mvwprintw(win, (h - 1), ((w - strlen(b)) / 2), "%s", b);
|
|
|
|
wattrset(win, color(15));
|
|
|
|
mvwprintw(win, 2, 3, "Filename : %-32.32s", msgline->messagename);
|
|
mvwprintw(win, 3, 3, "CTime : %ld", msgline->ctime);
|
|
mvwprintw(win, 4, 3, "MTime : %ld", msgline->mtime);
|
|
mvwprintw(win, 5, 3, "Compression: %d", msgline->compression);
|
|
mvwprintw(win, 6, 3, "Size : %d", msgline->size);
|
|
mvwprintw(win, 7, 3, "Name : %-32.32s", msgline->name);
|
|
mvwprintw(win, 8, 3, "CallerID : %-32.32s", msgline->callerid);
|
|
mvwprintw(win, 9, 3, "Phone : %-32.32s", msgline->phone);
|
|
mvwprintw(win, 10, 3, "Location : %-32.32s", msgline->location);
|
|
mvwprintw(win, 11, 3, "Flag new : %s", (msgline->new ? "Yes" : "No"));
|
|
mvwprintw(win, 12, 3, "Flag delete: %s", (msgline->delete ? "Yes" : "No"));
|
|
|
|
update_panels();
|
|
wrefresh(win);
|
|
wmove(win, (h - 2), (w - 2));
|
|
|
|
cbreak();
|
|
noecho();
|
|
wtimeout(win, 1000);
|
|
|
|
done = FALSE;
|
|
|
|
while (!done)
|
|
{
|
|
switch (wgetch(win))
|
|
{
|
|
case ERR:
|
|
if (++n > 30)
|
|
{
|
|
vboxd_put_message("NOOP");
|
|
|
|
n = 0;
|
|
}
|
|
break;
|
|
|
|
case 'Q':
|
|
case 'q':
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
del_panel(pan);
|
|
}
|
|
|
|
delwin(win);
|
|
}
|
|
}
|