Obtaining List of all Xorg Displays - c

I would like to know how I can obtain a list of all Xorg displays on my system, along with a list of screens associated with each display. I spent some time looking through the Xlib documentation, but was not able to find a function that does what I want. Please assume that I have no other dependencies other than a POSIX-complaint OS and X (e.g., no GTK). If what I ask is not possible assuming these minimal dependencies, then a solution using other libraries is fine.
Thank you very much for your help!

The only way I know of to get a list of displays is to check the /tmp/.X11-unix directory.
Once you do that, you can use Xlib to query each display for more information.
Per example:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <X11/Xlib.h>
int main(void) {
DIR* d = opendir("/tmp/.X11-unix");
if (d != NULL) {
struct dirent *dr;
while ((dr = readdir(d)) != NULL) {
if (dr->d_name[0] != 'X')
continue;
char display_name[64] = ":";
strcat(display_name, dr->d_name + 1);
Display *disp = XOpenDisplay(display_name);
if (disp != NULL) {
int count = XScreenCount(disp);
printf("Display %s has %d screens\n",
display_name, count);
int i;
for (i=0; i<count; i++)
printf(" %d: %dx%d\n",
i, XDisplayWidth(disp, i), XDisplayHeight(disp, i));
XCloseDisplay(disp);
}
}
closedir(d);
}
return 0;
}
Running the above gives me this output with my current displays/screens:
Display :0 has 1 screens
0: 3046x1050
Display :1 has 2 screens
0: 1366x768
1: 1680x1050
Never found a better way of listing X displays other than that. I'd very much like to know if any better alternative exists.

Like netcoder wrote, the problem has two distinct parts:
Connection to the X server
The process establishes a connection to an X server using XOpenDisplay(). The connection is torn down using XCloseDisplay(). netcoders code in this thread is a good example of how to do it correctly.
As netcoder mentioned, the problem is that there is no reliable way find out which X servers a process can connect to. His code checks the typical location where the X sockets are, /tmp/.X11-unix/. That approach does not work at all if the user is remotely connected, for example via SSH (with X forwarding enabled). In that case there is really only the DISPLAY environment variable (and perhaps some trickery wrt. ~/.Xauthority files).
Unfortunately, I do not know of any better method either. I personally prefer to use a per-user configuration file -- say ~/.application/displays --, where the user can list the server names the application should try to connect in the same format as the DISPLAY environment variable, in addition to the default one. It is not automatic (netcoder's code is), but this approach suits me better.
Finding out about the screens provided by an X server
XScreenCount() will return the number of screens provided by the X server the process is currently connected to. If you only need the screen dimensions, follow netcoders example. For more detailed information, use XScreenOfDisplay(Display,index) to obtain the Screen pointers; 0 <= index < XScreenCount(Display).
In C code, the macros ScreenCount() and ScreenOfDisplay() are usually a bit more efficient than the actual function calls.

Related

Iterating over an X509 certificate's subject elements and knowing the type

I'd like to iterate over the name entries in a connecting client's certificate and perform some logic.
I found the following example on this page:
X509_NAME *subj = X509_get_subject_name(cert);
for (int i = 0; i < X509_NAME_entry_count(subj); i++) {
X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, i);
ASN1_STRING *d = X509_NAME_ENTRY_get_data(e);
char *str = ASN1_STRING_data(d);
}
As part of my logic I'd like to know which kind of X509_NAME_ENTRY I'm looking at (ideally by it's NID, for instance NID_commonName), but I can't figure out how to extract this information. From looking at OpenSSL's code I see that I can get the ASN1_OBJECT using X509_NAME_ENTRY_get_object, and that has a nid field in it, but it doesn't seem to be exposed so I can't just grab it with ->nid.
Is there any API function I'm missing to get this information?
Another example on this page is this one:
for (;;) {
int lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, lastpos);
if (lastpos == -1)
break;
X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, lastpos);
/* Do something with e */
}
I'm considering using this approach instead, but I'm wondering if it's less efficient since I have several name entries I'd like to check, and instead of having one run through the subject I'll potentially be moving back and forth (and my server application needs to minimize connection time as much as possible).
To clarify, I don't just need the certificate's common name, I might need other parts of the certificate's subject (based on the server's configuration) so I'd like to be flexible but also go over the subject as cleanly as possible.

