0N/A/*
1351N/A * Copyright (c) 1993, 2013, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
908N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
908N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
0N/A */
0N/A
0N/A
0N/A/************************************************************
0N/A Basic boilerplate extension.
0N/A
0N/A This file also contains the code to make the priocntl on behalf
0N/A of the clients.
0N/A
0N/A Note that ChangePriority also sets the last client with focus
0N/A to the normal priority.
0N/A
0N/A If there are knobs to be added to the system, for say the nice
0N/A values for the IA class, they would be added here.
0N/A********************************************************/
0N/A
0N/A/* THIS IS NOT AN X CONSORTIUM STANDARD */
0N/A
98N/A#ifdef HAVE_DIX_CONFIG_H
98N/A#include <dix-config.h>
98N/A#endif
98N/A
0N/A#include <errno.h>
0N/A#include <sys/types.h>
0N/A#include <stdio.h>
0N/A
0N/A#include <sys/priocntl.h>
0N/A#include <sys/iapriocntl.h>
0N/A#include <unistd.h>
0N/A
0N/A
0N/A#include <X11/X.h>
0N/A#include <X11/Xproto.h>
0N/A#include "os.h"
0N/A#include "dixstruct.h"
0N/A#include "windowstr.h"
0N/A#include "inputstr.h"
0N/A#include "extnsionst.h"
0N/A#define _XIA_SERVER_
0N/A#include <X11/extensions/interactive.h>
0N/A#include <X11/Xfuncproto.h>
0N/A#include "dix.h"
1265N/A#include "client.h"
0N/A
908N/A#include "interactive_srv.h"
0N/A
1088N/Astatic int ProcIADispatch(ClientPtr client);
1088N/Astatic int SProcIADispatch(ClientPtr client);
1088N/Astatic int ProcIASetProcessInfo(ClientPtr client);
1088N/Astatic int SProcIASetProcessInfo(ClientPtr client);
1088N/Astatic int ProcIAGetProcessInfo(ClientPtr client);
1088N/Astatic int SProcIAGetProcessInfo(ClientPtr client);
1088N/Astatic int ProcIAQueryVersion(ClientPtr client);
1088N/Astatic int SProcIAQueryVersion(ClientPtr client);
0N/Astatic void IACloseDown(ExtensionEntry *ext);
1088N/Astatic void IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata,
1088N/A pointer calldata);
0N/A
1088N/Astatic int InitializeClass(void);
1088N/Astatic void SetIAPrivate(int *);
0N/Astatic void ChangeInteractive(ClientPtr);
606N/Astatic int SetPriority(const ClientProcessPtr, int);
0N/Astatic void ChangePriority(register ClientPtr client);
0N/A
1088N/Astatic int SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff,
1088N/A int length);
606N/Astatic void FreeProcessList(IAClientPrivatePtr priv);
0N/A/* static int LocalConnection(OsCommPtr); */
0N/Astatic int PidSetEqual(ClientProcessPtr, ClientProcessPtr);
0N/A
0N/Astatic int IAWrapProcVectors(void);
0N/Astatic int IAUnwrapProcVectors(void);
0N/A
1088N/Astatic CARD32 IAInitTimerCall(OsTimerPtr timer, CARD32 now, pointer arg);
0N/A
0N/Astatic iaclass_t IAClass;
0N/Astatic id_t TScid;
0N/Astatic ClientProcessPtr LastPids = NULL;
0N/Astatic int ia_nice = IA_BOOST;
606N/Astatic Bool InteractiveOS = TRUE;
0N/Astatic unsigned long IAExtensionGeneration = 0;
0N/Astatic OsTimerPtr IAInitTimer = NULL;
0N/Astatic int (* IASavedProcVector[256]) (ClientPtr client);
0N/A
1088N/Astatic DevPrivateKeyRec IAPrivKeyRec;
1088N/A#define IAPrivKey (&IAPrivKeyRec)
606N/A
606N/A#define GetIAClient(pClient) \
606N/A ((IAClientPrivatePtr) dixLookupPrivate(&(pClient)->devPrivates, IAPrivKey))
0N/A
606N/Astatic inline ClientProcessPtr
606N/AGetConnectionPids(ClientPtr pClient)
606N/A{
606N/A IAClientPrivatePtr priv = GetIAClient(pClient);
0N/A
606N/A if (priv == NULL) {
606N/A return NULL;
606N/A } else {
606N/A return priv->process;
606N/A }
606N/A}
0N/A
0N/A/* Set via xorg.conf option in loadable module */
0N/Aint IADebugLevel = 0;
0N/A
0N/A#define IA_DEBUG(level, func) \
0N/A if (IADebugLevel >= level) { func; } else (void)(0)
0N/A
0N/A#define IA_DEBUG_BASIC 1
0N/A#define IA_DEBUG_PRIOCNTL 3
0N/A
0N/Avoid
0N/AIAExtensionInit(void)
0N/A{
606N/A ConnectionPidRec myPid = P_MYID;
606N/A ClientProcessRec myProc = { 1, &myPid, FALSE };
908N/A
908N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO, "SolarisIA: Initializing (generation %ld)\n",
606N/A IAExtensionGeneration));
0N/A
0N/A if (IAExtensionGeneration == serverGeneration)
0N/A return;
0N/A
606N/A InteractiveOS = FALSE;
0N/A
0N/A if (InitializeClass() != Success)
0N/A return;
0N/A
606N/A if (SetPriority(&myProc, SET_INTERACTIVE) != Success)
0N/A return;
0N/A
606N/A if (SetPriority(&myProc, SET_PRIORITY) != Success)
0N/A return;
0N/A
1088N/A if (!dixRegisterPrivateKey(&IAPrivKeyRec, PRIVATE_CLIENT, 0))
1088N/A return;
1088N/A
0N/A if (!AddCallback(&ClientStateCallback, IAClientStateChange, NULL))
0N/A return;
0N/A
0N/A if (IAWrapProcVectors() != 0)
0N/A return;
0N/A
0N/A if (!AddExtension(IANAME, IANumberEvents, IANumberErrors,
606N/A ProcIADispatch, SProcIADispatch,
606N/A IACloseDown, StandardMinorOpcode))
0N/A return;
0N/A
0N/A /* InitExtensions is called before InitClientPrivates(serverClient)
0N/A so we set this timer to callback as soon as we hit WaitForSomething
0N/A to initialize the serverClient */
0N/A IAInitTimer = TimerSet(IAInitTimer, 0, 1, IAInitTimerCall, NULL);
0N/A
606N/A InteractiveOS = TRUE;
0N/A IAExtensionGeneration = serverGeneration;
0N/A
908N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: Finished initializing (generation %ld)\n",
606N/A IAExtensionGeneration));
606N/A}
606N/A
606N/A/* Allocate client private structure for this client */
606N/Astatic int
606N/AIAInitClientPrivate(ClientPtr pClient)
606N/A{
606N/A IAClientPrivatePtr priv;
606N/A
606N/A priv = GetIAClient(pClient);
606N/A if (priv != NULL) {
606N/A return Success;
606N/A }
908N/A
1088N/A priv = malloc(sizeof(IAClientPrivateRec));
606N/A if (priv == NULL) {
606N/A return BadAlloc;
606N/A }
606N/A
606N/A priv->process = NULL;
606N/A priv->wmgr = FALSE;
908N/A
606N/A dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, priv);
606N/A
606N/A return Success;
0N/A}
0N/A
0N/A/* Called when we first hit WaitForSomething to initialize serverClient */
908N/Astatic CARD32
1088N/AIAInitTimerCall(OsTimerPtr timer, CARD32 now, pointer arg)
0N/A{
0N/A ConnectionPidRec serverPid;
0N/A
606N/A if (InteractiveOS != TRUE)
0N/A return 0;
0N/A
606N/A IAInitClientPrivate(serverClient);
0N/A
0N/A serverPid = getpid();
0N/A SetClientPrivate(serverClient, &serverPid, 1);
0N/A
0N/A ChangePriority(serverClient);
0N/A return 0;
0N/A}
0N/A
0N/A/* Called when new client connects or existing client disconnects */
0N/Astatic void
0N/AIAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
0N/A{
0N/A NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
0N/A ClientPtr pClient = pci->client;
0N/A ClientProcessPtr CurrentPids;
606N/A IAClientPrivatePtr priv;
923N/A LocalClientCredRec *lcc;
0N/A
0N/A switch (pClient->clientState) {
606N/A case ClientStateGone:
606N/A case ClientStateRetained:
606N/A priv = GetIAClient(pClient);
606N/A if (priv == NULL) {
606N/A return;
606N/A }
606N/A CurrentPids = priv->process;
0N/A
606N/A if (priv->wmgr) {
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: WindowManager closed (pid %d)\n",
606N/A (CurrentPids && CurrentPids->pids) ?
606N/A CurrentPids->pids[0] : -1));
0N/A }
0N/A
606N/A if (CurrentPids && CurrentPids->boosted) {
606N/A SetPriority(CurrentPids, UNSET_PRIORITY);
606N/A }
908N/A
606N/A if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
606N/A LastPids = NULL;
606N/A }
0N/A
606N/A FreeProcessList(priv);
1088N/A free(priv);
606N/A dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, NULL);
0N/A break;
606N/A
0N/A case ClientStateInitial:
606N/A IAInitClientPrivate(pClient);
1265N/A {
1265N/A ConnectionPidRec clientPid = GetClientPid(pClient);
1265N/A if (clientPid != -1) {
923N/A SetClientPrivate(pClient, &clientPid, 1);
923N/A ChangeInteractive(pClient);
923N/A }
923N/A }
0N/A break;
0N/A
0N/A default:
0N/A break;
0N/A }
908N/A}
0N/A
0N/A
0N/Astatic int
0N/AProcIADispatch (ClientPtr client)
0N/A{
0N/A REQUEST(xReq);
0N/A switch (stuff->data)
0N/A {
0N/A case X_IAQueryVersion:
0N/A return ProcIAQueryVersion(client);
0N/A case X_IASetProcessInfo:
0N/A return ProcIASetProcessInfo(client);
0N/A case X_IAGetProcessInfo:
0N/A return ProcIAGetProcessInfo(client);
0N/A default:
0N/A return BadRequest;
0N/A }
0N/A}
0N/A
0N/Astatic int
0N/AProcIAQueryVersion(ClientPtr client)
0N/A{
0N/A REQUEST(xIAQueryVersionReq);
0N/A xIAQueryVersionReply rep;
0N/A
0N/A REQUEST_SIZE_MATCH(xIAQueryVersionReq);
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
0N/A rep.majorVersion = IA_MAJOR_VERSION;
0N/A rep.minorVersion = IA_MINOR_VERSION;
0N/A WriteToClient(client, sizeof(xIAQueryVersionReply), (char *)&rep);
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic int
0N/AProcIASetProcessInfo(ClientPtr client)
0N/A{
0N/A
0N/A REQUEST(xIASetProcessInfoReq);
0N/A register int length;
183N/A static uid_t ServerUid = (uid_t)-1;
0N/A
0N/A REQUEST_AT_LEAST_SIZE(xIASetProcessInfoReq);
0N/A
183N/A if (ServerUid == (uid_t)-1)
0N/A ServerUid=getuid();
0N/A
908N/A if ((stuff->flags & INTERACTIVE_INFO) &&
0N/A (stuff->uid==ServerUid || ServerUid==0 || stuff->uid==0) &&
1351N/A client->local) {
606N/A length = stuff->length - (sizeof(xIASetProcessInfoReq)>>2);
0N/A SetClientPrivate(client, (ConnectionPidPtr)&stuff[1], length);
0N/A ChangeInteractive(client);
0N/A }
0N/A
908N/A if ((stuff->flags & INTERACTIVE_SETTING) &&
0N/A (stuff->uid==ServerUid || ServerUid==0) &&
1351N/A client->local) {
1088N/A SetIAPrivate((int *)&stuff[1]);
0N/A }
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic int
0N/AProcIAGetProcessInfo(ClientPtr client)
0N/A{
606N/A IAClientPrivatePtr priv;
606N/A ClientProcessPtr CurrentPids;
0N/A REQUEST(xIAGetProcessInfoReq);
0N/A xIAGetProcessInfoReply rep;
606N/A register int length = 0;
1029N/A int i;
1088N/A int32_t *write_back = NULL;
0N/A
0N/A REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
1029N/A
0N/A if (stuff->flags & INTERACTIVE_INFO) {
606N/A priv = GetIAClient(client);
606N/A if ( (priv == NULL) || (priv->process == NULL) ) {
606N/A rep.count = 0;
606N/A } else {
1088N/A CurrentPids = priv->process;
606N/A rep.count = CurrentPids->count;
606N/A length = rep.count << 2;
1029N/A rep.length = rep.count;
1088N/A write_back = malloc((size_t) rep.count * sizeof(int32_t));
1029N/A if (write_back == NULL)
1029N/A return ~Success;
1088N/A else {
1088N/A int32_t *tmp = write_back;
1029N/A
1088N/A for (i = 0; i < CurrentPids->count; ++i)
1088N/A *tmp++ = *CurrentPids->pids++;
1088N/A }
606N/A }
0N/A }
0N/A if (stuff->flags & INTERACTIVE_SETTING) {
0N/A rep.count=1;
0N/A length=rep.count << 2;
1029N/A rep.length = rep.count;
1029N/A
1088N/A write_back = malloc(sizeof(int32_t));
1029N/A if (write_back == NULL)
1029N/A return ~Success;
1029N/A
1029N/A *write_back = (int32_t) ia_nice;
0N/A }
0N/A
0N/A WriteToClient(client, sizeof(xIAGetProcessInfoReply), (char *)&rep);
1029N/A
1029N/A if (rep.length > 0) {
1029N/A (void) WriteToClient(client, (int) sizeof(int32_t) * rep.count,
1029N/A (char *) write_back);
1088N/A free(write_back);
1029N/A }
1029N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic void
0N/AIACloseDown(ExtensionEntry *ext)
0N/A{
606N/A InteractiveOS = FALSE;
0N/A
0N/A IAUnwrapProcVectors();
0N/A
0N/A DeleteCallback(&ClientStateCallback, IAClientStateChange, NULL);
0N/A}
0N/A
908N/A/*
0N/A The SProc* functions are here for completeness. They should never get
0N/A called. But since they do the server has to eat the request and
0N/A return thanks for sharing.
0N/A*/
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIADispatch (ClientPtr client)
0N/A{
0N/A REQUEST(xReq);
0N/A switch (stuff->data)
0N/A {
0N/A case X_IAQueryVersion:
0N/A return SProcIAQueryVersion(client);
0N/A case X_IASetProcessInfo:
0N/A return SProcIASetProcessInfo(client);
0N/A case X_IAGetProcessInfo:
0N/A return SProcIAGetProcessInfo(client);
0N/A default:
0N/A return BadRequest;
0N/A }
0N/A}
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIAQueryVersion(ClientPtr client)
0N/A{
0N/A REQUEST_SIZE_MATCH(xIAQueryVersionReq);
0N/A return (client->noClientException);
0N/A}
908N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIASetProcessInfo(ClientPtr client)
0N/A{
0N/A REQUEST(xIASetProcessInfoReq);
0N/A REQUEST_AT_LEAST_SIZE(xIASetProcessInfoReq);
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIAGetProcessInfo(ClientPtr client)
0N/A{
0N/A REQUEST(xIAGetProcessInfoReq);
0N/A REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic void
0N/AChangeInteractive(ClientPtr client)
0N/A{
606N/A ClientProcessPtr CurrentPids = GetConnectionPids(client);
0N/A
606N/A if (InteractiveOS==FALSE)
0N/A return;
0N/A
606N/A if (!CurrentPids || !CurrentPids->pids)
0N/A return;
0N/A
606N/A SetPriority(CurrentPids, SET_INTERACTIVE);
0N/A}
0N/A
0N/A/*
606N/A * Loop through pids associated with client. Magically make last focus
606N/A * group go non-interactive -IA_BOOST.
606N/A */
0N/Astatic void
0N/AChangePriority(register ClientPtr client)
0N/A{
606N/A IAClientPrivatePtr priv = GetIAClient(client);
606N/A ClientProcessPtr CurrentPids = (priv == NULL ? NULL : priv->process);
0N/A
606N/A if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
606N/A /* Shortcut. Focus changed between two windows with same pid */
0N/A return;
606N/A }
0N/A
606N/A /* Remove priority boost for last focus group */
606N/A if (LastPids) {
606N/A SetPriority(LastPids, UNSET_PRIORITY);
606N/A LastPids = NULL;
606N/A }
908N/A
606N/A /* If no pid info for current client, then we're done here.
606N/A * This can happen if we have a remote client with focus or if the client
606N/A * is statically linked or if it is using a down rev version of libX11.
606N/A */
606N/A if ( (CurrentPids == NULL) || (CurrentPids->count == 0) ||
606N/A (CurrentPids->pids == NULL) ) {
606N/A return;
606N/A }
0N/A
606N/A /* Set the priority boost if it isn't already active */
606N/A if (!CurrentPids->boosted) {
606N/A SetPriority(CurrentPids, SET_PRIORITY);
606N/A }
908N/A
606N/A /* Make sure server or wmgr isn't unset by testing for them, so
606N/A * that LastPids is never set to point to the server or wmgr pid.
606N/A */
606N/A if ((client->index != serverClient->index) && (priv->wmgr != TRUE)) {
606N/A LastPids = CurrentPids;
606N/A }
0N/A}
0N/A
0N/Astatic int
0N/AInitializeClass(void)
0N/A{
606N/A pcinfo_t pcinfo;
0N/A
606N/A /* Get TS class information */
606N/A strcpy (pcinfo.pc_clname, "TS");
908N/A priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo);
606N/A TScid = pcinfo.pc_cid;
0N/A
606N/A /* Get IA class information */
606N/A strcpy (pcinfo.pc_clname, "IA");
606N/A if ((priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo)) == -1)
0N/A return ~Success;
908N/A
606N/A IAClass.pc_cid = pcinfo.pc_cid;
606N/A ((iaparms_t*)IAClass.pc_clparms)->ia_uprilim = IA_NOCHANGE;
606N/A ((iaparms_t*)IAClass.pc_clparms)->ia_upri = IA_NOCHANGE;
0N/A
606N/A return Success;
0N/A}
0N/A
0N/Astatic int
606N/ASetPriority(const ClientProcessPtr cpp, int cmd)
0N/A{
606N/A pcparms_t pcinfo;
606N/A long ret = Success;
0N/A gid_t usr_egid = getegid();
606N/A int i;
0N/A
606N/A if ( (cpp == NULL) || (cpp->pids == NULL) || (cpp->count == 0) ) {
606N/A return Success;
606N/A }
908N/A
606N/A if ( setegid(0) < 0 ) {
1265N/A ErrorF("Error in setting egid to 0: %s\n", strerror(errno));
0N/A }
0N/A
606N/A for (i = 0; i < cpp->count ; i++) {
606N/A id_t pid = cpp->pids[i];
0N/A
1088N/A pcinfo.pc_cid = PC_CLNULL;
606N/A if ((priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcinfo)) < 0) {
606N/A if ( setegid(usr_egid) < 0 ) {
1265N/A ErrorF("Error in resetting egid: %s\n", strerror(errno));
606N/A }
606N/A return ~Success; /* Scary time; punt */
606N/A }
606N/A
606N/A /* If process is in TS or IA class we can safely set parameters */
606N/A if ((pcinfo.pc_cid == IAClass.pc_cid) || (pcinfo.pc_cid == TScid)) {
606N/A
606N/A switch (cmd) {
606N/A case UNSET_PRIORITY:
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
0N/A break;
606N/A case SET_PRIORITY:
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_SET_INTERACTIVE;
0N/A break;
908N/A case SET_INTERACTIVE:
606N/A /* If this returns true, the process is already in the */
606N/A /* IA class, so we don't need to update it. */
606N/A if ( pcinfo.pc_cid == IAClass.pc_cid)
606N/A continue;
0N/A
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
0N/A break;
606N/A }
0N/A
606N/A if (priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&IAClass) == -1)
0N/A {
606N/A ret = ~Success;
0N/A }
0N/A
606N/A IA_DEBUG(IA_DEBUG_PRIOCNTL,
606N/A {
606N/A const char *cmdmsg;
0N/A
606N/A switch (cmd) {
606N/A case UNSET_PRIORITY: cmdmsg = "UNSET_PRIORITY"; break;
606N/A case SET_PRIORITY: cmdmsg = "SET_PRIORITY"; break;
606N/A case SET_INTERACTIVE: cmdmsg = "SET_INTERACTIVE"; break;
606N/A default: cmdmsg = "UNKNOWN_CMD!!!"; break;
606N/A }
908N/A LogMessage(X_INFO, "SolarisIA: SetPriority(%ld, %s): %s\n",
606N/A pid, cmdmsg,
606N/A (ret == Success) ? "succeeeded" : "failed");
606N/A });
606N/A }
0N/A }
0N/A
606N/A if (setegid(usr_egid) < 0)
1265N/A ErrorF("Error in resetting egid: %s\n", strerror(errno));
606N/A
606N/A if (ret == Success) {
606N/A if (cmd == SET_PRIORITY) {
606N/A cpp->boosted = TRUE;
606N/A } else if (cmd == UNSET_PRIORITY) {
606N/A cpp->boosted = FALSE;
606N/A }
606N/A }
908N/A
606N/A return ret;
0N/A}
0N/A
0N/Astatic void
1088N/ASetIAPrivate(int *value)
0N/A{
606N/A ia_nice = *value;
0N/A}
0N/A
0N/A/*****************************************************************************
0N/A * Various utility functions - in Xsun these lived in Xserver/os/process.c
0N/A */
0N/A
0N/A/* In Xsun we used the osPrivate in OsCommPtr, so this was SetOsPrivate. */
0N/Astatic int
0N/ASetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length)
606N/A{
0N/A ClientProcessPtr cpp;
606N/A IAClientPrivatePtr priv;
0N/A
606N/A priv = GetIAClient(client);
606N/A if (priv == NULL) {
606N/A IAInitClientPrivate(client);
606N/A } else {
606N/A FreeProcessList(priv);
606N/A }
606N/A
1088N/A cpp = malloc(sizeof(ClientProcessRec));
0N/A
0N/A if (cpp == NULL)
0N/A return BadAlloc;
0N/A
1088N/A cpp->pids = malloc(sizeof(ConnectionPidRec)*length);
0N/A
0N/A if (cpp->pids == NULL) {
1088N/A free(cpp);
0N/A return BadAlloc;
0N/A }
0N/A
0N/A cpp->count = length;
0N/A memcpy(cpp->pids, stuff, sizeof(ConnectionPidRec)*length);
606N/A cpp->boosted = FALSE;
606N/A
606N/A priv->process = cpp;
0N/A return Success;
0N/A}
0N/A
0N/Astatic void
606N/AFreeProcessList(IAClientPrivatePtr priv)
0N/A{
606N/A ClientProcessPtr cpp = priv->process;
606N/A
0N/A if (cpp == NULL)
0N/A return;
606N/A priv->process = NULL;
0N/A
1088N/A if (LastPids == cpp)
0N/A LastPids = NULL;
0N/A
0N/A if (cpp->pids != NULL)
1088N/A free(cpp->pids);
0N/A
1088N/A free(cpp);
0N/A}
0N/A
0N/A/*
606N/A Check to see that all in current (a) are in last (b).
606N/A And that a and b have the same number of members in the set.
0N/A*/
606N/Astatic int
0N/APidSetEqual(ClientProcessPtr a, ClientProcessPtr b)
0N/A{
606N/A int aN, bN;
606N/A int count = a->count;
606N/A int retval = 1;
0N/A
606N/A if (a->count != b->count) {
606N/A return 0; /* definately NOT the same set */
606N/A }
0N/A
606N/A for (aN = 0; aN < count; aN++) {
606N/A retval = 0;
606N/A for (bN = 0; bN < count ; bN++) {
606N/A if (a->pids[aN] == b->pids[bN]) {
606N/A retval = 1;
606N/A break;
606N/A }
606N/A }
606N/A if (retval == 0)
606N/A return retval;
606N/A }
0N/A
606N/A return retval;
0N/A}
0N/A
0N/A
0N/A/*****************************************************************************
0N/A * Wrappers for normal procs - in Xsun we modified the original procs directly
0N/A * in dix, but here we wrap them for a small performance loss but a large
0N/A * increase in maintainability and ease of porting to new releases.
0N/A */
0N/A
0N/Astatic int
0N/AIAProcSetInputFocus(ClientPtr client)
0N/A{
0N/A int res;
0N/A Window focusID;
606N/A WindowPtr focusWin;
0N/A REQUEST(xSetInputFocusReq);
0N/A
0N/A res = (*IASavedProcVector[X_SetInputFocus])(client);
606N/A if ((res != Success) || (InteractiveOS != TRUE))
0N/A return res;
0N/A
0N/A focusID = stuff->focus;
0N/A
98N/A switch (focusID) {
98N/A case None:
98N/A focusWin = NullWindow;
98N/A break;
98N/A case PointerRoot:
98N/A focusWin = PointerRootWin;
98N/A break;
98N/A default:
606N/A res = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
606N/A if (res != Success)
606N/A return res;
0N/A }
0N/A
0N/A if ((focusWin != NullWindow) && (focusWin != PointerRootWin)) {
606N/A register ClientPtr requestee = wClient(focusWin);
606N/A ChangePriority(requestee);
0N/A }
0N/A
0N/A return res;
0N/A}
0N/A
0N/Astatic int
0N/AIAProcSendEvent(ClientPtr client)
0N/A{
0N/A int res;
0N/A REQUEST(xSendEventReq);
0N/A
0N/A res = (*IASavedProcVector[X_SendEvent])(client);
606N/A if ((res != Success) || (InteractiveOS != TRUE))
0N/A return res;
0N/A
606N/A if ((InteractiveOS==TRUE) &&
606N/A (GetIAClient(client)->wmgr == TRUE) &&
0N/A (stuff->event.u.u.type == ClientMessage) &&
0N/A (stuff->event.u.u.detail == 32) ) {
908N/A
0N/A register ClientPtr requestee;
606N/A WindowPtr pWin = NULL;
705N/A DeviceIntPtr pPtr = PickPointer(client);
0N/A
0N/A if (stuff->destination == PointerWindow)
705N/A pWin = GetSpriteWindow(pPtr);
0N/A else if (stuff->destination == InputFocus)
0N/A {
0N/A WindowPtr inputFocus = inputInfo.keyboard->focus->win;
0N/A
0N/A if (inputFocus == NoneWin)
0N/A return Success;
908N/A
0N/A /* If the input focus is PointerRootWin, send the event to where
0N/A the pointer is if possible, then perhaps propogate up to root. */
0N/A if (inputFocus == PointerRootWin)
705N/A inputFocus = GetCurrentRootWindow(pPtr);
908N/A
705N/A if (IsParent(inputFocus, GetSpriteWindow(pPtr)))
705N/A pWin = GetSpriteWindow(pPtr);
0N/A else
0N/A pWin = inputFocus;
0N/A }
0N/A else
606N/A {
606N/A res = dixLookupWindow(&pWin, stuff->destination, client,
606N/A DixReadAccess);
606N/A if (res != Success)
606N/A return res;
606N/A }
606N/A
908N/A
0N/A if (!pWin)
0N/A return BadWindow;
908N/A
606N/A requestee = wClient(pWin);
606N/A ChangePriority(requestee);
0N/A }
0N/A return res;
0N/A}
0N/A
0N/Astatic Bool
0N/AIAProcChangeWindowAttributes(ClientPtr client)
0N/A{
0N/A REQUEST(xChangeWindowAttributesReq);
0N/A
606N/A if ((InteractiveOS==TRUE) && (stuff->valueMask & CWEventMask) &&
606N/A (GetIAClient(client)->wmgr == FALSE) ) {
0N/A
0N/A register XID *pVlist = (XID *) &stuff[1];
0N/A register Mask tmask = stuff->valueMask;
98N/A register Mask index2 = 0;
0N/A
0N/A while (tmask) {
0N/A index2 = (Mask) lowbit (tmask);
0N/A tmask &= ~index2;
0N/A if (index2 == CWEventMask) {
0N/A break;
0N/A }
0N/A pVlist++;
0N/A }
0N/A
0N/A if ((index2 == CWEventMask) && (*pVlist & SubstructureRedirectMask)) {
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A ClientProcessPtr CurrentPids=GetConnectionPids(client);
0N/A
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: WindowManager detected (pid %d)\n",
606N/A (CurrentPids && CurrentPids->pids) ?
606N/A CurrentPids->pids[0] : -1));
0N/A
606N/A GetIAClient(client)->wmgr = TRUE;
0N/A ChangePriority(client);
606N/A LastPids = NULL;
0N/A }
0N/A }
0N/A
0N/A return (*IASavedProcVector[X_ChangeWindowAttributes])(client);
0N/A}
0N/A
0N/A
908N/Astatic int
0N/AIAWrapProcVectors(void)
0N/A{
0N/A IASavedProcVector[X_SetInputFocus] = ProcVector[X_SetInputFocus];
0N/A ProcVector[X_SetInputFocus] = IAProcSetInputFocus;
0N/A
0N/A IASavedProcVector[X_SendEvent] = ProcVector[X_SendEvent];
0N/A ProcVector[X_SendEvent] = IAProcSendEvent;
0N/A
908N/A IASavedProcVector[X_ChangeWindowAttributes]
0N/A = ProcVector[X_ChangeWindowAttributes];
0N/A ProcVector[X_ChangeWindowAttributes] = IAProcChangeWindowAttributes;
0N/A
0N/A return 0;
0N/A}
0N/A
908N/Astatic int
0N/AIAUnwrapProcVectors(void)
0N/A{
0N/A ProcVector[X_SetInputFocus] = IASavedProcVector[X_SetInputFocus];
0N/A ProcVector[X_SendEvent] = IASavedProcVector[X_SendEvent];
0N/A ProcVector[X_ChangeWindowAttributes] = IASavedProcVector[X_ChangeWindowAttributes];
0N/A
0N/A return 0;
0N/A}
0N/A
0N/A