chiark / gitweb /
63d1e44738f7ff240a1523d898f42995e686b75c
[sympathy.git] / src / ptty.c
1 /*
2  * ptty.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id$";
10
11 /*
12  * $Log$
13  * Revision 1.4  2008/02/14 10:39:14  james
14  * *** empty log message ***
15  *
16  * Revision 1.3  2008/02/13 09:12:21  james
17  * *** empty log message ***
18  *
19  * Revision 1.2  2008/02/12 22:36:46  james
20  * *** empty log message ***
21  *
22  * Revision 1.1  2008/02/09 15:47:28  james
23  * *** empty log message ***
24  *
25  * Revision 1.2  2008/02/07 11:11:14  staffcvs
26  * *** empty log message ***
27  *
28  * Revision 1.1  2008/02/07 01:02:52  james
29  * *** empty log message ***
30  *
31  * Revision 1.3  2008/02/06 17:53:28  james
32  * *** empty log message ***
33  *
34  * Revision 1.2  2008/02/04 02:05:06  james
35  * *** empty log message ***
36  *
37  * Revision 1.1  2008/02/04 01:32:39  james
38  * *** empty log message ***
39  *
40  */
41
42 #include "project.h"
43
44
45 typedef struct
46 {
47   TTY_SIGNATURE;
48   int fd;
49   pid_t child;
50 } PTTY;
51
52
53 static void
54 ptty_close (TTY * _t)
55 {
56   PTTY *t = (PTTY *) _t;
57
58   if (!t)
59     return;
60
61   close (t->fd);
62   free (t);
63 }
64
65
66
67 static int
68 ptty_read (TTY * _t, void *buf, int len)
69 {
70   PTTY *t = (PTTY *) _t;
71   int red, done = 0;
72
73   do
74     {
75
76       red = wrap_read (t->fd, buf, len);
77       if (red < 0)
78         return -1;
79       if (!red)
80         return done;
81
82       buf += red;
83       len -= red;
84       done += red;
85     }
86   while (len);
87
88
89   return done;
90 }
91
92
93 static int
94 ptty_write (TTY * _t, void *buf, int len)
95 {
96   int writ, done = 0;
97   PTTY *t = (PTTY *) _t;
98
99   do
100     {
101
102       writ = wrap_write (t->fd, buf, len);
103       if (writ < 0)
104         return -1;
105       if (!writ)
106         sleep (1);
107
108       buf += writ;
109       len -= writ;
110       done += writ;
111     }
112   while (len);
113
114
115   return done;
116 }
117
118 TTY *
119 ptty_open (char *path, char *argv[])
120 {
121   PTTY *t;
122   pid_t child;
123   char name[1024];
124   struct winsize winsize = { 0 };
125   struct termios termios;
126   int fd;
127   char *default_argv[] = { "-", (char *) 0 };
128
129
130   default_termios (&termios);
131
132   winsize.ws_row = VT102_ROWS;
133   winsize.ws_col = VT102_COLS;
134
135   child = forkpty (&fd, name, &termios, &winsize);
136
137   switch (child)
138     {
139     case -1:                   /*boo hiss */
140       return NULL;
141     case 0:                    /*waaah */
142       setenv ("TERM", "vt102", 1);
143       setenv ("LANG", "C", 1);
144       if (!path)
145         path = "/bin/sh";
146
147       if (!argv)
148         argv = default_argv;
149
150       execv (path, argv);
151       _exit (-1);
152     }
153
154   set_nonblocking (fd);
155
156   t = (PTTY *) malloc (sizeof (PTTY));
157
158   strncpy (t->name, name, sizeof (t->name));
159   t->name[sizeof (t->name) - 1] = 0;
160
161   t->recv = ptty_read;
162   t->xmit = ptty_write;
163   t->close = ptty_close;
164   t->fd = fd;
165   t->child = child;
166   t->rfd = t->fd;
167   t->wfd = t->fd;
168   t->size.x = winsize.ws_row;
169   t->size.y = winsize.ws_col;
170   t->blocked = 0;
171
172   return (TTY *) t;
173 }