Program terminating without printing - c

Why does my while loop not print the print statements I want before terminating? None of my print statements print in the terminal when my program exits. I can't see any other places where the loop might exit.
while (1) {
int num_read;
// add the fd value into the fd_set value
FD_SET(sock_fd, &read_fds);
FD_SET(STDIN_FILENO, &read_fds);
// choose which fds to watch
select(sock_fd + 1, &read_fds, '\0', '\0', '\0');
if (FD_ISSET(STDIN_FILENO, &read_fds)) { //check whether the fd value is in the fd_set
num_read = read(STDIN_FILENO, buf, BUF_SIZE);
if (num_read == 0) {
printf("Print statement before terminating");
break;
}
buf[num_read] = '\0'; // Just because I'm paranoid
int num_written = write(sock_fd, buf, num_read);
if (num_written != num_read) {
perror("client: write");
printf("Print statement before terminating");
close(sock_fd);
printf("Print statement before terminating");
exit(1);
}
}
if (FD_ISSET(sock_fd, &read_fds)) { //the socket with the server
num_read = read(sock_fd, buf, BUF_SIZE);
buf[num_read] = '\0';
printf("%s", buf);
}
}
printf("Print statement before terminating");
close(sock_fd);
printf("Print statement before terminating");
return 0;
}

Printf() is a library function which uses library buffer. By default library uses lined buffer mechanism to print data on terminal. To make printf() to print messages immediately use "\n" in each string passed to printf().
When process terminates buffer is flushed that is why you got your prints.
Please read this.
https://stackoverflow.com/a/36573578/5694959

You can use what Monc suggested. i.e. adding '\n' in end of your statement. Alternatively you can use fflush(stdout). which also clears printf buffer and prints on stdout.

Monc and Devidas have provided clues for possible explanations, but unless you are programming to an ancient system, exit() should flush the pending output in stdout and any other streams.
A more likely explanation is you execute your program in an environment where stdout is not tied to the terminal or whatever serves to display output on your system. Some Windows based IDEs and some online systems have inadequate output handling and make it difficult to debug such problems.
Posting a complete program is necessary to let readers investigate if the problem has its source elsewhere in your program.

Related

How can I clean up the popen output of my C program?

I am rewriting a simple reverse-shell program I made in python, now in C.
The program is supposed to be trying to connect to a host(netcat listening on the specified port) and then take the output from nc, sent over a tcp socket, and make a system call using popen() and then send back the terminal output via the socket connection to nc where it is displayed.
When I try sending commands the program returns what I requested, but also some giberish.
Ex.:
/Users/jacob/Library/Developer/Xcode/DerivedData/backdoorfbhufkccmceisqaozrfitkmfsvge/Build/Products/Debu#Ԓ`? ??????0d?r?
(Output from nc in terminal, this was a 'pwd' command)
I also seem to have some kind of problem where a buffer isn't cleared? When I use the 'say' command(say [sentence] ) MacOS is supposed to use voice the sentence. This happens, but only the 2 first letters of the argument after 'say'(the 2 first characters of the sentence) and then says an earlier string. ('Successfully connected!')
Ex.: (command: 'say hello')
heSuccessfully connected!
I have tried to open the FILE stream in different places and
Code (after socket setup and connection):
const char conMsg[25] = "Successfully connected!\n";
send(netSock, conMsg, sizeof(conMsg), 0);
printf("Sent message...\n");
// variable setup
char command[] = "clear";
char buffer[256];
const char INPUTFIELD[3] = "\n> ";
// requests loop
while (1) {
send(netSock, INPUTFIELD, sizeof(INPUTFIELD), 0);
// recv command
recv(netSock, &command, sizeof(command), 0);
printf("recived command...\n");
printf(command);
// exit check
if ( strncmp(command, ":exit", 5) == 0) {
close(netSock);
exit(0);
} else {
// stream init
FILE *in;
in = popen(command, "r");
// popen output, send to host
while ( fgets(buffer, sizeof(buffer), in) != NULL) {
send(netSock, buffer, sizeof(buffer), 0);
}
pclose(in);
}
}
return 0;
How I use the program:
nc -l [specified port] (MAC or Linux terminal command(maybe Windows aswell))
Start binary (should not matter as I plan to have it try to connect, but that functonality is lacking as of now)
// recv command
recv(netSock, &command, sizeof(command), 0);
printf("recived command...\n");
printf(command);
You ignore the return value of recv, so none of your other code has any idea how many bytes of data you received. Also, you pass command to printf. This has two problems:
What if you didn't receive a zero byte? You could run right off the end of the buffer.
What if the received data includes a %s or other string that is special to printf?
I think your main issue is here:
// popen output, send to host
while ( fgets(buffer, sizeof(buffer), in) != NULL) {
send(netSock, buffer, sizeof(buffer), 0);
}
fgets will read just to an end of line (including the end of line character) and then null terminate. Unless a line exceeds the buffer size, it won't fill the buffer completely. Your send call is sending the entire buffer regardless, including any uninitialized gibberish that may be past what fgets read. This might work better:
// popen output, send to host
while ( fgets(buffer, sizeof(buffer), in) != NULL) {
send(netSock, buffer, strlen(buffer), 0);
}

