Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

191
Views
Why is my buffer length ignored?

I'm developing a receiver for a small hardware project. I'm working on a small board that uses UART to transfer data.
The receiver code is shown in full below, I'll explain the problematic bits separately shortly.

#define TTY "/dev/ttys002"

#include <stdio.h>
#include <string.h>
#include <unistd.h> //Unix standard functions
#include <fcntl.h> //File controls
#include <errno.h> //Error numbers
#include <assert.h>
#include <termios.h> //Posix terminal

int open_port(const char * tty) {
    int fd;
    fd = open(tty, (O_RDWR | O_NOCTTY | O_NDELAY));
    assert("__failed to open port__" && fd != -1);
    //Block until read
    fcntl(fd, F_SETFL, 0);
    return fd;
}

void configure_port(int fd) {
    struct termios options;
    //Get current options
    tcgetattr(fd, &options);

    //9600 Baud
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    //Receive & local mode
    options.c_cflag |= (CLOCAL | CREAD);

    //Raw output
    options.c_oflag &= ~OPOST;

    //No hardware flow control
    options.c_cflag &= ~CRTSCTS;

    //No parity, 1 stop bit
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;

    //8 data bits
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    //Write options back, set them immediately
    tcsetattr(fd, TCSANOW, &options);
}

int main(int argc, const char * argv[]) {
    int fd = open_port(TTY);
    const size_t count = 8;
    char buf[count + 1];
    ssize_t n;
    configure_port(fd);
    while (1) {
        n = read(fd, buf, count);
        buf[count] = '\0';
        if (n > 0) {
            printf("%s\n", buf);
        }
    }
    return 0;
}

Since I don't have my hardware at hand currently, I decided to test my receiver over a regular tty (#define TTY "/dev/ttys002"). To test it, I simply compiled and ran the above code and then opened a separate terminal and:

echo "text" >> /dev/ttys002

All this works fine and well and I get all the data I'm echoing into the tty.

However, the problem arises when I input a long message into the tty:

echo "this is a longer test message" >> /dev/ttys002

I receive the whole message as a single string in my program output. Why is this so? I would have expected the text to be split up into blocks of 8 chars (const size_t count = 8;).

If it's of importance, I'm using this guide as my go-to for the configuration.

Edit: Please see the comments for further discussion on the issue.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

IMHO, your message is split into blocks of eight chars : n = read(fd, buf, count); cannot give more than count bytes at a time.

But as you do not configure the tty line in RAW mode, is is still in line buffered mode. So the underlying driver blocks the first read until it has a full line terminated with a \n (or exceeding the buffer capacity).

Then the read returns with the first 8 bytes, and next reads immediately return with 8 bytes too since data is available in driver buffer.

You should look at non canonical mode in man termios, if you want to use the raw input mode :

options.c_cflags &= ~ICANON;
/* optionally if defaults are not appropriates */
options.c_cc[VMIN] = vmin; /* default is 1 */
options.c_cc[VTIME] = vtime; /* default is 0 */

But anyway, you read chararacters and never add the terminating null, so buf has no reason to be null terminated. You should only print the number of characters actually read:

const size_t count = 8;
char buf[count];
ssize_t n;
configure_port(fd);
while (1) {
    n = read(fd, buf, count);
    if (n > 0) {
        printf("%.*s\n", n, buf); /* only print the n characters */
    }
}
over 4 years ago · Santiago Trujillo Report

0

It seems that your problem has the same name that this site :)

You're allocating 8 bytes of data on the stack for your buf variable. Then, in read function, you're writing "this is a longer test message" string, which length is much more than 8 bytes. When you're using printf function with "%s", printf will stop printing when it will reach a null character(\0) because it expects your string to be null-terminated. In your case, you should make a check whether your buf variable is null-terminated. If it's not, you should make the last byte of the bufto be a null character

over 4 years ago · Santiago Trujillo Report

0

What you are looking for is a pseudo tty (PTY).

A simple way to create a PTY is to use socat(1) like so:

socat pty,link=/tmp/testpty stdio

This will create a PTY and attach the current terminal's stdio to its master side. Whatever data you put in here will be sent to the slave side of the PTY.

Now connect to the slave side from your program and it should work as you expect:

#define TTY "/tmp/testpty"
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!