title: How to read/write to Linux pseudoterminals using separate processes but without forking?
body: <p>I'd like to write a program that emulates a device on a serial port.  I'm trying to use pseudoterminals to accomplish this.  I want one distinct process to control the master.  This process acts as the serial device emulator.  I want another process (kermit for example) to be able to communicate with the master using the slave terminal.  Because of the distinct process requirement, I am not using any forks.  Almost every pseudoterminal example on the Internet shows the use of fork() for master/slave.</p>
  
  <p>I have it working in one direction.  That is, I can have the slave process write data to the slave pseudoterminal, and the master will read it off the master pseudoterminal just fine.</p>
  
  <p>The problem is in the other direction.  I can't get the master to write data and the slave to read data.</p>
  
  <p>I'll show both the nonworking bidirectional code and the working unidirectional code.</p>
  
  <p>Nonworking bidirectional master:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;fcntl.h&gt;
  
  int main(int argc, char* argv[])
  {
    // get the master fd
    int masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    if(masterfd &lt; 0)
    {
      perror("getpt");
      exit(1);
    }
  
    // grant access to the slave
    if(grantpt(masterfd) &lt; 0)
    {
      perror("grantpt");
      exit(1);
    }
  
    // unlock the slave
    if(unlockpt(masterfd) &lt; 0)
    {
      perror("unlockpt");
      exit(1);
    }
  
    // get the path to the slave
    char slavepath[64];
    if(ptsname_r(masterfd, slavepath, sizeof(slavepath)) &lt; 0)
    {
      perror("ptsname_r");
      exit(1);
    }
  
    printf("Using %s\n", slavepath);
  
    char bufout = 'D';
    char bufin;
  
    int c;
    while(1)
    {
      printf("reading\n");
      c = read(masterfd, &amp;bufin, 1);
      printf("read %i bytes: %c\n", c, bufin);
      if(c == -1) break;
  
      if(bufout == 'D') bufout = 'E';
      else if(bufout == 'E') bufout = 'D';
      printf("writing %c\n", bufout);
      c = write(masterfd, &amp;bufout, 1);
      printf("wrote %i bytes\n", c);
      if(c == -1) break;
  
      sleep(1);
    }
  
    close(masterfd);
  
    return 0;
  }
  </code></pre>
  
  <p>Nonworking bidrectional slave:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;unistd.h&gt;
  
  int main(int argc, char* argv[])
  {
    int fd = open("/dev/pts/15", O_RDWR | O_NOCTTY);
    if(fd &lt; 0)
    {
      perror("open");
      exit(1);
    }
  
    char bufout = 'A';
    char bufin;
  
    int c;
    while(1)
    {
      if(bufout == 'A') bufout = 'B';
      else if(bufout == 'B') bufout = 'A';
      printf("writing %c\n", bufout);
      c = write(fd, &amp;bufout, 1);
      if(c == -1) break;
  
      printf("reading\n");
      c = read(fd, &amp;bufin, 1);
      printf("read %i bytes: %c\n", c, bufin);
      if(c == -1) break;
  
      sleep(1);
    }
  
    close(fd);
  }
  </code></pre>
  
  <p>Output of nonworking master:
  (Notice the first character received came from the slave, then the rest are characters written by the master.  In other words, the master is reading off the same characters it wrote to the master pts and its ignoring what the slave is writing, except for the first character.)</p>
  
  <pre><code>Using /dev/pts/15
  reading
  read 1 bytes: B     [&lt;--- FROM THE SLAVE]
  writing E
  wrote 1 bytes
  reading
  read 1 bytes: E     [&lt;--- REST FROM THE MASTER]
  writing D
  wrote 1 bytes
  reading
  read 1 bytes: D
  writing E
  wrote 1 bytes
  reading
  read 1 bytes: E
  writing D
  wrote 1 bytes
  reading
  read 1 bytes: D
  ^C
  </code></pre>
  
  <p>Output of nonworking slave: (Never receives what the master is writing.)</p>
  
  <pre><code>writing B
  reading
  ^C
  </code></pre>
  
  <p>Working unidrectional master:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;fcntl.h&gt;
  
  int main(int argc, char* argv[])
  {
    // get the master fd
    int masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    if(masterfd &lt; 0)
    {
      perror("getpt");
      exit(1);
    }
  
    // grant access to the slave
    if(grantpt(masterfd) &lt; 0)
    {
      perror("grantpt");
      exit(1);
    }
  
    // unlock the slave
    if(unlockpt(masterfd) &lt; 0)
    {
      perror("unlockpt");
      exit(1);
    }
  
    // get the path to the slave
    char slavepath[64];
    if(ptsname_r(masterfd, slavepath, sizeof(slavepath)) &lt; 0)
    {
      perror("ptsname_r");
      exit(1);
    }
  
    printf("Using %s\n", slavepath);
  
    char bufout = 'D';
    char bufin;
  
    int c;
    while(1)
    {
      printf("reading\n");
      c = read(masterfd, &amp;bufin, 1);
      printf("read %i bytes: %c\n", c, bufin);
      if(c == -1) break;
  
      sleep(1);
    }
  
    close(masterfd);
  
    return 0;
  }
  </code></pre>
  
  <p>Working unidrectional slave:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;unistd.h&gt;
  
  int main(int argc, char* argv[])
  {
    int fd = open("/dev/pts/15", O_RDWR | O_NOCTTY);
    if(fd &lt; 0)
    {
      perror("open");
      exit(1);
    }
  
    char bufout = 'A';
    char bufin;
  
    int c;
    while(1)
    {
      if(bufout == 'A') bufout = 'B';
      else if(bufout == 'B') bufout = 'A';
      printf("writing %c\n", bufout);
      c = write(fd, &amp;bufout, 1);
      if(c == -1) break;
  
      sleep(1);
    }
  
    close(fd);
  }
  </code></pre>
  
  <p>Output of working master:  (Reads what the slave writes successfully.)</p>
  
  <pre><code>Using /dev/pts/15
  reading
  read 1 bytes: B
  reading
  read 1 bytes: A
  reading
  read 1 bytes: B
  reading
  read 1 bytes: A
  reading
  read 1 bytes: B
  ^C
  </code></pre>
  
  <p>Output of working slave:</p>
  
  <pre><code>writing B
  writing A
  writing B
  writing A
  writing B
  ^C
  </code></pre>