#include <sys/wait.h>
#include <signal.h>
#include <locale.h>
+#include <getopt.h>
#include "spiceterm.h"
#include <spice/macros.h>
#include <spice/qxl_dev.h>
-#include <gdk/gdkkeysyms.h>
-
#include "event_loop.h"
#include "translations.h"
#define TERMIDCODE "[?1;2c" // vt100 ID
-#define CHECK_ARGC(argc,argv,i) if (i >= argc-1) { \
- fprintf(stderr, "ERROR: not enough arguments for: %s\n", argv[i]); \
- print_usage(NULL); \
- exit(1); \
-}
-
/* these colours are from linux kernel drivers/char/vt.c */
unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15 };
-
-static void spiceterm_resize(spiceTerm *vt, uint32_t width, uint32_t height);
-
-static void vdagent_grab_clipboard(spiceTerm *vt, uint8_t selection);
-static void vdagent_request_clipboard(spiceTerm *vt, uint8_t selection);
-
-static void
-print_usage(const char *msg)
-{
- if (msg) { fprintf(stderr, "ERROR: %s\n", msg); }
- fprintf(stderr, "USAGE: spiceterm [spiceopts] [-c command [args]]\n");
-}
-
static void
draw_char_at(spiceTerm *vt, int x, int y, gunichar2 ch, TextAttributes attrib)
{
}
}
-static void
+void
spiceterm_refresh(spiceTerm *vt)
{
int x, y, y1;
spiceterm_show_cursor(vt, 1);
}
+static void
+spiceterm_clear_screen(spiceTerm *vt)
+{
+ int x, y;
+
+ for (y = 0; y <= vt->height; y++) {
+ int y1 = (vt->y_base + y) % vt->total_height;
+ TextCell *c = &vt->cells[y1 * vt->width];
+ for (x = 0; x < vt->width; x++) {
+ c->ch = ' ';
+ c->attrib = vt->default_attrib;
+ c->attrib.fgcol = vt->cur_attrib.fgcol;
+ c->attrib.bgcol = vt->cur_attrib.bgcol;
+
+ c++;
+ }
+ }
+
+ spice_screen_clear(vt->screen, 0, 0, vt->screen->primary_width,
+ vt->screen->primary_height);
+}
+
void
spiceterm_unselect_all(spiceTerm *vt)
{
- int i;
+ int x, y, y1;
- for (i = 0; i < vt->width*vt->total_height; i++) {
- if (vt->cells[i].attrib.selected) {
- vt->cells[i].attrib.selected = 0;
+ y1 = vt->y_displ;
+ for(y = 0; y < vt->total_height; y++) {
+ TextCell *c = vt->cells + y1 * vt->width;
+ for(x = 0; x < vt->width; x++) {
+ if (c->attrib.selected) {
+ c->attrib.selected = 0;
+ if (y < vt->height) {
+ draw_char_at(vt, x, y, c->ch, c->attrib);
+ }
+ }
+ c++;
}
+ if (++y1 == vt->total_height)
+ y1 = 0;
}
-
- spiceterm_refresh(vt);
}
static void
}
}
-static void
+void
spiceterm_virtual_scroll(spiceTerm *vt, int lines)
{
if (vt->altbuf || lines == 0) return;
spiceterm_refresh(vt);
}
-static void
+void
spiceterm_respond_esc(spiceTerm *vt, const char *esc)
{
int len = strlen(esc);
for (i = 0; i < len; i++) {
vt->ibuf[vt->ibuf_count++] = esc[i];
}
+ } else {
+ fprintf(stderr, "input buffer oferflow\n");
+ return;
+ }
+}
+
+void
+spiceterm_respond_data(spiceTerm *vt, int len, uint8_t *data)
+{
+ int i;
+
+ if (vt->ibuf_count < (IBUFSIZE - len)) {
+ for (i = 0; i < len; i++) {
+ vt->ibuf[vt->ibuf_count++] = data[i];
+ }
+ } else {
+ fprintf(stderr, "input buffer oferflow\n");
+ return;
}
}
break;
case 2:
/* clear entire screen */
- for (y = 0; y <= vt->height; y++) {
- for (x = 0; x < vt->width; x++) {
- spiceterm_clear_xy(vt, x, y);
- }
- }
+ spiceterm_clear_screen(vt);
break;
}
break;
vt->utf_char = (vt->utf_char << 6) | (c & 0x3f);
vt->utf_count--;
if (vt->utf_count == 0) {
- tc = vt->utf_char;
+ if (vt->utf_char <= G_MAXUINT16) {
+ tc = vt->utf_char;
+ } else {
+ tc = 0;
+ }
} else {
continue;
}
return len;
}
-/* fixme:
void
-spiceterm_set_xcut_text(char* str, int len, struct _rfbClientRec* cl)
-{
- spiceTerm *vt =(spiceTerm *)cl->screen->screenData;
-
- // seems str is Latin-1 encoded
- if (vt->selection) free (vt->selection);
- vt->selection = (gunichar2 *)malloc (len*sizeof (gunichar2));
- int i;
- for (i = 0; i < len; i++) {
- vt->selection[i] = str[i] & 0xff;
- }
- vt->selection_len = len;
-}
-*/
-
-static void
spiceterm_update_watch_mask(spiceTerm *vt, gboolean writable)
{
g_assert(vt != NULL);
gint len = g_unichar_to_utf8(uc, buf);
if (len > 0) {
- if ((vt->ibuf_count + len) < IBUFSIZE) {
- int i;
- for (i = 0; i < len; i++) {
- vt->ibuf[vt->ibuf_count++] = buf[i];
- }
- } else {
- fprintf(stderr, "warning: input buffer overflow\n");
- }
+ spiceterm_respond_data(vt, len, (uint8_t *)buf);
}
} else {
- if ((vt->ibuf_count + 1) < IBUFSIZE) {
- vt->ibuf[vt->ibuf_count++] = (char)uc;
- } else {
- fprintf(stderr, "warning: input buffer overflow\n");
- }
+ uint8_t buf[1] = { (uint8_t)uc };
+ spiceterm_respond_data(vt, 1, buf);
}
}
-static void
-my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
-{
- // spiceTerm *vt = SPICE_CONTAINEROF(sin, spiceTerm, keyboard_sin);
-
- /* we no not need this */
-
- return;
-}
-
-static void
-spiceterm_push_keyval(spiceTerm *vt, uint32_t keySym, uint32_t flags)
+void
+spiceterm_clear_selection(spiceTerm *vt)
{
- static int control = 0;
- static int shift = 0;
- char *esc = NULL;
-
- gunichar2 uc = 0;
-
- DPRINTF(1, "flags=%d keySym=%08x", flags, keySym);
-
- if (flags & VD_AGENT_KEYVAL_FLAG_DOWN) {
- if (keySym == GDK_KEY_Shift_L || keySym == GDK_KEY_Shift_R) {
- shift = 1;
- } if (keySym == GDK_KEY_Control_L || keySym == GDK_KEY_Control_R) {
- control = 1;
- } else if (vt->ibuf_count < (IBUFSIZE - 32)) {
-
- if (control) {
- if(keySym >= 'a' && keySym <= 'z')
- uc = keySym - 'a' + 1;
- else if (keySym >= 'A' && keySym <= 'Z')
- uc = keySym - 'A' + 1;
- else
- uc = 0;
+ DPRINTF(1, "mark_active = %d", vt->mark_active);
- } else {
- switch (keySym) {
- case GDK_KEY_Escape:
- uc = 27; break;
- case GDK_KEY_Return:
- uc = '\r'; break;
- case GDK_KEY_BackSpace:
- uc = 8; break;
- case GDK_KEY_Tab:
- uc = '\t'; break;
- case GDK_KEY_Delete: /* kdch1 */
- case GDK_KEY_KP_Delete:
- esc = "[3~";break;
- case GDK_KEY_Home: /* khome */
- case GDK_KEY_KP_Home:
- esc = "OH";break;
- case GDK_KEY_End:
- case GDK_KEY_KP_End: /* kend */
- esc = "OF";break;
- case GDK_KEY_Insert: /* kich1 */
- case GDK_KEY_KP_Insert:
- esc = "[2~";break;
- case GDK_KEY_Up:
- case GDK_KEY_KP_Up: /* kcuu1 */
- esc = "OA";break;
- case GDK_KEY_Down: /* kcud1 */
- case GDK_KEY_KP_Down:
- esc = "OB";break;
- case GDK_KEY_Right:
- case GDK_KEY_KP_Right: /* kcuf1 */
- esc = "OC";break;
- case GDK_KEY_Left:
- case GDK_KEY_KP_Left: /* kcub1 */
- esc = "OD";break;
- case GDK_KEY_Page_Up:
- if (shift) {
- spiceterm_virtual_scroll (vt, -vt->height/2);
- goto ret;
- }
- esc = "[5~";break;
- case GDK_KEY_Page_Down:
- if (shift) {
- spiceterm_virtual_scroll (vt, vt->height/2);
- goto ret;
- }
- esc = "[6~";break;
- case GDK_KEY_F1:
- esc = "OP";break;
- case GDK_KEY_F2:
- esc = "OQ";break;
- case GDK_KEY_F3:
- esc = "OR";break;
- case GDK_KEY_F4:
- esc = "OS";break;
- case GDK_KEY_F5:
- esc = "[15~";break;
- case GDK_KEY_F6:
- esc = "[17~";break;
- case GDK_KEY_F7:
- esc = "[18~";break;
- case GDK_KEY_F8:
- esc = "[19~";break;
- case GDK_KEY_F9:
- esc = "[20~";break;
- case GDK_KEY_F10:
- esc = "[21~";break;
- case GDK_KEY_F11:
- esc = "[23~";break;
- case GDK_KEY_F12:
- esc = "[24~";break;
- default:
- if (keySym < 0x100) {
- uc = keySym;
- }
- break;
- }
- }
-
- DPRINTF(1, "escape=%s unicode=%08x\n", esc, uc);
-
- if (vt->y_displ != vt->y_base) {
- vt->y_displ = vt->y_base;
- spiceterm_refresh(vt);
- }
-
- if (esc) {
- spiceterm_respond_esc(vt, esc);
- } else if (uc > 0) {
- spiceterm_respond_unichar2(vt, uc);
- }
- }
- }
-
-ret:
-
- if (!(flags & VD_AGENT_KEYVAL_FLAG_DOWN)) { // UP
- if (keySym == GDK_KEY_Shift_L || keySym == GDK_KEY_Shift_R) {
- shift = 0;
- } else if (keySym == GDK_KEY_Control_L || keySym == GDK_KEY_Control_R) {
- control = 0;
- }
- }
-
- spiceterm_update_watch_mask(vt, TRUE);
-}
-
-static uint8_t
-my_kbd_get_leds(SpiceKbdInstance *sin)
-{
- return 0;
+ vt->mark_active = 0;
+ if (vt->selection) free (vt->selection);
+ vt->selection = NULL;
+
+ spiceterm_unselect_all(vt);
}
-
-static SpiceKbdInterface my_keyboard_sif = {
- .base.type = SPICE_INTERFACE_KEYBOARD,
- .base.description = "spiceterm keyboard device",
- .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR,
- .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
- .push_scan_freg = my_kbd_push_key,
- .get_leds = my_kbd_get_leds,
-};
-
-
-/* vdagent interface - to get mouse/clipboarde support */
-
-#define VDAGENT_WBUF_SIZE (1024*50)
-static unsigned char vdagent_write_buffer[VDAGENT_WBUF_SIZE];
-static int vdagent_write_buffer_pos = 0;
-static int agent_owns_clipboard[256] = { 0, };
-
-static void
+
+void
spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons)
{
DPRINTF(1, "mask=%08x x=%d y=%d", buttons, x ,y);
if(button2_released) {
- if (agent_owns_clipboard[VD_AGENT_CLIPBOARD_SELECTION_PRIMARY]) {
+ if (vdagent_owns_clipboard(vt)) {
if (vt->selection) {
int i;
for(i = 0; i < vt->selection_len; i++) {
}
}
} else {
- vdagent_request_clipboard(vt, VD_AGENT_CLIPBOARD_SELECTION_PRIMARY);
+ vdagent_request_clipboard(vt);
}
}
DPRINTF(1, "selection length = %d", vt->selection_len);
- vdagent_grab_clipboard(vt, VD_AGENT_CLIPBOARD_SELECTION_PRIMARY);
- }
-}
-
-static void
-vdagent_reply(spiceTerm *vt, uint32_t type, uint32_t error)
-{
- uint32_t size;
-
- size = sizeof(VDAgentReply);
-
- int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
- g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE);
-
- unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
- vdagent_write_buffer_pos += msg_size;
-
- memset(buf, 0, msg_size);
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
- VDAgentReply *reply = (VDAgentReply *)&msg[1];
- reply->type = type;
- reply->error = error;
-
- hdr->port = VDP_CLIENT_PORT;
- hdr->size = sizeof(VDAgentMessage) + size;
-
- msg->protocol = VD_AGENT_PROTOCOL;
- msg->type = VD_AGENT_REPLY;
- msg->opaque = 0;
- msg->size = size;
-
- spice_server_char_device_wakeup(&vt->vdagent_sin);
-}
-
-static void
-dump_message(unsigned char *buf, int size)
-{
- int i;
-
- for (i = 0; i < size; i++) {
- printf("%d %02X\n", i, buf[i]);
+ vdagent_grab_clipboard(vt);
}
-
- // exit(0);
}
-static void vdagent_send_capabilities(spiceTerm *vt, uint32_t request)
-{
- VDAgentAnnounceCapabilities *caps;
- uint32_t size;
-
- size = sizeof(*caps) + VD_AGENT_CAPS_BYTES;
- caps = calloc(1, size);
- g_assert(caps != NULL);
-
- caps->request = request;
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF);
- VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_KEYVAL);
-
- int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
- g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE);
-
- unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
- vdagent_write_buffer_pos += msg_size;
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
-
- hdr->port = VDP_CLIENT_PORT;
- hdr->size = sizeof(VDAgentMessage) + size;
- msg->protocol = VD_AGENT_PROTOCOL;
- msg->type = VD_AGENT_ANNOUNCE_CAPABILITIES;
- msg->opaque = 0;
- msg->size = size;
-
- memcpy(buf + sizeof(VDIChunkHeader) + sizeof(VDAgentMessage), (uint8_t *)caps, size);
-
- if (0) dump_message(buf, msg_size);
-
- spice_server_char_device_wakeup(&vt->vdagent_sin);
-
- free(caps);
-}
-
-static void vdagent_grab_clipboard(spiceTerm *vt, uint8_t selection)
-{
- uint32_t size;
-
- agent_owns_clipboard[selection] = 1;
-
- size = 8;
-
- int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
- g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE);
-
- unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
- vdagent_write_buffer_pos += msg_size;
-
- memset(buf, 0, msg_size);
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
- uint8_t *grab = (uint8_t *)&msg[1];
- *((uint8_t *)grab) = selection;
- *((uint32_t *)(grab + 4)) = VD_AGENT_CLIPBOARD_UTF8_TEXT;
-
- hdr->port = VDP_CLIENT_PORT;
- hdr->size = sizeof(VDAgentMessage) + size;
-
- msg->protocol = VD_AGENT_PROTOCOL;
- msg->type = VD_AGENT_CLIPBOARD_GRAB;
- msg->opaque = 0;
- msg->size = size;
-
- if (0) dump_message(buf, msg_size);
-
- spice_server_char_device_wakeup(&vt->vdagent_sin);
-}
-
-static void vdagent_request_clipboard(spiceTerm *vt, uint8_t selection)
-{
- uint32_t size;
-
- agent_owns_clipboard[selection] = 1;
-
- size = 4 + sizeof(VDAgentClipboardRequest);
-
- int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
- g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE);
-
- unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
- vdagent_write_buffer_pos += msg_size;
-
- memset(buf, 0, msg_size);
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
- uint8_t *data = (uint8_t *)&msg[1];
- *((uint32_t *)data) = 0;
- data[0] = selection;
- ((uint32_t *)data)[1] = VD_AGENT_CLIPBOARD_UTF8_TEXT;
-
- hdr->port = VDP_CLIENT_PORT;
- hdr->size = sizeof(VDAgentMessage) + size;
-
- msg->protocol = VD_AGENT_PROTOCOL;
- msg->type = VD_AGENT_CLIPBOARD_REQUEST;
- msg->opaque = 0;
- msg->size = size;
-
- if (0) dump_message(buf, msg_size);
-
- spice_server_char_device_wakeup(&vt->vdagent_sin);
-}
-
-static void vdagent_send_clipboard(spiceTerm *vt, uint8_t selection)
-{
- uint32_t size;
-
- if (selection != VD_AGENT_CLIPBOARD_SELECTION_PRIMARY) {
- fprintf(stderr, "clipboard select %d is not supported\n", selection);
- return;
- }
-
- gchar *sel_data;
- glong sel_len;
- if (vt->utf8) {
- sel_data = g_utf16_to_utf8(vt->selection, vt->selection_len, NULL, &sel_len, NULL);
- } else {
- sel_len = vt->selection_len;
- sel_data = g_malloc(sel_len);
- int i;
- for (i = 0; i < sel_len; i++) { sel_data[i] = (char)vt->selection[i]; }
- sel_data[sel_len] = 0;
- }
-
- size = 8 + sel_len;
-
- int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
- g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE);
-
- unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
- vdagent_write_buffer_pos += msg_size;
-
- memset(buf, 0, msg_size);
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
- uint8_t *data = (uint8_t *)&msg[1];
- *((uint8_t *)data) = selection;
- data += 4;
- *((uint32_t *)data) = VD_AGENT_CLIPBOARD_UTF8_TEXT;
- data += 4;
-
- memcpy(data, sel_data, sel_len);
- g_free(sel_data);
-
- hdr->port = VDP_CLIENT_PORT;
- hdr->size = sizeof(VDAgentMessage) + size;
-
- msg->protocol = VD_AGENT_PROTOCOL;
- msg->type = VD_AGENT_CLIPBOARD;
- msg->opaque = 0;
- msg->size = size;
-
- spice_server_char_device_wakeup(&vt->vdagent_sin);
-}
-
-static int
-vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-{
- spiceTerm *vt = SPICE_CONTAINEROF(sin, spiceTerm, vdagent_sin);
-
- VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
- VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
-
- //g_assert(hdr->port == VDP_SERVER_PORT);
- g_assert(msg->protocol == VD_AGENT_PROTOCOL);
-
- DPRINTF(1, "%d %d %d %d", len, hdr->port, msg->protocol, msg->type);
-
- switch (msg->type) {
- case VD_AGENT_KEYVAL: {
- VDAgentKeyval *info = (VDAgentKeyval *)&msg[1];
- spiceterm_push_keyval(vt, info->keyval, info->flags);
- break;
- }
- case VD_AGENT_MOUSE_STATE: {
- VDAgentMouseState *info = (VDAgentMouseState *)&msg[1];
- spiceterm_motion_event(vt, info->x, info->y, info->buttons);
- break;
- }
- case VD_AGENT_ANNOUNCE_CAPABILITIES: {
- VDAgentAnnounceCapabilities *caps = (VDAgentAnnounceCapabilities *)&msg[1];
- DPRINTF(1, "VD_AGENT_ANNOUNCE_CAPABILITIES %d", caps->request);
- int i;
-
- int caps_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(hdr->size);
- for (i = 0; i < VD_AGENT_END_CAP; i++) {
- DPRINTF(1, "CAPABILITIES %d %d", i, VD_AGENT_HAS_CAPABILITY(caps->caps, caps_size, i));
- }
-
- vdagent_send_capabilities(vt, 0);
- break;
- }
- case VD_AGENT_CLIPBOARD_GRAB: {
- VDAgentClipboardGrab *grab = (VDAgentClipboardGrab *)&msg[1];
- uint8_t selection = *((uint8_t *)grab);
- DPRINTF(1, "VD_AGENT_CLIPBOARD_GRAB %d", selection);
- agent_owns_clipboard[selection] = 0;
- break;
- }
- case VD_AGENT_CLIPBOARD_REQUEST: {
- uint8_t *req = (uint8_t *)&msg[1];
- uint8_t selection = *((uint8_t *)req);
- uint32_t type = *((uint32_t *)(req + 4));
-
- DPRINTF(1, "VD_AGENT_CLIPBOARD_REQUEST %d %d", selection, type);
-
- vdagent_send_clipboard(vt, selection);
-
- break;
- }
- case VD_AGENT_CLIPBOARD: {
- uint8_t *data = (uint8_t *)&msg[1];
- uint8_t selection = data[0];
- uint32_t type = *(uint32_t *)(data + 4);
- int size = msg->size - 8;
- DPRINTF(1, "VD_AGENT_CLIPBOARD %d %d %d", selection, type, size);
-
- if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
- int i;
- for (i = 0; i < size; i++) {
- if ((vt->ibuf_count + 1) < IBUFSIZE) {
- vt->ibuf[vt->ibuf_count++] = *(char *)(data + 8 + i);
- } else {
- fprintf(stderr, "warning: input buffer overflow\n");
- }
- }
- spiceterm_update_watch_mask(vt, TRUE);
- }
- break;
- }
- case VD_AGENT_CLIPBOARD_RELEASE: {
- uint8_t *data = (uint8_t *)&msg[1];
- uint8_t selection = data[0];
-
- DPRINTF(0, "VD_AGENT_CLIPBOARD_RELEASE %d", selection);
-
- break;
- }
- case VD_AGENT_MONITORS_CONFIG: {
- VDAgentMonitorsConfig *list = (VDAgentMonitorsConfig *)&msg[1];
- g_assert(list->num_of_monitors > 0);
- DPRINTF(0, "VD_AGENT_MONITORS_CONFIG %d %d %d", list->num_of_monitors,
- list->monitors[0].width, list->monitors[0].height);
-
- spiceterm_resize(vt, list->monitors[0].width, list->monitors[0].height);
-
- vdagent_reply(vt, VD_AGENT_MONITORS_CONFIG, VD_AGENT_SUCCESS);
- break;
- }
- default:
- DPRINTF(0, "got uknown vdagent message type %d\n", msg->type);
- }
-
- return len;
-}
-
-static int
-vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-{
- DPRINTF(1, "%d %d", len, vdagent_write_buffer_pos);
- g_assert(len >= 8);
-
- if (!vdagent_write_buffer_pos) {
- return 0;
- }
-
- int size = (len >= vdagent_write_buffer_pos) ? vdagent_write_buffer_pos : len;
- memcpy(buf, vdagent_write_buffer, size);
- if (size < vdagent_write_buffer_pos) {
- memmove(vdagent_write_buffer, vdagent_write_buffer + size,
- vdagent_write_buffer_pos - size);
- }
- vdagent_write_buffer_pos -= size;
-
- DPRINTF(1, "RET %d %d", size, vdagent_write_buffer_pos);
- return size;
-}
-
-static void
-vmc_state(SpiceCharDeviceInstance *sin, int connected)
-{
- /* IGNORE */
-}
-
-static SpiceCharDeviceInterface my_vdagent_sif = {
- .base.type = SPICE_INTERFACE_CHAR_DEVICE,
- .base.description = "spice virtual channel char device",
- .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
- .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
- .state = vmc_state,
- .write = vmc_write,
- .read = vmc_read,
-};
-
-static void
+void
init_spiceterm(spiceTerm *vt, uint32_t width, uint32_t height)
{
int i;
vt->altcells = (TextCell *)calloc (sizeof (TextCell), vt->width*vt->height);
}
-static void
+void
spiceterm_resize(spiceTerm *vt, uint32_t width, uint32_t height)
{
- DPRINTF(0, "width=%u height=%u", width, height);
-
+ width = (width/8)*8;
+ height = (height/16)*16;
+
if (vt->screen->width == width && vt->screen->height == height) {
return;
}
+ DPRINTF(0, "width=%u height=%u", width, height);
+
spice_screen_resize(vt->screen, width, height);
init_spiceterm(vt, width, height);
ioctl(vt->pty, TIOCSWINSZ, &dimensions);
}
-static spiceTerm *
-create_spiceterm(int argc, char** argv, uint32_t maxx, uint32_t maxy, guint timeout)
-{
- SpiceCoreInterface *core = basic_event_loop_init();
- SpiceScreen *spice_screen = spice_screen_new(core, maxx, maxy, timeout);
-
- //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF);
-
- spiceTerm *vt = (spiceTerm *)calloc (sizeof(spiceTerm), 1);
-
- vt->keyboard_sin.base.sif = &my_keyboard_sif.base;
- spice_server_add_interface(spice_screen->server, &vt->keyboard_sin.base);
-
- vt->vdagent_sin.base.sif = &my_vdagent_sif.base;
- vt->vdagent_sin.subtype = "vdagent";
- spice_server_add_interface(spice_screen->server, &vt->vdagent_sin.base);
- vt->screen = spice_screen;
-
- init_spiceterm(vt, maxx, maxy);
-
- return vt;
-}
-
static gboolean
master_error_callback(GIOChannel *channel, GIOCondition condition,
gpointer data)
}
}
+static void
+spiceterm_print_usage(const char *msg)
+{
+ if (msg) {
+ fprintf(stderr, "ERROR: %s\n", msg);
+ }
+ fprintf(stderr, "USAGE: spiceterm [OPTIONS] [-- command [args]]\n");
+ fprintf(stderr, " --timeout <seconds> Wait this time before aborting (default is 10 seconds)\n");
+ fprintf(stderr, " --authpath <path> Authentication path (PVE AUTH)\n");
+ fprintf(stderr, " --permission <perm> Required permissions (PVE AUTH)\n");
+ fprintf(stderr, " --port <port> Bind to port <port>\n");
+ fprintf(stderr, " --addr <addr> Bind to address <addr>\n");
+ fprintf(stderr, " --sasl Enable SASL based authentication\n");
+ fprintf(stderr, " --noauth Disable authentication\n");
+ fprintf(stderr, " --keymap Spefify keymap (uses kvm keymap files)\n");
+}
+
int
main (int argc, char** argv)
{
- int i;
+ int c;
char **cmdargv = NULL;
char *command = "/bin/bash"; // execute normal shell as default
int pid;
int master;
char ptyname[1024];
struct winsize dimensions;
-
- g_thread_init(NULL);
-
- for (i = 1; i < argc; i++) {
- if (!strcmp (argv[i], "-c")) {
- command = argv[i+1];
- cmdargv = &argv[i+1];
- argc = i;
- argv[i] = NULL;
+ SpiceTermOptions opts = {
+ .timeout = 10,
+ .port = 5900,
+ .addr = NULL,
+ .noauth = FALSE,
+ .sasl = FALSE,
+ };
+
+ static struct option long_options[] = {
+ { "timeout", required_argument, 0, 't' },
+ { "authpath", required_argument, 0, 'A' },
+ { "permissions", required_argument, 0, 'P' },
+ { "port", required_argument, 0, 'p' },
+ { "addr", required_argument, 0, 'a' },
+ { "keymap", required_argument, 0, 'k' },
+ { "noauth", no_argument, 0, 'n' },
+ { "sasl", no_argument, 0, 's' },
+ { NULL, 0, 0, 0 },
+ };
+
+ while ((c = getopt_long(argc, argv, "nkst:a:p:P:", long_options, NULL)) != -1) {
+
+ switch (c) {
+ case 'n':
+ opts.noauth = TRUE;
+ break;
+ case 's':
+ opts.sasl = TRUE;
+ break;
+ case 'k':
+ opts.keymap = optarg;
+ break;
+ case 'A':
+ pve_auth_set_path(optarg);
+ break;
+ case 'P':
+ pve_auth_set_permissions(optarg);
break;
+ case 'p':
+ opts.port = atoi(optarg);
+ break;
+ case 'a':
+ opts.addr = optarg;
+ break;
+ case 't':
+ opts.timeout = atoi(optarg);
+ break;
+ case '?':
+ spiceterm_print_usage(NULL);
+ exit(-1);
+ break;
+ default:
+ spiceterm_print_usage("getopt returned unknown character code");
+ exit(-1);
}
}
+
+ if (optind < argc) {
+ command = argv[optind];
+ cmdargv = &argv[optind];
+ }
- if (0) print_usage(NULL); // fixme:
-
- spiceTerm *vt = create_spiceterm (argc, argv, 745, 400, 10);
+ spiceTerm *vt = spiceterm_create(744, 400, &opts);
+ if (!vt)
+ exit(-1);
setlocale(LC_ALL, ""); // set from environment