diff options
Diffstat (limited to 'kdm/backend/ctrl.c')
-rw-r--r-- | kdm/backend/ctrl.c | 1015 |
1 files changed, 0 insertions, 1015 deletions
diff --git a/kdm/backend/ctrl.c b/kdm/backend/ctrl.c deleted file mode 100644 index 622c9370d..000000000 --- a/kdm/backend/ctrl.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* - -Copyright 1988, 1998 The Open Group -Copyright 2001-2005 Oswald Buddenhagen <ossi@kde.org> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from the copyright holder. - -*/ - -/* - * xdm - display manager daemon - * Author: Keith Packard, MIT X Consortium - * - * display manager - */ - -#include "dm.h" -#include "dm_socket.h" -#include "dm_error.h" - -#include <string.h> -#include <signal.h> -#include <pwd.h> - -static void -acceptSock( CtrlRec *cr ) -{ - struct cmdsock *cs; - int fd; - - if ((fd = accept( cr->fd, 0, 0 )) < 0) { - bust: - LogError( "Error accepting command connection\n" ); - return; - } - if (!(cs = Malloc( sizeof(*cs) ))) { - close( fd ); - goto bust; - } - cs->sock.fd = fd; - cs->sock.buffer = 0; - cs->sock.buflen = 0; - cs->next = cr->css; - cr->css = cs; - fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ); - RegisterCloseOnFork( fd ); - RegisterInput( fd ); -} - -static void -nukeSock( struct cmdsock *cs ) -{ - UnregisterInput( cs->sock.fd ); - CloseNClearCloseOnFork( cs->sock.fd ); - if (cs->sock.buffer) - free( cs->sock.buffer ); - free( cs ); -} - -#ifdef HONORS_SOCKET_PERMS -static CtrlRec ctrl = { 0, 0, -1, 0, 0, { -1, 0, 0 } }; -#else -static CtrlRec ctrl = { 0, 0, 0, -1, 0, 0, { -1, 0, 0 } }; - -static int mkTempDir( char *dir ) -{ - int i, l = strlen( dir ) - 6; - - for (i = 0; i < 100; i++) { - randomStr( dir + l ); - if (!mkdir( dir, 0700 )) - return True; - if (errno != EEXIST) - break; - } - return False; -} -#endif - -void -openCtrl( struct display *d ) -{ - CtrlRec *cr; - const char *dname; - char *sockdir; - struct sockaddr_un sa; - - if (!*fifoDir) - return; - if (d) { - cr = &d->ctrl, dname = d->name; - if (!memcmp( dname, "localhost:", 10 )) - dname += 9; - } else - cr = &ctrl, dname = 0; - if (cr->fifo.fd < 0) { - if (mkdir( fifoDir, 0755 )) { - if (errno != EEXIST) { - LogError( "mkdir %\"s failed; no control FiFos will be available\n", - fifoDir ); - return; - } - } else - chmod( fifoDir, 0755 ); /* override umask */ - StrApp( &cr->fpath, fifoDir, dname ? "/xdmctl-" : "/xdmctl", - dname, (char *)0 ); - if (cr->fpath) { - unlink( cr->fpath ); - if (mkfifo( cr->fpath, 0 ) < 0) - LogError( "Cannot create control FiFo %\"s\n", cr->fpath ); - else { - cr->gid = fifoGroup; - if (!d) - chown( cr->fpath, -1, fifoGroup ); - chmod( cr->fpath, 0620 ); - if ((cr->fifo.fd = open( cr->fpath, O_RDWR | O_NONBLOCK )) >= 0) { - RegisterCloseOnFork( cr->fifo.fd ); - RegisterInput( cr->fifo.fd ); - goto fifok; - } - unlink( cr->fpath ); - LogError( "Cannot open control FiFo %\"s\n", cr->fpath ); - } - free( cr->fpath ); - cr->fpath = 0; - } - } - fifok: - if (cr->fd < 0) { - /* fifoDir is created above already */ - sockdir = 0; - StrApp( &sockdir, fifoDir, dname ? "/dmctl-" : "/dmctl", - dname, (char *)0 ); - if (sockdir) { - StrApp( &cr->path, sockdir, "/socket", (char *)0 ); - if (cr->path) { - if (strlen( cr->path ) >= sizeof(sa.sun_path)) - LogError( "path %\"s too long; no control sockets will be available\n", - cr->path ); -#ifdef HONORS_SOCKET_PERMS - else if (mkdir( sockdir, 0700 ) && errno != EEXIST) - LogError( "mkdir %\"s failed; no control sockets will be available\n", - sockdir ); - else if (unlink( cr->path ) && errno != ENOENT) - LogError( "unlink %\"s failed: %m; control socket will not be available\n", - cr->path ); - else { -#else - else if (unlink( sockdir ) && errno != ENOENT) - LogError( "unlink %\"s failed: %m; control socket will not be available\n", - sockdir ); - else if (!StrApp( &cr->realdir, sockdir, "-XXXXXX", (char *)0)) - ; - else if (!mkTempDir( cr->realdir )) { - LogError( "mkdir %\"s failed: %m; control socket will not be available\n", - cr->realdir ); - free( cr->realdir ); - cr->realdir = 0; - } else if (symlink( cr->realdir, sockdir )) { - LogError( "symlink %\"s => %\"s failed: %m; control socket will not be available\n", - sockdir, cr->realdir ); - rmdir( cr->realdir ); - free( cr->realdir ); - cr->realdir = 0; - } else { - chown( sockdir, 0, d ? 0 : fifoGroup ); - chmod( sockdir, 0750 ); -#endif - if ((cr->fd = socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) - LogError( "Cannot create control socket\n" ); - else { - sa.sun_family = AF_UNIX; - strcpy( sa.sun_path, cr->path ); - if (!bind( cr->fd, (struct sockaddr *)&sa, sizeof(sa) )) { - if (!listen( cr->fd, 5 )) { -#ifdef HONORS_SOCKET_PERMS - chmod( cr->path, 0660 ); - if (!d) - chown( cr->path, -1, fifoGroup ); - chmod( sockdir, 0755 ); -#else - chmod( cr->path, 0666 ); -#endif - RegisterCloseOnFork( cr->fd ); - RegisterInput( cr->fd ); - free( sockdir ); - return; - } - unlink( cr->path ); - LogError( "Cannot listen on control socket %\"s\n", - cr->path ); - } else - LogError( "Cannot bind control socket %\"s\n", - cr->path ); - close( cr->fd ); - cr->fd = -1; - } -#ifdef HONORS_SOCKET_PERMS - rmdir( sockdir ); -#else - unlink( sockdir ); - rmdir( cr->realdir ); - free( cr->realdir ); - cr->realdir = 0; -#endif - } - free( cr->path ); - cr->path = 0; - } - free( sockdir ); - } - } -} - -void -closeCtrl( struct display *d ) -{ - CtrlRec *cr = d ? &d->ctrl : &ctrl; - - if (cr->fd >= 0) { - UnregisterInput( cr->fd ); - CloseNClearCloseOnFork( cr->fd ); - cr->fd = -1; - unlink( cr->path ); - *strrchr( cr->path, '/' ) = 0; -#ifdef HONORS_SOCKET_PERMS - rmdir( cr->path ); -#else - unlink( cr->path ); - rmdir( cr->realdir ); - free( cr->realdir ); - cr->realdir = 0; -#endif - free( cr->path ); - cr->path = 0; - while (cr->css) { - struct cmdsock *cs = cr->css; - cr->css = cs->next; - nukeSock( cs ); - } - } - if (cr->fifo.fd >= 0) { - UnregisterInput( cr->fifo.fd ); - CloseNClearCloseOnFork( cr->fifo.fd ); - cr->fifo.fd = -1; - unlink( cr->fpath ); - free( cr->fpath ); - cr->fpath = 0; - if (cr->fifo.buffer) - free( cr->fifo.buffer ); - cr->fifo.buffer = 0; - cr->fifo.buflen = 0; - } -} - -void -chownCtrl( CtrlRec *cr, int uid ) -{ - if (cr->fpath) - chown( cr->fpath, uid, -1 ); - if (cr->path) -#ifdef HONORS_SOCKET_PERMS - chown( cr->path, uid, -1 ); -#else - chown( cr->realdir, uid, -1 ); -#endif -} - -void -updateCtrl( void ) -{ - unsigned ffl, slc; - - ffl = 0; - if (ctrl.path) - for (ffl = strlen( ctrl.path ), slc = 2; ;) - if (ctrl.path[--ffl] == '/') - if (!--slc) - break; - if (ffl != strlen( fifoDir ) || memcmp( fifoDir, ctrl.path, ffl ) || - ctrl.gid != fifoGroup) - { - closeCtrl( 0 ); - openCtrl( 0 ); - } -} - - -static void -fLog( struct display *d, int fd, const char *sts, const char *msg, ... ) -{ - char *fmsg, *otxt; - const char *what; - int olen; - va_list va; - - va_start( va, msg ); - VASPrintf( &fmsg, msg, va ); - va_end( va ); - if (!fmsg) - return; - if (fd >= 0) { - olen = ASPrintf( &otxt, "%s\t%\\s\n", sts, fmsg ); - if (otxt) { - Writer( fd, otxt, olen ); - free( otxt ); - } - what = "socket"; - } else - what = "FiFo"; - if (d) - Debug( "control %s for %s: %s - %s", what, d->name, sts, fmsg ); - else - Debug( "global control %s: %s - %s", what, sts, fmsg ); - free( fmsg ); -} - - -static char * -unQuote( const char *str ) -{ - char *ret, *adp; - - if (!(ret = Malloc( strlen( str ) + 1 ))) - return 0; - for (adp = ret; *str; str++, adp++) - if (*str == '\\') - switch (*++str) { - case 0: str--; /* fallthrough */ - case '\\': *adp = '\\'; break; - case 'n': *adp = '\n'; break; - case 't': *adp = '\t'; break; - default: *adp++ = '\\'; *adp = *str; break; - } - else - *adp = *str; - *adp = 0; - return ret; -} - -static void -str_cat_l( char **bp, const char *str, int max ) -{ - int dnl = StrNLen( str, max ); - memcpy( *bp, str, dnl ); - *bp += dnl; -} - -static void -str_cat( char **bp, const char *str ) -{ - int dnl = strlen( str ); - memcpy( *bp, str, dnl ); - *bp += dnl; -} - -static void -sd_cat( char **bp, SdRec *sdr ) -{ - if (sdr->how == SHUT_HALT) - str_cat( bp, "halt," ); - else - str_cat( bp, "reboot," ); - if (sdr->start == TO_INF) - str_cat( bp, "0," ); - else - *bp += sprintf( *bp, "%d,", sdr->start ); - if (sdr->timeout == TO_INF) - str_cat( bp, "-1," ); - else - *bp += sprintf( *bp, "%d,", sdr->timeout ); - if (sdr->force == SHUT_ASK) - str_cat( bp, "ask" ); - else if (sdr->force == SHUT_FORCE) - str_cat( bp, "force" ); - else if (sdr->force == SHUT_FORCEMY) - str_cat( bp, "forcemy" ); - else - str_cat( bp, "cancel" ); - *bp += sprintf( *bp, ",%d,%s", sdr->uid, sdr->osname ? sdr->osname : "-" ); -} - -static void -emitXSessC( struct display *di, struct display *d, void *ctx ) -{ - char *dname, *bp; - char cbuf[1024]; - - bp = cbuf; - *bp++ = '\t'; - dname = di->name; - if (!memcmp( dname, "localhost:", 10 )) - dname += 9; - str_cat_l( &bp, dname, sizeof(cbuf)/2 ); - *bp++ = ','; -#ifdef HAVE_VTS - if (di->serverVT) - bp += sprintf( bp, "vt%d", di->serverVT ); -#endif - *bp++ = ','; -#ifdef XDMCP - if (di->status == remoteLogin) { - *bp++ = ','; - str_cat_l( &bp, di->remoteHost, sizeof(cbuf)/3 ); - } else -#endif - { - if (di->userName) - str_cat_l( &bp, di->userName, sizeof(cbuf)/5 ); - *bp++ = ','; - if (di->sessName) - str_cat_l( &bp, di->sessName, sizeof(cbuf)/5 ); - } - *bp++ = ','; - if (di == d) - *bp++ = '*'; - if (di->userSess >= 0 && - (d ? (d->userSess != di->userSess && - (d->allowNuke == SHUT_NONE || - (d->allowNuke == SHUT_ROOT && d->userSess))) : - !fifoAllowNuke)) - *bp++ = '!'; - Writer( (int)ctx, cbuf, bp - cbuf ); -} - -static void -emitTTYSessC( STRUCTUTMP *ut, struct display *d, void *ctx ) -{ - struct passwd *pw; - char *bp; - int vt, l; - char cbuf[sizeof(ut->ut_line) + sizeof(ut->ut_user) + sizeof(ut->ut_host) + 16]; - char user[sizeof(ut->ut_user) + 1]; - -#ifndef BSD_UTMP - if (ut->ut_type != USER_PROCESS) - l = 0; - else -#endif - { - l = StrNLen( ut->ut_user, sizeof(ut->ut_user) ); - memcpy( user, ut->ut_user, l ); - } - user[l] = 0; - bp = cbuf; - *bp++ = '\t'; - str_cat_l( &bp, ut->ut_line, sizeof(ut->ut_line) ); - *bp++ = ','; - if (*ut->ut_host) { - *bp++ = '@'; - str_cat_l( &bp, ut->ut_host, sizeof(ut->ut_host) ); - } -#ifdef HAVE_VTS - else if ((vt = TTYtoVT( ut->ut_line ))) - bp += sprintf( bp, "vt%d", vt ); -#endif - *bp++ = ','; - str_cat( &bp, user ); - *bp++ = ','; - /* blank: session type unknown */ - *bp++ = ','; - /* blank: certainly not querying display */ - *bp++ = 't'; - if (*user && - (d ? ((d->allowNuke == SHUT_NONE || - (d->allowNuke == SHUT_ROOT && d->userSess)) && - (!(pw = getpwnam( user )) || d->userSess != (int)pw->pw_uid)) : - !fifoAllowNuke)) - *bp++ = '!'; - Writer( (int)ctx, cbuf, bp - cbuf ); -} - -static void -processCtrl( const char *string, int len, int fd, struct display *d ) -{ -#define Reply(t) Writer (fd, t, strlen (t)) - - struct display *di; - const char *word; - char **ar, **ap, *args, *bp; - SdRec sdr; - char cbuf[1024]; - - if (!(ar = initStrArr( 0 ))) - return; - for (word = string; ; string++, len--) - if (!len || *string == '\t') { - if (!(ar = addStrArr( ar, word, string - word ))) - return; - if (!len) - break; - word = string + 1; - } - word = fd >= 0 ? "socket" : "FiFo"; - if (d) - Debug( "control %s for %s received %'[s\n", word, d->name, ar ); - else - Debug( "global control %s received %'[s\n", word, ar ); - if (ar[0]) { - if (fd >= 0 && !strcmp( ar[0], "caps" )) { - if (ar[1]) - goto exce; - Reply( "ok\ttdm\tlist\t" ); - if (bootManager != BO_NONE) - Reply( "bootoptions\t" ); - if (d) { - if ((d->displayType & d_location) == dLocal) -#ifdef HAVE_VTS - Reply( "local\tactivate\t" ); -#else - Reply( "local\t" ); -#endif - if (d->allowShutdown != SHUT_NONE) { - if (d->allowShutdown == SHUT_ROOT && d->userSess) - Reply( "shutdown root\t" ); - else - Reply( "shutdown\t" ); - Reply( "shutdown ask\t" ); - if (d->allowNuke != SHUT_NONE) { - if (d->allowNuke == SHUT_ROOT && d->userSess) - Reply( "nuke root\t" ); - else - Reply( "nuke\t" ); - } - } - if ((d->displayType & d_location) == dLocal && - AnyReserveDisplays()) - Writer( fd, cbuf, sprintf( cbuf, "reserve %d\t", - idleReserveDisplays() ) ); - Reply( "lock\tsuicide\n" ); - } else { - if (fifoAllowShutdown) { - Reply( "shutdown\t" ); - if (fifoAllowNuke) - Reply( "nuke\t" ); - } - if (AnyReserveDisplays()) - Writer( fd, cbuf, sprintf( cbuf, "reserve %d\t", - idleReserveDisplays() ) ); -#ifdef HAVE_VTS - Reply( "login\tactivate\n" ); -#else - Reply( "login\n" ); -#endif - } - goto bust; - } else if (fd >= 0 && !strcmp( ar[0], "list" )) { - int flags = lstRemote | lstTTY; - if (ar[1]) { - if (!strcmp( ar[1], "all" )) - flags = lstRemote | lstPassive | lstTTY; - else if (!strcmp( ar[1], "alllocal" )) - flags = lstPassive | lstTTY; - else { - fLog( d, fd, "bad", "invalid list scope %\"s", ar[1] ); - goto bust; - } - if (ar[2]) - goto exce; - } - Reply( "ok" ); - ListSessions( flags, d, (void *)fd, emitXSessC, emitTTYSessC ); - Reply( "\n" ); - goto bust; - } else if (!strcmp( ar[0], "reserve" )) { - int lt = 60; /* XXX make default timeout configurable? */ - if (ar[1]) { - lt = strtol( ar[1], &bp, 10 ); - if (lt < 15 || *bp) { - fLog( d, fd, "bad", "invalid timeout %\"s", ar[1] ); - goto bust; - } - if (ar[2]) - goto exce; - } - if (d && (d->displayType & d_location) != dLocal) { - fLog( d, fd, "perm", "display is not local" ); - goto bust; - } - if (!StartReserveDisplay( lt )) { - fLog( d, fd, "noent", "no reserve display available" ); - goto bust; - } -#ifdef HAVE_VTS - } else if (!strcmp( ar[0], "activate" )) { - int vt; - if (!ar[1]) - goto miss; - if (ar[2]) - goto exce; - if (d && (d->displayType & d_location) != dLocal) { - fLog( d, fd, "perm", "display is not local" ); - goto bust; - } - if (ar[1][0] != 'v' || ar[1][1] != 't' || - (vt = atoi( ar[1] + 2 )) <= 0) - { - if (!(di = FindDisplayByName( ar[1] ))) { - fLog( d, fd, "noent", "display not found" ); - goto bust; - } - if ((di->displayType & d_location) != dLocal) { - fLog( d, fd, "inval", "target display is not local" ); - goto bust; - } - if (!di->serverVT) { - fLog( d, fd, "noent", "target display has no VT assigned" ); - goto bust; - } - vt = di->serverVT; - } - if (!activateVT( vt )) { - fLog( d, fd, "inval", "VT switch failed" ); - goto bust; - } -#endif - } else if (!strcmp( ar[0], "shutdown" )) { - ap = ar; - if (!*++ap) - goto miss; - sdr.force = SHUT_CANCEL; - sdr.osname = 0; - if (!strcmp( *ap, "status" )) { - if (fd < 0) - goto bust; - if (*++ap) - goto exce; - bp = cbuf; - *bp++ = 'o'; - *bp++ = 'k'; - if (sdRec.how) { - str_cat( &bp, "\tglobal," ); - sd_cat( &bp, &sdRec ); - } - if (d && d->hstent->sdRec.how) { - str_cat( &bp, "\tlocal," ); - sd_cat( &bp, &d->hstent->sdRec ); - } - *bp++ = '\n'; - Writer( fd, cbuf, bp - cbuf ); - goto bust; - } else if (!strcmp( *ap, "cancel" )) { - sdr.how = 0; - sdr.start = 0; - if (ap[1]) { - if (!d) - goto exce; - if (!strcmp( *++ap, "global" )) - sdr.start = TO_INF; - else if (strcmp( *ap, "local" )) { - fLog( d, fd, "bad", "invalid cancel scope %\"s", *ap ); - goto bust; - } - } - } else { - if (!strcmp( *ap, "reboot" )) - sdr.how = SHUT_REBOOT; - else if (!strcmp( *ap, "halt" )) - sdr.how = SHUT_HALT; - else { - fLog( d, fd, "bad", "invalid type %\"s", *ap ); - goto bust; - } - sdr.uid = -1; - if (!*++ap) - goto miss; - if (**ap == '=') { - switch (setBootOption( *ap + 1, &sdr )) { - case BO_NOMAN: - fLog( d, fd, "notsup", "boot options unavailable" ); - goto bust; - case BO_NOENT: - fLog( d, fd, "noent", "no such boot option" ); - goto bust; - case BO_IO: - fLog( d, fd, "io", "io error" ); - goto bust; - } - if (!*++ap) - goto miss; - } - sdr.start = strtol( *ap, &bp, 10 ); - if (bp != *ap && !*bp) { - if (**ap == '+') - sdr.start += now; - if (!*++ap) - goto miss; - sdr.timeout = strtol( *ap, &bp, 10 ); - if (bp == *ap || *bp) { - fLog( d, fd, "bad", "invalid timeout %\"s", ar[3] ); - goto bust; - } - if (**ap == '+') - sdr.timeout += sdr.start ? sdr.start : now; - if (sdr.timeout < 0) - sdr.timeout = TO_INF; - else { - if (!*++ap) - goto miss; - if (!strcmp( *ap, "force" )) - sdr.force = SHUT_FORCE; - else if (d && !strcmp( *ap, "forcemy" )) - sdr.force = SHUT_FORCEMY; - else if (strcmp( *ap, "cancel" )) { - fLog( d, fd, "bad", "invalid timeout action %\"s", - *ap ); - goto bust; - } - } - } else { - sdr.timeout = 0; - if (d && !strcmp( *ap, "ask" )) - sdr.force = SHUT_ASK; - else if (!strcmp( *ap, "forcenow" )) - sdr.force = SHUT_FORCE; - else if (!strcmp( *ap, "schedule" )) - sdr.timeout = TO_INF; - else if (strcmp( *ap, "trynow" )) { - fLog( d, fd, "bad", "invalid mode %\"s", *ap ); - goto bust; - } - } - } - if (*++ap) - goto exce; - if (d) { - sdr.uid = d->userSess >= 0 ? d->userSess : 0; - if (d->allowShutdown == SHUT_NONE || - (d->allowShutdown == SHUT_ROOT && sdr.uid && - sdr.force != SHUT_ASK)) - { - fLog( d, fd, "perm", "shutdown forbidden" ); - goto bust; - } - if (!sdr.how && !sdr.start) { - if (d->hstent->sdRec.osname) - free( d->hstent->sdRec.osname ); - d->hstent->sdRec = sdr; - } else { - if (sdRec.how && sdRec.force == SHUT_FORCE && - ((d->allowNuke == SHUT_NONE && sdRec.uid != sdr.uid) || - (d->allowNuke == SHUT_ROOT && sdr.uid))) - { - fLog( d, fd, "perm", "overriding forced shutdown forbidden" ); - goto bust; - } - if (sdr.force == SHUT_FORCE && - (d->allowNuke == SHUT_NONE || - (d->allowNuke == SHUT_ROOT && sdr.uid))) - { - fLog( d, fd, "perm", "forced shutdown forbidden" ); - goto bust; - } - if (!sdr.start) { - if (d->hstent->sdRec.osname) - free( d->hstent->sdRec.osname ); - d->hstent->sdRec = sdr; - } else { - if (!sdr.how) - cancelShutdown(); - else { - if (sdRec.osname) - free( sdRec.osname ); - sdRec = sdr; - } - } - } - } else { - if (!fifoAllowShutdown) { - fLog( d, fd, "perm", "shutdown forbidden" ); - goto bust; - } - if (sdRec.how && sdRec.force == SHUT_FORCE && - sdRec.uid != -1 && !fifoAllowNuke) - { - fLog( d, fd, "perm", "overriding forced shutdown forbidden" ); - goto bust; - } - if (!sdr.how) - cancelShutdown(); - else { - if (sdr.force != SHUT_CANCEL) { - if (!fifoAllowNuke) { - fLog( d, fd, "perm", "forced shutdown forbidden" ); - goto bust; - } - } else { - if (!sdr.start && !sdr.timeout && AnyActiveDisplays()) { - fLog( d, fd, "busy", "user sessions running" ); - goto bust; - } - } - sdr.uid = -1; - if (sdRec.osname) - free( sdRec.osname ); - sdRec = sdr; - } - } - } else if (fd >= 0 && !strcmp( ar[0], "listbootoptions" )) { - char **opts; - int def, cur, i, j; - - if (ar[1]) - goto exce; - switch (getBootOptions( &opts, &def, &cur )) { - case BO_NOMAN: - fLog( d, fd, "notsup", "boot options unavailable" ); - goto bust; - case BO_IO: - fLog( d, fd, "io", "io error" ); - goto bust; - } - Reply( "ok\t" ); - for (i = 0; opts[i]; i++) { - bp = cbuf; - if (i) - *bp++ = ' '; - for (j = 0; opts[i][j]; j++) - if (opts[i][j] == ' ') { - *bp++ = '\\'; - *bp++ = 's'; - } else - *bp++ = opts[i][j]; - Writer( fd, cbuf, bp - cbuf ); - } - freeStrArr( opts ); - Writer( fd, cbuf, sprintf( cbuf, "\t%d\t%d\n", def, cur ) ); - goto bust; - } else if (d) { - if (!strcmp( ar[0], "lock" )) { - if (ar[1]) - goto exce; - d->hstent->lock = 1; - } else if (!strcmp( ar[0], "unlock" )) { - if (ar[1]) - goto exce; - d->hstent->lock = 0; - } else if (!strcmp( ar[0], "suicide" )) { - if (ar[1]) - goto exce; - if (d->status == running && d->pid != -1) { - TerminateProcess( d->pid, SIGTERM ); - d->status = raiser; - } - } else { - fLog( d, fd, "nosys", "unknown command" ); - goto bust; - } - } else { - if (!strcmp( ar[0], "login" )) { - int nuke; - if (arrLen( ar ) < 5) { - miss: - fLog( d, fd, "bad", "missing argument(s)" ); - goto bust; - } - if (!(di = FindDisplayByName( ar[1] ))) { - fLog( d, fd, "noent", "display %s not found", ar[1] ); - goto bust; - } - if (ar[5]) { - if (!(args = unQuote( ar[5] ))) { - fLog( d, fd, "nomem", "out of memory" ); - goto bust; - } - if (ar[6]) { - free( args ); - exce: - fLog( d, fd, "bad", "excess argument(s)" ); - goto bust; - } - setNLogin( di, ar[3], ar[4], args, 2 ); - free( args ); - } else - setNLogin( di, ar[3], ar[4], 0, 2 ); - nuke = !strcmp( ar[2], "now" ); - switch (di->status) { - case running: - if (di->pid != -1 && (di->userSess < 0 || nuke)) { - TerminateProcess( di->pid, SIGTERM ); - di->status = raiser; - } - break; - case remoteLogin: - if (di->serverPid != -1 && nuke) - TerminateProcess( di->serverPid, di->termSignal ); - break; - case reserve: - di->status = notRunning; - break; - case textMode: -#ifndef HAVE_VTS - SwitchToX( di ); -#endif - break; - default: - break; - } - } else { - fLog( d, fd, "nosys", "unknown command" ); - goto bust; - } - } - if (fd >= 0) - Reply( "ok\n" ); - } - bust: - freeStrArr( ar ); -} - -static int -handleChan( struct display *d, struct bsock *cs, int fd, FD_TYPE *reads ) -{ - char *bufp, *nbuf, *obuf, *eol; - int len, bl, llen; - char buf[1024]; - - bl = cs->buflen; - obuf = cs->buffer; - if (bl <= 0 && FD_ISSET( cs->fd, reads )) { - FD_CLR( cs->fd, reads ); - bl = -bl; - memcpy( buf, obuf, bl ); - if ((len = Reader( cs->fd, buf + bl, sizeof(buf) - bl )) <= 0) - return -1; - bl += len; - bufp = buf; - } else { - len = 0; - bufp = obuf; - } - if (bl > 0) { - if ((eol = memchr( bufp, '\n', bl ))) { - llen = eol - bufp + 1; - bl -= llen; - if (bl) { - if (!(nbuf = Malloc( bl ))) - return -1; - memcpy( nbuf, bufp + llen, bl ); - } else - nbuf = 0; - cs->buffer = nbuf; - cs->buflen = bl; - processCtrl( bufp, llen - 1, fd, d ); - if (obuf) - free( obuf ); - return 1; - } else if (!len) { - if (fd >= 0) - cs->buflen = -bl; - else - fLog( d, -1, "bad", "unterminated command" ); - } - } - return 0; -} - -int -handleCtrl( FD_TYPE *reads, struct display *d ) -{ - CtrlRec *cr = d ? &d->ctrl : &ctrl; - struct cmdsock *cs, **csp; - - if (cr->fifo.fd >= 0) { - switch (handleChan( d, &cr->fifo, -1, reads )) { - case -1: - if (cr->fifo.buffer) - free( cr->fifo.buffer ); - cr->fifo.buflen = 0; - break; - case 1: - return 1; - default: - break; - } - } - if (cr->fd >= 0 && FD_ISSET( cr->fd, reads )) - acceptSock( cr ); - else { - for (csp = &cr->css; (cs = *csp); ) { - switch (handleChan( d, &cs->sock, cs->sock.fd, reads )) { - case -1: - *csp = cs->next; - nukeSock( cs ); - continue; - case 1: - return 1; - default: - break; - } - csp = &cs->next; - } - } - return 0; -} |