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