Check if running in X Window - c

Linux C program:
What function call can check if running in X Window?
If not in X Window, then printf.

Do you mean something like this:
#include <X11/Xlib.h>
// ...
char *display_name = NULL;
/* connect to X server */
if ( (display=XOpenDisplay(display_name)) == NULL )
{
//printf or whatever
}

What do you mean "running in X Window"? Do you mean whether your app is running inside a terminal emulator, like rxvt or xterm instead of a physical console? If so you could use the TERM variable I guess, but it's not reliable (since the user can change it to whatever).
The more important quesion is why is this information important to your application?

Related

Let a daemon simulate keypress with xdo

I'm trying to make a daemon simulate a keypress. I got it already working for a non daemon process.
#include <xdo.h>
int main()
{
xdo_t * x = xdo_new(NULL);
xdo_enter_text_window(x, CURRENTWINDOW, "Hallo xdo!", 500000);
return 0;
}
If I try the same code for my daemon I get the following error
Error: Can't open display: (null)
Is there a way to still make it work with xdo or something else?
Your process must know the $DESKTOP environment variable specifying the desktop session to send these keys to, and yours doesn't seem to have that environment set.
Which also means you must realize it needs to have all the necessary privileges, which means access to ~/.Xauthority of the owner of the session, and the sockets in /tmp/.X11-unix

How to detect the status of the capslock in linux programmatically

I want some way to know if the Capslock is active or not, thought I can use xet for this purpose, using pipe, by popen('xset -q | grep Capslock') I am able to find out, but I want some way by which there is no use of the commands, in the C program, is there any way to know this.
One more thing I want to ask in this context, xset doens't work in the console mode in linux, I do alt+ctrl+f1 then login there and if try to run xset -q this will throw error, perhaps this can't communicate with the XWindows in console, so what solution can be for this case.
I want some way to know if the Capslock is active or not
You probably want XkbGetIndicatorState. For instance:
#include <stdio.h>
#include <stdlib.h>
#include <X11/XKBlib.h>
/* Compile this with -lX11 */
int main ()
{
Display *display;
Status status;
unsigned state;
display = XOpenDisplay (getenv ("DISPLAY"));
if (!display)
return 1;
if (XkbGetIndicatorState (display, XkbUseCoreKbd, &state) != Success)
return 2;
printf ("Caps Lock is %s\n", (state & 1) ? "on" : "off");
return 0;
}
Alternatively, you can go with the same approach that is used in xset and use XkbGetNamedIndicator which is a more general function.
Download the source to xset and see how it does things. It's not black magic. It will give you the functions to call to get/set the things you want. For xset to work, it must be invoked under the Window manager, so it can't be done from a VT console.
For the VT, from man 2 ioctl_console, you can use the KDGKBLED and KDSKBLED ioctls to get/set the flags.

Function XOpenDisplay with and without parameter

