not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kdm / kfrontend / kdmctl.c
blobddacb1997d607a3ad0cc73719a38c5622de43f10
1 /*
3 KDM remote control application
5 Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <config-workspace.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
33 static int
34 openCtl( int fd, int err, const char *ctl, const char *dpy )
36 struct sockaddr_un sa;
38 sa.sun_family = AF_UNIX;
39 if (dpy)
40 snprintf( sa.sun_path, sizeof(sa.sun_path),
41 "%s/dmctl-%s/socket", ctl, dpy );
42 else
43 snprintf( sa.sun_path, sizeof(sa.sun_path),
44 "%s/dmctl/socket", ctl );
45 if (!connect( fd, (struct sockaddr *)&sa, sizeof(sa) ))
46 return 1;
47 if (err)
48 fprintf( stderr, "Cannot connect socket '%s'.\n", sa.sun_path );
49 return 0;
52 static const char *
53 readConfig( const char *cfg )
55 FILE *fp;
56 const char *ctl;
57 char *ptr, *ptr2;
58 char buf[1024];
60 if (!(fp = fopen( cfg, "r" ))) {
61 fprintf( stderr,
62 "Cannot open kdm config file '%s'.\n",
63 cfg );
64 return 0;
66 ctl = "/var/run/xdmctl";
67 while (fgets( buf, sizeof(buf), fp ))
68 if (!strncmp( buf, "FifoDir", 7 )) {
69 ptr = buf + 7;
70 while (*ptr && isspace( *ptr ))
71 ptr++;
72 if (*ptr++ != '=')
73 continue;
74 while (*ptr && isspace( *ptr ))
75 ptr++;
76 for (ptr2 = buf + strlen( buf );
77 ptr2 > ptr && isspace( *(ptr2 - 1) );
78 ptr2--);
79 *ptr2 = 0;
80 ctl = strdup( ptr );
81 break;
83 fclose( fp );
84 return ctl;
87 static int
88 exe( int fd, const char *in, int len )
90 char buf[4096];
92 if (write( fd, in, len ) != len) {
93 fprintf( stderr, "Cannot send command\n" );
94 return 1;
96 if ((len = read( fd, buf, sizeof(buf) )) <= 0) {
97 fprintf( stderr, "Cannot receive reply\n" );
98 return 1;
100 if (len == sizeof(buf) && buf[sizeof(buf) - 1] != '\n')
101 fprintf( stderr, "Warning: reply is too long\n" );
102 fwrite( buf, 1, len, stdout );
103 if (len == sizeof(buf) && buf[sizeof(buf) - 1] != '\n')
104 puts( "[...]" );
105 return 0;
108 static int
109 run( int fd, char **argv )
111 unsigned len, l;
112 char buf[1024];
114 if (!*argv)
115 return exe( fd, "caps\n", 5 );
116 if (!strcmp( *argv, "-" )) {
117 for (;;) {
118 if (isatty( 0 )) {
119 fputs( "> ", stdout );
120 fflush( stdout );
122 if (!fgets( buf, sizeof(buf), stdin ))
123 return 0;
124 if (exe( fd, buf, strlen( buf ) ))
125 return 1;
127 } else {
128 len = strlen( *argv );
129 if (len >= sizeof(buf))
130 goto bad;
131 memcpy( buf, *argv, len );
132 while (*++argv) {
133 l = strlen( *argv );
134 if (len + l + 1 >= sizeof(buf))
135 goto bad;
136 buf[len++] = '\t';
137 memcpy( buf + len, *argv, l );
138 len += l;
140 buf[len++] = '\n';
141 return exe( fd, buf, len );
142 bad:
143 fprintf( stderr, "Command too long\n" );
144 return 1;
149 main( int argc, char **argv )
151 char *dpy = getenv( "DISPLAY" );
152 const char *ctl = getenv( "DM_CONTROL" );
153 const char *cfg = KDE_CONFDIR "/kdm/kdmrc";
154 char *ptr;
155 int fd;
157 (void)argc;
158 while (*++argv) {
159 ptr = *argv;
160 if (*ptr != '-' || !*(ptr + 1))
161 break;
162 ptr++;
163 if (*ptr == '-')
164 ptr++;
165 if (!strcmp( ptr, "h" ) || !strcmp( ptr, "help" )) {
166 puts(
167 "Usage: kdmctl [options] [command [command arguments]]\n"
168 "\n"
169 "Options are:\n"
170 " -h -help This help message.\n"
171 " -g -global Use global control socket even if $DISPLAY is set\n"
172 " -d -display Override $DISPLAY\n"
173 " -s -sockets Override $DM_CONTROL\n"
174 " -c -config Use alternative kdm config file\n"
175 "\n"
176 "The directory in which the sockets are located is determined this way:\n"
177 "- the -s option is examined\n"
178 "- the $DM_CONTROL variable is examined\n"
179 "- the kdm config file is searched for the FifoDir key\n"
180 "- /var/run/xdmctl and /var/run are tried\n"
181 "\n"
182 "If $DISPLAY is set (or -d was specified) and -g was not specified, the\n"
183 "display-specific control socket will be used, otherwise the global one.\n"
184 "\n"
185 "Tokens in the command and the reply are tab-separated.\n"
186 "Command arguments can be specified as separate command line parameters,\n"
187 "in which case they are simply concatenated with tabs in between.\n"
188 "\n"
189 "If the command is '-', kdmctl reads commands from stdin.\n"
190 "The default command is 'caps'.\n"
192 return 0;
193 } else if (!strcmp( ptr, "g" ) || !strcmp( ptr, "global" ))
194 dpy = 0;
195 else if (!strcmp( ptr, "d" ) || !strcmp( ptr, "display" )) {
196 if (!argv[1])
197 goto needarg;
198 dpy = *++argv;
199 } else if (!strcmp( ptr, "s" ) || !strcmp( ptr, "sockets" )) {
200 if (!argv[1])
201 goto needarg;
202 ctl = *++argv;
203 } else if (!strcmp( ptr, "c" ) || !strcmp( ptr, "config" )) {
204 if (!argv[1]) {
205 needarg:
206 fprintf( stderr, "Option '%s' needs argument.\n",
207 ptr );
208 return 1;
210 cfg = *++argv;
211 } else {
212 fprintf( stderr, "Unknown option '%s'.\n", ptr );
213 return 1;
216 if ((!ctl || !*ctl) && *cfg)
217 ctl = readConfig( cfg );
218 if ((fd = socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) {
219 fprintf( stderr, "Cannot create UNIX socket\n" );
220 return 1;
222 if (dpy && (ptr = strchr( dpy, ':' )) && (ptr = strchr( ptr, '.' )))
223 *ptr = 0;
224 if (ctl && *ctl) {
225 if (!openCtl( fd, 1, ctl, dpy ))
226 return 1;
227 } else {
228 if (!openCtl( fd, 0, "/var/run/xdmctl", dpy ) &&
229 !openCtl( fd, 0, "/var/run", dpy ))
231 fprintf( stderr, "No command socket found.\n" );
232 return 1;
235 return run( fd, argv );