Monitor flashing when running a Windows SendInput API

Well, I certainly should go to python since I did several functions of this type, keyboard event and mouse event, but decide to try to learn the windows api.
My goal is to know when button 1 of the mouse is pressed.
I created this file in a very beginner way, it returns in mouseData only 0.
The curious thing is that whenever I run it, it flashes my monitor at short intervals in blinks, but between 1 second with it off. Very strange that, execution is not viable.
Could someone help me understand and try to execute to see if it is only here.
Code:
int main()
{
DWORD mouseData = 0;
MOUSEINPUT tagMouse;
tagMouse.dx = 0;
tagMouse.dy = 0;
tagMouse.mouseData = mouseData;
tagMouse.dwFlags = MOUSEEVENTF_XDOWN;
tagMouse.dwExtraInfo = 0;
INPUT tagInput;
tagInput.type = INPUT_MOUSE;
tagInput.mi = tagMouse;
while (true) {
if (GetAsyncKeyState(VK_DELETE)) break;
SendInput(1, &tagInput, sizeof(INPUT));
printf("KEYWORD: %d\n", mouseData);
Sleep(500);
}
system("pause");
return 0;
}
I can reproduce your reported 'symptoms' - and the effect is really brutal!
Now, while I cannot offer a full explanation, I can offer a fix! You have an uninitialized field in your tagMouse structure (the time member, which is a time-stamp used by the system). Setting this to zero (which tells the system to generate its own time-stamp) fixes the problem. So, just add this line to your other initializer statements:
//...
tagMouse.dwExtraInfo = 0;
tagMouse.time = 0; // Adding this line fixes it!
//...
Note: I, too, would appreciate a fuller explanation; however, an uninitialized field, to me, smells like undefined behaviour! I have tried a variety of other values (i.e. not zero) for the time field but haven't yet found one that works.
The discussion here on devblogs may help. This quote seems relevant:
And who knows what sort of havoc that will create if a program checks
the timestamps and notices that they are either from the future or
have traveled back in time.

Enumerating supplementary groups in a C Program