Avoid buffer underflow and overflow

My buffer size is 50 but I want to load my buffer only with 12 length characters
and again I have to load my buffer with different Character length but i am not able
to load buffer again, it is showing previous data with some garbage values.I tried to
remove garbage values by using hard coded value and again I reinitialized buffer to zero value but still I am getting same problem.
This code is for receiving data in C
{
if(PortRecvs(0,buff,sizeof(buff),1000)<0)
{
clrscr();
printf("Receive Fail..");
DelayMs(1000);
}
clrscr();
printf("Receive Buff:\n%s",buff);
DelayMs(1000);
if(PortRecvs(0,buff,12,1000)<0)
{
clrscr();
printf("Receive Fail..");
DelayMs(1000);
}
clrscr();
printf("Receive Buff:\n%s",buff);
DelayMs(1000);
}
There are too many clrscr() calls there for good debugging. The DelayMs() calls would drive me bonkers too (though some would deem driving me bonkers an unnecessary exercise).
It's a plausible inference that your PortRecvs() function returns the number of bytes read; you do not, however, ensure that printf() only prints the number of bytes that were read. It is likely that your code should look more like:
{
int nbytes;
if ((nbytes = PortRecvs(0, buff, sizeof(buff), 1000)) < 0)
{
printf("Receive Fail.\n");
DelayMs(1000);
}
else
printf("Receive Buff: [[%.*s]]\n", nbytes, buff); // Do not print if receive failed
DelayMs(1000);
if ((nbytes = PortRecvs(0, buff, 12, 1000)) < 0)
{
printf("Receive Fail.\n");
DelayMs(1000);
}
else
printf("Receive Buff: [[%.*s]]\n", nbytes, buff);
DelayMs(1000);
}
Note that this code does not print the buffer if the receive fails. It ensures that each message ends with a newline. It surrounds the data with markers [[ and ]] (choose your own if you don't like those — I often use << and >> instead) so that you can see more easily trailing blanks or embedded newlines. And, most importantly, it uses the %.*s conversion specification to print just the number of bytes that were received from PortRecvs().
Note that functions like PortRecvs() typically work with binary data and do not add a null terminator to the value received. The onus is on you to ensure that you handle data without null termination correctly.

Strange Behavoir from freopen() and streams

EDIT: I've managed to narrow down the problem, but it still doesn't make much sense to me. My code becomes 8 lines:
int savedOut = dup(1);
printf("Changing the outstream to process.txt!")
if ( freopen("process.txt", "w"m stdout) == NULL)
printf("FREOPEN() FAILURE")
printf("Print to File\n");
dup2(savedOut, 1);
printf("Done with print to file");
return 1;
This code prints all to the terminal. Removing the two lines with "savedOut" prints all to process.txt. I understand the latter result, but I don't understand the former.
END EDIT
I'm having a lot of difficulty working with freopen(). Take this snippet of code:
int savedIn = dup(0);
int savedOut = dup(1);
while(1)
{
readFile[0] = '\0';
writeFile[0] = '\0';
dup2(savedIn, 0);
dup2(savedOut, 1);
if(getInputFlag == 1)
{
printf("myshell$ ");
gotInputFlag = getUserInput(arguments, command, readFile, writeFile, catOrApp, bkgdFlag);
}
else
{
gotInputFlag = getUserInput(arguments, command, readFile, writeFile, catOrApp, bkgdFlag);
}
if(gotInputFlag == 1)
{
history[historySize] = (char*)malloc(sizeof(char) * 1000);
if (writeFile[0] != '\0' && *catOrApp == 0)
{
printf("Changing the outstream!\n");
freopen(writeFile, "w", stdout);
}
printf("Print to File\n");
dup2(savedIn, 0);
dup2(savedOut, 1);
printf("Done with print to file!\n");
...
This program will execute and print "Changing the Outstream!" just as expected. "Print to File!" is never printed, neither to the terminal nor to the writeFile. "Done with print to file!\n" does not print either. Later on in the code, the code calls an execv() on a Hello World program, which prints to terminal as expected. However, upon program termination suddenly all the printf statements print to terminal, even the "Print to File" statements.
Save for a single fgets(), getUserInput() does not work with streams.
I can't for the life of me understand why this is happening. Does anyone have any idea?
This is what I believe is happening is all associated with stream buffering. You are starting with stdout pointing at your terminal. Because it is a character device, the stream is line-buffered. You print Changing the outstream to process.txt! without a new-line so the text stays in the buffer. You now reopen stdout to a file; the stream switches to fully-buffered. You then print Print to File\n which remains in the buffer despite the new-line.
Now you use dup2 to change stdout back to the terminal. However, this works on the fd that underlies the stream. The stream library code is unaware of this change and leaves the stream fully buffered. You print once more and exit, which flushes the stream to the fd (now your terminal).
Add fflush calls after each printf and I'll bet you see the behavior you expect.

c recv() read until newline occurs

I'm working on writing a IRC bot in C, and have ran into a snag.
In my main function, I create my socket and connect, all that happy stuff. Then I have a (almost) infinite loop to read what's being sent back from the server. I then pass what's read off to a helper function, processLine(char *line) - the problem is, that the following code reads until my buffer is full - I want it to only read text until a newline (\n) or carriage return (\r) occurs (thus ending that line)
while (buffer[0] && buffer[1]) {
for (i=0;i<BUFSIZE;i++) buffer[i]='\0';
if (recv(sock, buffer, BUFSIZE, 0) == SOCKET_ERROR)
processError();
processLine(buffer);
}
What ends up happening is that many lines get jammed all together, and I can't process the lines properly when that happens.
If you're not familiar with IRC protocols, a brief summary would be that when a message is sent, it often looks like this: :YourNickName!YourIdent#YourHostName PRIVMSG #someChannel :The rest on from here is the message sent...
and a login notice, for instance, is something like this: :the.hostname.of.the.server ### bla some text bla with ### being a code(?) used for processing - i.e. 372 is an indicator that the following text is part of the Message Of The Day.
When it's all jammed together, I can't read what number is for what line because I can't find where a line begins or ends!
I'd appreciate help with this very much!
P.S.: This is being compiled/ran on linux, but I eventually want to port it to windows, so I am making as much of it as I can multi-platform.
P.S.S.: Here's my processLine() code:
void processLine(const char *line) {
char *buffer, *words[MAX_WORDS], *aPtr;
char response[100];
int count = 0, i;
buffer = strdup(line);
printf("BLA %s", line);
while((aPtr = strsep(&buffer, " ")) && count < MAX_WORDS)
words[count++] = aPtr;
printf("DEBUG %s\n", words[1]);
if (strcmp(words[0], "PING") == 0) {
strcpy(response, "PONG ");
strcat(response, words[1]);
sendLine(NULL, response); /* This is a custom function, basically it's a send ALL function */
} else if (strcmp(words[1], "376") == 0) { /* We got logged in, send login responses (i.e. channel joins) */
sendLine(NULL, "JOIN #cbot");
}
}
The usual way to deal with this is to recv into a persistent buffer in your application, then pull a single line out and process it. Later you can process the remaining lines in the buffer before calling recv again. Keep in mind that the last line in the buffer may only be partially received; you have to deal with this case by re-entering recv to finish the line.
Here's an example (totally untested! also looks for a \n, not \r\n):
#define BUFFER_SIZE 1024
char inbuf[BUFFER_SIZE];
size_t inbuf_used = 0;
/* Final \n is replaced with \0 before calling process_line */
void process_line(char *lineptr);
void input_pump(int fd) {
size_t inbuf_remain = sizeof(inbuf) - inbuf_used;
if (inbuf_remain == 0) {
fprintf(stderr, "Line exceeded buffer length!\n");
abort();
}
ssize_t rv = recv(fd, (void*)&inbuf[inbuf_used], inbuf_remain, MSG_DONTWAIT);
if (rv == 0) {
fprintf(stderr, "Connection closed.\n");
abort();
}
if (rv < 0 && errno == EAGAIN) {
/* no data for now, call back when the socket is readable */
return;
}
if (rv < 0) {
perror("Connection error");
abort();
}
inbuf_used += rv;
/* Scan for newlines in the line buffer; we're careful here to deal with embedded \0s
* an evil server may send, as well as only processing lines that are complete.
*/
char *line_start = inbuf;
char *line_end;
while ( (line_end = (char*)memchr((void*)line_start, '\n', inbuf_used - (line_start - inbuf))))
{
*line_end = 0;
process_line(line_start);
line_start = line_end + 1;
}
/* Shift buffer down so the unprocessed data is at the start */
inbuf_used -= (line_start - inbuf);
memmove(innbuf, line_start, inbuf_used);
}
TCP doesn't offer any sequencing of that sort. As #bdonlan already said you should implement something like:
Continuously recv from the socket into a buffer
On each recv, check if the bytes received contain an \n
If an \n use everything up to that point from the buffer (and clear it)
I don't have a good feeling about this (I read somewhere that you shouldn't mix low-level I/O with stdio I/O) but you might be able to use fdopen.
All you would need to do is
use fdopen(3) to associate your socket with a FILE *
use setvbuf to tell stdio that you want it line-buffered (_IOLBF) as opposed to the default block-buffered.
At this point you should have effectively moved the work from your hands to stdio. Then you could go on using fgets and the like on the FILE *.

Debugging read() system call - does not continue executing until CTRL-C is pressed

Hi I need to use the system call read() to read from I/O. I have the following code
//Reading in the commands
for(;;) {
n = read( fd, buf, 128 );
fflush(stdin);
printf("---\n");
}
It will not print the "---" string until I I terminate the program, then it'll print all at once. I've tried flushing the input stream as well with no luck. I'm not very familiar with read() so I don't exactly know how it works. The reason I need to use read() is because I need to make CTRL-D terminate the program. Would anyone mind enlighten me as to why is this happening and how to proceed? Thanks in advance.
PS: I did some more testing an got an interesting result:
for(i;i<3;i++) {
if( read( fd, buf, 128 ) < 0) {
printf("Read returned less than 0");
} else {
printf("Read is working\n");
}
}
removing the "\n" character makes it print "Read is working" 3 times after the third input is read. having the character in there will make it print after each input is read.
You need to check the return value of ‘read‘ to detect EOF on STDIN (i.e. pressing Ctrl-D). The code you posted is an infinite loop.
I still don't know why it was doing that but fflush(stdout) before it loops again solves the problem.
for my orginal code:
//Reading in the commands
for(;;) {
n = read( fd, buf, 128 );
fflush(stdin);
[Other statements]
fflush(stdout);
}
solved the problem. Still wondering why this needs to be done.

Resources