home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
minnie.tuhs.org
/
unixen.tar
/
unixen
/
PDP-11
/
Distributions
/
ucb
/
spencer_2bsd.tar.gz
/
2bsd.tar
/
src
/
net
/
sub.c
< prev
Wrap
C/C++ Source or Header
|
1980-02-17
|
15KB
|
667 lines
/* Copyright (c) 1979 Regents of the University of California */
# include "defs.h"
# include "config.h"
char netcmd[] = NETCMD;
char resfile[]= RESFILE;
char senddir[] = SENDDIR;
char logfile[]= LOGFILE;
char Bsh[]= BINSH;
char mailcmd[]= MMAILCMD;
char writecmd[]= MWRITECMD;
int debugflg = DBV; /* debug flag */
int datasize = SIZE; /* best if mult of 512 */
char tokval[BFS];
FILE *cfile;
char vaxtovax = 0;
/*
speeds baud setting
300 7
1200 9
9600 13
*/
int linkspeed = LINKS;
char local = LOCAL;
struct tokstruct toktab[]= {
"machine", MACHINE,
"login", LOGIN,
"password", PASSWORD,
"notify", NOTIFY,
"command", COMMAND,
"yes", YES,
"y", YES,
"no", NO,
"n", NO,
"default", DEFAULT,
"write", WRITE,
"force", FORCE,
"local", LOCALTOK,
"speed", SPEED,
"link", LINK,
"vaxtovax", VAXTOVAX,
"length", LENGTH,
"debug", DEBUGTOK,
"time", ALTIME,
"count", ALCOUNT,
0, 0
};
passwdent(){
register char *u;
register struct passwd *pwd;
pwd = getpwuid(getuid());
if(pwd == NULL){
err("Bad uid\n");
return;
}
strcpy(status.localname,pwd->pw_name);
status.muid = guid(pwd->pw_uid,pwd->pw_gid);
status.mgid = pwd->pw_gid;
if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
else status.jobno = 32767;
strcpy(status.dir,pwd->pw_dir);
u = pwd->pw_shell;
if(u[0] == 0 || strcmp("sh",u+strlen(u)-2) != 0)u= Bsh;
strcpy(status.loginshell,u);
}
promptlogin(){
register char *p;
char buf[BFS];
FILE *wf;
int c;
struct sgttyb stt;
int oflag;
if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){
wf = fopen("/dev/tty","r");
if(wf != NULL){
if(status.login[0]==0 || status.force){
printf("Name (%s): ",status.localname);
if(fgets(buf, BFS, wf) != buf){
perror("fgets");
exit(1);
}
c = strlen(buf);
buf[c > 0 ? c-1 : 0] = 0;
if(c > 10){
err("Login name too long.\n");
exit(1);
}
if(member(buf,' ')){
err("Login names don't have blanks in them.\n");
exit(1);
}
if(buf[0] == 0)strcpy(buf,status.localname);
strcpy(status.login,buf);
}
if(strcmp(status.login,"network") != 0
&& (status.mpasswd[0]== 0 || status.force)){
sprintf(buf,"Password (%s):",status.login);
strcpy(status.mpasswd,getpass(buf));
}
fclose(wf);
}
}
if(status.login[0] == 0) strcpy(status.login,status.localname);
if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
status.force = 0;
}
/*
called in netdaemon and debugging software,
handles parameter lists to setup
remote machine and pipes
*/
setupdaemon(argc,argv)
char **argv; {
remote = argc > 1 ? lookup(argv[1]) : getremote(local);
if(argc == 4){ /* simulate using pipes */
readfd = atoi(argv[2]);
writefd = atoi(argv[3]);
pipesim++;
}
initdaemon();
}
setup(str)
char *str; {
struct sgttyb stt;
static char readbuf[BUFSIZ],writebuf[BUFSIZ];
if(str == 0 || str[0] == 0){
err("invalid net device\n");
exit(1);
}
masterseqno = 1;
readtty = pipesim ? fdopen(readfd,"r") : fopen(str,"r");
if(readtty == NULL){
perror(str);
exit(1);
}
writetty = pipesim ? fdopen(writefd,"w") : fopen(str,"w");
if(writetty == NULL){
perror(str);
exit(1);
}
if(!pipesim){
/* set exclusive use for line */
if(ioctl(fileno(readtty),TIOCEXCL,&stt) != 0 ||
gtty(fileno(readtty),&stt) < 0){
perror(str);
exit(1);
}
stt.sg_ispeed = stt.sg_ospeed = linkspeed; /* user-set baud */
stt.sg_erase = stt.sg_kill = 0; /* erase and kill off */
stt.sg_flags = ANYP; /* even and odd parity, off everything else */
if(stty(fileno(readtty),&stt) < 0){
perror(str);
exit(1);
}
}
setbuf(readtty,readbuf);
setbuf(writetty,writebuf);
}
/* passwords work as follows:
passwd = "\n" means no password
*/
/* table of netrc options
option default
------ -------
default default machine
login string current login
password string -
notify yes/no yes
write yes/no yes
command string -
force yes/no no
*/
/*
Fabry has suggested that machine names be more general:
that you be able to say:
cory: fabry on Cory
caf: caf on Cory
c: fabry on C
so the formulation would look like:
default key
key: machine login passwd ...
key: ....
and so on
Gould has suggested the format be:
pseudo cory real Cory login fabry
pseudo caf real Cory login caf
pseudo c real C login fabry
*/
/* init file format local C remote A
default A
machine A local C link /dev/net-A speed 9
machine Cory local C link /dev/net-Cory speed 9
if remote == 0, default is A
also options:
vaxtovax, length, debug
*/
initdaemon(){
long timev;
int timei;
cfile = fopen(INITFILE,"r");
getfile();
err("remote %c local %c link %s speed %d vtov %d length %d\n",
remote,local,device,linkspeed,vaxtovax,datasize);
err("debug %d time %d count %d\n",debugflg,atime,maxbread);
setup(device);
timev = gettime();
timei = timev >> 16;
srand(timei);
# ifdef VAX
if(machtype[local - 'a'] != M_VAX)
# endif
# ifdef CORY
if(machtype[local - 'a'] != M_CORY)
# endif
# ifdef CC
if(machtype[local -'a'] != M_CC && machtype[local - 'a'] != M_SRC)
# endif
err("Machine type disagrees with local machine\n");
}
commandfile(){
char *hdir, buf[BFS*2];
hdir = getenv("HOME");
if(hdir == 0)hdir = ".";
if(strcmp(hdir,"/") == 0)return;
sprintf(buf,"%s/.netrc",hdir);
/*
debug("file %s",buf);
*/
cfile = fopen(buf,"r");
getfile();
}
getfile(){
int t;
if(cfile == NULL)return;
if(fstat(fileno(cfile),&statbuf) < 0 || (statbuf.st_mode & 0444) == 0)
return;
while((t = token())){
switch(t){
case DEFAULT:
if(token() == ID && remote == 0)remote = lookup(tokval);
/*
debug("rem %c\n",remote);
*/
break;
case MACHINE:
if(remote == 0)remote = getremote(local);
if(token() != ID)continue;
if(remote != lookup(tokval))continue;
/* this is the entry for the remote mach we want */
getnetline();
goto out;
break;
}
}
out:
fclose(cfile);
return;
}
getnetline(){
int t;
while((t = token())){
switch(t){
case MACHINE: return;
case LOGIN:
if(token() && status.login[0] == 0)
strcpy(status.login,tokval);
break;
case PASSWORD:
if(fstat(fileno(cfile),&statbuf) >= 0
&& (statbuf.st_mode & 077) != 0){
err("Error - .netrc file not correct mode.\n");
err("Remove password or correct mode.\n");
exit(1);
}
if(token() && status.mpasswd[0] == 0)
strcpy(status.mpasswd,tokval);
/*
debug("mp:%s:%s\n",status.mpasswd,tokval);
*/
break;
case NOTIFY:
status.nonotify = token() == NO;
break;
case WRITE:
status.nowrite = token() == NO;
break;
case COMMAND:
if(status.defcmd[0] == 0 && token())
strcpy(status.defcmd,tokval);
break;
case FORCE:
status.force = token() == YES;
break;
case LOCALTOK:
if(token())local = lookup(tokval);
break;
case LINK:
if(token())strcpy(device,tokval);
break;
case SPEED:
if(token())linkspeed = atoi(tokval);
break;
case VAXTOVAX:
vaxtovax++;
break;
case LENGTH:
if(token())datasize = atoi(tokval);
break;
case DEBUGTOK:
debugflg++;
break;
case ALTIME:
if(token())atime = atoi(tokval);
break;
case ALCOUNT:
if(token())maxbread = atoi(tokval);
break;
default:
err("Unknown .netrc option %s\n",tokval);
break;
}
}
}
token(){ /* returns next token in cfile, 0 on EOF */
char *p;
int c;
if(feof(cfile))return(0);
while((c = getc(cfile)) != EOF && (c == '\n' || c == '\t'
|| c == ' ' || c == ','));
/* next char begins token */
if(c == EOF)return(0);
p = tokval;
if(c == '"'){ /* process quoted string */
while((c = getc(cfile)) != EOF && c != '"'){
if(c == '\\')c = getc(cfile);
*p++ = c;
}
}
else {
*p++ = c;
while((c = getc(cfile)) != EOF && c != '\n' && c != '\t'
&& c != ' ' && c != ','){
if(c == '\\')c = getc(cfile);
*p++ = c;
}
}
*p = 0;
if(tokval[0] == 0)return(0);
/*
debug("tok %s",tokval);
*/
return(tlookup(tokval));
}
tlookup(str)
char *str; {
struct tokstruct *p;
for(p = toktab; p->tokstr; p++)
if(streql(p->tokstr,str) == 0){
return(p->tval);
}
return(ID);
}
/* just like strcmp except upper- and lower-case are ignored */
streql(s1,s2)
char *s1, *s2; {
char a,b;
while(*s1 && *s2){
a = isupper(*s1) ? tolower(*s1) : *s1;
b = isupper(*s2) ? tolower(*s2) : *s2;
if(a < b)return(-1);
if(a > b)return(1);
s1++, s2++;
}
if(*s2)return(-1);
if(*s1)return(1);
return(0);
}
/* determine through machine */
gothru(from,to){
register int i;
switch(from){
case 'a': i = configA[to-'a']; break;
case 'b': i = configB[to-'a']; break;
case 'c': i = configC[to-'a']; break;
case 'd': i = configD[to-'a']; break;
case 'e': i = configE[to-'a']; break;
case 'i': i = configI[to-'a']; break;
case 'q': i = configQ[to-'a']; break;
case 's': i = configS[to-'a']; break;
case 'v': i = configV[to-'a']; break;
case 'y': i = configY[to-'a']; break;
default: i = 0; break;
}
return(i);
}
/* note the pointers to returned values */
harg(ans,pargc,pargv)
char *ans,*pargc,***pargv;{
if((*pargv)[0][2]) /* no space */
strcpy(ans,(*pargv)[0] + 2);
else { /* space, get next arg */
strcpy(ans,(*pargv)[1]);
(*pargc)--;
(*pargv)++;
}
}
static struct stat x;
static struct direct y;
static FILE *file;
static int off = -1;
/* these three routines gwd, cat, ckroot and
data structures x, y, off, do a pwd to string name */
gwd(name)
register char *name; {
*name = 0;
for(;;){
stat(".",&x);
if((file = fopen("..","r")) == NULL)break;
do {
if(fread(&y,1,sizeof y,file) != sizeof y)break;
} while(y.d_ino != x.st_ino);
fclose(file);
if(y.d_ino == ROOTINO){
ckroot(name);
break;
}
if(cat(name))break;
chdir("..");
}
chdir(name);
}
cat(name)
register char *name; { /* return 1 to exit */
register int i,j;
i = -1;
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];
off = i + off + 1;
name[i] = '/';
for(--i; i>= 0; --i)name[i] = y.d_name[i];
return(0);
}
ckroot(name)
char *name; {
register int i;
if(stat(y.d_name,&x) < 0)return;
i = x.st_dev;
if(chdir("/") < 0)return;
if((file = fopen("/","r")) == NULL)return;
do {
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)
if(cat(name))return;
i = strlen(name);
name[i+1] = 0;
while(--i >= 0)name[i + 1] = name[i];
name[0] = '/';
return;
}
/* prints out commands before executing them */
/*VARARGS0*/
mexecl(s)
char *s;{
int *p = (int *)&s;
register int i;
if(debugflg){
for(i=0; p[i]; i++)err("%s ",p[i]);
putc('\n',stderr);
}
execl(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],
p[12],p[13],p[14],p[15],0);
perror(p[0]);
}
/* prints out commands before executing them */
mexecv(s,p)
register char *s, **p;{
register int i;
if(debugflg){
err("%s ",s);
for(i=0; p[i]; i++)err("%s ",p[i]);
putc('\n',stderr);
}
execv(s,p);
perror("execv");
}
/*VARARGS0*/
/* fills in -l - -p from commands like rcp */
/* must be called with at least two arguments */
kexecl(s)
char *s; {
char *a[20], i = 2, j = 2;
char **p = (char **)&s;
a[0] = p[0];
a[1] = p[1];
if(status.login[0]){
a[i++] = "-l";
a[i++] = status.login;
}
if(status.mpasswd[0]){
a[i++] = "-p";
a[i++] = status.mpasswd;
}
if(status.nonotify)a[i++] = "-n";
if(status.force)a[i++] = "-f";
while(p[j])a[i++] = p[j++];
a[i] = 0;
mexecl(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],
a[12],a[13],a[14],a[15],0);
}
analyze(S,f)
char *S;
register struct fd *f; {
register char *file;
char work[FNS], *s, c0,c1,c2,c3;
s = work;
strcpy(s,S);
f->mach = local;
file = s;
if(member(s,':')){ /* name specified */
while(*s && *s != ':')s++;
*s = 0;
f->mach = lookup(file);
if(f->mach == 0){
err("Unknown machine %s",file);
exit(1);
}
while(*++s && *s == ':');
file = s;
}
else {
c0 = *s++;
c1 = *s++;
c2 = *s++;
c3 = *s++;
if(c0 == '/' && c1 != '/' && islower(c1))
if(c2 == '/')f->mach = 'y'; /* Cory name */
else if(c3 == '/')f->mach = c1; /* CC name */
}
f->fn = calloc(strlen(file)+1,1);
strcpy(f->fn,file);
}
/* returns a single character for machine S */
lookup(s)
register char *s; {
register struct tt *t;
if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
for(t = table; t->bigname; t++)
if(streql(s,t->bigname) == 0)return(t->lname);
return(0);
}
/* returns a long name (string) for single character machine c */
char *longname(c)
register char c;
{
register struct tt *t;
if(c == 0)return("UNKNOWN");
for(t = table; t->bigname; t++)
if(c == t->lname)return(t->bigname);
return("UNKNOWN");
}
/*VARARGS0*/
error(s,a,b,c,d,e,f,g,h)
char *s; {
char buf[10];
if(remote != 0) sprintf(buf,"%s",longname(remote));
else buf[0] = 0;
fflush(stdout);
if(debugflg){
fprintf(stderr,s,a,b,c,d,e,f,g,h);
putc('\n',stderr);
}
addtolog(remote,"Err %s: ",buf);
addtolog(remote,s,a,b,c,d,e,f,g,h);
addtolog(remote,"\n");
}
/*VARARGS0*/
debug(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t)
char *s; {
if(debugflg){
printf(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t);
putchar('\n');
}
}
member(s,c)
register char *s, c; {
while(*s)if(*s++ == c)return(1);
return(0);
}
/* this is really not right - we should use the rcslog format */
/* also, the user must be able to write on the
public logfile to get error messages such as
directory not found after he has
setuid'd from root
*/
/*VARARGS0*/
addtolog(mach,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
char *s;
{
static FILE *log = NULL;
logfile[strlen(logfile)-1] = mach;
if(log == NULL){
if(stat(logfile,&statbuf) < 0)return;
log = fopen(logfile,"a");
}
if(log == NULL)return;
fseek(log,0L,2);
fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
fflush(log);
}
/* return a static string with the form "X hrs X mins X secs" */
/* t is # of secs */
char *comptime(t)
long t; {
static char str[30];
char buf[20];
long w;
str[0] = 0;
w = t/3600L;
if(w > 0L){
sprintf(buf,"%ld hr ",w);
strcat(str,buf);
}
t = t % 3600L;
w = t/60L;
if(w > 0L){
sprintf(buf,"%ld min ",w);
strcat(str,buf);
}
t = t % 60L;
sprintf(buf,"%ld sec",t);
strcat(str,buf);
return(str);
}
/* VARARGS0 */
static err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
}