I'm wanting to get a list of supplementary groups for the user by sending a request through NSS. To my reckoning, the following program should let me enumerate all the groups (so I can then compare members):
#include <stdio.h>
#include <grp.h>
#include <stdlib.h>
struct group *groupStruct;
int main(){
setgrent();
while ( groupStruct=getgrent() )
printf("%s\n", groupStruct->gr_name);
endgrent();
return 0;
}
I'm basing this assumption on this part of the source code for id that gets executed with id -Gn (since that's the functionality I want to replicate). Looking at that it looks like it gets the list of groups via getugroups (0, NULL, username, gid) with getugroups() being defined in another file (essentially the same code found here). It looks like that is going through the same setgrent()/getgrent() procedure as above, so my feeling is that my simple program ought to enumerate the system's groups (instead, it only does the groups in /etc/group but I have winbind on this machine and id -Gn pulls in the winbind groups the user is a member of).
For posterity:
I still don't know why the id -Gn code works but not mine, but I think I fixed my own issue after a lot of back and forth. Basically I'm building a shared object and enumerating their current memberships by way of a helper program that uses initgroups/getgroups to set the running processes's (the helper executable) persona to the target user's default persona (what they would get after logging in. This is the full code of the helper program:
#include <stdio.h>
#include <unistd.h>
struct group *groupStruct;
int main(int argc, char *argv[]){
int numgroups, iter, retCode;
int numgroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
gid_t groupList[numgroups_max];
if (argc != 2){
printf("Insufficient Arguments.\n");
return 1;
}
retCode=initgroups(argv[1], 0);
if (retCode != 0){
printf("Unspecified failure: %d\n\n", retCode);
return 1;
}
numgroups = getgroups(numgroups_max, groupList);
for (iter=0; iter <= numgroups; iter++){
if (iter != 0 && iter != numgroups )
printf(" ");
// "zero" means both "nothing more" and could be the root user's primary group, allow the first one through
if ( groupList[iter] == 0 && getuid() == 0 ){
if ( iter != 0 )
break;
}else if ( groupList[iter] == 0 )
break;
printf("%d", groupList[iter]);
}
return 0;
}
Username is hard coded just for testing purposes. After compiling and testing it produces the group ID's for the user. Changing the hard coded value (or pushing it into argv) resolves the problem. I pushed this into a helper executable because it's changing the running process's persona (at least the group membership portion).
I'll probably move it into the library's calling routine for performance/security (I can save the supplementary and primary groups before with getgroups and setgroups), but it was quicker for me to do a proof of concept in a separate executable.

Is there a Linux equivalent of SetWindowPos?

A while ago I wrote a script in C that used the Windows API functions EnumWindows, SetWindowPos and SetForegroundWindow to automatically arrange windows (by title) in a particular layout that I commonly wanted.
Are there Linux equivalents for these functions? I will be using Kubuntu, so KDE-specific and/or Ubuntu-specific solutions are fine.
The best way to do this is either in the window manager itself (if yours supports extensions) or with the protocols and hints designed to support "pagers" (pager = any non-window-manager process that does window organization or navigation things).
The EWMH spec includes a _NET_MOVERESIZE_WINDOW designed for use by pagers. http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2731465
Raw Xlib or Xcb is pretty rough but there's a library called libwnck specifically designed to do the kind of thing you're talking about. (I wrote the original library long ago but it's been maintained by others forever.) Even if you don't use it, read the code to see how to do stuff. KDE may have an equivalent with KDE-style APIs I'm not sure.
There should be no need to use anything KDE or GNOME or distribution specific since the needed stuff is all spelled out in EWMH. That said, for certain window managers doing this as an extension may be easier than writing a separate app.
Using old school X calls directly can certainly be made to work but there are lots of details to handle there that require significant expertise if you want to iron out all the bugs and corner cases, in my opinion, so using a WM extension API or pager library would be my advice.
#andrewdotn has a fine answer there but you can do this old school as well fairly simply by walking the tree starting at the root window of the display using XQueryTree and fetching the window name with XFetchName then moving it with XMoveWindow. Here is an example that will list all the windows and if any are called 'xeyes' they get moved to the top left. Like most X programs, there is more to it and this should probably be calling XGetWindowProperty to fetch the _NET_WM_NAME extended window manager property but the example works ok as a starter. Compile with gcc -Wall -g -o demo demo.c -lX11
#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>
static int
EnumWindows(Display *display, Window window, int depth)
{
Window parent, *children;
unsigned int count = 0;
int r = 1, n = 0;
char *name = NULL;
XFetchName(display, window, &name);
for (n = 0; n < depth; ++n) putchar(' ');
printf("%08x %s\n", (int)window, name?name:"(null)");
if (name && strcmp("xeyes", name) == 0) {
XMoveWindow(display, window, 5, 5);
}
if (name) XFree(name);
if (XQueryTree(display, window, &window, &parent, &children, &count) == 0) {
fprintf(stderr, "error: XQueryTree error\n");
return 0;
}
for (n = 0; r && n < count; ++n) {
r = EnumWindows(display, children[n], depth+1);
}
XFree(children);
return r;
}
int
main(int argc, char *const argv[])
{
Display *display = NULL;
if ((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "error: cannot connect to X server\n");
return 1;
}
EnumWindows(display, DefaultRootWindow(display), 0);
XCloseDisplay(display);
return 0;
}
Yes, you can do this using the X Windows protocol. It’s a very low-level protocol so it will take some work. You can use xcb_query_tree to find the window to operate on, and then move it with xcb_configure_window. This page gives some details on how to do it. There’s a basic tutorial on using the library those functions come from, but you’ll probably want to Google for a better one.
It may seem daunting, but it’s not too bad. Here’s a 50-line C program that will move all your xterms 10px to the right:
#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>
void handle(xcb_connection_t* connection, xcb_window_t window) {
xcb_query_tree_reply_t *tree = xcb_query_tree_reply(connection,
xcb_query_tree(connection, window), NULL);
xcb_window_t *children = xcb_query_tree_children(tree);
for (int i = 0; i < xcb_query_tree_children_length(tree); i++) {
xcb_get_property_reply_t *class_reply = xcb_get_property_reply(
connection,
xcb_get_property(connection, 0, children[i], XCB_ATOM_WM_CLASS,
XCB_ATOM_STRING, 0, 512), NULL);
char* class = (char*)xcb_get_property_value(class_reply);
class[xcb_get_property_value_length(class_reply)] = '\0';
if (!strcmp(class, "xterm")) {
/* Get geometry relative to parent window */
xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(
connection,
xcb_get_geometry(connection, window),
NULL);
/* Move 10 pixels right */
uint32_t values[] = {geom->x + 10};
xcb_configure_window(connection, children[i],
XCB_CONFIG_WINDOW_X, values);
}
/* Recurse down window tree */
handle(connection, children[i]);
}
}
int main() {
xcb_connection_t *connection;
const xcb_setup_t *setup;
connection = xcb_connect(NULL, NULL);
setup = xcb_get_setup(connection);
xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup);
handle(connection, screen.data->root);
return 0;
}
There’s no error-checking or memory management, and what it can do is pretty limited. But it should be straightforward to update into a program that does what you want, or to turn it into a general-purpose helper program by adding command-line options to specify which windows to operate on and which operations to perform on them.
As it seems you are not looking specifically for a solution in code, but rather in a desktop environment, you need to take a look at one of the window managers that handle the window placement in such a desktop environment.
KDE's KWin's Window Attributes
Compiz (GNOME) has "Window Rules" and "Place Windows" in the CompizConfig Settings Manager application. See e.g. here
Openbox seems a lot harder to get right, although they link to a GUI tool at the bottom of this page.
The problem with using X directly is that X in itself knows nothing about your desktop environment (panels, shortcuts, etc.) and you'll have to compensate manually.
After googling for this, I'm surprised KDE is the only one that has a simple way to do this.

C programming. Why does 'this' code work but not 'that' code?

Hello I am studying for a test for an intro to C programming class and yesterday I was trying to write this program to print out the even prime numbers between 2 and whatever number the user enters and I spent about 2 hours trying to write it properly and eventually I did it. I have 2 pictures I uploaded below. One of which displays the correct code and the correct output. The other shows one of my first attempts at the problem which didn't work correctly, I went back and made it as similar to the working code as I could without directly copying and pasting everything.
unfortunately new users aren't allowed to post pictures hopefully these links below will work.
This fails, it doesn't print all numbers in range with natural square root:
for (i = 2; i <= x; i++)
{
//non relevant line
a = sqrt(i);
aa = a * a;
if (aa == i);
printf("%d ",i);
}
source: http://i.imgur.com/WGG6n.jpg
While this succeeds, and prints even numbers with natural sqaure root
for (i = 2; i <= x; i++)
{
a = sqrt(i);
aa = a * a;
if (aa == i && ((i/2) *2) == i)
printf("%d ", i);
}
source: http://i.imgur.com/Kpvpq.jpg
Hopefully you can see and read the screen shots I have here. I know that the 'incorrect code' picture does not have the (i/2)*2 == i part but I figured that it would still print just the odd and even numbers, it also has the code to calculate "sqrd" but that shouldn't affect the output. Please correct me if I'm wrong on that last part though.
And Yes I am using Dev-C++ which I've read is kinda crappy of a program but I initally did this on code::blocks and it did the same thing...
Please I would very much appreciate any advice or suggestions as to what I did wrong 2 hours prior to actually getting the darn code to work for me.
Thank you,
Adam
your code in 'that' includes:
if (aa == i);
// ^
printf(...);
[note the ; at the end of the if condition]
Thus, if aa == i - an empty statement happens, and the print always occures, because it is out of the scope of the if statement.
To avoid this issue in the future, you might want to use explicit scoping1 [using {, } after control flow statements] - at least during your first steps of programming the language.
1: spartan programmers will probably hate this statement
Such errors are common. I use "step Over", "Step Into", "Break Points" and "watch window" to debug my program. Using these options, you can execute your program line by line and keep track of the variables used in each line. This way, u'll know which line is not getting executed in the desired way.

Resources