I have little issue with XOpenDisplay function. In school I can run program and it works good when using XOpenDisplay("ip:0"), but on my local machine in home when I run program (changed ip on current) got "Segmentation fault (core dumped)", but with empy string XOpenDisplay("") it works fine. I need to be able to use ip. Used host +, but nothing changes.
My system is Kubuntu 14.04.1: 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015
Here is code of program:
#include <X11/Xlib.h>
#include <X11/X.h>
#include <stdio.h>
Display *mydisplay;
Window mywindow;
XSetWindowAttributes mywindowattributes;
XGCValues mygcvalues;
GC mygc;
Visual *myvisual;
int mydepth;
int myscreen;
Colormap mycolormap;
XColor mycolor,mycolor1,dummy;
int i;
main()
{
mydisplay = XOpenDisplay("192.168.0.12:0");
myscreen = DefaultScreen(mydisplay);
myvisual = DefaultVisual(mydisplay,myscreen);
mydepth = DefaultDepth(mydisplay,myscreen);
mywindowattributes.background_pixel = XWhitePixel(mydisplay,myscreen);
mywindowattributes.override_redirect = True;
mywindow = XCreateWindow(mydisplay,XRootWindow(mydisplay,myscreen),
0,0,500,500,10,mydepth,InputOutput,
myvisual,CWBackPixel|CWOverrideRedirect,
&mywindowattributes);
mycolormap = DefaultColormap(mydisplay,myscreen);
XAllocNamedColor(mydisplay,mycolormap,"cyan",&mycolor,&dummy);
XAllocNamedColor(mydisplay,mycolormap,"red",&mycolor1,&dummy);
XMapWindow(mydisplay,mywindow);
mygc = DefaultGC(mydisplay,myscreen);
XSetForeground(mydisplay,mygc,mycolor.pixel);
XFillRectangle(mydisplay,mywindow,mygc,100,100,300,300);
XSetForeground(mydisplay,mygc,mycolor1.pixel);
XSetFunction(mydisplay,mygc,GXcopy);
XSetLineAttributes(mydisplay,mygc,10,LineSolid,CapProjecting,JoinMiter);
XDrawLine(mydisplay,mywindow,mygc,100,100,400,400);
XDrawLine(mydisplay,mywindow,mygc,100,400,400,100);
XFlush(mydisplay);
sleep(10);
XCloseDisplay(mydisplay);
exit(0);
}
I can only guess that need to set something, but have no idea where is that option.
You shall always check whether functions returned successfully, or not. It is not a Haskell, where all the checking done for you by monad, it is C. As for your particular case, the problem is that the function XOpenDisplay fails and returns null for you. In the next line you're trying to use DefaultScreen with the result. The DefaultScreen is defined as
#define DefaultScreen(dpy) ((dpy)->default_screen)
I.e. it just a macro, which using the first argument as a pointer. In your case it does ((0)->default_screen), i.e. it dereferencing the null pointer, and that leads to the segfault you see.
Also, about the XOpenDisplay("192.168.0.12:0"); — you didn't mentioned that you're trying to connect to another PC, so, if it's the same computer where the app running, try to call the function as XOpenDisplay("127.0.0.1:0");
UPD: okay, I tried to run the code at my PC, and the function doesn't work for me too. To find the reason I started the code under strace app, and saw
…
connect(3, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)
…
Aha! So, the app trying to connect to XServer, but Xserver refuses the connection. Actually, it have a security reason to disable it by default — so, that nobody would connect to your XServer from a network unless you specifically allowed it. For the function to work you need to launch your XServer with the option that allows such a connection. Right now DisplayManagers are the ones, who manages xsessions, so you need to set some option depending on your DM.
The solution for lightdm
Open the /etc/lightdm/lightdm.conf, and paste the line xserver-allow-tcp=true in the section [SeatDefaults](you will see it).
The solution for gdm
Edit the file /etc/gdm/gdm.schemas, you will find there something like
<schema>
<key>security/DisallowTCP</key>
<signature>b</signature>
<default>true</default>
</schema>
Change the true to false.

How can I have skinnier pthreads?

I have a really basic ncurses program to monitor machine statistics and launch remote xterms. It just sits on a window all day and helps me choose a not-heavily-loaded machine to work on. It works fine, and I love it dearly. But it's really fat. Much fatter than it needs to be, I think.
The program basically is as follows:
void * run(void * task) {
// once per minute:
popen( /* stats checking command */ )
// save output to global var
pclose
}
int main() {
// setup ncurses with halfdelay
for ( /* each machine */ )
pthread_create(somethread, NULL, run, (void *)somestruct);
while ( ( c = getch() ) != 'q' )
for ( /* each machine */ )
// print machine stats
// maybe launch an xterm
// die gracefully
}
And as stated above, it works just fine. The problem is that each thread has all the ncurses baloney tucked in private memory leading to one very fat process with a boatload of wasted bits.
The question, then, is this: how can I re-write or re-arrange this program so that each pthread doesn't carry around all the unnecessary ncurses stuff?
Side-question: You'll have to really sell me on it, but does anyone know of a better method than ncurses to do this? I want the stats on fixed positions in the terminal window, not scrolling text.

