Hello everyone, im having a hard time figuring out why the program posted below prints an extra newline every time I type the enter key.I suspect this has to do with the terminal line discipline, but I can't really understand why.I have tried turning on/off several terminal options and disable special characters but to no avail.
Any help is greatly appreciated.
Source code follows(compiled in x86, linux-2.6.31.5 - gcc 4.3.3):
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <termios.h>
void
die(char *ptr, ...)
{
va_list vlist;
va_start(vlist, ptr);
char ch;
while ((ch = *ptr++) != '\0') {
if (ch == '%' && *ptr != '\0') {
ch = *ptr++;
switch(ch) {
case 'd': printf("%d", va_arg(vlist, int)); break;
case 'e': printf("%e", va_arg(vlist, double)); break;
case 'c': printf("%c", va_arg(vlist, int)); break;
case 's': printf("%s", va_arg(vlist, char *)); break;
default: va_end(vlist);exit(1);
}
} else
printf("%c", ch);
}
va_end(vlist);
exit(1);
}
int
main(void)
{
int pid,pid2;
int ptm;
int pts;
char *ptr;
char *program_name[2] = {"/usr/bin/passwd", NULL};
char buf[512];
int n,i;
FILE *fp;
struct termios term;
int fd;
if ((ptm = posix_openpt(O_RDWR)) == -1)
die("posix_openpt error: %s\n", strerror(errno));
if (grantpt(ptm) == -1)
die("grantpt error: %s\n", strerror(errno));
if (unlockpt(ptm) == -1)
die("unlockpt error: %s\n", strerror(errno));
if ((pid = fork()) < 0)
die("fork error: %s\n", strerror(errno));
else if (pid > 0) { /* parent */
if ((pid2 = fork()) < 0)
die("2 fork error");
else if (pid2 == 0) { /* child in parent */
if(dup2(ptm, STDOUT_FILENO) != STDOUT_FILENO)
die("dup2 failed");
for ( ; ;) {
if ((n = read(STDIN_FILENO, buf,511)) <= 0)
die("read error");
buf[n] = '\0';
write(STDOUT_FILENO, buf, strlen(buf));
}
} else { /* parent in parent */
if (dup2(ptm, STDIN_FILENO) != STDIN_FILENO)
die("dup2 of parent failed");
for (; ;) {
if ((n = read(STDIN_FILENO, buf, 511)) <= 0)
die("read error");
buf[n] = '\0';
write(STDOUT_FILENO, buf, strlen(buf));
}
}
} else { /* child */
if(setsid() == (pid_t) -1)
die("setsid() error: %s\n", strerror(errno));
if ((ptr = (char *) ptsname(ptm)) == NULL)
die("ptsname error: %s\n", strerror(errno));
if ((pts = open(ptr, O_RDWR)) < 0)
die("open of slave failed: %a\n", strerror(errno));
close(ptm);
if (dup2(pts, STDIN_FILENO) != STDIN_FILENO ||
dup2(pts, STDOUT_FILENO) != STDOUT_FILENO ||
dup2(pts, STDERR_FILENO) != STDERR_FILENO)
die("error doing dup's : %s\n", strerror(errno));
if (execve(*program_name, program_name , NULL) == -1)
die("execve error: %s\n", strerror(errno));
exit(1);
}
/* should not get this far */
return 0;
}