#include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/file.h> #include <sys/time.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> /* Code-submitter for Ubermud [eventually this should be replaced with an intelligent /load option in the client code, hint hint]. Marcus J. Ranum, 1990, with mods by Random. Use as: usubmit -l login -p password -f file other options: -h hostname -n port # -d defines (for cpp) */ #define USECPP #ifdef USECPP #ifndef DEFAULTCPP #define DEFAULTCPP "/lib/cpp -P" #endif char *preprocess_file(); #endif #ifndef DEFAULTHOST #define DEFAULTHOST "atreus.umiacs.umd.edu" #endif /* yes - this is a STRING - it gets interpreted later. */ #ifndef DEFAULTPORT #define DEFAULTPORT "6666" #endif /* size of the largest buffer we can send to a client */ #define MUDBUFSIZ 512 extern char *malloc(); extern char *getenv(); extern char *strcat(); extern char *mktemp(); extern void exit(); extern void bzero(); extern void bcopy(); extern void perror(); #ifdef DGUX extern struct in_addr inet_addr(); #else extern unsigned long inet_addr(); #endif int vflg = 1; /* run with some verbosity */ char defines[BUFSIZ]; static void sendto_server(fd,s) int fd; char *s; { int l = strlen(s); if(write(fd,s,l) != l) { if(vflg) (void)fprintf(stderr,"<<<cannot write to server>>>\n"); exit(1); } } main(ac,av) int ac; char *av[]; { static char *cmmsg = "@compile"; static char *prmsg = "@program"; static char *flmsg = "@flush"; static char *qmsg = "@quit"; int servfd; int infd; int sv; char *host; char *portp; char *login; char *pass; char *fil = NULL; char buf[MUDBUFSIZ]; int byts; /* look in the env. for starters */ if((host = getenv("UMUDHOST")) == NULL) host = ""; if((portp = getenv("UMUDPORT")) == NULL) portp = ""; if((login = getenv("UMUDLOGIN")) == NULL) login = ""; if((pass = getenv("UMUDPASS")) == NULL) pass = ""; strcpy(defines,""); /* I hate getopt() - so sue me */ for(byts = 1; byts < ac; byts++) { if(av[byts][0] == '-') { switch(av[byts][1]) { case 'f': /* file */ fil = av[byts + 1]; break; case 'h': /* hostname of mud is... */ host = av[byts + 1]; break; case 'l': /* login as... */ login = av[byts + 1]; break; case 'n': /* port # of mud is... */ portp = av[byts + 1]; break; case 'p': /* password as... */ pass = av[byts + 1]; break; case 'q': /* quiet down */ vflg = 0; break; case 'd': /* define passing */ strcat(defines," -D"); strcat(defines,av[byts + 1]); break; default: exit(usage()); } } } /* no file set */ if(fil == NULL) { (void)fprintf(stderr,"must provide the name of input file\n"); exit(1); } /* no password given */ if(pass == NULL) { (void)fprintf(stderr,"must provide a password\n"); exit(1); } else { char *junk; char *pp; pp = malloc(strlen(pass) + 1); if(pp == (char *)0) { perror("malloc"); exit(1); } (void)strcpy(pp,pass); for(junk = pass; *junk != '\0'; junk++) *junk = 'X'; pass = pp; } #ifdef USECPP if((fil = preprocess_file(fil)) == NULL) exit(1); #endif if((infd = open(fil,O_RDONLY,0600)) < 0) { perror(fil); exit(1); } /* no host set - accept the default. */ if(*host == '\0') host = DEFAULTHOST; /* no port set - accept the default. */ if(*portp == '\0') portp = DEFAULTPORT; /* connect */ if((servfd = connect_to(host,portp)) < 0) { if(vflg) (void)fprintf(stderr,"<<<connection failed>>>\n"); exit(1); } if(fork()) { /* reader */ while((byts = read(servfd,buf,MUDBUFSIZ - 1)) > 0) { buf[byts] = '\0'; (void)fprintf(stderr,"%s",buf); } (void)close(servfd); exit(0); } else { /* writer */ /* if a login/password was provided, try to use it */ if(*login != '\0' && *pass != '\0') { if(login_user(servfd,login,pass)) { (void)fprintf(stderr,"<<<login failed>>>\n"); exit(1); } } sendto_server(servfd,prmsg); sleep(1); sendto_server(servfd,flmsg); sleep(1); /* now we are ready to commence sending data to the server. */ while((byts = read(infd,buf,MUDBUFSIZ - 1)) > 0) { buf[byts] = '\0'; sendto_server(servfd,buf); } /* send compile directive */ sleep(4); if(vflg) (void)fprintf(stderr,"<<<compiling>>>\n"); sendto_server(servfd,cmmsg); sleep(1); /* send quit directive */ sendto_server(servfd,qmsg); (void)close(servfd); if(vflg) (void)fprintf(stderr,"<<<disconnecting>>>\n"); #ifdef USECPP (void)unlink(fil); #endif exit(0); } } int connect_to(host,portstr) char *host; char *portstr; { struct sockaddr_in sin; struct hostent *hp; int s; short port; char *p = host; if(p == 0 || *p == '\0') { (void)fprintf(stderr,"no host address provided\n"); return(-1); } /* here we try to make some sense of the host address we were given. if the string is all digits and dots, assume it is a 'dot' format address. otherwise, assume it is a named host. */ while(*p != '\0' && (*p == '.' || isdigit(*p))) p++; if(*p != '\0') { if((hp = gethostbyname(host)) == NULL) { (void)fprintf(stderr,"unknown host \"%s\"\n",host); return(-1); } (void)bcopy(hp->h_addr,(char *)&sin.sin_addr,hp->h_length); } else { #ifdef DGUX struct in_addr f; f = inet_addr(host); if(f.S_un.S_addr == -1L) { (void)fprintf(stderr,"bad host addr \"%s\"\n",host); return(-1); } (void)bcopy((char *)&f.S_un.S_addr,(char *)&sin.sin_addr,sizeof(f.S_un.S_addr)); #else unsigned long f; if((f = inet_addr(host)) == -1L) { (void)fprintf(stderr,"bad host addr \"%s\"\n",host); return(-1); } (void)bcopy((char *)&f,(char *)&sin.sin_addr,sizeof(f)); #endif } if(vflg) (void)fprintf(stderr,"<<<connecting to %s, port %s>>>\n",host,portstr); /* misc host connect setup */ port = htons(atoi(portstr)); sin.sin_port = port; sin.sin_family = AF_INET; /* open a socket */ if((s = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket"); return(-1); } /* hook it up */ if(connect(s,(struct sockaddr *)&sin,sizeof(sin)) < 0) { perror("connect"); return(-1); } if(vflg) (void)fprintf(stderr,"<<<connected>>>\n"); return(s); } usage() { (void)fprintf(stderr,"usage:: usubmit [options]\n"); (void)fprintf(stderr,"where options are:\n"); (void)fprintf(stderr,"\t-v\tenable verbose output\n"); (void)fprintf(stderr,"\t-h name\thost name to connect to\n"); (void)fprintf(stderr,"\t-n #\tport number to connect to\n"); (void)fprintf(stderr,"\t-l name\tlogin as name\n"); (void)fprintf(stderr,"\t-p password\tlogin with password\n"); (void)fprintf(stderr,"\t\t(must provide both)\n"); return(1); } login_user(fd,user,pass) int fd; char *user; char *pass; { int x; char buf[500]; *buf = '\0'; (void)strcat(buf,"\""); (void)strcat(buf,user); (void)strcat(buf,"\""); (void)strcat(buf," "); (void)strcat(buf,pass); if(vflg) (void)fprintf(stderr,"<<<attempting login %s>>>\n",buf); (void)strcat(buf,"\n"); sendto_server(fd,buf); sleep(1); return(0); } #ifdef USECPP /* run a file through the pre-processor and return 0 or the resulting file perforce, this is system specific! */ char * preprocess_file(f) char *f; { static char *tmpf = "/tmp/usubXXXXXX"; int sval; char cbuf[600]; if((tmpf = mktemp(tmpf)) == NULL) return(NULL); (void)strcpy(cbuf,DEFAULTCPP); if(*defines) (void)strcat(cbuf,defines); (void)strcat(cbuf," "); (void)strcat(cbuf,f); (void)strcat(cbuf," "); (void)strcat(cbuf,tmpf); if(vflg) (void)fprintf(stderr,"<<<calling preprocessor:%s>>>\n",cbuf); sval = system(cbuf); if(sval == 127) { (void)fprintf(stderr,"<<<system() - no shell>>>\n"); return(NULL); } if(sval != 0) { (void)fprintf(stderr,"<<<cpp returns non-zero>>>\n"); return(NULL); } return(tmpf); } #endif