Cannot mimic the action of 'echo' with C

I realise this is not entirely a shell question because it involves the C language but it centers around a Bash script I have written.

I have written a couple of bash script files that communicate via two serial ports. One script can be thought of as a receiver and the other as a transmitter. The receiving script reads and displays data line by line until it reads the character sequence <break>. It then stops listening, and sends a character sequence of either one or two back to the transmitter. The script is thus:

#!/bin/bash

# Read and reply bash script.

exec 3<> /dev/ttyS4
while true; do
    #cat -v /dev/ttyS4 | while read -r input; do
    while read -r -u 3 input; do
        if [ "$input" = "<break>" ]
        then
            echo "break command received."
            break
        else
            echo -e "${input}"
        fi
    done 

    echo "Sending selection"
    if [ "$selection" = "one" ]
    then
        selection="two"
    else
        selection="one"
    fi
    echo "$selection" >&3

done

The transmitter script transmits some character data and then waits for the reply of one or two from the receiver script above:

exec 4<> /dev/ttyS0
selection="one"
while true; do
    echo "************************************" > /dev/ttyS0
    echo "       Selection: ${selection}" > /dev/ttyS0
    echo "************************************" > /dev/ttyS0
    echo "<break>" > /dev/ttyS0
    read -r -t 3 -u 4 input
    if [ -z "$input" ]
    then
        echo "Response from remote timed out."
    elif [ "$input" = "one" ]
    then
        selection=$input
    elif [ "$input" = "two" ]
    then
        selection=$input
        colour=$RED
    else
        echo "Unknown selection: $input"
    fi

    sleep 1 
done

The above two scripts work fine and the receiver script correctly identifies the <break> character sequence.

I wish to replace the 'transmitter' script with a small C program however I find that when I send the character sequence <break> the receiver script this time does NOT identify is as the 'end-of-transmission', is simple echos <break> to stdout, and NOT break command received. I have tried several things such as adding escape characters but there is obviously something different about the way Bash echo works and how I send the data in my C code:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>

#define TRUE 1
#define FALSE 0

int main(int argc, char *argv[]) {
    int selected_tool = DEFAULT_TOOL_SELECTION;
    FILE *ser2_fd_write, *ser2_fdrw;
    struct termios tios, tios_w;        // ser 2 termios structure
    int ser2_fd, ser2_fdw;
    char read_buffer[BUFFER_SIZE];
    struct timespec tdelay;

    bzero(&tdelay, sizeof(tdelay));
    tdelay.tv_sec = 1;
    tdelay.tv_nsec = 5000;

    if ((ser2_fd = open("/dev/ttyS0", O_RDWR)) == -1){
        printf("Unable to open ttyS0 as read-write only.\n");
        return EXIT_FAILURE;
    }

    bzero(&tios, sizeof(tios));
    cfsetispeed(&tios, B38400);
    cfsetospeed(&tios, B38400);


    tios.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CRTSCTS;
    tios.c_iflag = IGNPAR;
    tios.c_oflag = 0;
    tios.c_lflag = ICANON; //0
    tios.c_cc[VTIME] = 0;
    tios.c_cc[VMIN] = 10;

    tcflush(ser2_fd, TCIFLUSH);
    if (tcsetattr(ser2_fd, TCSANOW, &tios) == -1){
        printf("Could not set ser 2 attributes.\n");
        return -1;
    }

    if ((ser2_fdrw = fdopen(ser2_fd, "awr")) == NULL){
        printf("Unable to open file descriptor.\n");
        return EXIT_FAILURE;
    }

while(1){

    push_to_ser2(ser2_fdrw, selected_tool);
    /*
     * This is where sending <break> differs from echo
     */

    //fputs("break", ser2_fdrw);
    fprintf(ser2_fdrw, "break\r\n");
    //fprintf(ser2_fdrw, "\r\n");
    //write(ser2_fd,"break\r\n", 9);
    fflush(ser2_fdrw);
    int c = 0;

    nanosleep(&tdelay, NULL);
    tcflush(ser2_fd, TCIOFLUSH);
    tcdrain(ser2_fd);
    fcntl(ser2_fd, F_SETFL, 0);

    if ( (c = read(ser2_fd, read_buffer, BUFFER_SIZE)) > 0){
        read_buffer[c] = 0;
        if (strcmp(read_buffer, "one\r\n") == 0){
            selected_tool = 1;
        } else if (strcmp(read_buffer, "two\r\n") == 0){
            selected_tool = 2;
        }
    }else{

    }
}
    return EXIT_SUCCESS;
}


/*
 * Convenience function to push data to ser 2
 * *c_data      pointer to the card data
 * *t_data      pointer to the tool data
 */
void push_to_ser2(FILE * fd, int tool){

    fprintf(fd, "**********************************************************\n");
    fprintf(fd, "*                                                        *\n");
    fprintf(fd, "*                     Tool %d Data                       *\n", tool);
    fprintf(fd, "*                                                        *\n");
    fprintf(fd, "**********************************************************\n");


    fprintf(fd,"\r\n");
    fflush(fd);
}

I've tried various alterations to the termios struct too but it makes no difference and I also wonder it the re-direct may have something to do with it. Any suggestions?

One difference seems to be that the C transmitter writes:

BREAK<CR>

where <CR> stands for a CR character,

whereas the bash script tests for

<BREAK>

I realised that the C code didn't quite match what I was trying to achieve in that it was sending "break" and not <break>. This was as a result of me trying various things and the bash script I pasted was out-of-sync with the C code.

It did turn out to be a carriage-return and line-feed issue and was to do with the way I had set up the serial ports. Issue is now resolved.

Thanks for updating us.