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