Execute command just before Mac going to sleep

I wrote a C program/LaunchDaemon that checks if my MacBook is at home (connected to my WLAN). If so, it disables my password protection; if not, it enables it.
Easy. But the problem is that when I take my MacBook anywhere else and password protection is disabled, it will wake up without a password protection.
My fix for this would be: enable the password protection every time just before it goes to sleep.
QUESTION: is there any way find out when my Mac is preparing for sleep? Some interupt I can let my program listen to?
You can do it using I/O Kit, check Apple's QA1340: Registering and
unregistering for sleep and wake notifications. You may also want to
analyze the SleepWatcher utility sources or use/integrate for your needs.
From the homepage:
SleepWatcher 2.2 (running with Mac OS X 10.5 to 10.8, source code included)
is a command line tool (daemon) for Mac OS X that monitors sleep, wakeup and
idleness of a Mac. It can be used to execute a Unix command when the Mac or
the display of the Mac goes to sleep mode or wakes up, after a given time
without user interaction or when the user resumes activity after a break or
when the power supply of a Mac notebook is attached or detached. It also can
send the Mac to sleep mode or retrieve the time since last user activity. A
little bit knowledge of the Unix command line is required to benefit from
this software.
I attach below the contents of my C file beforesleep.c which executes some command line commands (in my case shell commands and AppleScript scripts) when a "will sleep" notification is received.
Where you can put your code:
In order to run your code when the mac is going to sleep, just replace the system(...) calls with the code you wish to run.
In my case, I use system() as it allows me to run shell commands passed as strings, but if you prefer to run just C code instead, you can just put your C code there.
How to build it
In order to build this file, I run:
gcc -framework IOKit -framework Cocoa beforesleep.c
Remark
If you are going to use this code, make sure it is always running in background. For example, I have a Cron job which makes sure that this code is always running, and it launches it again in case it is accidentally killed for any reason (although it never happened to me so far). If you are experienced enough, you can find smarter ways to ensure this.
Further info
See this link (already suggested by sidyll) for more details about how this works.
Code template
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
io_connect_t root_port; // a reference to the Root Power Domain IOService
void
MySleepCallBack( void * refCon, io_service_t service, natural_t messageType, void * messageArgument )
{
switch ( messageType )
{
case kIOMessageCanSystemSleep:
IOAllowPowerChange( root_port, (long)messageArgument );
break;
case kIOMessageSystemWillSleep:
system("/Users/andrea/bin/mylogger.sh");
system("osascript /Users/andrea/bin/pause_clockwork.scpt");
IOAllowPowerChange( root_port, (long)messageArgument );
break;
case kIOMessageSystemWillPowerOn:
//System has started the wake up process...
break;
case kIOMessageSystemHasPoweredOn:
//System has finished waking up...
break;
default:
break;
}
}
int main( int argc, char **argv )
{
// notification port allocated by IORegisterForSystemPower
IONotificationPortRef notifyPortRef;
// notifier object, used to deregister later
io_object_t notifierObject;
// this parameter is passed to the callback
void* refCon;
// register to receive system sleep notifications
root_port = IORegisterForSystemPower( refCon, &notifyPortRef, MySleepCallBack, &notifierObject );
if ( root_port == 0 )
{
printf("IORegisterForSystemPower failed\n");
return 1;
}
// add the notification port to the application runloop
CFRunLoopAddSource( CFRunLoopGetCurrent(),
IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );
/* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
manage the main thread's run loop for you as part of their event handling
mechanisms.
*/
CFRunLoopRun();
//Not reached, CFRunLoopRun doesn't return in this case.
return (0);
}

Resources