Better way to discard output from function tested by glib test - c

If i test functions with glib's testharness, I always face the ugly fact, that the output of the functions I'm testign is mixed with the output of glib's functions.
This code:
#include <stdlib.h>
#include <glib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void to_test(void)
{
printf("this function is being tested");
}
void test_to_test(void)
{
to_test();
}
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/test", test_to_test);
return g_test_run();
}
generates:
/test: this function is being testedOK
The only solution I found was redirecting the filedescriptors of standardout/-err to /dev/null for the time the function is called and resetting them afterwards, like:
void test_to_test(void)
{
int backup, new;
new = open("/dev/null", O_WRONLY);
backup = dup(STDOUT_FILENO);
dup2(new, STDOUT_FILENO);
to_test();
fflush(stdout);
close(new);
dup2(backup, STDOUT_FILENO);
}
The output looks as intended:
/test: OK
Unfortunately this approach is 1.) ugly and 2.) POSIX specific. So my question is: Is there any other way to do this, so that the code is portable and at the same time aestetically appealing?
Thanks in advance!
Yours in neverending, beautiful, transcendetal love
floxo

This is possible using freopen and/or fdopen. There isn't a cross platform way of doing this unfortunately, luckily Windows has an fdopen equivalent which you can use (Is there a Windows equivalent to fdopen for HANDLEs?).
Note that this will only work if using stdio. It won't work if for some reason something is writing directly to the fd
As a longer term recommendation, why not use fprintf instead? and maintain a FILE* field in your structure which can be directed to custom output or wherever.

Related

How can i clearscreen in a while loop, in C programming? [duplicate]

