|
|
1.1 root 1:
2: static char SCCSID[] = "@(#)pupucommon.c 2.1 DKHOST 85/01/15";
3:
4: #include <sys/types.h>
5: #include "sysexits.h"
6: #include <signal.h>
7: #include "tdefs.h"
8: #include "udefs.h"
9: #include <varargs.h>
10: #include <errno.h>
11: #include <string.h>
12: #include <stdio.h>
13: #include "pupu.h"
14: extern int errno ;
15:
16: Xint cfd;
17:
18: Xchar mhead[H_DATA] = "\206\006";
19: Xchar buf[BLOCKSIZE];
20: XcharP mnext;
21: Xchar sseq, rseq;
22:
23: Xjmp giveup;
24: XfnP alarmwas;
25:
26: Xchar wdir[NAMELEN];
27: Xchar basedir[NAMELEN];
28: Xchar wholename[NAMELEN];
29:
30: Xlink linkhead;
31:
32: XfnP errorfunction;
33: Xint lasterror;
34: XcharP remoteorlocal;
35: XcharP currentfile, timeoutmsg;
36:
37: Xchar openfiles[TOPFD+4];
38:
39: Efn gotinit, gotinitreply;
40:
41: Xexp inittable[] = {
42: 'I', gotinit,
43: 'i', gotinitreply,
44: 0, 0
45: };
46:
47: Efn remotedone, remoteerror, alldone;
48:
49: Xexp justquit[] = {
50: 'x', remotedone,
51: 'e', remoteerror,
52: 'X', alldone,
53: 0, 0
54: };
55:
56: SexpP toexpect;
57:
58: Xchar myversion[6] = "1";
59: Xchar theirversion[6];
60:
61: Xchar options[32];
62:
63: Efn timeout;
64:
65: begin(fd, errfcn, rol, initwdir)
66: PfnP errfcn;
67: PcharP rol, initwdir;
68: {
69: cfd = fd;
70: errorfunction = errfcn;
71: remoteorlocal = rol;
72: currentfile = NIL;
73: lasterror = 0;
74:
75: strcpy(wdir, initwdir);
76:
77: signal(SIGALRM, timeout);
78: }
79:
80: sendinit(opt)
81: PcharP opt;
82: {
83: msginit('I');
84: msgfmt("%s", myversion);
85: msgfmt("%s", opt);
86:
87: msgconf(inittable);
88: }
89:
90: gotinit()
91: {
92: msgtake("%s", theirversion);
93: msgtake("%s", options);
94:
95: msginit('i');
96: msgfmt("%s", myversion);
97: msgsend();
98:
99: return(1);
100: }
101:
102: gotinitreply()
103: {
104: msgtake("%s", theirversion);
105:
106: return(1);
107: }
108:
109: err(msg, parm, en)
110: PcharP msg, parm;
111: {
112: warn(msg, parm, en);
113:
114: if(*remoteorlocal == 'r')
115: reply('X');
116:
117: stopnow(en);
118: }
119:
120: warn(msg, parm, en)
121: PcharP msg, parm;
122: {
123: RcharP ep;
124: Achar ebuf[BUFSIZ];
125:
126: ep = ebuf;
127:
128: ep += sprintf(ep, "(%s): %s", remoteorlocal, msg);
129:
130: if(parm)
131: ep += sprintf(ep, " [%s]", parm);
132:
133: if(en > 0 && errno >= 0 && errno <= sys_nerr)
134: sprintf(ep, " -- %s", sys_errlist[errno]);
135:
136: db(stderr, "warn * %s\n", ebuf);
137: if(*remoteorlocal == 'l')
138: (*errorfunction)(ebuf);
139: else{
140: msginit('e');
141: msgfmt("%s", ebuf);
142: msgsend();
143: }
144:
145: lasterror = en < 0 ? -en : en;
146: }
147:
148: creatn(name, mode)
149: PcharP name;
150: {
151: Rint fd;
152:
153: fd = creat(name, mode);
154:
155: if(fd >= 0)
156: openfiles[fd] = 1;
157:
158: return(fd);
159: }
160:
161: openn(name, flags)
162: PcharP name;
163: {
164: Rint fd;
165:
166: fd = open(name, flags);
167:
168: if(fd >= 0)
169: openfiles[fd] = 1;
170:
171: return(fd);
172: }
173:
174: closen(fd)
175: {
176: close(fd);
177:
178: openfiles[fd] = 0;
179: }
180:
181: remotedone()
182: {
183: Aint en;
184:
185: msgtake("%d", &en);
186:
187: if(en)
188: lasterror = en;
189:
190: return(1);
191: }
192:
193: alldone()
194: {
195: stopnow(0);
196: }
197:
198: stopnow(en)
199: {
200: Rint i;
201: RlinkP lp, nlp;
202:
203: alarm(0);
204: signal(SIGALRM, alarmwas);
205:
206: for(i = 0; i < sizeof(openfiles)/sizeof(openfiles[0]); i++)
207: if(openfiles[i])
208: closen(i);
209:
210: for(lp = linkhead.next; lp; lp = nlp){
211: nlp = lp->next;
212: free(lp);
213: }
214: linkhead.next = 0;
215:
216: if(en > 0)
217: lasterror = en;
218: else if(en < 0)
219: lasterror = -en;
220:
221: longjmp(giveup, 1);
222: }
223:
224: msgtake(fmt, ptr)
225: PcharP fmt, ptr;
226: {
227: if(strcmp(fmt, "%s") == 0)
228: strcpy(ptr, mnext); /* Foo! sscanf stops at white space */
229: else
230: sscanf(mnext, fmt, ptr);
231:
232: mnext += strlen(mnext)+1;
233: }
234:
235: reply(type)
236: Pchar type;
237: {
238: if(++sseq > SEQMAX)
239: sseq = SEQMIN;
240: mhead[H_SEQN] = sseq;
241:
242: mhead[H_TYPE] = type;
243:
244: timeoutmsg = "Protocol exchange timed out";
245:
246: alarm(WTIMEOUT);
247:
248: msgwrite(cfd, mhead, sizeof(mhead));
249:
250: alarm(0);
251: }
252:
253: confirmed()
254: {
255: return(1);
256: }
257:
258: remoteerror()
259: {
260: Achar ebuf[BUFSIZ];
261:
262: msgtake("%s", ebuf);
263:
264: (*errorfunction)(ebuf);
265:
266: return(0);
267: }
268:
269: msginit(type)
270: Pchar type;
271: {
272: if(toexpect){
273: msgwait(toexpect);
274: toexpect = 0;
275: }
276:
277: if(++sseq > SEQMAX)
278: sseq = SEQMIN;
279: mhead[H_SEQN] = sseq;
280:
281: mhead[H_TYPE] = type;
282:
283: strcpy(buf, mhead);
284:
285: mnext = &buf[H_DATA];
286: }
287:
288: /* VARARGS0 */
289: msgfmt(va_alist)
290: va_dcl
291: {
292: RcharP fmt;
293: va_list args;
294:
295: va_start(args);
296:
297: fmt = va_arg(args, TcharP);
298:
299: mnext += vsprintf(mnext, fmt, args) + 1;
300: }
301:
302: msgconf(expect)
303: PexpP expect;
304: {
305: msgsend();
306:
307: toexpect = expect;
308: }
309:
310: msgsend()
311: {
312: Rint len;
313: db(stderr, "msgsend %c\n", buf[H_TYPE]);
314:
315: len = mnext - buf;
316:
317: timeoutmsg = "Protocol exchange timed out";
318:
319: alarm(WTIMEOUT);
320:
321: if(msgwrite(cfd, buf, len) != len)
322: if(*remoteorlocal == 'r')
323: stopnow(EX_IOERR);
324: else
325: err("Message write failed", NIL, EX_IOERR);
326:
327: alarm(0);
328: }
329:
330: msgwait(expect)
331: PexpP expect;
332: {
333: Rint len;
334: RexpP ep;
335:
336: db(stderr, "msgwait %X\n", expect);
337: timeoutmsg = "Protocol exchange timed out";
338:
339: for(;;){
340: alarm(RTIMEOUT);
341:
342: len = msgread(cfd, buf, sizeof(buf));
343:
344: alarm(0);
345: db(stderr, "read len %d type %c\n", len, buf[H_TYPE]);
346:
347: if(len <= 0)
348: err("Message read error", NIL, EX_IOERR);
349:
350: if(++rseq > SEQMAX)
351: rseq = SEQMIN;
352: if(buf[H_MAG1] != mhead[H_MAG1] || buf[H_MAG2] != mhead[H_MAG2])
353: err("Bad magic number on message", NIL, -EX_PROTOCOL);
354: if(buf[H_SEQN] != rseq)
355: err("Bad sequence number on message", NIL, -EX_PROTOCOL);
356:
357: mnext = &buf[H_DATA];
358:
359: for(ep = expect; ep->type; ep++)
360: if(ep->type == buf[H_TYPE])
361: if((*ep->fn)())
362: return;
363: else
364: break;
365:
366: if(!ep->type)
367: err("Unexpected message type", &buf[H_TYPE], -EX_PROTOCOL);
368: }
369: }
370:
371:
372: sendfile(name)
373: RcharP name;
374: {
375: AcharP d;
376:
377: db(stderr, "sendfile %s\n", name);
378: if(d = strrchr(name, '/')){
379: if(!wdir[0])
380: curdir(wdir);
381:
382: if(d == name)
383: name = "/";
384: else
385: *d = '\0';
386:
387: if(chdir(name) < 0){
388: warn("Can't change directory to", name, EX_NOINPUT);
389: return;
390: }
391:
392: name = d+1;
393: }
394:
395: putfile(name, name);
396:
397: if(d)
398: chdir(wdir);
399: }
400:
401: timeout()
402: {
403: err(timeoutmsg, currentfile, -EX_IOERR);
404: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.