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