At first glance we are doing pretty much the same thing. My code assumes the port has already been set to 8N1 and just tweaks the settings needed:

(The BBS messes with the alignment here but you get the idea.)

//Opens the serial port. Returns true on success.
bool open_serial()
{
struct termios attribs;

handle_serial = open(EMPEG_GPS_SERIAL_PORT, O_RDWR | O_NOCTTY ); //| O_EXCL

if(handle_serial == -1)
{
printf("open() of port %s failed.", EMPEG_GPS_SERIAL_PORT);
return(false);
}

tcdrain(handle_serial);

if(tcgetattr(handle_serial,&attribs)<0)
{
printf("tcsetattr failed.");
return(false);
}


/* Save off the original port settings.
*/
serial_orig_c_lflag = attribs.c_lflag;
serial_orig_speed = cfgetospeed(&attribs);

/* Set new mode and speed.
*/
attribs.c_lflag &= ~ICANON;
cfsetospeed(&attribs, B4800);

tcdrain(handle_serial);
if(tcsetattr(handle_serial, TCSAFLUSH, &attribs)<0)
{
printf("tcsetattr failed.");
return(false);
}
return(true);
}

Clearing ICANON isn't needed for the GPS code but is for the OBDII code which is related.

Reading is done with a select() and read(), much like you do.

Cheers,

Rex.