I want to know: how to clean screen on an UNIX-based system? I searched on the Internet, but I've just found how to do it on Windows: system("CLS")
I don't want exactly to clean cpmpletely the screen, but I want to open a "new page", such as in the NANO and VI editors. Thanks
Maybe you can make use of escape codes
#include <stdio.h>
#define clear() printf("\033[H\033[J")
int main(void)
{
clear();
return 0;
}
But keep in mind that this method is not compatible with all terminals
You can use the following code which use termcap for clear screen.
(don't forget to link with the library)
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
void clear_screen()
{
char buf[1024];
char *str;
tgetent(buf, getenv("TERM"));
str = tgetstr("cl", NULL);
fputs(str, stdout);
}
#include <stdlib.h>
int main(void)
{
system("clear");
}
Portable UNIX code should be using the terminfo database for all cursor and screen manipulation. This is what libraries like curses uses to achieve its effects like windowing and so forth.
The terminfo database maintains a list of capabailities (like clear which is what you would use to clear the screen and send the cursor to the top). It maintains such capabilities for a wide range of devices so that you don't have to worry about whether you're using a Linux console or a (very dated) VT52 terminal.
As to how you get the character streams for certain operations, you can choose the time-honored but rather horrible method of just using system to do it:
system ("tput clear");
Or you can capture the output of that command to a buffer so later use involve only outputting the characters rather than re-running the command:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static char scrTxtCls[20]; static size_t scrSzCls;
// Do this once.
FILE *fp = popen ("tput clear", "r");
scrSzCls = fread (scrTxtCls, 1, sizeof(scrTxtCls), fp);
pclose (fp);
if (scrSzCls == sizeof(scrTxtCls)) {
actIntelligently ("you may want to increase buffer size");
}
// Do this whenever you want to clear the screen.
write (1, cls, clssz);
Or, you can link with ncurses and use its API to get whatever capabilities you want, though this might drag in quite a bit of stuff for something as simple as clearing the screen. Still, it's an option to be considered seriously since it gives you a lot more flexibility.
It is usually not a matter of just clearing the screen, but of making a terminal aware application.
You should use the ncurses library and read the NCURSES programming HowTo
(You could perhaps use some ANSI escape codes as David RF answered, but I don't think it is a good idea)
You can achieve this using CSI sequences:
#include <stdio.h>
int main()
{
printf("\x1b[H\x1b[J");
}
What does \x1b[H?
Actually it is the same as \x1b[1;1;H, it means that it will move the cursor to row 1 and column 1.
What does \x1b[J a.k.a \x1b[0;J?
If n is 0 or missing, it will clear from cursor to end of screen.
Source: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
Just use #include<stdlib.h> after #include<stdio.h>.
Then you can use the command system("clear");after main() {
i.e:
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("clear");
After these commands you can continue with your program.
Hope this helps :)
To clear the screen using termcaps, use this :
write(1, tgetstr("cl", 0), strlen(tgetstr("cl", 0)));
Use system("clear"); with header #include <stdlib.h> (for C Language) or #include <cstdlib> (for C++).
This code is for clear screen with reset scrollbar position in terminal style windows
#include <iostream>
int main(){
std::cout << "\033c";
return 0;
}

C stdout alternative

I'm using a library for my project. This library sometimes prints some messages to stdout. This is a problem for me because the messages are mixed up along with the application messages. It will be useful to a stop this behaviour or have them printed to a different window. I'm using C Language and Mingw32 enviroment. How can I do this? Thanks.
You might be able to (nonportably) swap the stdout with another stream:
#include <stdio.h>
FILE *devnull;
#define SWAPSTDOUT() do{ FILE *tmp = stdout; stdout = devnull; devnull = tmp; }while(0)
int main(void)
{
/*program initialization*/
if(0==(devnull= fopen("/dev/null", "r"))) return 1;
fputs("your code 0\n",stdout);
SWAPSTDOUT();
fputs("library code 0\n",stdout); //should be silent
SWAPSTDOUT();
fputs("your code 1\n", stdout);
}
Unfortunately, that's unlikely to work with functions that hardcode stdout (e.g., printf or puts).
If you're on a POSIX platform, you might have freopen but that won't help much if you can't save the original stream. However, on POSIX you could fflush(stdout) and then shuffle the underlying file descriptors, which should be quite reliable:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int devnull, tmp;
int swapstdout(void);
int main(void)
{
/*program initialization*/
if(0>(devnull=open("/dev/null", O_RDONLY))) return EXIT_FAILURE;
if(0>(tmp=dup(devnull))) return EXIT_FAILURE; //reserve a fd spot
fputs("your code 0\n",stdout);
if(0>swapstdout()) return EXIT_FAILURE:
fputs("library code 0\n",stdout); //should be silent
if(0>swapstdout()) return EXIT_FAILURE:
fputs("your code 1\n", stdout);
}
int swapstdout(void)
{
if(0>fflush(stdout)) return -1;
if(0>dup2(STDOUT_FILENO,tmp)) return -1; /*really shouldn't happen*/
if(0>dup2(devnull,STDOUT_FILENO)) return -1; /*really shouldn't happen*/
if(0>tmp=dup(devnull)) return -1; /*really shouldn't happen unless we're multithreaded and another thread steals the fd spot*/
}
Either solution depends on your code being single threaded.
In any case, well behaved library functions should leave files they don't own alone, unless you explicitly request them to do something with such files.

Why does using `execl` instead of `system` stops my program from working?

I'm trying to do basic IPC using pipes. I spent hours searching the internet, doing this and that, reading the API documentations, and ended up with the code below. But it does not work, as I quite expected. Just any help making my code 'work' would be many thanks.
<edit>
I've just found that using system instead of execl makes my program run perfectly as expected. So what is going wrong here when I use execl, while it doesn't happen with the system function?
</edit>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void){
int hInPipe[2];
int hOutPipe[2];
FILE *hInFile;
FILE *hOutFile;
char *s;
pipe(hInPipe);
pipe(hOutPipe);
if(fork()){
close(hInPipe[0]);
close(hOutPipe[1]);
hInFile=fdopen(hInPipe[1],"w");
fprintf(hInFile,"2^100\n");
fclose(hInFile);
hOutFile=fdopen(hOutPipe[0],"r");
fscanf(hOutFile,"%ms",&s);
fclose(hOutFile);
printf("%s\n",s);
free(s);
}else{
dup2(hInPipe[0],STDIN_FILENO);
dup2(hOutPipe[1],STDOUT_FILENO);
close(hInPipe[0]);
close(hInPipe[1]);
close(hOutPipe[0]);
close(hOutPipe[1]);
system("bc -q");/*this works*/
/*execl("bc","-q",NULL);*/ /*but this doesn't*/
}
}
Read the fine man page. :)
execl(const char *path, const char *arg0, ... /*, (char *)0 */);
arg0 (aka argv[0], the name the program is told it was invoked under) is not the same argument as the path (the location of the executable for said program). Moreover, execl takes, as its first argument, a fully-qualified pathname.
Thus, you want:
execl("/usr/bin/bc", "bc", "-q", NULL);
...or, to search the PATH for bc rather than hardcoding a location:
execlp("bc", "bc", "-q", NULL);

Interacting with a Shell using C

I have a binary called TEST which spawns a bash shell, I was hoping to write a C program that runs TEST and then passes commands to the bash shell that it spawns - I have tried the following - can someone indicate if this is possible. I can run the file using, but don't know how to then pass commands to shell it spawns:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
system("/var/testfolder/TEST"); #run the test file
return 0;
}
The UNIX styled popen() function is what you want to use.
See the man page for specifics.
It runs your command in a subprocess and gives you a pipe to interact with it. It returns a FILE handle like fopen() does, but you close it with pclose() rather than fclose(). Otherwise you can interact with the pipe the same way as for a file stream. Very easy to use and useful.
Here's a link to a use case example
Also check out this example illustrating a way to do what you are trying to do:
#include <stdio.h>
int main(void) {
FILE *in;
extern FILE *popen();
char buf[512];
if (!(in = popen("ls -sail", "r")))
exit(1);
while (fgets(buf, sizeof(buf), in) != NULL)
printf("%s", buf);
pclose(in);
}

Can I get executed commands not using history or ~/.bash_history?

My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
int ret;
char *argv[] = {"history",NULL};
ret = execvp("history",argv);
if(ret == -1)
perror("execl error");
printf("exiting main process ----\n");
return 0;
}
Output:
entering main process---
execl error: No such file or directory
exiting main process ----
Question:
Can I get executed commands not using history or ~/.bash_history?
It seems that something is wrong using function like execvp .
I've tried system function.
Code:
#include <stdio.h>
int main()
{
system("history");
return 0 ;
}
Nothing output.
If you try a man history you will get into the BASH_BUILTINS(1) General Commands Manual page. This means history is part of the bash shell internals. In order to have something executed via execvp() you need to have an actual executable somewhere in your PATH.
It's unclear why reading ~/.bash_history is not enough. Is it perhaps because you want the history of the currently running shell?
The short answer is no, you can't get it.
The long answer is you could attach with ptrace or through /proc/pid/mem, find the history in memory, and print it.
Probably not worth the effort.
You can pipe the output of the history builtin if you wish, by running your program with
history | ./myprog

Resources