ctrl.c revision 6e9aa255e3376b2da5824c09c4c62bc233463bfe
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Copyright 2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Oracle elects to use only
* the General Public License version 2 (GPLv2) at this time for any software where
* a choice of GPL license versions is made available with the language indicating
* that GPLv2 or any later version may be used, or where a choice of which version
* of the GPL is applied is otherwise unspecified.
*/
#include "rdesktop.h"
#include "ssl.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#define CTRL_LINEBUF_SIZE 1024
#define CTRL_RESULT_SIZE 32
#define RDESKTOP_CTRLSOCK_STORE "/.local/share/rdesktop/ctrl"
#define CTRL_HASH_FLAG_SEAMLESS 1
#define ERR_RESULT_OK 0x00
#define ERR_RESULT_NO_SUCH_COMMAND 0xffffffff
extern RD_BOOL g_seamless_rdp;
extern uint8 g_static_rdesktop_salt_16[];
static RD_BOOL _ctrl_is_slave;
static int ctrlsock;
static char ctrlsock_name[PATH_MAX];
static struct _ctrl_slave_t *_ctrl_slaves;
#define CMD_SEAMLESS_SPAWN "seamless.spawn"
typedef struct _ctrl_slave_t
{
int sock;
char linebuf[CTRL_LINEBUF_SIZE];
static void
_ctrl_slave_new(int sock)
{
/* initialize new slave list item */
/* append new slave to end of list */
it = _ctrl_slaves;
/* find last element in list */
/* if last found append new */
if (it)
{
}
else
{
/* no elemnts in list, lets add first */
_ctrl_slaves = ns;
}
}
static void
{
if (!_ctrl_slaves)
return;
it = _ctrl_slaves;
/* find slave with sock */
{
/* shutdown socket */
/* remove item from list */
if (it == _ctrl_slaves)
{
else
_ctrl_slaves = NULL;
}
{
}
}
}
static void
{
char buf[64] = { 0 };
/* translate and send result code back to client */
if (result == 0)
else
{
}
}
static void
{
char *p;
char *cmd;
unsigned int res;
/* unescape linebuffer */
{
/* process seamless spawn request */
if (p)
else
res = ERR_RESULT_OK;
if (seamless_send_spawn(p) == (unsigned int) -1)
res = 1;
}
else
{
}
}
static RD_BOOL
{
int s, len;
struct sockaddr_un saun;
{
perror("Error creating ctrl client socket: socket()");
exit(1);
}
/* test connection */
return False;
close(s);
return True;
}
static void
{
/* version\0user\0domain\0host\0flags */
flags = 0;
delim = '\0';
version = 0x0100;
if (g_seamless_rdp)
if (user)
if (domain)
if (host)
}
/** Initialize ctrl
Ret values: <0 failure, 0 master, 1 client
*/
int
{
struct sockaddr_un saun;
char *home;
/* check if ctrl already initialized */
if (ctrlsock != 0 || _ctrl_is_slave)
return 0;
{
return -1;
}
/* get uniq hash for ctrlsock name */
/* make sure that ctrlsock store path exists */
{
return -1;
}
/* check if ctrl socket already exist then this process becomes a client */
{
/* verify that unix socket is not stale */
if (_ctrl_verify_unix_socket() == True)
{
return 1;
}
else
{
}
}
/* setup ctrl socket and start listening for connections */
{
perror("Error creating ctrl socket:");
exit(1);
}
/* bind and start listening on server socket */
{
perror("Error binding ctrl socket:");
exit(1);
}
{
perror("Error listening on socket:");
exit(1);
}
/* add ctrl cleanup func to exit hooks */
return 0;
}
void
{
if (ctrlsock)
{
}
}
{
return _ctrl_is_slave;
}
void
{
if (ctrlsock == 0)
return;
/* add connected slaves to fd set */
it = _ctrl_slaves;
while (it)
{
}
}
void
{
struct sockaddr_un fsaun;
if (ctrlsock == 0)
return;
/* check if we got any connections on server socket */
{
if (ns < 0)
{
perror("server: accept()");
exit(1);
}
return;
}
/* check if any of our slaves fds has data */
it = _ctrl_slaves;
while (it)
{
{
/* linebuffer full let's disconnect slave */
{
break;
}
if (res > 0)
{
/* Check if we got full command line */
char *p;
continue;
/* iterate over string and check against escaped \n */
while (p)
{
/* Check if newline is escaped */
break;
}
/* If we havent found an nonescaped \n we need more data */
if (p == NULL)
continue;
/* strip new linebuf and dispatch command */
*p = '\0';
}
else
{
/* Peer disconnected or socket error */
break;
}
}
}
}
#if HAVE_ICONV
extern char g_codepage[16];
#endif
int
{
struct sockaddr_un saun;
if (!_ctrl_is_slave)
return -1;
{
perror("Error creating ctrl client socket: socket()");
exit(1);
}
{
perror("Error connecting to ctrl socket: connect()");
exit(1);
}
/* Bundle cmd and argument into string, convert to UTF-8 if needed */
if (ret != 0)
goto bail_out;
/* escape the utf-8 string */
goto bail_out;
/* send escaped utf-8 command to master */
/* read result from master */
index = 0;
{
index++;
}
{
ret = -1;
}
close(s);
return ret;
}