The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/drivers/tty/pty.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      pty.c - pseudo terminal driver                  Author: Kees J. Bot
    2  *                                                              30 Dec 1995
    3  * PTYs can be seen as a bidirectional pipe with TTY
    4  * input and output processing.  For example a simple rlogin session:
    5  *
    6  *      keyboard -> rlogin -> in.rld -> /dev/ptypX -> /dev/ttypX -> shell
    7  *      shell -> /dev/ttypX -> /dev/ptypX -> in.rld -> rlogin -> screen
    8  *
    9  * This file takes care of copying data between the tty/pty device pairs and
   10  * the open/read/write/close calls on the pty devices.  The TTY task takes
   11  * care of the input and output processing (interrupt, backspace, raw I/O,
   12  * etc.) using the pty_read() and pty_write() functions as the "keyboard" and
   13  * "screen" functions of the ttypX devices.
   14  * Be careful when reading this code, the terms "reading" and "writing" are
   15  * used both for the tty and the pty end of the pseudo tty.  Writes to one
   16  * end are to be read at the other end and vice-versa.
   17  */
   18 
   19 #include "../drivers.h"
   20 #include <assert.h>
   21 #include <termios.h>
   22 #include <signal.h>
   23 #include <minix/com.h>
   24 #include <minix/callnr.h>
   25 #include <sys/select.h>
   26 #include "tty.h"
   27 
   28 #if NR_PTYS > 0
   29 
   30 /* PTY bookkeeping structure, one per pty/tty pair. */
   31 typedef struct pty {
   32   tty_t         *tty;           /* associated TTY structure */
   33   char          state;          /* flags: busy, closed, ... */
   34 
   35   /* Read call on /dev/ptypX. */
   36   char          rdsendreply;    /* send a reply (instead of notify) */
   37   char          rdcaller;       /* process making the call (usually FS) */
   38   char          rdproc;         /* process that wants to read from the pty */
   39   vir_bytes     rdvir;          /* virtual address in readers address space */
   40   int           rdleft;         /* # bytes yet to be read */
   41   int           rdcum;          /* # bytes written so far */
   42 
   43   /* Write call to /dev/ptypX. */
   44   char          wrsendreply;    /* send a reply (instead of notify) */
   45   char          wrcaller;       /* process making the call (usually FS) */
   46   char          wrproc;         /* process that wants to write to the pty */
   47   vir_bytes     wrvir;          /* virtual address in writers address space */
   48   int           wrleft;         /* # bytes yet to be written */
   49   int           wrcum;          /* # bytes written so far */
   50 
   51   /* Output buffer. */
   52   int           ocount;         /* # characters in the buffer */
   53   char          *ohead, *otail; /* head and tail of the circular buffer */
   54   char          obuf[128];      /* buffer for bytes going to the pty reader */
   55 
   56   /* select() data. */
   57   int           select_ops,     /* Which operations do we want to know about? */
   58                 select_proc,    /* Who wants to know about it? */
   59                 select_ready_ops;       /* For callback. */
   60 } pty_t;
   61 
   62 #define PTY_ACTIVE      0x01    /* pty is open/active */
   63 #define TTY_CLOSED      0x02    /* tty side has closed down */
   64 #define PTY_CLOSED      0x04    /* pty side has closed down */
   65 
   66 PRIVATE pty_t pty_table[NR_PTYS];       /* PTY bookkeeping */
   67 
   68 FORWARD _PROTOTYPE( int pty_write, (tty_t *tp, int try)                 );
   69 FORWARD _PROTOTYPE( void pty_echo, (tty_t *tp, int c)                   );
   70 FORWARD _PROTOTYPE( void pty_start, (pty_t *pp)                         );
   71 FORWARD _PROTOTYPE( void pty_finish, (pty_t *pp)                        );
   72 FORWARD _PROTOTYPE( int pty_read, (tty_t *tp, int try)                  );
   73 FORWARD _PROTOTYPE( int pty_close, (tty_t *tp, int try)                 );
   74 FORWARD _PROTOTYPE( int pty_icancel, (tty_t *tp, int try)               );
   75 FORWARD _PROTOTYPE( int pty_ocancel, (tty_t *tp, int try)               );
   76 FORWARD _PROTOTYPE( int pty_select, (tty_t *tp, message *m)             );
   77 
   78 /*===========================================================================*
   79  *                              do_pty                                       *
   80  *===========================================================================*/
   81 PUBLIC void do_pty(tp, m_ptr)
   82 tty_t *tp;
   83 message *m_ptr;
   84 {
   85 /* Perform an open/close/read/write call on a /dev/ptypX device. */
   86   pty_t *pp = tp->tty_priv;
   87   int r;
   88   phys_bytes p;
   89 
   90   switch (m_ptr->m_type) {
   91     case DEV_READ:
   92         /* Check, store information on the reader, do I/O. */
   93         if (pp->state & TTY_CLOSED) {
   94                 r = 0;
   95                 break;
   96         }
   97         if (pp->rdleft != 0 || pp->rdcum != 0) {
   98                 r = EIO;
   99                 break;
  100         }
  101         if (m_ptr->COUNT <= 0) {
  102                 r = EINVAL;
  103                 break;
  104         }
  105 #if DEAD_CODE
  106         if (numap_local(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  107                                                         m_ptr->COUNT) == 0) {
  108 #else
  109         if ((r = sys_umap(m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,
  110                 m_ptr->COUNT, &p)) != OK) {
  111 #endif
  112                 break;
  113         }
  114         pp->rdsendreply = TRUE;
  115         pp->rdcaller = m_ptr->m_source;
  116         pp->rdproc = m_ptr->PROC_NR;
  117         pp->rdvir = (vir_bytes) m_ptr->ADDRESS;
  118         pp->rdleft = m_ptr->COUNT;
  119         pty_start(pp);
  120         handle_events(tp);
  121         if (pp->rdleft == 0) return;                    /* already done */
  122 
  123         if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
  124                 r = EAGAIN;                             /* don't suspend */
  125                 pp->rdleft = pp->rdcum = 0;
  126         } else {
  127                 r = SUSPEND;                            /* do suspend */
  128                 pp->rdsendreply = FALSE;
  129         }
  130         break;
  131 
  132     case DEV_WRITE:
  133         /* Check, store information on the writer, do I/O. */
  134         if (pp->state & TTY_CLOSED) {
  135                 r = EIO;
  136                 break;
  137         }
  138         if (pp->wrleft != 0 || pp->wrcum != 0) {
  139                 r = EIO;
  140                 break;
  141         }
  142         if (m_ptr->COUNT <= 0) {
  143                 r = EINVAL;
  144                 break;
  145         }
  146 #if DEAD_CODE
  147         if (numap_local(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  148                                                         m_ptr->COUNT) == 0) {
  149                 r = EFAULT;
  150 #else
  151         if ((r = sys_umap(m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,
  152                 m_ptr->COUNT, &p)) != OK) {
  153 #endif
  154                 break;
  155         }
  156         pp->wrsendreply = TRUE;
  157         pp->wrcaller = m_ptr->m_source;
  158         pp->wrproc = m_ptr->PROC_NR;
  159         pp->wrvir = (vir_bytes) m_ptr->ADDRESS;
  160         pp->wrleft = m_ptr->COUNT;
  161         handle_events(tp);
  162         if (pp->wrleft == 0) return;                    /* already done */
  163 
  164         if (m_ptr->TTY_FLAGS & O_NONBLOCK) {            /* don't suspend */
  165                 r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
  166                 pp->wrleft = pp->wrcum = 0;
  167         } else {
  168                 pp->wrsendreply = FALSE;                        /* do suspend */
  169                 r = SUSPEND;
  170         }
  171         break;
  172 
  173     case DEV_OPEN:
  174         r = pp->state != 0 ? EIO : OK;
  175         pp->state |= PTY_ACTIVE;
  176         pp->rdcum = 0;
  177         pp->wrcum = 0;
  178         break;
  179 
  180     case DEV_CLOSE:
  181         r = OK;
  182         if (pp->state & TTY_CLOSED) {
  183                 pp->state = 0;
  184         } else {
  185                 pp->state |= PTY_CLOSED;
  186                 sigchar(tp, SIGHUP);
  187         }
  188         break;
  189 
  190     case DEV_SELECT:
  191         r = pty_select(tp, m_ptr);
  192         break;
  193 
  194     case CANCEL:
  195         if (m_ptr->PROC_NR == pp->rdproc) {
  196                 /* Cancel a read from a PTY. */
  197                 pp->rdleft = pp->rdcum = 0;
  198         }
  199         if (m_ptr->PROC_NR == pp->wrproc) {
  200                 /* Cancel a write to a PTY. */
  201                 pp->wrleft = pp->wrcum = 0;
  202         }
  203         r = EINTR;
  204         break;
  205 
  206     default:
  207         r = EINVAL;
  208   }
  209   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  210 }
  211 
  212 /*===========================================================================*
  213  *                              pty_write                                    *
  214  *===========================================================================*/
  215 PRIVATE int pty_write(tp, try)
  216 tty_t *tp;
  217 int try;
  218 {
  219 /* (*dev_write)() routine for PTYs.  Transfer bytes from the writer on
  220  * /dev/ttypX to the output buffer.
  221  */
  222   pty_t *pp = tp->tty_priv;
  223   int count, ocount, s;
  224   phys_bytes user_phys;
  225 
  226   /* PTY closed down? */
  227   if (pp->state & PTY_CLOSED) {
  228         if (try) return 1;
  229         if (tp->tty_outleft > 0) {
  230                 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
  231                                                         tp->tty_outproc, EIO);
  232                 tp->tty_outleft = tp->tty_outcum = 0;
  233         }
  234         return;
  235   }
  236 
  237   /* While there is something to do. */
  238   for (;;) {
  239         ocount = buflen(pp->obuf) - pp->ocount;
  240         if (try) return (ocount > 0);
  241         count = bufend(pp->obuf) - pp->ohead;
  242         if (count > ocount) count = ocount;
  243         if (count > tp->tty_outleft) count = tp->tty_outleft;
  244         if (count == 0 || tp->tty_inhibited)
  245                 break;
  246 
  247         /* Copy from user space to the PTY output buffer. */
  248         if ((s = sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
  249                 SELF, D, (vir_bytes) pp->ohead, (phys_bytes) count)) != OK) {
  250                 printf("pty tty%d: copy failed (error %d)\n",  s);
  251                 break;
  252         }
  253 
  254         /* Perform output processing on the output buffer. */
  255         out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
  256         if (count == 0) break;
  257 
  258         /* Assume echoing messed up by output. */
  259         tp->tty_reprint = TRUE;
  260 
  261         /* Bookkeeping. */
  262         pp->ocount += ocount;
  263         if ((pp->ohead += ocount) >= bufend(pp->obuf))
  264                 pp->ohead -= buflen(pp->obuf);
  265         pty_start(pp);
  266         tp->tty_out_vir += count;
  267         tp->tty_outcum += count;
  268         if ((tp->tty_outleft -= count) == 0) {
  269                 /* Output is finished, reply to the writer. */
  270                 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
  271                                         tp->tty_outproc, tp->tty_outcum);
  272                 tp->tty_outcum = 0;
  273         }
  274   }
  275   pty_finish(pp);
  276   return 1;
  277 }
  278 
  279 /*===========================================================================*
  280  *                              pty_echo                                     *
  281  *===========================================================================*/
  282 PRIVATE void pty_echo(tp, c)
  283 tty_t *tp;
  284 int c;
  285 {
  286 /* Echo one character.  (Like pty_write, but only one character, optionally.) */
  287 
  288   pty_t *pp = tp->tty_priv;
  289   int count, ocount;
  290 
  291   ocount = buflen(pp->obuf) - pp->ocount;
  292   if (ocount == 0) return;              /* output buffer full */
  293   count = 1;
  294   *pp->ohead = c;                       /* add one character */
  295 
  296   out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
  297   if (count == 0) return;
  298 
  299   pp->ocount += ocount;
  300   if ((pp->ohead += ocount) >= bufend(pp->obuf)) pp->ohead -= buflen(pp->obuf);
  301   pty_start(pp);
  302 }
  303 
  304 /*===========================================================================*
  305  *                              pty_start                                    *
  306  *===========================================================================*/
  307 PRIVATE void pty_start(pp)
  308 pty_t *pp;
  309 {
  310 /* Transfer bytes written to the output buffer to the PTY reader. */
  311   int count;
  312 
  313   /* While there are things to do. */
  314   for (;;) {
  315         int s;
  316         count = bufend(pp->obuf) - pp->otail;
  317         if (count > pp->ocount) count = pp->ocount;
  318         if (count > pp->rdleft) count = pp->rdleft;
  319         if (count == 0) break;
  320 
  321         /* Copy from the output buffer to the readers address space. */
  322         if ((s = sys_vircopy(SELF, D, (vir_bytes)pp->otail,
  323                 (vir_bytes) pp->rdproc, D, (vir_bytes) pp->rdvir, (phys_bytes) count)) != OK) {
  324                 printf("pty tty%d: copy failed (error %d)\n",  s);
  325                 break;
  326         }
  327 
  328         /* Bookkeeping. */
  329         pp->ocount -= count;
  330         if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf;
  331         pp->rdvir += count;
  332         pp->rdcum += count;
  333         pp->rdleft -= count;
  334   }
  335 }
  336 
  337 /*===========================================================================*
  338  *                              pty_finish                                   *
  339  *===========================================================================*/
  340 PRIVATE void pty_finish(pp)
  341 pty_t *pp;
  342 {
  343 /* Finish the read request of a PTY reader if there is at least one byte
  344  * transferred.
  345  */
  346   if (pp->rdcum > 0) {
  347         if (pp->rdsendreply) {
  348                 tty_reply(TASK_REPLY, pp->rdcaller, pp->rdproc, pp->rdcum);
  349                 pp->rdleft = pp->rdcum = 0;
  350         }
  351         else
  352                 notify(pp->rdcaller);
  353   }
  354 
  355 }
  356 
  357 /*===========================================================================*
  358  *                              pty_read                                     *
  359  *===========================================================================*/
  360 PRIVATE int pty_read(tp, try)
  361 tty_t *tp;
  362 int try;
  363 {
  364 /* Offer bytes from the PTY writer for input on the TTY.  (Do it one byte at
  365  * a time, 99% of the writes will be for one byte, so no sense in being smart.)
  366  */
  367   pty_t *pp = tp->tty_priv;
  368   char c;
  369 
  370   if (pp->state & PTY_CLOSED) {
  371         if (try) return 1;
  372         if (tp->tty_inleft > 0) {
  373                 tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
  374                                                                 tp->tty_incum);
  375                 tp->tty_inleft = tp->tty_incum = 0;
  376         }
  377         return 1;
  378   }
  379 
  380   if (try) {
  381         if (pp->wrleft > 0)
  382                 return 1;
  383         return 0;
  384   }
  385 
  386   while (pp->wrleft > 0) {
  387         int s;
  388 
  389         /* Transfer one character to 'c'. */
  390         if ((s = sys_vircopy(pp->wrproc, D, (vir_bytes) pp->wrvir,
  391                 SELF, D, (vir_bytes) &c, (phys_bytes) 1)) != OK) {
  392                 printf("pty: copy failed (error %d)\n", s);
  393                 break;
  394         }
  395 
  396         /* Input processing. */
  397         if (in_process(tp, &c, 1) == 0) break;
  398 
  399         /* PTY writer bookkeeping. */
  400         pp->wrvir++;
  401         pp->wrcum++;
  402         if (--pp->wrleft == 0) {
  403                 if (pp->wrsendreply) {
  404                         tty_reply(TASK_REPLY, pp->wrcaller, pp->wrproc,
  405                                 pp->wrcum);
  406                         pp->wrcum = 0;
  407                 }
  408                 else
  409                         notify(pp->wrcaller);
  410         }
  411   }
  412 }
  413 
  414 /*===========================================================================*
  415  *                              pty_close                                    *
  416  *===========================================================================*/
  417 PRIVATE int pty_close(tp, try)
  418 tty_t *tp;
  419 int try;
  420 {
  421 /* The tty side has closed, so shut down the pty side. */
  422   pty_t *pp = tp->tty_priv;
  423 
  424   if (!(pp->state & PTY_ACTIVE)) return;
  425 
  426   if (pp->rdleft > 0) {
  427         assert(!pp->rdsendreply);
  428         notify(pp->rdcaller);
  429   }
  430 
  431   if (pp->wrleft > 0) {
  432         assert(!pp->wrsendreply);
  433         notify(pp->wrcaller);
  434   }
  435 
  436   if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
  437 }
  438 
  439 /*===========================================================================*
  440  *                              pty_icancel                                  *
  441  *===========================================================================*/
  442 PRIVATE int pty_icancel(tp, try)
  443 tty_t *tp;
  444 int try;
  445 {
  446 /* Discard waiting input. */
  447   pty_t *pp = tp->tty_priv;
  448 
  449   if (pp->wrleft > 0) {
  450         assert(!pp->wrsendreply);
  451         pp->wrcum += pp->wrleft;
  452         pp->wrleft= 0;
  453         notify(pp->wrcaller);
  454   }
  455 }
  456 
  457 /*===========================================================================*
  458  *                              pty_ocancel                                  *
  459  *===========================================================================*/
  460 PRIVATE int pty_ocancel(tp, try)
  461 tty_t *tp;
  462 int try;
  463 {
  464 /* Drain the output buffer. */
  465   pty_t *pp = tp->tty_priv;
  466 
  467   pp->ocount = 0;
  468   pp->otail = pp->ohead;
  469 }
  470 
  471 /*===========================================================================*
  472  *                              pty_init                                     *
  473  *===========================================================================*/
  474 PUBLIC void pty_init(tp)
  475 tty_t *tp;
  476 {
  477   pty_t *pp;
  478   int line;
  479 
  480   /* Associate PTY and TTY structures. */
  481   line = tp - &tty_table[NR_CONS + NR_RS_LINES];
  482   pp = tp->tty_priv = &pty_table[line];
  483   pp->tty = tp;
  484   pp->select_ops = 0;
  485 
  486   /* Set up output queue. */
  487   pp->ohead = pp->otail = pp->obuf;
  488 
  489   /* Fill in TTY function hooks. */
  490   tp->tty_devread = pty_read;
  491   tp->tty_devwrite = pty_write;
  492   tp->tty_echo = pty_echo;
  493   tp->tty_icancel = pty_icancel;
  494   tp->tty_ocancel = pty_ocancel;
  495   tp->tty_close = pty_close;
  496   tp->tty_select_ops = 0;
  497 }
  498 
  499 /*===========================================================================*
  500  *                              pty_status                                   *
  501  *===========================================================================*/
  502 PUBLIC int pty_status(message *m_ptr)
  503 {
  504         int i, event_found;
  505         pty_t *pp;
  506 
  507         event_found = 0;
  508         for (i= 0, pp = pty_table; i<NR_PTYS; i++, pp++) {
  509                 if ((((pp->state & TTY_CLOSED) && pp->rdleft > 0) ||
  510                         pp->rdcum > 0) &&
  511                         pp->rdcaller == m_ptr->m_source)
  512                 {
  513                         m_ptr->m_type = DEV_REVIVE;
  514                         m_ptr->REP_PROC_NR = pp->rdproc;
  515                         m_ptr->REP_STATUS = pp->rdcum;
  516 
  517                         pp->rdleft = pp->rdcum = 0;
  518                         event_found = 1;
  519                         break;
  520                 }
  521 
  522                 if ((((pp->state & TTY_CLOSED) && pp->wrleft > 0) ||
  523                         pp->wrcum > 0) &&
  524                         pp->wrcaller == m_ptr->m_source)
  525                 {
  526                         m_ptr->m_type = DEV_REVIVE;
  527                         m_ptr->REP_PROC_NR = pp->wrproc;
  528                         if (pp->wrcum == 0)
  529                                 m_ptr->REP_STATUS = EIO;
  530                         else
  531                                 m_ptr->REP_STATUS = pp->wrcum;
  532 
  533                         pp->wrleft = pp->wrcum = 0;
  534                         event_found = 1;
  535                         break;
  536                 }
  537 
  538                 if (pp->select_ready_ops && pp->select_proc == m_ptr->m_source) {
  539                         m_ptr->m_type = DEV_IO_READY;
  540                         m_ptr->DEV_MINOR = PTYPX_MINOR + i;
  541                         m_ptr->DEV_SEL_OPS = pp->select_ready_ops;
  542                         pp->select_ready_ops = 0;
  543                         event_found = 1;
  544                         break;
  545                 }
  546         }
  547         return event_found;
  548 }
  549 
  550 /*===========================================================================*
  551  *                              select_try_pty                               *
  552  *===========================================================================*/
  553 PRIVATE int select_try_pty(tty_t *tp, int ops)
  554 {
  555         pty_t *pp = tp->tty_priv;
  556         int r = 0;
  557 
  558         if (ops & SEL_WR)  {
  559                 /* Write won't block on error. */
  560                 if (pp->state & TTY_CLOSED) r |= SEL_WR;
  561                 else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
  562                 else r |= SEL_WR;
  563         }
  564 
  565         if (ops & SEL_RD) {
  566                 /* Read won't block on error. */
  567                 if (pp->state & TTY_CLOSED) r |= SEL_RD;
  568                 else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
  569                 else if (pp->ocount > 0) r |= SEL_RD;   /* Actual data. */
  570         }
  571 
  572         return r;
  573 }
  574 
  575 /*===========================================================================*
  576  *                              select_retry_pty                             *
  577  *===========================================================================*/
  578 PUBLIC void select_retry_pty(tty_t *tp)
  579 {
  580         pty_t *pp = tp->tty_priv;
  581         int r;
  582 
  583         /* See if the pty side of a pty is ready to return a select. */
  584         if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) {
  585                 pp->select_ops &= ~r;
  586                 pp->select_ready_ops |= r;
  587                 notify(pp->select_proc);
  588         }
  589 }
  590 
  591 /*===========================================================================*
  592  *                              pty_select                                   *
  593  *===========================================================================*/
  594 PRIVATE int pty_select(tty_t *tp, message *m)
  595 {
  596         pty_t *pp = tp->tty_priv;
  597         int ops, ready_ops = 0, watch;
  598 
  599         ops = m->PROC_NR & (SEL_RD|SEL_WR|SEL_ERR);
  600         watch = (m->PROC_NR & SEL_NOTIFY) ? 1 : 0;
  601 
  602         ready_ops = select_try_pty(tp, ops);
  603 
  604         if (!ready_ops && ops && watch) {
  605                 pp->select_ops |= ops;
  606                 pp->select_proc = m->m_source;
  607         }
  608 
  609         return ready_ops;
  610 }
  611 
  612 #endif /* NR_PTYS > 0 */

Cache object: d946d63c92e904900bee60054c218fec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.