summaryrefslogtreecommitdiffstats
path: root/tdm/kfrontend/tdmctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'tdm/kfrontend/tdmctl.c')
-rw-r--r--tdm/kfrontend/tdmctl.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/tdm/kfrontend/tdmctl.c b/tdm/kfrontend/tdmctl.c
new file mode 100644
index 000000000..d6abe959a
--- /dev/null
+++ b/tdm/kfrontend/tdmctl.c
@@ -0,0 +1,234 @@
+/*
+
+TDM remote control application
+
+Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+static int
+openctl( int fd, int err, const char *ctl, const char *dpy )
+{
+ struct sockaddr_un sa;
+
+ sa.sun_family = AF_UNIX;
+ if (dpy)
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl-%s/socket", ctl, dpy );
+ else
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl/socket", ctl );
+ if (!connect( fd, (struct sockaddr *)&sa, sizeof(sa) ))
+ return 1;
+ if (err)
+ fprintf( stderr, "Cannot connect socket '%s'.\n", sa.sun_path );
+ return 0;
+}
+
+static const char *
+readcfg( const char *cfg )
+{
+ FILE *fp;
+ const char *ctl;
+ char *ptr, *ptr2;
+ char buf[1024];
+
+ if (!(fp = fopen( cfg, "r" ))) {
+ fprintf( stderr,
+ "Cannot open tdm config file '%s'.\n",
+ cfg );
+ return 0;
+ }
+ ctl = "/var/run/xdmctl";
+ while (fgets( buf, sizeof(buf), fp ))
+ if (!strncmp( buf, "FifoDir", 7 )) {
+ ptr = buf + 7;
+ while (*ptr && isspace( *ptr ))
+ ptr++;
+ if (*ptr++ != '=')
+ continue;
+ while (*ptr && isspace( *ptr ))
+ ptr++;
+ for (ptr2 = buf + strlen( buf );
+ ptr2 > ptr && isspace( *(ptr2 - 1) );
+ ptr2--);
+ *ptr2 = 0;
+ ctl = strdup( ptr );
+ break;
+ }
+ fclose( fp );
+ return ctl;
+}
+
+static int
+exe( int fd, const char *in, int len )
+{
+ char buf[4096];
+
+ if (write( fd, in, len ) != len) {
+ fprintf( stderr, "Cannot send command\n" );
+ return 1;
+ }
+ do {
+ if ((len = read(fd, buf, sizeof(buf))) <= 0) {
+ fprintf(stderr, "Cannot receive reply\n");
+ return 1;
+ }
+ fwrite(buf, 1, len, stdout);
+ } while (buf[len - 1] != '\n');
+ return 0;
+}
+
+static int
+run( int fd, char **argv )
+{
+ unsigned len, l;
+ char buf[1024];
+
+ if (!*argv)
+ return exe( fd, "caps\n", 5 );
+ if (!strcmp( *argv, "-" )) {
+ for (;;) {
+ if (isatty( 0 )) {
+ fputs( "> ", stdout );
+ fflush( stdout );
+ }
+ if (!fgets( buf, sizeof(buf), stdin ))
+ return 0;
+ if (exe( fd, buf, strlen( buf ) ))
+ return 1;
+ }
+ } else {
+ len = strlen( *argv );
+ if (len >= sizeof(buf))
+ goto bad;
+ memcpy( buf, *argv, len );
+ while (*++argv) {
+ l = strlen( *argv );
+ if (len + l + 1 >= sizeof(buf))
+ goto bad;
+ buf[len++] = '\t';
+ memcpy( buf + len, *argv, l );
+ len += l;
+ }
+ buf[len++] = '\n';
+ return exe( fd, buf, len );
+ bad:
+ fprintf( stderr, "Command too long\n" );
+ return 1;
+ }
+}
+
+int
+main( int argc, char **argv )
+{
+ char *dpy = getenv( "DISPLAY" );
+ const char *ctl = getenv( "DM_CONTROL" );
+ const char *cfg = KDE_CONFDIR "/tdm/tdmrc";
+ char *ptr;
+ int fd;
+
+ (void)argc;
+ while (*++argv) {
+ ptr = *argv;
+ if (*ptr != '-' || !*(ptr + 1))
+ break;
+ ptr++;
+ if (*ptr == '-')
+ ptr++;
+ if (!strcmp( ptr, "h" ) || !strcmp( ptr, "help" )) {
+ puts(
+"Usage: tdmctl [options] [command [command arguments]]\n"
+"\n"
+"Options are:\n"
+" -h -help This help message.\n"
+" -g -global Use global control socket even if $DISPLAY is set\n"
+" -d -display Override $DISPLAY\n"
+" -s -sockets Override $DM_CONTROL\n"
+" -c -config Use alternative tdm config file\n"
+"\n"
+"The directory in which the sockets are located is determined this way:\n"
+"- the -s option is examined\n"
+"- the $DM_CONTROL variable is examined\n"
+"- the tdm config file is searched for the FifoDir key\n"
+"- /var/run/xdmctl and /var/run are tried\n"
+"\n"
+"If $DISPLAY is set (or -d was specified) and -g was not specified, the\n"
+"display-specific control socket will be used, otherwise the global one.\n"
+"\n"
+"Tokens in the command and the reply are tab-separated.\n"
+"Command arguments can be specified as separate command line parameters,\n"
+"in which case they are simply concatenated with tabs in between.\n"
+"\n"
+"If the command is '-', tdmctl reads commands from stdin.\n"
+"The default command is 'caps'.\n"
+ );
+ return 0;
+ } else if (!strcmp( ptr, "g" ) || !strcmp( ptr, "global" ))
+ dpy = 0;
+ else if (!strcmp( ptr, "d" ) || !strcmp( ptr, "display" )) {
+ if (!argv[1])
+ goto needarg;
+ dpy = *++argv;
+ } else if (!strcmp( ptr, "s" ) || !strcmp( ptr, "sockets" )) {
+ if (!argv[1])
+ goto needarg;
+ ctl = *++argv;
+ } else if (!strcmp( ptr, "c" ) || !strcmp( ptr, "config" )) {
+ if (!argv[1]) {
+ needarg:
+ fprintf( stderr, "Option '%s' needs argument.\n",
+ ptr );
+ return 1;
+ }
+ cfg = *++argv;
+ } else {
+ fprintf( stderr, "Unknown option '%s'.\n", ptr );
+ return 1;
+ }
+ }
+ if ((!ctl || !*ctl) && *cfg)
+ ctl = readcfg( cfg );
+ if ((fd = socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) {
+ fprintf( stderr, "Cannot create UNIX socket\n" );
+ return 1;
+ }
+ if (dpy && (ptr = strchr( dpy, ':' )) && (ptr = strchr( ptr, '.' )))
+ *ptr = 0;
+ if (ctl && *ctl) {
+ if (!openctl( fd, 1, ctl, dpy ))
+ return 1;
+ } else {
+ if (!openctl( fd, 0, "/var/run/xdmctl", dpy ) &&
+ !openctl( fd, 0, "/var/run", dpy ))
+ {
+ fprintf( stderr, "No command socket found.\n" );
+ return 1;
+ }
+ }
+ return run( fd, argv );
+}