How to stop my .exe from disappearing when using CMake - c

I am using cmake to build my project from the command line. The problem is, as soon as the executable finishes running it disappear immediately and I have mere milliseconds the contents that are printed on screen. I can't read much in milliseconds. Is there anything I can do so that the console screen doesnt disappear as soon as it has finished executing?
here is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(TotallyFree C)
add_executable(Acrolibre acrolibre.c)
set(LIBSRC acrodict.c acrodict.h)
add_library(acrodict ${LIBSRC})
add_executable(Acrodictlibre acrolibre.c)
target_link_libraries(Acrodictlibre acrodict)
set_target_properties(Acrodictlibre PROPERTIES COMPILE_FLAGS "-DUSE_ACRODICT")
and here is my equivalent of main.cpp:
//#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef USE_ACRODICT
#include "acrodict.h"
#endif
int main(int argc, char* argv[])
{
//int waitTime = 10000000;
const char* name;
#ifdef USE_ACRODICT
const acroItem_t* item;
#endif
if(argc < 2)
{
fprintf(stderr, "%s: you need one argument\n", argv[0]);
fprintf(stderr, "%s <name>\n", argv[0]);
exit(EXIT_FAILURE);
}
name = argv[1];
#ifndef USE_ACRODICT
//if(strcasecmp(name, "toulibre")==0){
if(_stricmp(name, "toulibre")==0){
printf("Toulibre is a French organization promoting FLOSS.\n");
}
#else
item = acrodict_get(name);
if(NULL != item){
printf("%s: %s\n", item->name, item->description);
}else if(item = acrodict_get(name)){
printf("<%s> is unknown maybe you mean:\n", name);
printf("%s: %s\n", item->name, item->description);
}
#endif
else{
printf("Sorry, I don't know: <%s>\n", name);
//Sleep(waitTime);
return EXIT_FAILURE;
}
//Sleep(waitTime);
return EXIT_SUCCESS;
}
As you can see I even used Sleep() and #include to delay this shutting down of the console. But it doesn't work. Is there anything anyone can recommend?

The problem is not in the make files here. Your program exits, and the console window disappears. Try using getch() before returning from main() for the program to wait for any key before exiting. Or, you can run your program from a console.

This has nothing to do with CMake, and everything to do with the way you're running your application.
When you double-click a console EXE in Windows, it opens a new console, runs the program, and closes the console, lie it should.
You have two options:
Run the program from the command-line of an already open console (cmd.exe)
Add this code to the end of main:
printf("Press Enter to exit\n");
getchar();

Related

Permission denied when running compiled C program in Linux

