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