static char sccsid
[] = "@(#)net.c 4.2 (Berkeley) %G%";
static char *net_sid
= "@(#)net.c 1.8";
/* must be setuid root */
net - -b -c cmd -f -i file -l name -mmach -n -o file -p passwd
-r file -s file -u uid -w -x -y -z command
- take from standard input
-b never send anything back
-c cmd think of this as a "cmd" *
-f force prompting of user name and password
-l name remote login name
-n do not write back anything, always mail them back
-o file remote stdout & stderr *
-q quiet option, send back only if rcode !=0 or if there is stdout
-r file local response file
-s file local stdin file *
(super users only, always skip login/passwd check:)
-u uid net queue files should be owned by uid (16 bits)
-w this is a write/mail response cmd *
-x this is being forwarded through us to another machine *
-y skip login/password check *
-z this is a response file being returned *
* = not documented in net(NEW)
w -w message to be written back
-x being forwarded through us
y -y simply skips login check (used by netlpr)
static char dfname
[]= DFNAME
;
char localin
[FNS
], skey
[30];
char buf
[BUFSIZ
], suid
[10];
char sin
=0, zopt
= 0, wopt
= 0, yopt
= 0, xopt
= 0;
long cnt
= 0L, maxfile
= MAXFILELARGE
;
FILE *file
, *temp
, *rfile
;
hd
.hd_scmdact
[0] = hd
.hd_srespfile
[0] = hd
.hd_soutfile
[0] = 0;
hd
.hd_sinfile
[0] = hd
.hd_scmdvirt
[0] = hd
.hd_sttyname
[0] = 0;
if(isatty(0)) strcat(hd
.hd_sttyname
,ttyname(0));
else if(isatty(2)) strcat(hd
.hd_sttyname
,ttyname(2));
if (signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
signal(SIGHUP
, outerror
);
if (signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
signal(SIGQUIT
, outerror
);
if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
signal(SIGINT
, outerror
);
if (signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
signal(SIGTERM
, outerror
);
while(argc
> 1 && argv
[1][0] == '-'){
fprintf(stderr
,"Unknown machine %s\n",buf
);
if(status
.mpasswd
[0] == 0)
strcpy(status
.mpasswd
,"\n\n");
addir(hd
.hd_srespfile
,buf
);
fprintf(stderr
,"Unknown option %s\n",argv
[0]);
strcat(hd
.hd_scmdact
,argv
[0]);
strcat(hd
.hd_scmdact
," ");
sargv
[1] = 0; /* so ps won't show passwd ??? */
hd
.hd_uidfrom
= uid
= getuid();
hd
.hd_gidfrom
= getgid();
if(zopt
|| wopt
|| yopt
|| xopt
|| suid
[0] != 0){
/* check z or w or y or x option permission */
/* check effective user id ?? */
if (uid
!= SUPERUSER
&& uid
!= NUID
) {
fprintf(stderr
, "Error: Not super-user\n");
fprintf(stderr
,"zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt
, wopt
, yopt
, xopt
, suid
);
fprintf(stderr
,"uid %d\n", uid
);
outerror(EX_UNAVAILABLE
);
hd
.hd_code
= zopt
? 's': 'w';
hd
.hd_code
= yopt
? 'y': hd
.hd_code
;
if (status
.mpasswd
[0] == 0) /* no passwd required */
strcpy(status
.mpasswd
, "\n");
debug("zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt
, wopt
, yopt
, xopt
, suid
);
strcpy( status
.jobno
, MAGICCRN
); /* default (invalid) crn */
strcpy( status
.jobno
, "XYZZ"); /* default (invalid) crn */
if(hd
.hd_code
== 'q' && !xopt
){
/* read passwd file, get status.localname & crn */
/* sets remote,status.login,status.force,status.mpasswd,
status.nonotify, status.nowrite */
/* may read passwd file if getenv(HOME) reads it */
if(status
.force
)status
.login
[0] = status
.mpasswd
[0] = 0;
/* look up login name and passwd in the environment */
envloginpasswd(remote
,status
.login
,status
.mpasswd
);
if(remote
== 0)remote
= getremote(local
);
fprintf(stderr
,"Request sent to local machine - doesn't make sense\n");
strcat(status
.defcmd
," ");
if(strlen(hd
.hd_scmdact
) == 0)strcpy(hd
.hd_scmdact
,status
.defcmd
);
hd
.hd_scmdact
[strlen(hd
.hd_scmdact
)-1] = 0;
mktemp(dfname
); /* make until unique!! */
} while(stat(dfname
,&statbuf
) >= 0);
/* determine through machine */
i
= gothru(local
,remote
);
if(s
!= 0)fprintf(stderr
,"No path to %s machine.\n",s
);
else fprintf(stderr
,"Unknown machine\n");
dfname
[strlen(dfname
)-11] = i
; /* set directory */
dfname
[strlen(dfname
)-7] = i
; /* set file (unused) */
/* check to see if data files are directories */
if(isdirectory(hd
.hd_srespfile
) || isdirectory(hd
.hd_sinfile
) || isdirectory(hd
.hd_soutfile
)){
fprintf(stderr
,"%s is a directory, must be a file\n",
isdirectory(hd
.hd_srespfile
) ? hd
.hd_srespfile
:
isdirectory(hd
.hd_sinfile
) ? hd
.hd_sinfile
:
if(suid
[0] != 0)uid
= atoi(suid
);
if(strcmp(hd
.hd_srespfile
,"/dev/tty") == 0){
fprintf(stderr
,"Can't have /dev/tty as response file.\n");
if(stat(hd
.hd_srespfile
,&statbuf
) == -1){
strcpy(buf
,hd
.hd_srespfile
);
while(*s
!= '/' && s
> &(buf
[0]))s
--;
if(strlen(buf
) == 0)strcpy(buf
,".");
if((rfile
=fopen(hd
.hd_srespfile
,"w")) == NULL
){
chmod(hd
.hd_srespfile
,0600);
mchown(hd
.hd_srespfile
,uid
,hd
.hd_gidfrom
);
else if(access(hd
.hd_srespfile
,2) == -1){
else if(getsize(&statbuf
) != 0L){
fprintf(stderr
,"%s must have 0-length or not exist\n",
/* go ahead and prompt for login name and passwd, if neccessary,
as long as the X option has not been specified */
if(hd
.hd_code
== 'q' && !xopt
)promptlogin(remote
);
/* at this point, we create the dfa... file */
file
= fopen(dfname
,"w");
mchown(dfname
,uid
,getgid());
if(status
.mpasswd
[0] == '\n')
if(status
.mpasswd
[0] == 0 && hd
.hd_code
== 'q' &&
strcmp(status
.login
,"network") != 0){
fprintf(stderr
,"Zero-length password not allowed\n");
if(hd
.hd_code
== 'q' && (streql(status
.login
,"root") == 0 ||
streql(status
.login
,"ruut") == 0)){
fprintf(stderr
,"Can't login as root through the network\n");
makeuukey(skey
,status
.login
,remote
);
nbsencrypt(status
.mpasswd
,skey
,hd
.hd_sencpasswd
);
if(hd
.hd_sttyname
[0] && status
.nowrite
== 0){
putmp
= getutmp(hd
.hd_sttyname
);
if(putmp
!= NULL
) hd
.hd_lttytime
= putmp
->ut_time
;
debug("p:%s:\n",status.mpasswd);
/* write the header info onto 'file' */
hd
.hd_mesgid
.msg_mch
= hd
.hd_mchfrom
= local
;
strcpy(hd
.hd_snto
,status
.login
);
strcpy(hd
.hd_snfrom
,status
.localname
);
strcpy(hd
.hd_spasswd
,status
.mpasswd
);
strcpy(hd
.hd_ijobno
, status
.jobno
);
hd
.hd_mesgid
.msg_ltime
= hd
.hd_ltimesent
= gettime();
hd
.hd_fquiet
= status
.quiet
;
hd
.hd_fnonotify
= status
.nonotify
;
hd
.hd_mesgid
.msg_pid
= getpid();
/* handle account pairs, accounts which do not require
a passwd if you are logged in on the same one here */
hd
.hd_facctpair
= fisacctpair(&hd
);
while((i
= fread(buf
,1,BUFSIZ
,stdin
)) > 0){
if(fwrite(buf
,1,i
,file
) != i
){
perror("net queue file");
if((cnt
+= i
) > maxfile
)goto toobig
;
if(access(localin
,4) == -1){
temp
= fopen(localin
,"r");
while((i
= fread(buf
,1,BUFSIZ
,temp
)) > 0){
if((cnt
+= i
) > maxfile
)goto toobig
;
if(fwrite(buf
,1,i
,file
) != i
){
perror("net queue file");
dfname
[strlen(dfname
)-9] = 'c';
file
= fopen(dfname
,"w");
mchown(dfname
,uid
,getgid());
fprintf(stderr
,"No more than %ld bytes can be sent\n",maxfile
);
outerror(EX_USAGE
); /* no return */
called if there is an error, makes sure that the files created
are deleted and the terminal is reset to echo
signal(SIGHUP
,SIG_IGN
); signal(SIGINT
,SIG_IGN
);
signal(SIGQUIT
,SIG_IGN
); signal(SIGTERM
,SIG_IGN
);
dfname
[i
] = (dfname
[i
] == 'c' ? 'd' : 'c');
*s
&= 0177; /* strip quote bites */
*s
++ ^= 040; /* invert upper-lower */
if(t
[0] == '/')strcpy(s
,t
);
/* returns true if phd is an account pair, false otherwise */
register struct header
*phd
;
/* these three routines gwd, cat, ckroot and
data structures x, y, off, do a pwd to string name */
if((file
= fopen("..","r")) == NULL
)break;
if(fread(&y
,1,sizeof y
,file
) != sizeof y
)break;
} while(y
.d_ino
!= x
.st_ino
);
if(stat(y
.d_name
,&x
) < 0)return;
if(chdir("/") < 0)return;
if((file
= fopen("/","r")) == NULL
)return;
if(fread(&y
,1,sizeof y
,file
) != sizeof y
)return;
if(y
.d_ino
== 0)continue;
if(stat(y
.d_name
,&x
) < 0)return;
} while(x
.st_dev
!=i
|| (x
.st_mode
&S_IFMT
)!=S_IFDIR
);
if(strcmp(y
.d_name
,".") != 0 && strcmp(y
.d_name
,"..") != 0)
while(--i
>= 0)name
[i
+ 1] = name
[i
];
register struct direct
*dp
;
if (x
.st_ino
== rino
&& x
.st_dev
== rdev
)
if ((file
= opendir("..")) == NULL
)
if (x
.st_dev
== xx
.st_dev
) {
if (x
.st_ino
== xx
.st_ino
)
if ((dp
= readdir(file
)) == NULL
)
while (dp
->d_ino
!= x
.st_ino
);
if ((dp
= readdir(file
)) == NULL
)
} while (xx
.st_ino
!= x
.st_ino
|| xx
.st_dev
!= x
.st_dev
);
blkcpy(dp
, &y
, DIRSIZ(dp
));
while (--i
>= 0) name
[i
+1] = name
[i
];
register char *name
; { /* return 1 to exit */
while(y
.d_name
[++i
] != 0);
if((off
+i
+2) > 511)return(1);
for(j
= off
+1; j
>= 0; --j
)name
[j
+i
+1] = name
[j
];
for(--i
; i
>= 0; --i
)name
[i
] = y
.d_name
[i
];
this function takes a file name and tells whether it is a
directory or on. Returns 1 if so, 0 otherwise.
null strings etc. return 0.
if(fn
== NULL
|| *fn
== 0)return(0);
if(strcmp(fn
,".") == 0)ret
= 1;
if(strcmp(fn
,"/") == 0)ret
= 1;
if(strcmp(fn
,"..") == 0)ret
= 1;
if(strcmp(fn
,"/.") == 0)ret
= 1;
if(strcmp(fn
+i
-2,"/.") == 0)ret
= 1;
if(strcmp(fn
+i
-3,"/..") == 0)ret
= 1;