tsolutils.c revision 168
98N/A/* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
0N/A *
0N/A * Permission is hereby granted, free of charge, to any person obtaining a
0N/A * copy of this software and associated documentation files (the
0N/A * "Software"), to deal in the Software without restriction, including
0N/A * without limitation the rights to use, copy, modify, merge, publish,
0N/A * distribute, and/or sell copies of the Software, and to permit persons
0N/A * to whom the Software is furnished to do so, provided that the above
0N/A * copyright notice(s) and this permission notice appear in all copies of
0N/A * the Software and that both the above copyright notice(s) and this
0N/A * permission notice appear in supporting documentation.
0N/A *
0N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
0N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
0N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
0N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
0N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
0N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0N/A *
0N/A * Except as contained in this notice, the name of a copyright holder
0N/A * shall not be used in advertising or otherwise to promote the sale, use
0N/A * or other dealings in this Software without prior written authorization
0N/A * of the copyright holder.
0N/A */
0N/A
168N/A#pragma ident "@(#)tsolutils.c 1.16 07/06/08 SMI"
0N/A
168N/A#ifdef HAVE_DIX_CONFIG_H
168N/A#include <dix-config.h>
98N/A#endif
0N/A
0N/A#define NEED_EVENTS
0N/A#include <stdio.h>
0N/A#include <X11/X.h>
0N/A#include <X11/Xproto.h>
0N/A#include <X11/Xprotostr.h>
0N/A#include <bsm/auditwrite.h>
0N/A#include <bsm/audit_uevents.h>
0N/A#include <regex.h>
36N/A#include <priv.h>
168N/A#include <X11/Xproto.h>
0N/A#include "windowstr.h"
0N/A#include "scrnintstr.h"
0N/A#include "tsolinfo.h"
168N/A#include <X11/keysym.h>
0N/A#include "misc.h"
0N/A#include "inputstr.h"
0N/A#include "propertyst.h"
0N/A
0N/A#define MAX_SL_ENTRY 256
0N/A#define MAX_UID_ENTRY 64
0N/A#define ALLOCATED 1
0N/A#define EMPTIED 0
0N/A#define FamilyTSOL 5
0N/A#define TSOLUIDlength 4
0N/A
0N/A#define BOXES_OVERLAP(b1, b2) \
0N/A (!( ((b1)->x2 <= (b2)->x1) || \
0N/A ( ((b1)->x1 >= (b2)->x2)) || \
0N/A ( ((b1)->y2 <= (b2)->y1)) || \
0N/A ( ((b1)->y1 >= (b2)->y2)) ) )
0N/A
0N/ABool system_audit_on = FALSE;
0N/ABool priv_win_colormap = FALSE;
0N/ABool priv_win_config = FALSE;
0N/ABool priv_win_devices = FALSE;
0N/ABool priv_win_dga = FALSE;
0N/ABool priv_win_fontpath = FALSE;
0N/ATsolInfoPtr dying_tsolinfo = (TsolInfoPtr)NULL;
0N/AExtensionFlag extflag = { FALSE, FALSE, FALSE, FALSE, FALSE,
0N/A FALSE, FALSE, FALSE, FALSE, FALSE,
0N/A FALSE, FALSE, FALSE, FALSE, FALSE,
0N/A FALSE, FALSE, FALSE, FALSE, FALSE,
0N/A FALSE, FALSE, FALSE, FALSE, FALSE,
0N/A FALSE };
0N/A
0N/A/*
0N/A * The following need to be moved to tsolextension.c
0N/A * after all references in Xsun is pulled out
0N/A */
0N/AWindowPtr tpwin = NULL; /* only one trusted path window at a time */
0N/ATsolPolyInstInfoRec tsolpolyinstinfo;
0N/A#define TsolMaxPolyNameSize 80
0N/A/*
0N/A * Use the NodeRec struct in tsolinfo.h. This is referenced
0N/A * in policy routines. So we had to move it there
0N/A */
0N/ATsolPolyAtomRec tsolpolyprop = {FALSE, 0, 0, NULL};
0N/ATsolPolyAtomRec tsolpolyseln = {TRUE, 0, 0, NULL};
0N/A
0N/A
0N/A/*
0N/A * Private indices
0N/A */
0N/Aint tsolClientPrivateIndex = -1;
0N/Aint tsolWindowPrivateIndex = -1;
0N/Aint tsolPixmapPrivateIndex = -1;
0N/A
0N/Abclear_t SessionHI; /* HI Clearance */
0N/Abclear_t SessionLO; /* LO Clearance */
0N/Aunsigned int StripeHeight = 0;
0N/Auid_t OwnerUID = (uid_t)(-1);
0N/Abslabel_t PublicObjSL;
0N/A
0N/AAtom tsol_lastAtom = None;
0N/Aint tsol_nodelength = 0;
0N/ATsolNodePtr tsol_node = NULL;
0N/A
0N/A/* This structure is used for protocol request ListHosts */
0N/Astruct xUIDreply
0N/A{
0N/A unsigned char family;
0N/A unsigned char pad;
0N/A unsigned short length;
0N/A int uid; /* uid type */
0N/A};
0N/A
0N/Astruct slentry
0N/A{
0N/A bslabel_t senlabel;
0N/A char allocated;
0N/A};
0N/A
0N/Astatic struct slentry sltable[MAX_SL_ENTRY];
0N/A
0N/A/* This table contains list of users who can connect to the server */
0N/Astruct uidentry
0N/A{
0N/A int userid; /* uid type */
0N/A char allocated;
0N/A};
0N/A
0N/Astatic struct uidentry uidtable[MAX_UID_ENTRY];
0N/A
0N/A/* Index must match with keywords */
0N/Astatic char *tsolconfig_keywords[] = {"atom", "property", "selection",
0N/A "extension", "privilege"};
0N/A
0N/A#define KEYWORDCOUNT sizeof(tsolconfig_keywords)/sizeof(char *)
0N/A
0N/Atypedef struct _TsolConfig
0N/A{
0N/A int count;
0N/A char **list;
0N/A} TsolConfigRec;
0N/A
0N/ATsolConfigRec tsolconfig[KEYWORDCOUNT] = {
0N/A {0, NULL},
0N/A {0, NULL},
0N/A {0, NULL},
0N/A {0, NULL},
0N/A {0, NULL}
0N/A};
0N/A
0N/A#define TSOL_ATOMCOUNT 4
0N/Astatic char *tsolatomnames[TSOL_ATOMCOUNT] = {
0N/A "_TSOL_CMWLABEL_CHANGE",
0N/A "_TSOL_GRABNOTIFY",
0N/A "_TSOL_CLIENT_TERM",
0N/A "_TSOL_SEL_AGNT"
0N/A};
0N/A
0N/A#ifdef DEBUG
0N/A/*
0N/A * selectively enable debugging. upto 32 levels of debugging supported
0N/A * flags are defined in tsolinfo.h
0N/A */
0N/A#define TSOL_ERR_FILE "/tmp/Xsun.err" /* error log file */
0N/Aunsigned long tsoldebug = 0; /* TSOLD_SELECTION; */
0N/A#endif /* DEBUG */
0N/A
0N/Avoid
0N/Ainit_TSOL_cached_SL()
0N/A{
0N/A sltable[0].allocated = ALLOCATED;
0N/A bsllow (&(sltable[0].senlabel));
0N/A
0N/A sltable[1].allocated = ALLOCATED;
0N/A bslhigh(&(sltable[1].senlabel));
0N/A
0N/A}
0N/A
0N/A/* Initialize UID table, this table should at least contains owner UID */
0N/Avoid
0N/Ainit_TSOL_uid_table()
0N/A{
0N/A uidtable[0].allocated = ALLOCATED;
0N/A uidtable[0].userid = 0;
0N/A}
0N/A
0N/A/* Count how many valid entried in the uid table */
0N/Aint
0N/Acount_uid_table()
0N/A{
0N/A int i, count = 0;
0N/A
0N/A /* Search entire table */
0N/A for (i = 0; i < MAX_UID_ENTRY; i++)
0N/A {
0N/A if (uidtable[i].allocated == ALLOCATED)
0N/A count++;
0N/A }
0N/A return (count);
0N/A}
0N/A
0N/A/* return (1); if userid is in the table */
0N/Aint
0N/AlookupUID(userid)
0N/A int userid;
0N/A{
0N/A int i;
0N/A for (i = 0; i < MAX_UID_ENTRY; i++)
0N/A {
0N/A if (uidtable[i].allocated == ALLOCATED &&
0N/A uidtable[i].userid == userid)
0N/A {
0N/A return (1); /* yes, found it */
0N/A }
0N/A }
0N/A return (0); /* not found */
0N/A}
0N/A
0N/A/* Passed into a pointer to a storage which is used to store UID */
0N/A/* and nUid represents how many UID in the table(returned by count_uid_table) */
0N/Aint
0N/AListUID(uidaddr, nUid)
0N/A struct xUIDreply * uidaddr;
0N/A int nUid;
0N/A{
0N/A int i, j = 0;
0N/A
0N/A for (i = 0; i < MAX_UID_ENTRY; i++)
0N/A {
0N/A if (uidtable[i].allocated == ALLOCATED)
0N/A {
0N/A uidaddr[j].family = FamilyTSOL;
0N/A uidaddr[j].length = TSOLUIDlength;
0N/A uidaddr[j].uid = uidtable[i].userid;
0N/A j++;
0N/A }
0N/A }
0N/A if (nUid != j)
0N/A {
0N/A ErrorF("Invalid no. of uid entries? \n");
0N/A return (0);
0N/A }
0N/A
0N/A return (1);
0N/A}
0N/A
0N/A/* add userid into UIDtable */
0N/Aint
0N/AAddUID(userid)
0N/A int *userid;
0N/A{
0N/A
0N/A int i = 0;
0N/A
0N/A /*
0N/A * Search entire uidtable, to prevent duplicate uid
0N/A * entry in the table
0N/A */
0N/A while (i < MAX_UID_ENTRY)
0N/A {
0N/A if ((uidtable[i].allocated == ALLOCATED) &&
0N/A (uidtable[i].userid == *userid))
0N/A {
0N/A /* this uid entry is already in the table; no-op */
0N/A return (1); /* Success, uid in the table */
0N/A }
0N/A i++;
0N/A }
0N/A
0N/A i = 0;
0N/A /*
0N/A * If we can find an empty entry, then add this uid
0N/A * into the table
0N/A */
0N/A while (i < MAX_UID_ENTRY)
0N/A {
0N/A if (uidtable[i].allocated != ALLOCATED)
0N/A {
0N/A uidtable[i].allocated = ALLOCATED;
0N/A uidtable[i].userid = *userid;
0N/A return (1); /* Success, uid in the table */
0N/A }
0N/A i++;
0N/A }
0N/A
0N/A /* uidtable overflow */
0N/A ErrorF("Server problem: Please enlarge the table size of uidtable \n");
0N/A return (0);
0N/A}
0N/A
0N/A
0N/A/* remove userid from UIDtable */
0N/Aint
0N/ARemoveUID(userid)
0N/A int *userid;
0N/A{
0N/A int i = 0;
0N/A
0N/A if (*userid == 0)
0N/A {
0N/A ErrorF("\n UID 0 can not be removed from server UID list");
0N/A return (0);
0N/A }
0N/A
0N/A while (i < MAX_UID_ENTRY)
0N/A {
0N/A if ((uidtable[i].allocated == ALLOCATED) &&
0N/A (uidtable[i].userid == *userid))
0N/A {
0N/A /* delete this entry in the table */
0N/A uidtable[i].allocated = EMPTIED;
0N/A return (1); /* Success, uid in the table */
0N/A
0N/A }
0N/A i++;
0N/A }
0N/A
0N/A /* no such entry in the table, why delete it? no-op */
0N/A return (0);
0N/A}
0N/A
0N/A
0N/A
0N/A
0N/Abslabel_t *
0N/AlookupSL_low()
0N/A{
0N/A return (&(sltable[0].senlabel));
0N/A}
0N/A
0N/A
0N/Abslabel_t *
0N/AlookupSL(slptr)
0N/Abslabel_t *slptr;
0N/A{
0N/A int i = 0;
0N/A
0N/A if (slptr == NULL)
0N/A return (slptr);
0N/A
0N/A while ((i < MAX_SL_ENTRY) && sltable[i].allocated == ALLOCATED)
0N/A {
0N/A if (blequal(slptr, &(sltable[i].senlabel)))
0N/A {
0N/A /* found a matching sensitivity label in sltable */
0N/A return (&(sltable[i].senlabel));
0N/A }
0N/A i++;
0N/A }
0N/A
0N/A if (i < MAX_SL_ENTRY)
0N/A {
0N/A /*
0N/A * can't find a matching entry in sltable,
0N/A * however, we have empty entry to store this
0N/A * new sensitivity label; store it.
0N/A */
0N/A sltable[i].allocated = ALLOCATED;
0N/A memcpy (&(sltable[i].senlabel), slptr, sizeof (bslabel_t));
0N/A return (&(sltable[i].senlabel));
0N/A }
0N/A
0N/A /*
0N/A * no matching entry in sltable, and no room to
0N/A * store this new sensitivity label,
0N/A * the server needs to recomplie with a larger slabel
0N/A */
0N/A
0N/A ErrorF("Server problem: Please enlarge the table size of sltable \n");
0N/A return (0);
0N/A}
0N/A
0N/Aint
0N/ADoScreenStripeHeight(screen_num)
0N/A int screen_num;
0N/A{
0N/A extern char *ConnectionInfo;
0N/A extern int connBlockScreenStart;
0N/A int i, j;
0N/A xWindowRoot *root;
0N/A register xDepth *pDepth;
0N/A ScreenPtr pScreen;
0N/A
0N/A root = (xWindowRoot *)(ConnectionInfo + connBlockScreenStart);
0N/A for (i = 0; i < screen_num; i++)
0N/A {
0N/A pDepth = (xDepth *)(root + 1);
0N/A for (j = 0; j < (int)root->nDepths; j++)
0N/A {
0N/A pDepth = (xDepth *)(((char *)(pDepth + 1)) +
0N/A pDepth->nVisuals * sizeof (xVisualType));
0N/A }
0N/A root = (xWindowRoot *) pDepth;
0N/A
0N/A }
0N/A
0N/A pScreen = screenInfo.screens[screen_num];
0N/A root->pixHeight = pScreen->height - StripeHeight;
0N/A
0N/A /* compute new millimeter height */
0N/A
0N/A root->mmHeight = (pScreen->mmHeight * root->pixHeight +
0N/A ((int)(pScreen->height)/2))/(int)(pScreen->height);
0N/A
0N/A return (0);
0N/A}
0N/Avoid
0N/Ainit_xtsol()
0N/A{
36N/A extern Bool system_audit_on;
0N/A extern bslabel_t PublicObjSL;
0N/A extern bclear_t SessionHI; /* HI Clearance */
0N/A extern bclear_t SessionLO; /* LO Clearance */
36N/A extern int cannot_audit(int); /* bsm function */
0N/A
0N/A bclearhigh(&SessionHI);
0N/A bclearlow(&SessionLO);
0N/A bsllow(&PublicObjSL);
0N/A init_TSOL_cached_SL();
0N/A init_TSOL_uid_table();
0N/A
36N/A if (cannot_audit(TRUE))
36N/A system_audit_on = FALSE;
36N/A else
36N/A system_audit_on = TRUE;
36N/A
0N/A auditwrite(AW_QUEUE, XAUDIT_Q_SIZE, AW_END);
0N/A}
0N/A
0N/A/*
0N/A * Converts keycode to keysym, helper function.
0N/A * Modelled after Xlib code
0N/A */
0N/Astatic KeySym
0N/AKeycodetoKeysym(KeyCode keycode, int col)
0N/A{
0N/A KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
0N/A int per = curKeySyms->mapWidth;
0N/A KeySym *syms = curKeySyms->map;
0N/A KeySym lsym, usym;
0N/A
0N/A if ((col < 0) || ((col >= per) && (col > 3)) ||
0N/A ((int)keycode < curKeySyms->minKeyCode) ||
0N/A ((int)keycode > curKeySyms->maxKeyCode))
0N/A return NoSymbol;
0N/A
0N/A syms = &curKeySyms->map[(keycode - curKeySyms->minKeyCode) * per];
0N/A if (col < 4) {
0N/A if (col > 1) {
0N/A while ((per > 2) && (syms[per - 1] == NoSymbol))
0N/A per--;
0N/A if (per < 3)
0N/A col -= 2;
0N/A }
0N/A if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
0N/A if (!(col & 1))
0N/A return lsym;
0N/A else if (usym == lsym)
0N/A return NoSymbol;
0N/A else
0N/A return usym;
0N/A }
0N/A }
0N/A return syms[col];
0N/A}
0N/A
0N/A/*
0N/A * Converts keysym to a keycode
0N/A * Modelled after Xlib code
0N/A */
0N/Astatic KeyCode
0N/AKeysymToKeycode(KeySym ks)
0N/A{
0N/A int i, j;
0N/A KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
0N/A
0N/A for (j = 0; j < curKeySyms->mapWidth; j++) {
0N/A for (i = curKeySyms->minKeyCode; i <= curKeySyms->maxKeyCode; i++) {
0N/A if (KeycodetoKeysym((KeyCode) i, j) == ks)
0N/A return i;
0N/A }
0N/A }
0N/A return 0;
0N/A}
0N/A
0N/A/*
0N/A * converts a keysym to modifier equivalent mask
0N/A * Modelled after Xlib
0N/A */
0N/Astatic unsigned
0N/AKeysymToModifier(KeySym ks)
0N/A{
0N/A CARD8 code, mods;
0N/A KeySym *kmax;
0N/A KeySym *k;
0N/A KeySymsPtr keysyms = &inputInfo.keyboard->key->curKeySyms;
0N/A KeyClassPtr key = inputInfo.keyboard->key;
0N/A
0N/A kmax = keysyms->map + (keysyms->maxKeyCode - keysyms->minKeyCode + 1) *
0N/A keysyms->mapWidth;
0N/A k = keysyms->map;
0N/A mods = 0;
0N/A while (k < kmax) {
0N/A if (*k == ks ) {
0N/A int j = key->maxKeysPerModifier << 3;
0N/A
0N/A code = (((k - keysyms->map) / keysyms->mapWidth) + keysyms->minKeyCode);
0N/A
0N/A while (--j >= 0) {
0N/A if (code == key->modifierKeyMap[j])
0N/A mods |= (1 << (j / key->maxKeysPerModifier));
0N/A }
0N/A }
0N/A k++;
0N/A }
0N/A return mods;
0N/A}
0N/A
0N/A/*
0N/A * Initialize Hot Key keys. On A Sun type 5/6 keyboard
0N/A * It's Meta(Diamond) + Stop. On a non-Sun keyboard, it's
0N/A * Alt + Break(Pause) key. Hold down the meta or alt key
0N/A * press stop or break key.
0N/A *
0N/A * NOTE:
0N/A * Both Left & Right keys for (Meta or Alt) return the
0N/A * same modifier mask
0N/A */
0N/Avoid
0N/AInitHotKey(HotKeyPtr hk)
0N/A{
0N/A /* Meta + Stop */
0N/A hk->shift = KeysymToModifier(XK_Meta_L);
0N/A hk->key = KeysymToKeycode(XK_L1);
0N/A
0N/A /* Alt + Break/Pause */
0N/A hk->altshift = KeysymToModifier(XK_Alt_L);
168N/A hk->altkey = KeysymToKeycode(XK_Pause);
0N/A
0N/A hk->initialized = TRUE;
0N/A}
0N/Avoid
0N/AUpdateTsolConfig(char *keyword, char *value)
0N/A{
0N/A int i;
0N/A int count;
0N/A char **newlist;
0N/A
0N/A if (keyword == NULL || value == NULL)
0N/A return; /* ignore incomplete entries */
0N/A
0N/A /* find a matching keyword */
0N/A for (i = 0; i < KEYWORDCOUNT; i++) {
0N/A if (strcmp(keyword, tsolconfig_keywords[i]) == 0) {
0N/A break;
0N/A }
0N/A }
0N/A
0N/A /* Invalid keyword */
0N/A if (i >= KEYWORDCOUNT) {
0N/A ErrorF("Invalid keyword : %s\n", keyword);
0N/A return;
0N/A }
0N/A
0N/A count = tsolconfig[i].count;
0N/A newlist = (char **)Xrealloc(tsolconfig[i].list, (count + 1) * sizeof(char **));
0N/A if (newlist == NULL) {
0N/A ErrorF("Not enough memory for %s %s\n", keyword, value);
0N/A return;
0N/A }
0N/A
0N/A newlist[count] = strdup(value);
0N/A tsolconfig[i].list = newlist;
0N/A tsolconfig[i].count++;
0N/A}
0N/A
0N/Avoid
0N/AInitPrivileges()
0N/A{
0N/A int i;
0N/A int count;
0N/A char **list;
0N/A
0N/A count = tsolconfig[TSOL_PRIVILEGE].count;
0N/A list = tsolconfig[TSOL_PRIVILEGE].list;
0N/A
0N/A for (i = 0; i < count; i++) {
0N/A if (strcmp(list[i], PRIV_WIN_COLORMAP) == 0)
0N/A priv_win_colormap = TRUE;
0N/A else if (strcmp(list[i], PRIV_WIN_CONFIG) == 0)
0N/A priv_win_config = TRUE;
0N/A else if (strcmp(list[i], PRIV_WIN_DEVICES) == 0)
0N/A priv_win_devices = TRUE;
0N/A else if (strcmp(list[i], PRIV_WIN_FONTPATH) == 0)
0N/A priv_win_fontpath = TRUE;
0N/A else if (strcmp(list[i], PRIV_WIN_DGA) == 0)
0N/A priv_win_dga = TRUE;
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Load Trusted Solaris configuration file
0N/A * TBD: Process extension keywords
0N/A */
0N/Avoid
0N/ALoadTsolConfig()
0N/A{
0N/A FILE *fp;
0N/A char buf[BUFSIZ];
0N/A char *keyword;
0N/A char *value;
0N/A
0N/A /* open the file from /etc first followed by /usr */
0N/A if ((fp = fopen(TSOLPOLICYFILE, "r")) == NULL) {
0N/A ErrorF("Cannot load %s. Some desktop applications may not\n"
0N/A "work correctly\n", TSOLPOLICYFILE);
0N/A return;
0N/A }
0N/A
0N/A /* Read and parse the config file */
0N/A while (fgets(buf, sizeof (buf), fp) != NULL) {
0N/A
0N/A /* ignore all comments, lines starting with white space */
0N/A if (buf[0] == '#' || isspace((int)buf[0]))
0N/A continue;
0N/A
0N/A keyword = strtok(buf, " \t");
0N/A value = strtok(NULL, " \t\n");
0N/A UpdateTsolConfig(keyword, value);
0N/A }
0N/A
0N/A InitPrivileges();
0N/A}
0N/A
0N/A
0N/A/*
0N/A * It does not really tell if this atom is to be polyinstantiated
0N/A * or not. Further check should be done to determine this.
0N/A */
0N/Aint
0N/ASpecialName(char *string, int len)
0N/A{
0N/A
0N/A return (MatchTsolConfig(string, len));
0N/A}
0N/A
0N/A
0N/Avoid
0N/AMakeTSOLAtoms()
0N/A{
0N/A int i;
0N/A char *atomname;
0N/A Atom a;
0N/A
0N/A /* Create new TSOL atoms */
0N/A for (i = 0; i < TSOL_ATOMCOUNT; i++) {
0N/A if (MakeAtom(tsolatomnames[i], strlen(tsolatomnames[i]), TRUE) == None)
0N/A AtomError();
0N/A }
0N/A
0N/A /* Create atoms defined in config file */
0N/A for (i = 0; i < tsolconfig[TSOL_ATOM].count; i++) {
0N/A atomname = tsolconfig[TSOL_ATOM].list[i];
0N/A if (MakeAtom(atomname, strlen(atomname), TRUE) == None) {
0N/A AtomError();
0N/A }
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Names starting with a slash in selection.atoms and property.atoms
0N/A * are treated as regular expressions to be matched against the
0N/A * selection and property names. They may optionally end with a slash.
0N/A */
0N/Aint
0N/Aregexcompare(char *string, int len, char *regexp)
0N/A{
0N/A int status;
0N/A regex_t compiledregexp;
0N/A char *regexpstrp;
0N/A int regexpstrlen;
0N/A char buffer[BUFSIZ];
0N/A
0N/A if (regexp[0] == '/' && len < BUFSIZ) {
0N/A /* Extract regular expression from between slashes */
0N/A regexpstrp = regexp + 1;
0N/A regexpstrlen = strlen(regexpstrp);
0N/A if (regexpstrp[regexpstrlen - 1] == '/')
0N/A regexpstrp[regexpstrlen - 1] = '\0';
0N/A /* Compile the regular expression */
0N/A status = regcomp(&compiledregexp, regexpstrp,
0N/A REG_EXTENDED | REG_NOSUB);
0N/A if (status == 0) {
0N/A /* Make null-terminated copy of string */
0N/A memcpy(buffer, string, len);
0N/A buffer[len] = '\0';
0N/A /* Compare string to regular expression */
0N/A status = regexec(&compiledregexp,
0N/A buffer, (size_t) 0, NULL, 0);
0N/A regfree(&compiledregexp);
0N/A
0N/A if (status == 0)
0N/A return (TRUE);
0N/A else
0N/A return (FALSE);
0N/A }
0N/A } else if (strncmp(string, regexp, len) == 0) {
0N/A return (TRUE);
0N/A }
0N/A
0N/A return (FALSE);
0N/A}
0N/A
0N/Aint
0N/AMatchTsolConfig(char *name, int len)
0N/A{
0N/A int i;
0N/A int count;
0N/A char **list;
0N/A unsigned int flags = 0;
0N/A
0N/A count = tsolconfig[TSOL_PROPERTY].count;
0N/A list = tsolconfig[TSOL_PROPERTY].list;
0N/A for (i = 0; i < count; i++) {
0N/A if (regexcompare(name, len, list[i])) {
0N/A flags |= TSOLM_PROPERTY;
0N/A break;
0N/A }
0N/A }
0N/A
0N/A count = tsolconfig[TSOL_SELECTION].count;
0N/A list = tsolconfig[TSOL_SELECTION].list;
0N/A for (i = 0; i < count; i++) {
0N/A if (regexcompare(name, len, list[i])) {
0N/A flags |= TSOLM_SELECTION;
0N/A break;
0N/A }
0N/A }
0N/A
0N/A return (flags);
0N/A}
0N/A
0N/ATsolInfoPtr
0N/AGetClientTsolInfo(client)
0N/A ClientPtr client;
0N/A{
0N/A return (TsolInfoPtr)(client->devPrivates[tsolClientPrivateIndex].ptr);
0N/A}
0N/A
0N/A/* Property is polyinstantiated only on root window */
0N/Aint
0N/APolyProperty(Atom atom, WindowPtr pWin)
0N/A{
0N/A if (WindowIsRoot(pWin) &&
0N/A ((!tsolpolyprop.polyinst && !(tsol_node[atom].IsSpecial & TSOLM_PROPERTY)) ||
0N/A (tsolpolyprop.polyinst && (tsol_node[atom].IsSpecial & TSOLM_PROPERTY))))
0N/A return TRUE;
0N/A return FALSE;
0N/A}
0N/A
0N/Aint
0N/APolySelection(Atom atom)
0N/A{
0N/A if ((tsolpolyseln.polyinst && (tsol_node[atom].IsSpecial & TSOLM_SELECTION)) ||
0N/A (!tsolpolyseln.polyinst && !(tsol_node[atom].IsSpecial & TSOLM_SELECTION)))
0N/A return TRUE;
0N/A return FALSE;
0N/A}
0N/A
0N/A/*
0N/A * Returns true if a matching sl.uid pair found. Must be applied
0N/A * only to polyprops.
0N/A */
0N/Aint
0N/APolyPropReadable(PropertyPtr pProp, ClientPtr client)
0N/A{
0N/A TsolPropPtr tsolprop = (TsolPropPtr)(pProp->secPrivate);
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A while (tsolprop)
0N/A {
0N/A if (tsolpolyinstinfo.enabled)
0N/A {
0N/A if (tsolprop->uid == tsolpolyinstinfo.uid &&
0N/A tsolprop->sl == tsolpolyinstinfo.sl)
0N/A return TRUE;
0N/A }
0N/A else
0N/A {
0N/A if (tsolprop->uid == tsolinfo->uid &&
0N/A tsolprop->sl == tsolinfo->sl)
0N/A return TRUE;
0N/A }
0N/A tsolprop = tsolprop->next;
0N/A }
0N/A return FALSE;
0N/A}
0N/A
0N/A/*
0N/A * client_private returns true if xid is owned/created by
0N/A * client or is a default server xid
0N/A */
0N/Aint
0N/Aclient_private (ClientPtr client, XID xid)
0N/A{
0N/A if (same_client(client, xid) || (xid & SERVER_BIT))
0N/A return TRUE;
0N/A else
0N/A return FALSE;
0N/A}
0N/A/*
0N/A * Same as TopClientWin()
0N/A * except that it returns a Window ID
0N/A * and not a ptr
0N/A */
0N/AWindow
0N/ARootOfClient(WindowPtr pWin)
0N/A{
0N/A if (pWin)
0N/A {
0N/A return (TopClientWin(pWin)->drawable.id);
0N/A }
0N/A return (NULL);
0N/A}
0N/A/*
0N/A * Return root window of pWin
0N/A */
0N/AWindowPtr
0N/ARootWin(WindowPtr pWin)
0N/A{
0N/A if (pWin)
0N/A {
0N/A while (pWin->parent)
0N/A pWin = pWin->parent;
0N/A }
0N/A return (pWin);
0N/A}
0N/AWindow
0N/ARootOf(WindowPtr pWin)
0N/A{
0N/A if (pWin)
0N/A {
0N/A while (pWin->parent)
0N/A pWin = pWin->parent;
0N/A return (pWin->drawable.id);
0N/A }
0N/A return (NULL);
0N/A}
0N/A
0N/A
0N/A/*
0N/A * same_client returns true if xid is owned/created by
0N/A * client
0N/A */
0N/Aint
0N/Asame_client (ClientPtr client, XID xid)
0N/A{
0N/A TsolInfoPtr tsolinfo_client;
0N/A TsolInfoPtr tsolinfo_xid;
0N/A ClientPtr xid_client;
0N/A
0N/A if (CLIENT_ID(xid) == 0 || (clients[CLIENT_ID(xid)] == NULL))
0N/A return FALSE;
0N/A
0N/A if((SERVER_BIT & xid) == 0)
0N/A {
0N/A if (client->index == CLIENT_ID(xid))
0N/A return TRUE;
0N/A xid_client = clients[CLIENT_ID(xid)];
0N/A tsolinfo_client = GetClientTsolInfo(client);
0N/A tsolinfo_xid = GetClientTsolInfo(xid_client);
0N/A if (tsolinfo_client && tsolinfo_xid && tsolinfo_client->pid > 0)
0N/A {
0N/A if (tsolinfo_client->pid == tsolinfo_xid->pid)
0N/A return TRUE;
0N/A }
0N/A }
0N/A return FALSE;
0N/A}
0N/AWindowPtr
0N/AAnyWindowOverlapsJustMe(pWin, pHead, box)
0N/A WindowPtr pWin, pHead;
0N/A register BoxPtr box;
0N/A{
0N/A register WindowPtr pSib;
0N/A BoxRec sboxrec;
0N/A register BoxPtr sbox;
0N/A TsolResPtr win_res =
0N/A (TsolResPtr)(pWin->devPrivates[tsolWindowPrivateIndex].ptr);
0N/A
0N/A for (pSib = pWin->prevSib; (pSib != NULL && pSib != pHead); pSib = pSib->prevSib)
0N/A {
0N/A TsolResPtr sib_res =
0N/A (TsolResPtr)(pSib->devPrivates[tsolWindowPrivateIndex].ptr);
0N/A if (pSib->mapped && !bldominates(win_res->sl, sib_res->sl))
0N/A {
0N/A sbox = WindowExtents(pSib, &sboxrec);
0N/A if (BOXES_OVERLAP(sbox, box)
0N/A#ifdef SHAPE
0N/A && ShapeOverlap (pWin, box, pSib, sbox)
0N/A#endif
0N/A )
0N/A return(pSib);
0N/A }
0N/A }
0N/A return((WindowPtr)NULL);
0N/A}
0N/A/*
0N/A * Return Top level client window of pWin
0N/A */
0N/AWindowPtr
0N/ATopClientWin(WindowPtr pWin)
0N/A{
0N/A ClientPtr client;
0N/A
0N/A if (pWin)
0N/A {
0N/A client = wClient(pWin);
0N/A while (pWin->parent)
0N/A {
0N/A if (client != wClient(pWin->parent))
0N/A break;
0N/A pWin = pWin->parent;
0N/A }
0N/A }
0N/A return (pWin);
0N/A}
0N/A/*
0N/A * returns the window under pointer. This is function because
0N/A * sprite is static & TsolPointerWindow is called in policy functions.
0N/A */
0N/AWindowPtr
0N/ATsolPointerWindow()
0N/A{
0N/A return (GetSpriteWindow()); /* Window currently under mouse */
0N/A}
36N/A
36N/A/*
36N/A * Matches in the list of disabled extensions via
36N/A * the policy file (TrustedExtensionsPolicy)
36N/A * Returns
36N/A * TRUE - if a match is found
36N/A * FALSE - otherwise
36N/A */
36N/Aint
36N/ATsolDisabledExtension(char *extname, int extlen)
36N/A{
36N/A int i;
36N/A
36N/A for (i = 0; i < tsolconfig[TSOL_EXTENSION].count; i++) {
36N/A if (strncmp(extname, tsolconfig[TSOL_EXTENSION].list[i], extlen) == 0) {
36N/A return TRUE;
36N/A }
36N/A }
36N/A
36N/A return FALSE;
36N/A}