xref: /csrg-svn/old/berknet/net.c (revision 8191)
1*8191Smckusick static char sccsid[] = "@(#)net.c	4.1	(Berkeley)	09/12/82";
2*8191Smckusick 
3*8191Smckusick /* sccs id variable */
4*8191Smckusick static char *net_sid = "@(#)net.c	1.8";
5*8191Smckusick 
6*8191Smckusick # include "defs.h"
7*8191Smckusick /* must be setuid root */
8*8191Smckusick /*
9*8191Smckusick 	net - -b -c cmd -f -i file -l name -mmach -n -o file -p passwd
10*8191Smckusick 		-r file -s file -u uid -w -x -y -z command
11*8191Smckusick 
12*8191Smckusick 	-	take from standard input
13*8191Smckusick 	-b	never send anything back
14*8191Smckusick 	-c cmd	think of this as a "cmd" *
15*8191Smckusick 	-f	force prompting of user name and password
16*8191Smckusick 	-i file	remote stdin *
17*8191Smckusick 	-l name remote login name
18*8191Smckusick 	-m Mach	remote machine
19*8191Smckusick 	-n	do not write back anything, always mail them back
20*8191Smckusick 	-o file	remote stdout & stderr *
21*8191Smckusick 	-p pass remote password
22*8191Smckusick 	-q 	quiet option, send back only if rcode !=0 or if there is stdout
23*8191Smckusick 	-r file	local response file
24*8191Smckusick 	-s file	local stdin file *
25*8191Smckusick 
26*8191Smckusick 	(super users only, always skip login/passwd check:)
27*8191Smckusick 	-u uid	net queue files should be owned by uid (16 bits)
28*8191Smckusick 	-w	this is a write/mail response cmd *
29*8191Smckusick 	-x	this is being forwarded through us to another machine *
30*8191Smckusick 	-y	skip login/password check *
31*8191Smckusick 	-z	this is a response file being returned *
32*8191Smckusick 
33*8191Smckusick 	* = not documented in net(NEW)
34*8191Smckusick 
35*8191Smckusick */
36*8191Smckusick /*
37*8191Smckusick 	code	option	reason
38*8191Smckusick 	q		normal request
39*8191Smckusick 	w	-w	message to be written back
40*8191Smckusick 	 	-x	being forwarded through us
41*8191Smckusick 	y	-y	simply skips login check (used by netlpr)
42*8191Smckusick 	s	-z	normal response
43*8191Smckusick */
44*8191Smckusick /* global variables */
45*8191Smckusick struct userinfo status;
46*8191Smckusick 
47*8191Smckusick /* local variables */
48*8191Smckusick static char dfname[]=		DFNAME;
49*8191Smckusick 
50*8191Smckusick main(argc, argv)
51*8191Smckusick   char **argv; {
52*8191Smckusick 	register int i;
53*8191Smckusick 	int outerror(),uid;
54*8191Smckusick 	char localin[FNS], skey[30];
55*8191Smckusick 	char buf[BUFSIZ], suid[10];
56*8191Smckusick 	char sin =0, zopt = 0, wopt = 0, yopt = 0, xopt = 0;
57*8191Smckusick 	char *s,**sargv;
58*8191Smckusick 	long cnt = 0L, maxfile = MAXFILELARGE;
59*8191Smckusick 	FILE *file, *temp, *rfile;
60*8191Smckusick 	struct utmp *putmp;
61*8191Smckusick 	struct stat statbuf;
62*8191Smckusick 	struct header hd;
63*8191Smckusick 
64*8191Smckusick 	debugflg = DBV;
65*8191Smckusick 	hd.hd_scmdact[0] = hd.hd_srespfile[0] = hd.hd_soutfile[0] = 0;
66*8191Smckusick 	hd.hd_sinfile[0] = hd.hd_scmdvirt[0] = hd.hd_sttyname[0] = 0;
67*8191Smckusick 	localin[0] = 0;
68*8191Smckusick 	suid[0] = 0;
69*8191Smckusick 	sargv = argv;
70*8191Smckusick 
71*8191Smckusick 	if(isatty(0)) strcat(hd.hd_sttyname,ttyname(0));
72*8191Smckusick 	else if(isatty(2)) strcat(hd.hd_sttyname,ttyname(2));
73*8191Smckusick 	remote = 0;
74*8191Smckusick 	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
75*8191Smckusick 		signal(SIGHUP, outerror);
76*8191Smckusick 	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
77*8191Smckusick 		signal(SIGQUIT, outerror);
78*8191Smckusick 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
79*8191Smckusick 		signal(SIGINT, outerror);
80*8191Smckusick 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
81*8191Smckusick 		signal(SIGTERM, outerror);
82*8191Smckusick 
83*8191Smckusick 	while(argc > 1 && argv[1][0] == '-'){
84*8191Smckusick 		argc--; argv++;
85*8191Smckusick 		switch(argv[0][1]){
86*8191Smckusick 		case 0:
87*8191Smckusick 			sin++;
88*8191Smckusick 			break;
89*8191Smckusick 		case 'b':
90*8191Smckusick 			status.nonotify++;
91*8191Smckusick 			break;
92*8191Smckusick 		case 'c':
93*8191Smckusick 			harg(hd.hd_scmdvirt);
94*8191Smckusick 			break;
95*8191Smckusick 		case 'f':
96*8191Smckusick 			status.force++;
97*8191Smckusick 			break;
98*8191Smckusick 		case 'i':
99*8191Smckusick 			harg(hd.hd_sinfile);
100*8191Smckusick 			break;
101*8191Smckusick 		case 'l':
102*8191Smckusick 			harg(status.login);
103*8191Smckusick 			break;
104*8191Smckusick 		case 'm':
105*8191Smckusick 			harg(buf);
106*8191Smckusick 			remote = lookup(buf);
107*8191Smckusick 			if(remote == 0){
108*8191Smckusick 				fprintf(stderr,"Unknown machine %s\n",buf);
109*8191Smckusick 				exit(EX_NOHOST);
110*8191Smckusick 			}
111*8191Smckusick 			break;
112*8191Smckusick 		case 'n':
113*8191Smckusick 			status.nowrite++;
114*8191Smckusick 			break;
115*8191Smckusick 		case 'o':
116*8191Smckusick 			harg(hd.hd_soutfile);
117*8191Smckusick 			break;
118*8191Smckusick 		case 'p':
119*8191Smckusick 			harg(status.mpasswd);
120*8191Smckusick 			if(status.mpasswd[0] == 0)
121*8191Smckusick 			  	strcpy(status.mpasswd,"\n\n");
122*8191Smckusick 			break;
123*8191Smckusick 		case 'q':
124*8191Smckusick 			status.quiet++;
125*8191Smckusick 			break;
126*8191Smckusick 		case 'r':
127*8191Smckusick 			harg(buf);
128*8191Smckusick 			addir(hd.hd_srespfile,buf);
129*8191Smckusick 			break;
130*8191Smckusick 		case 's':
131*8191Smckusick 			harg(localin);
132*8191Smckusick 			break;
133*8191Smckusick 		case 'u':
134*8191Smckusick 			harg(suid);
135*8191Smckusick 			break;
136*8191Smckusick 		case 'w':
137*8191Smckusick 			wopt++;
138*8191Smckusick 			break;
139*8191Smckusick 		case 'x':
140*8191Smckusick 			xopt++;
141*8191Smckusick 			break;
142*8191Smckusick 		case 'y':
143*8191Smckusick 			yopt++;
144*8191Smckusick 			break;
145*8191Smckusick 		case 'z':
146*8191Smckusick 			zopt++;
147*8191Smckusick 			break;
148*8191Smckusick 		default:
149*8191Smckusick 			fprintf(stderr,"Unknown option %s\n",argv[0]);
150*8191Smckusick 			break;
151*8191Smckusick 		}
152*8191Smckusick 		}
153*8191Smckusick 	while(argc > 1){
154*8191Smckusick 		argc--; argv++;
155*8191Smckusick 		strcat(hd.hd_scmdact,argv[0]);
156*8191Smckusick 		strcat(hd.hd_scmdact," ");
157*8191Smckusick 		}
158*8191Smckusick 	sargv[1] = 0;		/* so ps won't show passwd ??? */
159*8191Smckusick 	hd.hd_uidfrom = uid = getuid();
160*8191Smckusick 	hd.hd_gidfrom = getgid();
161*8191Smckusick 	hd.hd_code = 'q';
162*8191Smckusick 	if(zopt || wopt || yopt || xopt || suid[0] != 0){
163*8191Smckusick 		/* check z or w or y or x option permission */
164*8191Smckusick # ifndef TESTING
165*8191Smckusick 		/* check effective user id ?? */
166*8191Smckusick 		if (uid != SUPERUSER && uid != NUID) {
167*8191Smckusick 			fprintf(stderr, "Error: Not super-user\n");
168*8191Smckusick 			fprintf(stderr,"zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt, wopt, yopt, xopt, suid);
169*8191Smckusick 			fprintf(stderr,"uid %d\n", uid);
170*8191Smckusick 			debugflg = 1;
171*8191Smckusick 			printhd(&hd);
172*8191Smckusick 			outerror(EX_UNAVAILABLE);
173*8191Smckusick 			}
174*8191Smckusick # endif
175*8191Smckusick 		hd.hd_code = zopt? 's': 'w';
176*8191Smckusick 		hd.hd_code = yopt? 'y': hd.hd_code;
177*8191Smckusick 		if (status.mpasswd[0] == 0)	/* no passwd required */
178*8191Smckusick 			strcpy(status.mpasswd, "\n");
179*8191Smckusick 		debug("zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt, wopt, yopt, xopt, suid);
180*8191Smckusick 		debug("uid %d\n", uid);
181*8191Smckusick 		if(xopt)
182*8191Smckusick 			setuid(SUPERUSER);
183*8191Smckusick 	}
184*8191Smckusick #ifdef CRN
185*8191Smckusick 	strcpy( status.jobno, MAGICCRN );	/* default (invalid) crn */
186*8191Smckusick #else
187*8191Smckusick 	strcpy( status.jobno, "XYZZ");		/* default (invalid) crn */
188*8191Smckusick #endif
189*8191Smckusick 
190*8191Smckusick 	if(hd.hd_code == 'q' && !xopt){
191*8191Smckusick 		/* read passwd file, get status.localname & crn */
192*8191Smckusick 		passwdent();
193*8191Smckusick 	}
194*8191Smckusick 
195*8191Smckusick 	/* sets remote,status.login,status.force,status.mpasswd,
196*8191Smckusick 		status.nonotify, status.nowrite */
197*8191Smckusick 	/* may read passwd file if getenv(HOME) reads it */
198*8191Smckusick 	commandfile();
199*8191Smckusick 	if(status.force)status.login[0] = status.mpasswd[0] = 0;
200*8191Smckusick 
201*8191Smckusick 	/* look up login name and passwd in the environment */
202*8191Smckusick 	envloginpasswd(remote,status.login,status.mpasswd);
203*8191Smckusick 
204*8191Smckusick 
205*8191Smckusick 	if(remote == 0)remote = getremote(local);
206*8191Smckusick # ifndef TESTING
207*8191Smckusick 	if(remote == local){
208*8191Smckusick 		fprintf(stderr,"Request sent to local machine - doesn't make sense\n");
209*8191Smckusick 		/* outerror(); */
210*8191Smckusick 		}
211*8191Smckusick # endif
212*8191Smckusick 	strcat(status.defcmd," ");
213*8191Smckusick 	if(strlen(hd.hd_scmdact) == 0)strcpy(hd.hd_scmdact,status.defcmd);
214*8191Smckusick 	hd.hd_scmdact[strlen(hd.hd_scmdact)-1] = 0;
215*8191Smckusick 	do {
216*8191Smckusick 		mktemp(dfname); /* make until unique!! */
217*8191Smckusick 	} while(stat(dfname,&statbuf) >= 0);
218*8191Smckusick 	/* determine through machine */
219*8191Smckusick 	i = gothru(local,remote);
220*8191Smckusick 	if(i == 0){
221*8191Smckusick 		s = longname(remote);
222*8191Smckusick 		if(s != 0)fprintf(stderr,"No path to %s machine.\n",s);
223*8191Smckusick 		else fprintf(stderr,"Unknown machine\n");
224*8191Smckusick 		outerror(EX_NOHOST);
225*8191Smckusick 		}
226*8191Smckusick 	dfname[strlen(dfname)-11] = i;		/* set directory */
227*8191Smckusick 	dfname[strlen(dfname)-7] = i;		/* set file (unused) */
228*8191Smckusick 	/* check to see if data files are directories */
229*8191Smckusick 	if(isdirectory(hd.hd_srespfile) || isdirectory(hd.hd_sinfile) || isdirectory(hd.hd_soutfile)){
230*8191Smckusick 		fprintf(stderr,"%s is a directory, must be a file\n",
231*8191Smckusick 			isdirectory(hd.hd_srespfile)    ? hd.hd_srespfile :
232*8191Smckusick 			isdirectory(hd.hd_sinfile)  ? hd.hd_sinfile :
233*8191Smckusick 			hd.hd_soutfile);
234*8191Smckusick 		outerror(EX_USAGE);
235*8191Smckusick 	}
236*8191Smckusick 	if(suid[0] != 0)uid = atoi(suid);
237*8191Smckusick 	if(hd.hd_srespfile[0]){
238*8191Smckusick 		if(strcmp(hd.hd_srespfile,"/dev/tty") == 0){
239*8191Smckusick 		fprintf(stderr,"Can't have /dev/tty as response file.\n");
240*8191Smckusick 			outerror(EX_USAGE);
241*8191Smckusick 			}
242*8191Smckusick 		if(stat(hd.hd_srespfile,&statbuf) == -1){
243*8191Smckusick 			strcpy(buf,hd.hd_srespfile);
244*8191Smckusick 			s = &buf[0];
245*8191Smckusick 			s = s + strlen(buf) - 1;
246*8191Smckusick 			while(*s != '/' && s > &(buf[0]))s--;
247*8191Smckusick 			*s = 0;
248*8191Smckusick 			debug("chkdir %s",buf);
249*8191Smckusick 			if(strlen(buf) == 0)strcpy(buf,".");
250*8191Smckusick 			if(access(buf,2) == -1){
251*8191Smckusick 				perror(buf);
252*8191Smckusick 				outerror(EX_USAGE);
253*8191Smckusick 				}
254*8191Smckusick 			if((rfile=fopen(hd.hd_srespfile,"w")) == NULL){
255*8191Smckusick 				perror(hd.hd_srespfile);
256*8191Smckusick 				outerror(EX_USAGE);
257*8191Smckusick 				}
258*8191Smckusick 			chmod(hd.hd_srespfile,0600);
259*8191Smckusick 			fclose(rfile);
260*8191Smckusick 			mchown(hd.hd_srespfile,uid,hd.hd_gidfrom);
261*8191Smckusick 			}
262*8191Smckusick 		else if(access(hd.hd_srespfile,2) == -1){
263*8191Smckusick 			perror(hd.hd_srespfile);
264*8191Smckusick 			outerror(EX_USAGE);
265*8191Smckusick 			}
266*8191Smckusick 		else if(getsize(&statbuf) != 0L){
267*8191Smckusick 			fprintf(stderr,"%s must have 0-length or not exist\n",
268*8191Smckusick 				hd.hd_srespfile);
269*8191Smckusick 			outerror(EX_USAGE);
270*8191Smckusick 		}
271*8191Smckusick 	}
272*8191Smckusick 	/* go ahead and prompt for login name and passwd, if neccessary,
273*8191Smckusick 	   as long as the X option has not been specified */
274*8191Smckusick 	if(hd.hd_code == 'q' && !xopt)promptlogin(remote);
275*8191Smckusick 
276*8191Smckusick 	/* at this point, we create the dfa... file */
277*8191Smckusick 	file = fopen(dfname,"w");
278*8191Smckusick 	if(file == NULL){
279*8191Smckusick 		perror(dfname);
280*8191Smckusick 		outerror(EX_OSERR);
281*8191Smckusick 		}
282*8191Smckusick 	chmod(dfname,0600);
283*8191Smckusick 	mchown(dfname,uid,getgid());
284*8191Smckusick 	if(xopt)goto stickit;
285*8191Smckusick 	if(status.mpasswd[0] == '\n')
286*8191Smckusick 		status.mpasswd[0] = 0;
287*8191Smckusick 	if(status.mpasswd[0] == 0 && hd.hd_code == 'q' &&
288*8191Smckusick 		strcmp(status.login,"network") != 0){
289*8191Smckusick 		fprintf(stderr,"Zero-length password not allowed\n");
290*8191Smckusick 		outerror(EX_USAGE);
291*8191Smckusick 		}
292*8191Smckusick 	if(hd.hd_code == 'q' && (streql(status.login,"root") == 0 ||
293*8191Smckusick 		streql(status.login,"ruut") == 0)){
294*8191Smckusick 		fprintf(stderr,"Can't login as root through the network\n");
295*8191Smckusick 		outerror(EX_USAGE);
296*8191Smckusick 		}
297*8191Smckusick 	makeuukey(skey,status.login,remote);
298*8191Smckusick 	nbsencrypt(status.mpasswd,skey,hd.hd_sencpasswd);
299*8191Smckusick 	enmask(status.mpasswd);
300*8191Smckusick 	hd.hd_lttytime = 0;
301*8191Smckusick 	if(hd.hd_sttyname[0] && status.nowrite == 0){
302*8191Smckusick 		putmp = getutmp(hd.hd_sttyname);
303*8191Smckusick 		if(putmp != NULL) hd.hd_lttytime = putmp->ut_time;
304*8191Smckusick 	}
305*8191Smckusick /*
306*8191Smckusick 	debug("p:%s:\n",status.mpasswd);
307*8191Smckusick */
308*8191Smckusick 	/* write the header info onto 'file' */
309*8191Smckusick 	hd.hd_mchto = remote;
310*8191Smckusick 	hd.hd_mesgid.msg_mch = hd.hd_mchfrom = local;
311*8191Smckusick 	hd.hd_vmajor = VMAJOR;
312*8191Smckusick 	hd.hd_vminor = VMINOR;
313*8191Smckusick 	strcpy(hd.hd_snto,status.login);
314*8191Smckusick 	strcpy(hd.hd_snfrom,status.localname);
315*8191Smckusick 	strcpy(hd.hd_spasswd,status.mpasswd);
316*8191Smckusick 	strcpy(hd.hd_ijobno, status.jobno );
317*8191Smckusick 	hd.hd_mesgid.msg_ltime = hd.hd_ltimesent = gettime();
318*8191Smckusick 	hd.hd_fquiet = status.quiet;
319*8191Smckusick 	hd.hd_fnonotify = status.nonotify;
320*8191Smckusick 	hd.hd_mesgid.msg_pid = getpid();
321*8191Smckusick 	hd.hd_fcompressed = 0;
322*8191Smckusick 	/* handle account pairs, accounts which do not require
323*8191Smckusick 	   a passwd if you are logged in on the same one here */
324*8191Smckusick 	hd.hd_facctpair = fisacctpair(&hd);
325*8191Smckusick 
326*8191Smckusick 	writehdfd(&hd,file);
327*8191Smckusick 	printhd(&hd);
328*8191Smckusick stickit:
329*8191Smckusick 	if(sin)
330*8191Smckusick 		while((i = fread(buf,1,BUFSIZ,stdin)) > 0){
331*8191Smckusick 			if(fwrite(buf,1,i,file) != i){
332*8191Smckusick 				perror("net queue file");
333*8191Smckusick 				outerror(EX_OSFILE);
334*8191Smckusick 				}
335*8191Smckusick 			if((cnt += i) > maxfile)goto toobig;
336*8191Smckusick 			if(feof(stdin))break;
337*8191Smckusick 			}
338*8191Smckusick 	else if(localin[0]){
339*8191Smckusick 		if(access(localin,4) == -1){
340*8191Smckusick 			perror(localin);
341*8191Smckusick 			outerror(EX_OSFILE);
342*8191Smckusick 			}
343*8191Smckusick 		temp = fopen(localin,"r");
344*8191Smckusick 		if(temp == NULL){
345*8191Smckusick 			perror(localin);
346*8191Smckusick 			outerror(EX_OSFILE);
347*8191Smckusick 			}
348*8191Smckusick 		while((i = fread(buf,1,BUFSIZ,temp)) > 0){
349*8191Smckusick 			if((cnt += i) > maxfile)goto toobig;
350*8191Smckusick 			if(fwrite(buf,1,i,file) != i){
351*8191Smckusick 				perror("net queue file");
352*8191Smckusick 				outerror(EX_OSFILE);
353*8191Smckusick 				}
354*8191Smckusick 			}
355*8191Smckusick 		fclose(temp);
356*8191Smckusick 		}
357*8191Smckusick 	fclose(file);
358*8191Smckusick 	chmod(dfname,0400);
359*8191Smckusick 	dfname[strlen(dfname)-9] = 'c';
360*8191Smckusick 	file = fopen(dfname,"w");
361*8191Smckusick 	chmod(dfname,0400);
362*8191Smckusick 	fclose(file);
363*8191Smckusick 	mchown(dfname,uid,getgid());
364*8191Smckusick 	exit(EX_OK);
365*8191Smckusick toobig:
366*8191Smckusick 	fprintf(stderr,"No more than %ld bytes can be sent\n",maxfile);
367*8191Smckusick 	outerror(EX_USAGE);		/* no return */
368*8191Smckusick 	}
369*8191Smckusick /*
370*8191Smckusick    called if there is an error, makes sure that the files created
371*8191Smckusick    are deleted and the terminal is reset to echo
372*8191Smckusick */
373*8191Smckusick outerror(ret){
374*8191Smckusick 	register int i;
375*8191Smckusick 	struct sgttyb stt;
376*8191Smckusick 	signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN);
377*8191Smckusick 	signal(SIGQUIT,SIG_IGN); signal(SIGTERM,SIG_IGN);
378*8191Smckusick 	unlink(dfname);
379*8191Smckusick 	i = strlen(dfname) - 9;
380*8191Smckusick 	dfname[i] = (dfname[i] == 'c' ? 'd' : 'c');
381*8191Smckusick 	unlink(dfname);
382*8191Smckusick 	if(gtty(0,&stt) >= 0){
383*8191Smckusick 		stt.sg_flags |= ECHO;
384*8191Smckusick 		stty(0,&stt);
385*8191Smckusick 		}
386*8191Smckusick 	exit(ret);
387*8191Smckusick 	}
388*8191Smckusick enmask(s)
389*8191Smckusick   register char *s; {
390*8191Smckusick 	while(*s){
391*8191Smckusick 		*s &= 0177;		/* strip quote bites */
392*8191Smckusick 		*s++ ^= 040;		/* invert upper-lower */
393*8191Smckusick 		}
394*8191Smckusick 	}
395*8191Smckusick addir(s,t)
396*8191Smckusick   register char *s, *t; {
397*8191Smckusick 	if(t[0] == '/')strcpy(s,t);
398*8191Smckusick 	else {
399*8191Smckusick 		gwd(s);
400*8191Smckusick 		strcat(s,t);
401*8191Smckusick 		}
402*8191Smckusick 	}
403*8191Smckusick 
404*8191Smckusick /* returns true if phd is an account pair, false otherwise */
405*8191Smckusick fisacctpair(phd)
406*8191Smckusick register struct header *phd;
407*8191Smckusick {
408*8191Smckusick 	return(0);
409*8191Smckusick }
410*8191Smckusick 
411*8191Smckusick 
412*8191Smckusick 
413*8191Smckusick static struct stat x;
414*8191Smckusick static struct direct y;
415*8191Smckusick static FILE *file;
416*8191Smckusick static int off = -1;
417*8191Smckusick 
418*8191Smckusick 
419*8191Smckusick /* these three routines gwd, cat, ckroot and
420*8191Smckusick    data structures x, y, off, do a pwd to string name */
421*8191Smckusick #ifdef V6
422*8191Smckusick gwd(name)
423*8191Smckusick   register char *name; {
424*8191Smckusick 	*name = 0;
425*8191Smckusick 	for(;;){
426*8191Smckusick 		stat(".",&x);
427*8191Smckusick 		if((file = fopen("..","r")) == NULL)break;
428*8191Smckusick 		do {
429*8191Smckusick 			if(fread(&y,1,sizeof y,file) != sizeof y)break;
430*8191Smckusick 			} while(y.d_ino != x.st_ino);
431*8191Smckusick 		fclose(file);
432*8191Smckusick 		if(y.d_ino == ROOTINO){
433*8191Smckusick 			ckroot(name);
434*8191Smckusick 			break;
435*8191Smckusick 			}
436*8191Smckusick 		if(cat(name))break;
437*8191Smckusick 		chdir("..");
438*8191Smckusick 		}
439*8191Smckusick 	chdir(name);
440*8191Smckusick 	}
441*8191Smckusick ckroot(name)
442*8191Smckusick   char *name; {
443*8191Smckusick 	register int i;
444*8191Smckusick 	if(stat(y.d_name,&x) < 0)return;
445*8191Smckusick 	i = x.st_dev;
446*8191Smckusick 	if(chdir("/") < 0)return;
447*8191Smckusick 	if((file = fopen("/","r")) == NULL)return;
448*8191Smckusick 	do {
449*8191Smckusick 		if(fread(&y,1,sizeof y,file) != sizeof y)return;
450*8191Smckusick 		if(y.d_ino == 0)continue;
451*8191Smckusick 		if(stat(y.d_name,&x) < 0)return;
452*8191Smckusick 		} while(x.st_dev!=i || (x.st_mode&S_IFMT)!=S_IFDIR);
453*8191Smckusick 	if(strcmp(y.d_name,".") != 0 && strcmp(y.d_name,"..") != 0)
454*8191Smckusick 		if(cat(name))return;
455*8191Smckusick 	i = strlen(name);
456*8191Smckusick 	name[i+1] = 0;
457*8191Smckusick 	while(--i >= 0)name[i + 1] = name[i];
458*8191Smckusick 	name[0] = '/';
459*8191Smckusick 	return;
460*8191Smckusick 	}
461*8191Smckusick #else
462*8191Smckusick static struct stat xx;
463*8191Smckusick 
464*8191Smckusick gwd(name)
465*8191Smckusick   register char *name;  {
466*8191Smckusick 	int rdev, rino;
467*8191Smckusick 	register int i;
468*8191Smckusick 
469*8191Smckusick 	*name = 0;
470*8191Smckusick 	stat("/", &x);
471*8191Smckusick 	rdev = x.st_dev;
472*8191Smckusick 	rino = x.st_ino;
473*8191Smckusick 	for (;;) {
474*8191Smckusick 		stat(".", &x);
475*8191Smckusick 		if (x.st_ino == rino && x.st_dev == rdev)
476*8191Smckusick 			break;
477*8191Smckusick 		if ((file = fopen("..", "r")) == NULL)
478*8191Smckusick 			break;
479*8191Smckusick 		fstat(fileno(file), &xx);
480*8191Smckusick 		chdir("..");
481*8191Smckusick 		if (x.st_dev == xx.st_dev) {
482*8191Smckusick 			if (x.st_ino == xx.st_ino)
483*8191Smckusick 				break;
484*8191Smckusick 			do
485*8191Smckusick 				if (fread((char *)&y, 1, sizeof y, file) != sizeof y)
486*8191Smckusick 					break;
487*8191Smckusick 			while (y.d_ino != x.st_ino);
488*8191Smckusick 		}
489*8191Smckusick 		else do {
490*8191Smckusick 			if (fread((char *)&y, 1, sizeof y, file) != sizeof y)
491*8191Smckusick 				break;
492*8191Smckusick 			stat(y.d_name, &xx);
493*8191Smckusick 		} while (xx.st_ino != x.st_ino || xx.st_dev != x.st_dev);
494*8191Smckusick 		fclose(file);
495*8191Smckusick 		if (cat(name))
496*8191Smckusick 			break;
497*8191Smckusick 	}
498*8191Smckusick 	i = strlen(name);
499*8191Smckusick 	name[i+1] = 0;
500*8191Smckusick 	while (--i >= 0) name[i+1] = name[i];
501*8191Smckusick 	name[0] = '/';
502*8191Smckusick }
503*8191Smckusick #endif
504*8191Smckusick 
505*8191Smckusick cat(name)
506*8191Smckusick   register char *name; {		/* return 1 to exit */
507*8191Smckusick 	register int i,j;
508*8191Smckusick 	i = -1;
509*8191Smckusick 	while(y.d_name[++i] != 0);
510*8191Smckusick 	if((off+i+2) > 511)return(1);
511*8191Smckusick 	for(j = off +1; j >= 0; --j)name[j+i+1] = name[j];
512*8191Smckusick 	off = i + off + 1;
513*8191Smckusick 	name[i] = '/';
514*8191Smckusick 	for(--i; i>= 0; --i)name[i] = y.d_name[i];
515*8191Smckusick 	return(0);
516*8191Smckusick 	}
517*8191Smckusick 
518*8191Smckusick 
519*8191Smckusick /*
520*8191Smckusick 	this function takes a file name and tells whether it is a
521*8191Smckusick 	directory or on. Returns 1 if so, 0 otherwise.
522*8191Smckusick 	null strings etc. return 0.
523*8191Smckusick */
524*8191Smckusick isdirectory(fn)
525*8191Smckusick 	char *fn;
526*8191Smckusick {
527*8191Smckusick 	int i,ret=0;
528*8191Smckusick 	if(fn == NULL || *fn == 0)return(0);
529*8191Smckusick 	i = strlen(fn);
530*8191Smckusick 	if(i == 1){
531*8191Smckusick 		if(strcmp(fn,".")       == 0)ret = 1;
532*8191Smckusick 		if(strcmp(fn,"/")       == 0)ret = 1;
533*8191Smckusick 	}
534*8191Smckusick 	else if(i == 2){
535*8191Smckusick 		if(strcmp(fn,"..")      == 0)ret = 1;
536*8191Smckusick 		if(strcmp(fn,"/.")      == 0)ret = 1;
537*8191Smckusick 	}
538*8191Smckusick 	else {
539*8191Smckusick 		if(strcmp(fn+i-2,"/.")  == 0)ret = 1;
540*8191Smckusick 		if(strcmp(fn+i-3,"/..") == 0)ret = 1;
541*8191Smckusick 	}
542*8191Smckusick 	return(ret);
543*8191Smckusick }
544