I am attempting to write a simple program that calls git checkout -- . on a Github repo that would be a command line argument. I would like to call it like > clearRepo repoName. I keep all my repos in the same Github directory.
The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
void print_error()
{
fprintf(stderr, "Error executing: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
void print_usage(char* this)
{
printf("SYNTAX ERROR:\n%s [directoryName]\n", this);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
if(argc != 2)
{
print_usage(argv[0]);
}
pid_t pid = fork();
if (pid == 0)
{
static char* params[] = {"git", "checkout", "--", ".", NULL};
char s[50], s2[50];
strcpy(s, "/home/myname/Documents/Github/");
strcpy(s2, argv[1]);
strcat(s, s2);
printf("s: %s\n", s);
int err = execv(s, params);
if(err == -1)
{
print_error();
}
exit(127);
}
else
{
waitpid(pid, 0, 0);
}
return 0;
}
It compiles fine, but print_error() will spit out Error executing: Permission denied every time I run it. I am not too familiar with writing programs for Linux, so it is probably a simple mistake. Information on what I'm doing wrong is appreciated. Thanks.
The first argument you're passing to execv is a directory, but execv expects a program. The error "Permission denied" is slightly misleading, because there is no such thing as "permission to execute directories".
To change the current directory, call chdir. Then, call whichever one of the exec* functions you like to invoke git.
chmod u+x filename for changing file permission.
If you want to checkout of a branch, but save the changes, use git stash. You can use git stash pop or git stash apply when you come back to the branch.
https://git-scm.com/docs/git-stash
Git commands and programs are quite tricky.
Follow these steps and you might debug your problem.
Enter the git commands written in the program into a terminal and check if the logic actually works. (Suggested this as you said you were new to Linux)
If it works, change the permission of your file by typing "chmod +x filename.extention".

Why does `ioctl(fd, EVIOCGRAB, 1)` cause key spam sometimes?

I'm trying to write my own "keyboard driver" (without actually writing a kernel module),
by grabbing the keyboard at what I assume is the lowest level of abstraction in userland: /dev/input/event*.
The following code does the grabbing, provided you change the first ocurrence of ioctl(fd, EVIOCGRAB, UNGRAB)
to ioctl(fd, EVIOCGRAB, GRAB).
// gcc main.c -o main
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <errno.h>
#define EXIT_KEY KEY_ESC
#define UNGRAB 0
#define GRAB 1
const char* kbd_device = "/dev/input/event4";
// ------------------------------------------------------------------------------------------------
int main(void){
int fd = open(kbd_device, O_RDONLY);
if(fd == -1){
printf("Cannot open %s. %s.\n", kbd_device, strerror(errno));
return -1;
}
if(ioctl(fd, EVIOCGRAB, UNGRAB))
printf("Couldn't grab %s. %s.\n", kbd_device, strerror(errno));
else
printf("Grabbed %s!\n", kbd_device);
while(1){
struct input_event event;
read(fd, &event, sizeof(event));
if (event.type == EV_KEY && event.value >= 0 && event.value <= 2){
printf("%d %3d\n", event.value, event.code);
if(event.code == EXIT_KEY){
ioctl(fd, EVIOCGRAB, UNGRAB);
close(fd);
return 0;
}
}
}
}
Problem
If I run gcc main.c -o main && sudo ./main, everything works as expected.
If first compile and then I run sudo ./main, however, the terminal scrolls down nonstop, as if the RETURN key was held down.
Why does happen?
Notes
I'm running Ubuntu 14.04
On my platform, /dev/input/event4 happens to be the keyboard
Motivation
I'm trying to write a keyboard "driver" that works both on X and not on X (eg. a TTY).
I understand X11's keyboard library/extension is XKB. I think the TTY's keyboard library is linux/divers/tty/vt/keyboard.c (source),
the initial keyboard map it uses is in linux/drivers/tty/vt/defkeymap.map (source), and it can be modified by using loadkeys (source here). Do correct me if I'm wrong.
When you type
gcc main.c -o main && sudo ./main ↵
GCC takes some time, so the ↵ key has been released by the time ./main runs.
When you type
sudo ./main ↵
the terminal sends the shell a newline as soon as you push down ↵, and starts executing ./main. Then the ↵ released event is seen by your program, but not by your terminal, because your program has grabbed the input device. Thus, to the terminal it looks like ↵ is stuck down, so it continues to produce newlines.
This question has been answered already, but it still lacks an elegant solution to the problem.
I had the same issue with a driver I implemented some time ago that also required capturing the keyboard.
I could not find a way to force the the kernel to recognize a key release in the device before capturing it, so the solution consists in not grabbing the device until you detect that all keys have actually been released. This can be accomplished by monitoring the device with the EVIOCGKEY ioctl AFTER opening it and BEFORE grabbing it.
OBS: Please observe that the apparently dummy read function within the while loop is necessary in order to avoid a busy wait and so that the loop will iterate after each event from the input device. Also note that the file descriptor must be configured for blocking I/O (the default).
void waitReleaseAll(int fd) {
struct input_event evt;
unsigned char key_b[KEY_MAX/8 + 1];
int i, nothing;
while ( 1 ) {
memset(key_b, 0, sizeof(key_b));
ioctl(fd, EVIOCGKEY(sizeof(key_b)), key_b);
for ( nothing = 1 , i = 0 ; i < KEY_MAX/8 + 1 ; i++ ) {
if ( key_b[i] != 0 ) { nothing = 0; break; }
}
if ( nothing ) break;
read(fd, &evt, sizeof(evt));
}
printf("All keys are now released\n");
}
To fix your problem, you should use SIGINT in your code to identify Ctrl-C keystroke from the user.
Implement SIGNAL in your code:
static volatile sig_atomic_t stop = 0;
static void interrupt_handler(int sig)
{
stop = 1;
} // Outside of the main function.
int main(int argc, char *argv[])
{
signal(SIGINT, interrupt_handler);
while (!stop) {
//your code
}
exit(0);
}

Is it normal to call uv_run several times?

I am new to uvlib. Is it normal to call uv_run twice if one wants to avoid blocking inside function? If not, then which instruments are available, except threads? Here I just open and close file.
#include <uv.h>
#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#ifdef _WIN32
#include <conio.h>
#include <Windows.h>
#define Sleep(x) Sleep(x)
#else
#include <unistd.h>
#define Sleep(x) sleep(x)
#endif
uv_loop_t* loop;
uv_fs_t open_req;
uv_fs_t close_req;
void open_cb(uv_fs_t*);
void close_cb(uv_fs_t*);
const char *filename = "C:/c/somedata.txt";
int main(int argc, char **argv) {
int r;
loop = uv_loop_new();
r = uv_fs_open(loop, &open_req, filename, O_RDONLY, S_IREAD, open_cb);
if (r < 0) {
printf("Error at opening file: %s\n", uv_strerror(r));
}
printf("in main now\n");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
return 0;
}
void open_cb(uv_fs_t* req) {
int result = req->result;
if (result < 0) {
printf("Error at opening file: %s\n", uv_strerror(result));
} else {
printf("Successfully opened file.\n");
}
uv_fs_req_cleanup(req);
uv_fs_close(loop, &close_req, result, close_cb);
uv_run(loop, UV_RUN_DEFAULT);
Sleep(5000);
printf("ok now\n");
}
void close_cb(uv_fs_t* req) {
int result = req->result;
printf("in close_cb now\n");
if (result < 0) {
printf("Error at closing file: %s\n", uv_strerror(result));
} else {
printf("Successfully closed file.\n");
}
}
Set aside your example, libuv offers the opportunity to run the loop more than once.
See the documentation for further details.
In particular, uv_run function accepts a parameter of type uv_run_mode.
Possible values are:
UV_RUN_DEFAULT: it doesn't stop unless you explicitly stop it and until there exists at least on referenced or active resource on the loop.
UV_RUN_ONCE: poll for I/O once and execute all the functions that are ready to be served. It has the drawback that it is blocking if there are no pending callbacks.
UV_RUN_NOWAIT: this is probably the one you are looking for, similar to the previous one, but it doesn't block if there are no pending callbacks.
Note that with both UV_RUN_ONCE and UV_RUN_NOWAIT you'll have to run the loop more than once.
Return value usually indicates if there are some other pending callbacks. In this case, the loop must be run sooner or later in the future.
The last mode, UV_RUN_NOWAIT, is probably the one you are looking for.
As an example, it can be used in scenarios where the client has its own loop and cannot block on the libuv's one.
Is it normal to run the loop more than once?
Well, yes, but it mostly depends on your actual problem if it's right.
It's hard to say from a 100 line snippet on SO.

How can I use chdir function in Linux?

I have a question, here is my original code in the testchdir.c file:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
if (argc < 2)
{
printf("Usage: %s <pathname\n",argv[0]);
exit(1);
}
if (chdir(argv[1]) == 0)
{
printf("success in chdir\n");
return 0;
}
else
{
printf("error happened");
exit(1);
}
}
In my Linux system, my original path is /home/Tom3543, then when I compile my codes above using gcc -o testchdir testchdir.c, it looks good. Later on, I want to change my path and execute the program, so I type
./testchdir /home/tom3543/C++
"success in chdir" appeared in my terminal, but my path is still /home/Tom3543 in my terminal. Can someone help me explain why? I am confused about that!
It's because the shell starts a new process for your program, and you only change the current directory in that new process. The shells process will be unaffected.
Unfortunately (for you) there's no real good (or legal) way to change the working directory of the parent process (the process of the shell).

How do I open a file in its default program - Linux

How do I programmatically open a file in its default program in Linux (im using Ubuntu 10.10).
For example, opening *.mp3 will open the file in Movie Player (or something else).
You need to run gnome-open, kde-open, or exo-open, depending on which desktop you are using.
I believe there is a project called xdg-utils that attempts to provide a unified interface to the local desktop.
So, something like:
snprintf(s, sizeof s, "%s %s", "xdg-open", the_file);
system(s);
Beware of code injection. It's safer to bypass scripting layers with user input, so consider something like:
pid = fork();
if (pid == 0) {
execl("/usr/bin/xdg-open", "xdg-open", the_file, (char *)0);
exit(1);
}
// parent will usually wait for child here
Ubuntu 10.10 is based on GNOME. So, it would be good idea to use
g_app_info_launch_default_for_uri().
Something like this should work.
#include <stdio.h>
#include <gio/gio.h>
int main(int argc, char *argv[])
{
gboolean ret;
GError *error = NULL;
g_type_init();
ret = g_app_info_launch_default_for_uri("file:///etc/passwd",
NULL,
&error);
if (ret)
g_message("worked");
else
g_message("nop: %s", error->message);
return 0;
}
BTW, xdg-open, a shell script, tries to determin your desktop environment and call a known helper like gvfs-open for GNOME, kde-open for KDE, or something else. gvfs-open ends up calling g_app_info_launch_default_for_uri().
A simple solution with less coding:
I've tested this program on my Ubuntu and it is working fine, and if I am not wrong you are looking for something like this
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("firefox file:///dox/song.mp3");
return 0;
}

Resources