1/*	$NetBSD: supmsg.c,v 1.17 2009/10/17 22:26:13 christos Exp $	*/
2
3/*
4 * Copyright (c) 1992 Carnegie Mellon University
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
12 *
13 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
14 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
15 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 *
17 * Carnegie Mellon requests users of this software to return to
18 *
19 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
20 *  School of Computer Science
21 *  Carnegie Mellon University
22 *  Pittsburgh PA 15213-3890
23 *
24 * any improvements or extensions that they make and grant Carnegie Mellon
25 * the rights to redistribute these changes.
26 */
27/*
28 **********************************************************************
29 * HISTORY
30 *
31 * 7-July-93  Nate Williams at Montana State University
32 *	Modified SUP to use gzip based compression when sending files
33 *	across the network to save BandWidth
34 *
35 * Revision 2.4  92/09/09  22:05:17  mrt
36 * 	Moved PFI definition under __STDC__ conditional since it
37 * 	is already defined in libc.h in this case.
38 * 	[92/09/01            mrt]
39 *
40 * Revision 2.3  92/08/11  12:08:12  mrt
41 * 	Added copyright
42 * 	[92/08/10            mrt]
43 * 	Brad's changes: Delinted, Incorporated updated variable
44 * 	argument list usage from old msgxfer.c
45 * 	[92/07/24            mrt]
46 *
47 * Revision 2.2  89/08/23  15:02:56  gm0w
48 * 	Created from separate message modules.
49 * 	[89/08/14            gm0w]
50 *
51 **********************************************************************
52 */
53#include <stdio.h>
54#include <sys/types.h>
55#include <sys/stat.h>
56#include "libc.h"
57#include "c.h"
58#include "supcdefs.h"
59#include "supextern.h"
60#define MSGSUBR
61#define MSGFILE
62#include "supmsg.h"
63
64/*
65 * signon message
66 */
67extern int pgmver;		/* program version of partner */
68extern int pgmversion;		/* my program version */
69extern char *scmver;		/* scm version of partner */
70extern int fspid;		/* process id of fileserver */
71
72static int refuseone(TREE *, void *);
73static int listone(TREE *, void *);
74static int needone(TREE *, void *);
75static int denyone(TREE *, void *);
76static int writeone(TREE *, void *);
77
78int
79msgsignon(void)
80{
81	int x;
82
83	if (isserver) {
84		x = readmsg(MSGSIGNON);
85		if (x == SCMOK)
86			x = readint(&protver);
87		if (x == SCMOK)
88			x = readint(&pgmver);
89		if (x == SCMOK)
90			x = readstring(&scmver);
91		if (x == SCMOK)
92			x = readmend();
93	} else {
94		x = writemsg(MSGSIGNON);
95		if (x == SCMOK)
96			x = writeint(PROTOVERSION);
97		if (x == SCMOK)
98			x = writeint(pgmversion);
99		if (x == SCMOK)
100			x = writestring(scmversion);
101		if (x == SCMOK)
102			x = writemend();
103	}
104	return (x);
105}
106
107int
108msgsignonack(void)
109{
110	int x;
111
112	if (isserver) {
113		x = writemsg(MSGSIGNONACK);
114		if (x == SCMOK)
115			x = writeint(PROTOVERSION);
116		if (x == SCMOK)
117			x = writeint(pgmversion);
118		if (x == SCMOK)
119			x = writestring(scmversion);
120		if (x == SCMOK)
121			x = writeint(fspid);
122		if (x == SCMOK)
123			x = writemend();
124	} else {
125		x = readmsg(MSGSIGNONACK);
126		if (x == SCMOK)
127			x = readint(&protver);
128		if (x == SCMOK)
129			x = readint(&pgmver);
130		if (x == SCMOK)
131			x = readstring(&scmver);
132		if (x == SCMOK)
133			x = readint(&fspid);
134		if (x == SCMOK)
135			x = readmend();
136	}
137	return (x);
138}
139/*
140 * setup message
141 */
142extern int xpatch;		/* setup crosspatch to a new client */
143extern char *xuser;		/* user,group,acct for crosspatch */
144extern char *collname;		/* base directory */
145extern char *basedir;		/* base directory */
146extern int basedev;		/* base directory device */
147extern int baseino;		/* base directory inode */
148extern time_t lasttime;		/* time of last upgrade */
149extern int listonly;		/* only listing files, no data xfer */
150extern int newonly;		/* only send new files */
151extern char *release;		/* release name */
152extern int setupack;		/* ack return value for setup */
153
154int
155msgsetup(void)
156{
157	int x;
158
159	if (isserver) {
160		x = readmsg(MSGSETUP);
161		if (x != SCMOK)
162			return (x);
163		if (protver >= 7) {
164			x = readint(&xpatch);
165			if (x != SCMOK)
166				return (x);
167		} else
168			xpatch = FALSE;
169		if (xpatch) {
170			x = readstring(&xuser);
171			if (x != SCMOK)
172				return (x);
173			return (readmend());
174		}
175		x = readstring(&collname);
176		if (x == SCMOK)
177			x = readint((void *) &lasttime);
178		if (x == SCMOK)
179			x = readstring(&basedir);
180		if (x == SCMOK)
181			x = readint(&basedev);
182		if (x == SCMOK)
183			x = readint(&baseino);
184		if (x == SCMOK)
185			x = readint(&listonly);
186		if (x == SCMOK)
187			x = readint(&newonly);
188		if (x == SCMOK) {
189			if (protver < 6)
190				release = NULL;
191			else
192				x = readstring(&release);
193		}
194		if (x == SCMOK)
195			x = readmend();
196	} else {
197		x = writemsg(MSGSETUP);
198		if (x != SCMOK)
199			return (x);
200		if (protver >= 7) {
201			x = writeint(xpatch);
202			if (x != SCMOK)
203				return (x);
204		}
205		if (xpatch) {
206			x = writestring(xuser);
207			if (x != SCMOK)
208				return (x);
209			return (writemend());
210		}
211		if (x == SCMOK)
212			x = writestring(collname);
213		if (x == SCMOK)
214			x = writeint((int) lasttime);
215		if (x == SCMOK)
216			x = writestring(basedir);
217		if (x == SCMOK)
218			x = writeint(basedev);
219		if (x == SCMOK)
220			x = writeint(baseino);
221		if (x == SCMOK)
222			x = writeint(listonly);
223		if (x == SCMOK)
224			x = writeint(newonly);
225		if (x == SCMOK && protver >= 6)
226			x = writestring(release);
227		if (x == SCMOK)
228			x = writemend();
229	}
230	return (x);
231}
232
233int
234msgsetupack(void)
235{
236	if (isserver)
237		return (writemint(MSGSETUPACK, setupack));
238	return (readmint(MSGSETUPACK, &setupack));
239}
240/*
241 * crypt test message
242 */
243extern char *crypttest;		/* encryption test string */
244
245int
246msgcrypt(void)
247{
248	if (isserver)
249		return (readmstr(MSGCRYPT, &crypttest));
250	return (writemstr(MSGCRYPT, crypttest));
251}
252
253int
254msgcryptok(void)
255{
256	if (isserver)
257		return (writemnull(MSGCRYPTOK));
258	return (readmnull(MSGCRYPTOK));
259}
260/*
261 * login message
262 */
263extern char *logcrypt;		/* login encryption test */
264extern char *loguser;		/* login username */
265extern char *logpswd;		/* password for login */
266extern int logack;		/* login ack status */
267extern char *logerror;		/* error from login */
268
269int
270msglogin(void)
271{
272	int x;
273	if (isserver) {
274		x = readmsg(MSGLOGIN);
275		if (x == SCMOK)
276			x = readstring(&logcrypt);
277		if (x == SCMOK)
278			x = readstring(&loguser);
279		if (x == SCMOK)
280			x = readstring(&logpswd);
281		if (x == SCMOK)
282			x = readmend();
283	} else {
284		x = writemsg(MSGLOGIN);
285		if (x == SCMOK)
286			x = writestring(logcrypt);
287		if (x == SCMOK)
288			x = writestring(loguser);
289		if (x == SCMOK)
290			x = writestring(logpswd);
291		if (x == SCMOK)
292			x = writemend();
293	}
294	return (x);
295}
296
297int
298msglogack(void)
299{
300	int x;
301	if (isserver) {
302		x = writemsg(MSGLOGACK);
303		if (x == SCMOK)
304			x = writeint(logack);
305		if (x == SCMOK)
306			x = writestring(logerror);
307		if (x == SCMOK)
308			x = writemend();
309	} else {
310		x = readmsg(MSGLOGACK);
311		if (x == SCMOK)
312			x = readint(&logack);
313		if (x == SCMOK)
314			x = readstring(&logerror);
315		if (x == SCMOK)
316			x = readmend();
317	}
318	return (x);
319}
320/*
321 * refuse list message
322 */
323extern TREE *refuseT;		/* tree of files to refuse */
324
325static int
326/*ARGSUSED*/
327refuseone(TREE * t, void *v __unused)
328{
329	return (writestring(t->Tname));
330}
331
332int
333msgrefuse(void)
334{
335	int x;
336	if (isserver) {
337		char *name;
338		x = readmsg(MSGREFUSE);
339		if (x == SCMOK)
340			x = readstring(&name);
341		while (x == SCMOK) {
342			if (name == NULL)
343				break;
344			(void) Tinsert(&refuseT, name, FALSE);
345			free(name);
346			name = NULL;
347			x = readstring(&name);
348		}
349		if (x == SCMOK)
350			x = readmend();
351	} else {
352		x = writemsg(MSGREFUSE);
353		if (x == SCMOK)
354			x = Tprocess(refuseT, refuseone, NULL);
355		if (x == SCMOK)
356			x = writestring(NULL);
357		if (x == SCMOK)
358			x = writemend();
359	}
360	return (x);
361}
362/*
363 * list files message
364 */
365extern TREE *listT;		/* tree of files to list */
366extern time_t scantime;		/* time that collection was scanned */
367
368static int
369/*ARGSUSED*/
370listone(TREE * t, void *v __unused)
371{
372	int x;
373
374	x = writestring(t->Tname);
375	if (x == SCMOK)
376		x = writeint((int) t->Tmode);
377	if (x == SCMOK)
378		x = writeint((int) t->Tflags);
379	if (x == SCMOK)
380		x = writeint(t->Tmtime);
381	return (x);
382}
383
384int
385msglist(void)
386{
387	int x;
388	if (isserver) {
389		x = writemsg(MSGLIST);
390		if (x == SCMOK)
391			x = Tprocess(listT, listone, NULL);
392		if (x == SCMOK)
393			x = writestring(NULL);
394		if (x == SCMOK)
395			x = writeint((int) scantime);
396		if (x == SCMOK)
397			x = writemend();
398	} else {
399		char *name;
400		int mode, flags, mtime;
401		TREE *t;
402		x = readmsg(MSGLIST);
403		if (x == SCMOK)
404			x = readstring(&name);
405		while (x == SCMOK) {
406			if (name == NULL)
407				break;
408			x = readint(&mode);
409			if (x == SCMOK)
410				x = readint(&flags);
411			if (x == SCMOK)
412				x = readint(&mtime);
413			if (x != SCMOK)
414				break;
415			t = Tinsert(&listT, name, TRUE);
416			free(name);
417			t->Tmode = mode;
418			t->Tflags = flags;
419			t->Tmtime = mtime;
420			x = readstring(&name);
421		}
422		if (x == SCMOK)
423			x = readint((void *) &scantime);
424		if (x == SCMOK)
425			x = readmend();
426	}
427	return (x);
428}
429/*
430 * files needed message
431 */
432extern TREE *needT;		/* tree of files to need */
433
434static int
435/*ARGSUSED*/
436needone(TREE * t, void *v __unused)
437{
438	int x;
439	x = writestring(t->Tname);
440	if (x == SCMOK)
441		x = writeint((t->Tflags & FUPDATE) != 0);
442	return (x);
443}
444
445int
446msgneed(void)
447{
448	int x;
449	if (isserver) {
450		char *name;
451		int update;
452		TREE *t;
453		x = readmsg(MSGNEED);
454		if (x == SCMOK)
455			x = readstring(&name);
456		while (x == SCMOK) {
457			if (name == NULL)
458				break;
459			x = readint(&update);
460			if (x != SCMOK)
461				break;
462			t = Tinsert(&needT, name, TRUE);
463			free(name);
464			if (update)
465				t->Tflags |= FUPDATE;
466			x = readstring(&name);
467		}
468		if (x == SCMOK)
469			x = readmend();
470	} else {
471		x = writemsg(MSGNEED);
472		if (x == SCMOK)
473			x = Tprocess(needT, needone, NULL);
474		if (x == SCMOK)
475			x = writestring(NULL);
476		if (x == SCMOK)
477			x = writemend();
478	}
479	return (x);
480}
481/*
482 * files denied message
483 */
484extern TREE *denyT;		/* tree of files to deny */
485
486static int
487/*ARGSUSED*/
488denyone(TREE * t, void *v __unused)
489{
490	return (writestring(t->Tname));
491}
492
493int
494msgdeny(void)
495{
496	int x;
497	if (isserver) {
498		x = writemsg(MSGDENY);
499		if (x == SCMOK)
500			x = Tprocess(denyT, denyone, NULL);
501		if (x == SCMOK)
502			x = writestring(NULL);
503		if (x == SCMOK)
504			x = writemend();
505	} else {
506		char *name;
507		x = readmsg(MSGDENY);
508		if (x == SCMOK)
509			x = readstring(&name);
510		while (x == SCMOK) {
511			if (name == NULL)
512				break;
513			(void) Tinsert(&denyT, name, FALSE);
514			free(name);
515			name = NULL;
516			x = readstring(&name);
517		}
518		if (x == SCMOK)
519			x = readmend();
520	}
521	return (x);
522}
523/*
524 * send file message
525 */
526int
527msgsend(void)
528{
529	if (isserver)
530		return (readmnull(MSGSEND));
531	return (writemnull(MSGSEND));
532}
533/*
534 * receive file message
535 */
536extern TREE *upgradeT;		/* pointer to file being upgraded */
537
538static int
539/*ARGSUSED*/
540writeone(TREE * t, void *v __unused)
541{
542	return (writestring(t->Tname));
543}
544
545
546int
547msgrecv(int (*xferfile)(TREE *, va_list), ...)
548{
549	va_list args;
550	int x;
551	TREE *t = upgradeT;
552
553	va_start(args, xferfile);
554	if (isserver) {
555		x = writemsg(MSGRECV);
556		if (t == NULL) {
557			if (x == SCMOK)
558				x = writestring(NULL);
559			if (x == SCMOK)
560				x = writemend();
561			va_end(args);
562			return (x);
563		}
564		if (x == SCMOK)
565			x = writestring(t->Tname);
566		if (x == SCMOK)
567			x = writeint(t->Tmode);
568		if (t->Tmode == 0) {
569			if (x == SCMOK)
570				x = writemend();
571			va_end(args);
572			return (x);
573		}
574		if (x == SCMOK)
575			x = writeint(t->Tflags);
576		if (x == SCMOK)
577			x = writestring(t->Tuser);
578		if (x == SCMOK)
579			x = writestring(t->Tgroup);
580		if (x == SCMOK)
581			x = writeint(t->Tmtime);
582		if (x == SCMOK)
583			x = Tprocess(t->Tlink, writeone, NULL);
584		if (x == SCMOK)
585			x = writestring(NULL);
586		if (x == SCMOK)
587			x = Tprocess(t->Texec, writeone, NULL);
588		if (x == SCMOK)
589			x = writestring(NULL);
590		if (x == SCMOK)
591			x = (*xferfile) (t, args);
592		if (x == SCMOK)
593			x = writemend();
594	} else {
595		char *linkname, *execcmd;
596		if (t == NULL) {
597			va_end(args);
598			return (SCMERR);
599		}
600		x = readmsg(MSGRECV);
601		if (x == SCMOK)
602			x = readstring(&t->Tname);
603		if (x == SCMOK && t->Tname == NULL) {
604			x = readmend();
605			if (x == SCMOK)
606				x = (*xferfile) (NULL, args);
607			va_end(args);
608			return (x);
609		}
610		if (x == SCMOK)
611			x = readint(&t->Tmode);
612		if (t->Tmode == 0) {
613			x = readmend();
614			if (x == SCMOK)
615				x = (*xferfile) (t, args);
616			va_end(args);
617			return (x);
618		}
619		if (x == SCMOK)
620			x = readint(&t->Tflags);
621		if (x == SCMOK)
622			x = readstring(&t->Tuser);
623		if (x == SCMOK)
624			x = readstring(&t->Tgroup);
625		if (x == SCMOK)
626			x = readint(&t->Tmtime);
627		t->Tlink = NULL;
628		if (x == SCMOK)
629			x = readstring(&linkname);
630		while (x == SCMOK) {
631			if (linkname == NULL)
632				break;
633			(void) Tinsert(&t->Tlink, linkname, FALSE);
634			free(linkname);
635			linkname = NULL;
636			x = readstring(&linkname);
637		}
638		t->Texec = NULL;
639		if (x == SCMOK)
640			x = readstring(&execcmd);
641		while (x == SCMOK) {
642			if (execcmd == NULL)
643				break;
644			(void) Tinsert(&t->Texec, execcmd, FALSE);
645			free(execcmd);
646			execcmd = NULL;
647			x = readstring(&execcmd);
648		}
649		if (x == SCMOK)
650			x = (*xferfile) (t, args);
651		if (x == SCMOK)
652			x = readmend();
653	}
654	va_end(args);
655	return (x);
656}
657/*
658 * protocol done message
659 */
660extern int doneack;
661extern char *donereason;
662
663int
664msgdone(void)
665{
666	int x;
667
668	if (protver < 6) {
669		printf("Error, msgdone should not have been called.");
670		return (SCMERR);
671	}
672	if (isserver) {
673		x = readmsg(MSGDONE);
674		if (x == SCMOK)
675			x = readint(&doneack);
676		if (x == SCMOK)
677			x = readstring(&donereason);
678		if (x == SCMOK)
679			x = readmend();
680	} else {
681		x = writemsg(MSGDONE);
682		if (x == SCMOK)
683			x = writeint(doneack);
684		if (x == SCMOK)
685			x = writestring(donereason);
686		if (x == SCMOK)
687			x = writemend();
688	}
689	return (x);
690}
691/*
692 * go away message
693 */
694extern char *goawayreason;	/* reason for goaway */
695
696int
697msggoaway(void)
698{
699	return (writemstr(MSGGOAWAY, goawayreason));
700}
701/*
702 * cross-patch protocol message
703 */
704extern int xargc;		/* arg count for crosspatch */
705extern char **xargv;		/* arg array for crosspatch */
706
707int
708msgxpatch(void)
709{
710	int x;
711	int i;
712
713	if (isserver) {
714		x = readmsg(MSGXPATCH);
715		if (x != SCMOK)
716			return (x);
717		x = readint(&xargc);
718		if (x != SCMOK)
719			return (x);
720		xargc += 2;
721		xargv = (char **) calloc(sizeof(char *), (unsigned) xargc + 1);
722		if (xargv == NULL)
723			return (SCMERR);
724		for (i = 2; i < xargc; i++) {
725			x = readstring(&xargv[i]);
726			if (x != SCMOK)
727				return (x);
728		}
729		x = readmend();
730	} else {
731		x = writemsg(MSGXPATCH);
732		if (x != SCMOK)
733			return (x);
734		x = writeint(xargc);
735		if (x != SCMOK)
736			return (x);
737		for (i = 0; i < xargc; i++) {
738			x = writestring(xargv[i]);
739			if (x != SCMOK)
740				return (x);
741		}
742		x = writemend();
743	}
744	return (x);
745}
746/*
747 * Compression check protocol message
748 */
749extern int docompress;		/* Compress file before sending? */
750
751int
752msgcompress(void)
753{
754	if (isserver)
755		return (readmint(MSGCOMPRESS, &docompress));
756	return (writemint(MSGCOMPRESS, docompress));
757}
758