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