Clean up process wait to use POSIX waitpid() interface.
[mmh] / uip / vmhsbr.c
1
2 /*
3  * vmhsbr.c -- routines to help vmh along
4  *
5  * This code is Copyright (c) 2002, by the authors of nmh.  See the
6  * COPYRIGHT file in the root directory of the nmh distribution for
7  * complete copyright information.
8  */
9
10 /*
11  * TODO (for vrsn 2):
12  *     INI: include width of windows
13  */
14
15 #include <h/mh.h>
16 #include <h/vmhsbr.h>
17 #include <h/utils.h>
18 #include <errno.h>
19
20 static char *types[] = {
21     "OK",
22     "INI", "ACK", "ERR", "CMD", "QRY", "TTY", "WIN", "DATA", "EOF", "FIN",
23     "XXX", NULL
24 };
25
26 static  FILE *fp = NULL;
27
28 static int PEERrfd = NOTOK;
29 static int PEERwfd = NOTOK;
30
31 /*
32  * static prototypes
33  */
34 static int rclose (struct record *, char *, ...);
35
36
37 int
38 rcinit (int rfd, int wfd)
39 {
40     char *cp, buffer[BUFSIZ];
41
42     PEERrfd = rfd;
43     PEERwfd = wfd;
44
45     if ((cp = getenv ("MHVDEBUG")) && *cp) {
46         snprintf (buffer, sizeof(buffer), "%s.out", invo_name);
47         if ((fp = fopen (buffer, "w"))) {
48           fseek (fp, 0L, SEEK_END);
49           fprintf (fp, "%d: rcinit (%d, %d)\n", (int) getpid(), rfd, wfd);
50           fflush (fp);
51         }
52     }
53
54     return OK;
55 }
56
57
58 int
59 rcdone (void)
60 {
61     if (PEERrfd != NOTOK)
62         close (PEERrfd);
63     if (PEERwfd != NOTOK)
64         close (PEERwfd);
65
66     if (fp) {
67         fclose (fp);
68         fp = NULL;
69     }
70     return OK;
71 }
72
73
74 int
75 rc2rc (char code, int len, char *data, struct record *rc)
76 {
77     if (rc2peer (code, len, data) == NOTOK)
78         return NOTOK;
79
80     return peer2rc (rc);
81 }
82
83
84 int
85 str2rc (char code, char *str, struct record *rc)
86 {
87     return rc2rc (code, str ? strlen (str) : 0, str, rc);
88 }
89
90
91 int
92 peer2rc (struct record *rc)
93 {
94     if (rc->rc_data)
95         free (rc->rc_data);
96
97     if (read (PEERrfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc))
98         return rclose (rc, "read from peer lost(1)");
99     if (rc->rc_len) {
100         rc->rc_data = mh_xmalloc ((unsigned) rc->rc_len + 1);
101         if (read (PEERrfd, rc->rc_data, rc->rc_len) != rc->rc_len)
102             return rclose (rc, "read from peer lost(2)");
103         rc->rc_data[rc->rc_len] = 0;
104     }
105     else
106         rc->rc_data = NULL;
107
108     if (fp) {
109         fseek (fp, 0L, SEEK_END);
110         fprintf (fp, "%d: <--- %s %d: \"%*.*s\"\n", (int) getpid(),
111                 types[(unsigned char)rc->rc_type], rc->rc_len,
112                 rc->rc_len, rc->rc_len, rc->rc_data);
113         fflush (fp);
114     }
115
116     return rc->rc_type;
117 }
118
119
120 int
121 rc2peer (char code, int len, char *data)
122 {
123     struct record   rcs;
124     register struct record *rc = &rcs;
125
126     rc->rc_type = code;
127     rc->rc_len = len;
128
129     if (fp) {
130         fseek (fp, 0L, SEEK_END);
131         fprintf (fp, "%d: ---> %s %d: \"%*.*s\"\n", (int) getpid(),
132                 types[(unsigned char)rc->rc_type], rc->rc_len,
133                 rc->rc_len, rc->rc_len, data);
134         fflush (fp);
135     }
136
137     if (write (PEERwfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc))
138         return rclose (rc, "write to peer lost(1)");
139
140     if (rc->rc_len)
141         if (write (PEERwfd, data, rc->rc_len) != rc->rc_len)
142             return rclose (rc, "write to peer lost(2)");
143
144     return OK;
145 }
146
147
148 int
149 str2peer (char code, char *str)
150 {
151     return rc2peer (code, str ? strlen (str) : 0, str);
152 }
153
154
155 int
156 fmt2peer (char code, char *fmt, ...)
157 {
158     va_list ap;
159
160     va_start(ap, fmt);
161     return verr2peer (code, NULL, fmt, ap);
162     va_end(ap);
163 }
164
165
166 int
167 err2peer (char code, char *what, char *fmt, ...)
168 {
169     int     return_value;
170     va_list ap;
171
172     va_start(ap, fmt);
173     return_value = verr2peer(code, what, fmt, ap);
174     va_end(ap);
175     return return_value;  /* This routine returned garbage before 1999-07-15. */
176 }
177
178
179 int
180 verr2peer (char code, char *what, char *fmt, va_list ap)
181 {
182     int eindex = errno;
183     int len, buflen;
184     char *bp, *s, buffer[BUFSIZ * 2];
185
186     /* Get buffer ready to go */
187     bp = buffer;
188     buflen = sizeof(buffer);
189
190     vsnprintf (bp, buflen, fmt, ap);
191     len = strlen (bp);
192     bp += len;
193     buflen -= len;
194
195     if (what) {
196         if (*what) {
197             snprintf (bp, buflen, " %s: ", what);
198             len = strlen (bp);
199             bp += len;
200             buflen -= len;
201         }
202         if ((s = strerror (eindex)))
203             strncpy (bp, s, buflen);
204         else
205             snprintf (bp, buflen, "unknown error %d", eindex);
206         len = strlen (bp);
207         bp += len;
208         buflen -= len;
209     }
210
211     return rc2peer (code, bp - buffer, buffer);
212 }
213
214
215 static int
216 rclose (struct record *rc, char *fmt, ...)
217 {
218     va_list ap;
219     static char buffer[BUFSIZ * 2];
220
221     va_start(ap, fmt);
222     vsnprintf (buffer, sizeof(buffer), fmt, ap);
223     va_end(ap);
224
225     rc->rc_len = strlen (rc->rc_data = getcpy (buffer));
226     return (rc->rc_type = RC_XXX);
227 }