Newsgroups: comp.sources.unix From: bcr@physics.purdue.edu (Bill C. Riemers) Subject: v28i171: term-2.2.5 - SLIP-like functionality between two *IX hosts (REPOST), Part08/09 References: <1.784237938.15304@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: bcr@physics.purdue.edu (Bill C. Riemers) Posting-Number: Volume 28, Issue 171 Archive-Name: term-2.2.5/part08 #!/bin/sh # This is `part08' (part 8 of a multipart archive). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `term-2.2.5/termnet.c' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 8; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping term-2.2.5/termnet.c' else echo 'x - continuing file term-2.2.5/termnet.c' sed 's/^X//' << 'SHAR_EOF' >> 'term-2.2.5/termnet.c' && X (UDP_T_SENDIGNOREHDR))) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_USOCK local %d failed: %s", X client,command_result); X print_err(1); X } X X close(s); X X if (i < 0) return MAX_CLIENTS; X X if (term_localaddr == INADDR_ANY) get_term_localaddr(inet_addr("127.0.0.1")); X if ((i=send_command(Sock, C_UBIND, 1, "%d %d", client, 0)) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_UBIND failed: %s",command_result); X print_err(1); X }else if ((i=send_command(Sock, C_GETSOCKNAME, 1, "%d", client)) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_GETSOCKNAME failed: %s",command_result); X print_err(1); X }else if (!(addr_in=(struct sockaddr_in *)str_to_sockaddr(command_result, X htonl(term_localaddr)))) { X tmp_errno = ~0; X sprintf(term_error,"Can't translate socket address: %s",command_result); X print_err(1); X i = -1; X } X X if (i < 0) { X if (S >= 0) X term_close(S); X return MAX_CLIENTS; X } X X len = sizeof(udp_addr); X memcpy(&udp_addr, addr_in, len); X return store_sockinfo(S,client,&udp_addr); X} X Xvoid term_do_exit(void) { X int k; X for(k=0;k 0) term_close(k); X if (Sock >= 0) close(Sock); X Sock = -1; X return; X} X X/* This handles printing termnet errors after term returns. */ X Xchar *term_strerror(int errnum) { X char *s; X s=strerror(errnum); X if (! use_term || errnum != ~0) return s; X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X if (term_error[0]) return term_error; X return s; X} X X/* This handles printing termnet errors after term returns. */ X Xvoid term_perror(char *message) { X if (! use_term || errno != ~0) { X perror(message); X return; X } X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X errno = ~0; X if (! term_error[0]) { X perror(message); X return; X } X fprintf(stderr,"%s: %s\n",message,term_error); X} X X/* This is a lookup routine so I can return the remote peer name instead X * of the local name. X */ X Xint term_getpeername(int S, struct sockaddr *name, int *namelen){ X int i; X X if(! use_term) return getpeername(S,name,namelen); X X if(S<0) return -1; X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_getpeername"); X print_err(32768); X } X X for(i=0;isizeof(struct sockaddr_in)) ? sizeof(struct sockaddr_in) : *namelen; X /* Only open the connection once for a client! */ X if (Sock < 0) X if((Sock=socket_connect_server(-1,term_server)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term 4: %s", command_result); X print_err(1); X return getpeername(S,name,namelen); X } X if(send_command(Sock, C_GETPEERNAME, 0, "%d", sockinfo[i].client) < 0) { X tmp_errno = ~0; X sprintf(term_error, "C_GETPEERNAME: %s", command_result); X print_err(1); X return getpeername(S,name,namelen); X } X X if(name != NULL && namelen != NULL){ X *namelen = ( *namelen < sizeof(struct sockaddr) ) ? *namelen : sizeof(struct sockaddr); X memcpy(name,str_to_sockaddr(command_result,htonl(term_remoteaddr)), X *namelen); X remote_connect=1; X return 0; X } X } X if (use_term < 1) X return getpeername(S,name,namelen); X errno = ENOTCONN; X return -1; X} X X X/* This is a lookup routine so I can return the remote socket name instead X * of the local name. X */ X Xint term_getsockname(int S, struct sockaddr *name, int *namelen){ X int i,j = -1; X struct hostent *hp; X struct sockaddr_in *name_in; X X if(! use_term) return getsockname(S,name,namelen); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_getsockname"); X print_err(32768); X } X X if (use_term < 1) { X if ((j=getsockname(S,name,namelen)) < 0) return j; X } X if (S < 0) { X errno = EBADF; X return j; X } X X for(i=0;isin_family == AF_INET X && name_in->sin_addr.s_addr == INADDR_ANY ) { X char hostname[259]; X X#if defined(SYSV) && !defined(DYNIXPTX) X { struct utsname unam; X uname(&unam); X strcpy(hostname, unam.nodename); } X#else X gethostname (hostname, sizeof(hostname)); X#endif X if (isdigit(hostname[0])) { X name_in->sin_addr.s_addr = inet_addr(hostname); X }else if ((hp=host_lookup(hostname,0,AF_INET,0,NULL))) { X memcpy(&name_in->sin_addr, hp->h_addr, hp->h_length); X } X } X return j; X } X if (i == MAX_CLIENTS) return -1; X X if (sockinfo[i].sockport) { X if ((! name) || (! namelen)) return 0; X if (*namelen >= sizeof(struct sockaddr_in)) { X name_in->sin_family = AF_INET; X name_in->sin_addr.s_addr = htonl(term_remoteaddr); X name_in->sin_port = htons(sockinfo[i].sockport); X } X } X X /* Only open the connection once for a client! */ X if (Sock < 0) X if ((Sock=socket_connect_server(-1,term_server)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term 1: %s", command_result); X print_err(1); X return j; X } X if (send_command(Sock, C_GETSOCKNAME, 0, "%d", sockinfo[i].client) < 0) { X tmp_errno = ~0; X sprintf(term_error, "C_GETSOCKNAME: %d %d : %s", S, sockinfo[i].client, command_result); X print_err(1); X return j; X } X X X *namelen = (*namelen>sizeof(struct sockaddr)) ? X sizeof(struct sockaddr) : *namelen; X memcpy(name,str_to_sockaddr(command_result,htonl(term_remoteaddr)), X *namelen); X if(*namelen >= sizeof(struct sockaddr_in)) { X sockinfo[i].sockport = ntohs(name_in->sin_port); X } X X remote_connect=1; X return j; X} X X X/* For term gethostbyname() is executed on the remote machine when X * the connection is established. So here, I just list the hostname X * in a table. I list the index as 0.0.0.index. Since I doubt that X * 0.0.0.index is used by any host in the world as an IP # this should X * allow routines to work with and without term. (NOTE: This limits X * use to 255 term hosts listed in each program. If you access more X * than that, the original hostnames will be replaced.) X */ X Xstruct hostent *term_gethostbyname(char *host){ X static char hostname[259]; X static struct hostent *hp; X X if(! use_term) return host_lookup(host,0,AF_INET,0,NULL); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_gethostbyname"); X print_err(32768); X } X X if (host != NULL) X if (use_term < 1 && (hp=host_lookup(host,0,AF_INET,0,NULL))) X return hp; X X X /* Copy the passed-in name, to make sure it doesn't get munged */ X if (host != NULL){ X if ((hp=host_lookup(host,0,AF_INET,1,NULL))) return hp; X if(!strcmp(host,"127.0.0.254")) X hostname[0] = '\0'; X else X strncpy(hostname,host,256); X }else X hostname[0] = '\0'; X X /* Only open the connection once for a client! */ X if (Sock < 0) X if ((Sock = socket_connect_server(-1,term_server)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: %s %s", host, command_result); X print_err(1); X remote_connect = 0; X return NULL; X } X if (send_command(Sock, C_GETHOSTNAME, 0, "%s", hostname) < 0) { X tmp_errno = ~0; X sprintf(term_error, "C_GETHOSTNAME: %s", command_result); X print_err(1); X return NULL; X } X return host_lookup(host,0,AF_INET,1,str_to_hostent(command_result)); X} X Xstruct hostent *term_gethostbyaddr(char *addr, int len, int type){ X struct hostent *hs; X static char host[16]; X X if(! use_term || type != AF_INET) { X return host_lookup(addr,len,type,0,NULL); X } X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_gethostbyaddr"); X print_err(32768); X } X X if(use_term < 1 && (hs=host_lookup(addr, len, AF_INET,0,NULL))) X return hs; X X { X unsigned long int *j; X struct in_addr tmp; X memset(&tmp,0,sizeof(tmp)); X j = (unsigned long *)addr; X tmp.s_addr = *j; X strcpy(host,inet_ntoa(tmp)); X }; X X return term_gethostbyname(host); X} X Xint term_shutdown(int fd,int how){ X X if(! use_term) return shutdown(fd,how); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_shutdown"); X print_err(32768); X } X X close_fd(fd,how); X return shutdown(fd,how); X} X Xint term_close(int fd){ X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_close"); X print_err(32768); X } X X close_fd(fd,2); X return close(fd); X} X X X/* For term connections, this is needed because the program may either X * listen() or connect() after a bind(). X */ X Xint term_listen(int fd, int backlog){ X int k; X X if(! use_term) return listen(fd,backlog); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_listen"); X print_err(32768); X } X X if(fd < 0) return listen(fd,backlog); X X for(k=0;ksin_addr.s_addr != inet_addr("127.0.0.254") X && name_in->sin_addr.s_addr != htonl(term_remoteaddr)) { X j = bind(S, my_addr, addrlen); /* Try the address requested */ X tmperrno = errno; X errno = tmperrno; X if (j == -1 && tmperrno != EBADF) return j; X } X X /* Next check if this socket is also usable by term */ X X if (k == MAX_CLIENTS) return j; /* Since it is not available just return */ X X /* Now we redirect a remote port, so that the local socket is */ X /* bound both locally and remotely. */ X X iport=ntohs(name_in->sin_port); X X if ((s=Sock) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: Not connect to server"); X print_err(1); X errno = tmperrno; X return j; X } X X if ((i=send_command(s, C_UBIND, 0, "%d %d", X sockinfo[k].client, iport)) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_UBIND failed: %s %d %d",command_result, X sockinfo[k].client, iport); X print_err(1); X }else if ((i=getsockname(S,&addr,&len)) < 0) { X perror("getsockname()"); X }else if ((i=send_command(s, C_UDPSET, 1, "%d :%s", X sockinfo[k].client, sockaddr_to_str(&addr,0))) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: C_UDPSET failed: %s",command_result); X print_err(1); X } X X if (i < 0) { X errno = EACCES; X return -1; X }else return 0; X }else { X int iport,client = -1; X struct servent *service=NULL; X X name_in=(struct sockaddr_in *) my_addr; X if (S < 0 || name_in->sin_family != AF_INET X || (!remote_connect && !name_in->sin_port X && name_in->sin_addr.s_addr != htonl(term_remoteaddr) X && name_in->sin_addr.s_addr != inet_addr("127.0.0.254"))) X return bind(S,my_addr,addrlen); X X if ((iport=ntohs(name_in->sin_port))) { X service=getservbyport(iport,"tcp"); X if (service) X if ((service=getservbyname(service->s_name,"term"))) X iport=ntohs(service->s_port); X if (!service && !remote_connect && X name_in->sin_addr.s_addr != inet_addr("127.0.0.254") ) X return bind(S,my_addr,addrlen); X } X X if (Sock < 0) X if ((Sock=socket_connect_server(-1,term_server)) < 0) { X return bind(S,my_addr,addrlen); X } X X if ((s = duplicate_connect(S,Sock)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: %s", command_result); X print_err(1); X i = -1; X }else if ((i=send_command(s, C_STATS, 1, "%d", -6)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: C_STATS -6 failed: %s",command_result); X print_err(1); X }else{ X client=atoi(command_result); X if ((i=send_command(s,C_BIND,0,"%d %d",iport,0)) < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_BIND failed: %s",command_result); X print_err(1); X }else { X int port; X port = atoi(command_result); X if ((k=store_sockinfo(s, client, NULL)) < MAX_CLIENTS) { X sockinfo[k].sockport = port; X remote_connect=1; X } X } X } X X if(i<0){ X if(s >= 0) close(s); X return i; X } X return 0; X } X} X X X/* Finally for term connections, accept simply continues where X * bind left off. X */ X Xint term_accept(int pending, struct sockaddr *addr, int *addrlen){ X int j=MAX_CLIENTS,s = -1,i = -1; X char port[34]; X X if(! use_term) return accept(pending,addr,addrlen); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_accept"); X print_err(32768); X } X X if(pending>=0) X for(j=0;jsizeof(struct sockaddr)) ? sizeof(struct sockaddr) : *addrlen; X memcpy(addr,str_to_sockaddr(command_result,htonl(term_remoteaddr)), X *addrlen); X send_command(s, C_DUMB, 1, 0); X return s; X } X } X if (s >= 0) { X term_close(s); X } X return -1; X} X X Xint term_connect(int S, struct sockaddr *addr, int addrlen){ X int i = -1, k, s, client = -1, old=0; X struct sockaddr_in *addr_in; X char host[59],*ihost; X unsigned long j; X X if(! use_term) return connect(S,addr,addrlen); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_connect"); X print_err(32768); X } X X for(k=0;ksin_family != AF_INET) { X close_fd(S,2); X return connect(S,addr,addrlen); X } X X j = addr_in->sin_addr.s_addr; X ihost=(char *) &j; X X if (j == INADDR_ANY || j == inet_addr("127.0.0.254")) { X ihost = "\0"; X }else { X if (host_lookup(ihost,sizeof(unsigned long),addr_in->sin_family,0,NULL)) { X close_fd(S,2); X return connect(S,addr,addrlen); X } X#define UC(a) (unsigned char) ((a) & 0xff) X sprintf(host,"%u.%u.%u.%u",UC(ihost[0]),UC(ihost[1]),UC(ihost[2]),UC(ihost[3])); X ihost=host; X } X X if (k == MAX_CLIENTS) for(i=0;i= 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: Not connected to term"); X print_err(1); X } X }else if ((i=send_command(s, C_UDPSET, 0, "%d :%s", X client, sockaddr_to_str(addr,0))) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: C_UDPSET failed: %s",command_result); X print_err(1); X } X }else { X i = 0; X if (k == MAX_CLIENTS) { X if (Sock < 0) X if((Sock=socket_connect_server(-1,term_server)) < 0) X i = -1; X if (i >= 0) if ((i = duplicate_connect(S,Sock)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term 8: %s", command_result); X print_err(1); X }else if ((i=send_command(S, C_STATS, 1, "%d", -6)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: C_STATS -6 failed: %s",command_result); X print_err(1); X }else X client = atoi(command_result); X } else{ X client = sockinfo[k].client; X old = 1; X } X if (i >= 0) { X if (! *ihost) { X if ((i=send_command(S,C_PORT,0,"%d %d",ntohs(addr_in->sin_port), X old))< 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_PORT '%d' : %s",ntohs(addr_in->sin_port), X command_result); X print_err(1); X } X }else { X if ((i=send_command(S,C_PORT,0,"%s:%d",ihost,ntohs(addr_in->sin_port), X old))< 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_PORT '%s:%d' : %s",ihost,ntohs(addr_in->sin_port), X command_result); X print_err(1); X } X } X } X if (i < 0) { X term_close(S); X return -1; X }else if (i >= 0) { X send_command(S, C_DUMB, 1, 0); X store_sockinfo(S, client, NULL); X } X } X return ((i<0) ? connect(S,addr,addrlen) : 0); X} X X X/* term_gethostname() - get hostname of remote system, not local X * ytalk sends gethostbyname of the local hostname to talkd, X * so we give it the remote hostname X */ X Xint term_gethostname(char *name, size_t len) { X int len2; X struct hostent *hs=NULL; X X if(! use_term) return gethostname(name, len); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_gethostname"); X print_err(32768); X } X X if (! remote_connect) return gethostname(name, len); X X if ( remote_term_version < 20054) { X if (!(hs=term_gethostbyname(NULL))) { X return gethostname(name, len); X } X hs = str_to_hostent(command_result); X len2 = strlen(hs->h_name)+1; X }else { X len2 = strlen(term_remotehost) + 1; X } X X if (len2 > len) { X errno = EINVAL; X return -1; X } X X if (hs) X strncpy(name,hs->h_name,len2); X else X strncpy(name,term_remotehost,len2); X X return 0; X} X X X/* term_socket() X * Basically, we create a new client, C_USOCK both ends, C_UBIND the local end X * (to listen to the local program's sendto's) and C_GETPEERNAME the local UDP X * socket so term_sendto sends to the right place X */ X Xint term_socket( int domain, int type, int protocol) { X int s,i; X X if(! use_term) return socket(domain, type, protocol); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_socket"); X print_err(32768); X } X X /* If the same file descriptor was closed with fclose, then term */ X /* didn't know about it, so we take care of that now. */ X X if ((s = socket(domain,type,protocol)) < 0) return s; X X for(i=0;isin_addr.s_addr; X ihost=(char *) &j; X } X X if (k == MAX_CLIENTS) { X for(i=0;isin_family,0,NULL)) break; X ihost = NULL; X k=term_udpsocket(s); X break; X } X if (k == MAX_CLIENTS || k < 0) { X if (to && tolen) X return sendto(s, msg, len, flags, to, tolen); X else X return send(s, msg, len, flags); X } X } X X if (ihost && host_lookup(ihost,sizeof(long unsigned),AF_INET,0,NULL)) X return sendto(s, msg, len, flags, to, tolen); X X X if (alloced < (len+HEADER_SIZE)) { /* malloc it */ X if (! buff) X buff = (un_char *)malloc(sizeof(char)*(len+HEADER_SIZE+1)); /* +1 just to make sure... */ X else X buff = (un_char *)realloc(buff,sizeof(char)*(len+HEADER_SIZE+1)); X alloced = len + HEADER_SIZE + 1; X } X X memset(buff, 0, alloced); X X { X unsigned long int lhost; X unsigned short int lport; X if (to_addr != NULL && tolen) if (to_addr->sin_family == AF_INET) { X lhost = ntohl(to_addr->sin_addr.s_addr); X lport = ntohs(to_addr->sin_port); X buff[0] = (lhost>>24)&255; X buff[1] = (lhost>>16)&255; X buff[2] = (lhost>>8)&255; X buff[3] = lhost&255; X buff[4] = (lport>>8)&255; X buff[5] = lport&255; X } X to_addr = (struct sockaddr_in *)sockinfo[k].udp_addr; X } X memcpy(buff+HEADER_SIZE,msg,len); X X i = sendto(s, buff, len+HEADER_SIZE, flags, sockinfo[k].udp_addr, X sizeof(struct sockaddr)); X X return (i - HEADER_SIZE); X} X X/* This simulates rcmd(). locuser is ignored! Also term_error X * is piped with stdout. For term_error I send a closed pipe descriptor. This X * seems to keep "rsh" happy. (Otherwise you'll create lots of zombies.) X * So far I've only defined "shell", "cmd", "login", and "who". X * X * Programs that use rcmd() should be SUID root, so I take extra security X * measures here. X */ X Xint term_rcmd(char **ahost,unsigned short inport, char *locuser, X char *remuser, char *cmd, int *fd2p){ X int i = 0,s = -1; X char *rcommand, *term; X struct servent *sp; X X if(! use_term) return rcmd(ahost,inport,locuser,remuser,cmd,fd2p); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_rcmd"); X print_err(32768); X } X X/* If the host is listed by gethostbyname(), don't use term */ X X if (! geteuid() && *ahost) X if (strcmp(*ahost,"remotehost") && strcmp(*ahost,"127.0.0.254")) X if (use_term < 1 && host_lookup(*ahost,0,AF_INET,0,NULL)) X return rcmd(ahost,inport,locuser,remuser,cmd,fd2p); X X/* These values will need to be passed to the rd_exec function */ X X if (fd2p!=NULL) X *fd2p = -1; X X sp = getservbyport(inport,"tcp"); X if(!strcmp(sp->s_name,"shell")||!strcmp(sp->s_name,"cmd")){ X use_term_command(PRIVILEGED); X setuid(getuid()); X rcommand=(char *)cmd; X }else if(!strcmp(sp->s_name,"login")){ X use_term_command(PRIVILEGED); X setuid(getuid()); X rcommand=NULL; X }else if(!strcmp(sp->s_name,"who")){ X rcommand="rwho"; X }else{ X tmp_errno = ~0; X sprintf(term_error,"%s is not understood by term yet.",sp->s_name); X print_err(1); X return -1; X }; X X s = socket(AF_INET, SOCK_STREAM, 0); X if ((s = socket_connect_server(s,term_server)) <0) { X tmp_errno = ~0; X sprintf(term_error, "Term 6: %s", command_result); X print_err(1); X i = -1; X }else{ X /* Convert the "127.0.0.254 remotehost" alias */ X if (! *ahost || ! strcmp(*ahost,"remotehost") X || !strcmp(*ahost,"127.0.0.254") ) { X struct hostent *hs; X if (remote_term_version < 11714 ) { X *ahost = "127.0.0.1"; X }else if (send_command(s, C_GETHOSTNAME, 0, "%s","\0") < 0) { X tmp_errno = ~0; X sprintf(term_error, "C_GETHOSTNAME failed: %s", command_result); X print_err(1); X *ahost = "127.0.0.1"; X }else if ((hs = str_to_hostent(command_result))){ X *ahost = (char *) hs->h_name; X }; X /* If after all that work we still have "remotehost", just change it */ X /* We don't do this to begin with, because not everyone has listed */ X /* "localhost" in their .rhosts file & hosts.equiv file. */ X if ( !strcmp(*ahost,"127.0.0.254") X || !strcmp(*ahost,"remotehost") ) X *ahost = "127.0.0.1"; X } X term = getenv("TERM"); X if ( i >= 0 ) { X if ((i=send_command(s, C_STATS, 1, "%d", -6)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term: C_STATS -6 failed: %s",command_result); X print_err(1); X }else { X store_sockinfo(s, atoi(command_result),NULL); X if (! rcommand) { X if (! term) X i=send_command(s,C_EXEC,0,"rlogin %s -l %s", X *ahost,remuser); X else X i=send_command(s,C_EXEC,0,"-DTERM=%s%crlogin %s -l %s", X term,'\377',*ahost,remuser); X }else { X if (! term) X i=send_command(s,C_EXEC,0,"rsh %s -l %s %s", X *ahost,remuser,rcommand); X else X i=send_command(s,C_EXEC,0,"-DTERM=%s%crsh %s -l %s %s", X term,'\377',*ahost,remuser,rcommand); X }; X if (i < 0) { X tmp_errno = ~0; X sprintf(term_error,"Term: C_EXEC %s",command_result); X print_err(1); X term_close(s); X }else { X send_command(s, C_DUMB, 1, 0); X }; X }; X }; X }; X X if (i<0) { X if (s>=0) { X close(s); X s = -1; X } X }else if (fd2p!=NULL) { X int stat_pipe[2]; X if((pipe(stat_pipe))>=0){ /* open a pipe for passing the connect status */ X *fd2p=stat_pipe[0]; X close(stat_pipe[1]); X }; X }; X return s; X} X X/* Replacing exec calls is very tricky. But normally fork() is called before */ X/* exec, so this should patch most of the security problems. */ X Xint term_fork(void) { X X if(! use_term) return fork(); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_fork"); X print_err(32768); X } X X return fork(); X} X Xint term_chroot(char *path) { X X if(! use_term) return chroot(path); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_chroot"); X print_err(32768); X } X X if (Sock < 0) X if ((Sock=socket_connect_server(-1,term_server)) < 0) { X tmp_errno = ~0; X sprintf(term_error, "Term A: %s", command_result); X print_err(1); X } X return chroot(path); X} X Xint term_vfork(void) { X X if(! use_term) return vfork(); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_vfork"); X print_err(32768); X } X X return vfork(); X} X X/* term_recvfrom() X * X * recvfrom() replacement which correctly assigns the from-address X * to the remote site instead of localhost, and strip header. -danjo X */ X Xint term_recvfrom( int s, char *buff, int len, int flags, X struct sockaddr *from, int *fromlen) X{ X static un_char *mybuff = NULL; X static int alloced; X int avail, myfromlen, k, h; X struct sockaddr_in myfrom; X X if(! use_term) return recvfrom(s,buff,len,flags,from,fromlen); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_connect"); X print_err(32768); X } X X for(k=0;k len + HEADER_SIZE) X avail = len + HEADER_SIZE; X#endif X#endif X X if( alloced < avail) { /* not enough room, let's alloc more */ X if (! mybuff) { X mybuff = (un_char *)malloc(sizeof(char)*(avail+1)); /* +1 needed? */ X alloced = avail+1; X }else { X mybuff = (un_char *)realloc(mybuff,sizeof(char)*(avail+1)); X alloced = avail+1; X } X } X X h = HEADER_SIZE; X X avail=recvfrom(s,mybuff,avail,flags,(struct sockaddr *)&myfrom, X &myfromlen); X k=errno; X X if (avail < h) X h=0; X else if (fromlen != NULL && from != NULL && myfromlen) { X struct sockaddr_in *udp_in; X udp_in = (struct sockaddr_in *) sockinfo[k].udp_addr; X if (myfrom.sin_family != udp_in->sin_family X && myfrom.sin_addr.s_addr != udp_in->sin_addr.s_addr X && myfrom.sin_port != udp_in->sin_port) h=0; X } X X if (! h) { X if (avail >= 0) X memcpy(buff, mybuff,avail*sizeof(char)); X }else { X avail -= h; X if (fromlen != NULL && from != NULL) { X myfrom.sin_family = AF_INET; X myfrom.sin_addr.s_addr = X htonl((mybuff[0]<<24)+(mybuff[1]<<16)+(mybuff[2]<<8)+mybuff[3]); X myfrom.sin_port = htons((mybuff[4]<<8)+mybuff[5]); X X if (myfrom.sin_addr.s_addr == inet_addr("127.0.0.1") || X myfrom.sin_addr.s_addr == inet_addr("127.0.0.254") || X myfrom.sin_addr.s_addr == INADDR_ANY ) X myfrom.sin_addr.s_addr = htonl(term_remoteaddr); X } X memcpy(buff,mybuff+HEADER_SIZE,avail*sizeof(char)); X } X if (avail >= 0 && fromlen != NULL && from != NULL) { X *fromlen = (*fromlen > myfromlen) ? myfromlen : *fromlen; X memcpy(from,&myfrom,*fromlen * sizeof(char)); X } X X errno=k; X return avail; X} X X X/* term_recv() X * X * just call term_recvfrom ignoring the garbage -danjo X */ X Xint term_recv(int s, char *buf, int len, int flags) X{ X if(! use_term) return recv(s,buf,len,flags); X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X } X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_recvfrom"); X print_err(32768); X } X X return term_recvfrom(s,buf,len,flags,NULL,NULL); X} X X/* The following 3 functions all do the same thing, duplicate the X * sockinfo when the file descriptor gets duplicated. X */ X Xint term_dup(int oldfd) { X int k, newfd; X X if(! use_term) return dup(oldfd); X X if ((newfd = dup(oldfd)) < 0) return newfd; X X if (term_debug & 32768) { X tmp_errno = errno; X sprintf(term_error,"test term_dup"); X print_err(32768); X } X X if (remote_connect < 0) { X remote_connect=use_term_command(PUBLIC); X store_sockinfo(-1,-1,NULL); X }else { X for(k=0;k _sharnew.tmp echo 'x - extracting term-2.2.5/termnet.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/termnet.h' && X/* Replace normal networking commands */ X X#define accept term_accept X#define bind term_bind X#define chroot term_chroot X#define close term_close X#define connect term_connect X#define dup term_dup X#define dup2 term_dup2 X#define fcntl term_fcntl X#define fork term_fork X#define gethostbyname term_gethostbyname X#define gethostbyaddr term_gethostbyaddr X#define gethostname term_gethostname X#define getpeername term_getpeername X#define getsockname term_getsockname X#define listen term_listen X#define perror term_perror X#define rcmd term_rcmd X#define recv term_recv X#define recvfrom term_recvfrom X#define send term_send X#define sendto term_sendto X#define shutdown term_shutdown X#define socket term_socket X#define strerror term_strerror X#define vfork term_vfork X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/termnet.h' && chmod 0644 'term-2.2.5/termnet.h' || echo 'restore of term-2.2.5/termnet.h failed' shar_count="`wc -c < 'term-2.2.5/termnet.h'`" test 947 -eq "$shar_count" || echo "term-2.2.5/termnet.h: original size 947, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/termtest.1 ============== if test -f 'term-2.2.5/termtest.1' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/termtest.1 (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/termtest.1 (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/termtest.1' && X.TH TERMTEST 1 X.SH NAME Xtermtest \- debugging tool for X.IR term X.SH SYNOPSIS X.B "termtest " X[\-1 ] [\-2 ] [-local ] [--remote ] X[] X.SH DESCRIPTION XYou should perform two sets of tests before you ever try to run X.IR term Xitself. XThe X.IR termtest Xprogram lets you Xexercise X.IR term Xand its clients locally by starting two X.IR term Xdaemons on the same system. X.IR Termtest Xwhen run, establishes two connected instances of X.IR term Xon the local system so you may see if they and the clients work. XTo avoid problems with other programs also called 'termtest' you should Xrun X.IR termtest Xfrom the source directory of X.IR term Xby typing X.PP X\ \ \ setenv TERMMODE 0 X.PP X.PP X\ \ \ ./termtest \ \-n \ on X.PP X.IR Termtest Xopens the files 'local.log' and 'remote.log' in the local directory to Xrecord the stderr output of the two term daemons. XOptions on the command line of X.B termtest Xare passed on to both of them. XIf you need to debug you can use X.B \-d 64 Xor even X.B \-d 2112. XFamiliarity with the sources is essential if you use debugging. XThe termrc file is used to set the parameters of both daemons. XYou can specify a different term daemon (e.g. an old one that is Xalready installed on your system) as the 'remote' by giving the Xoption X.B \-2 program Xas the first option for test. Similarly, you can use a Xdifferent 'local' term daemon with the X.B \-1 Xoption. X.PP XOnce X.IR termtest Xis running you should be able to use the clients from any shell: X.PP X\ \ \ trsh X.PP Xgive you a 'remote' shell. You may need to type 'reset ^J' to reset Xthe tty of the new shell (that's Cntl-J). X.PP X\ \ \ trsh -s who X.PP Xwill run the who command 'remotely' to list the current users. X.PP X\ \ \ tupload -fvv ... /tmp X.PP Xwill copy the listed files into the /tmp directory and provide CPS statistics. X.PP X\ \ \ tredir 4000 23 X.PP Xwill map port 4000 to 23 and put itself in the background. Then, typing X.PP X\ \ \ telnet 0 4000 X.PP Xshould give you a login prompt that works. XIf you're running X, you should be able to use X.IR txconn Xto establish a new display (screen) that maps to the existing screen. X.PP XBe sure to run X.IR ./termtest Xon both the local and remote systems, Xparticularly if the systems use different architectures. X.SH BUGS X.SH SEE ALSO X.IR term (1), X.IR linecheck (1), X.IR term_setup (1), X.IR term_clients (1) X.SH AUTHOR XMichael O'Reilly, michael@iinet.com.au X.br XBill C. Riemers, bcr@physics.purdue.edu, is temporarily maintaining term. X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/termtest.1' && chmod 0644 'term-2.2.5/termtest.1' || echo 'restore of term-2.2.5/termtest.1 failed' shar_count="`wc -c < 'term-2.2.5/termtest.1'`" test 2506 -eq "$shar_count" || echo "term-2.2.5/termtest.1: original size 2506, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/termtest.c ============== if test -f 'term-2.2.5/termtest.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/termtest.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/termtest.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/termtest.c' && X/* test.c - start two connected term daemons for testing purposes X XThis program is for testing term. It starts two term daemons that are Xconnected. The "local" one listens on server (socket) name "" and Xwrites its output to "local.log". The "remote" one listens on server Xname "remote", is started with the -r switch and writes its output to X"remote.log". This means that clients started without special Xarguments connect to the "local" term daemon. X X"test" understands the following options: X-1 program - use "program"as the primary term daemon (default ./term) X-local option - use "option" for the primary term daemon X-2 program - use "option" as the secondary term daemon (default ./term) X-remote option - use "option" for the secondary term daemon X XAll other options will be given to both daemons. X XThis program prints the actual command lines that are started for both Xdaemons, then backgrounds itself. Killing either of its processes Xor using "tshutdown" kills all of them. */ X X#define I_ERRNO X#define I_IOCTL X#define I_SIGNAL X#include "includes.h" X Xint childa=0, childb=0; X Xstatic void killall(int i) { X kill(childa, SIGKILL); X kill(childb, SIGKILL); X exit(0); X} X Xint main(int argc, char *argv[]) { X int i,j, use_defaults=1; X int soc[2]; X char path[256]; X char *args[256]; X X S_Pipe(soc); X X if (!(childa = fork())) { X sprintf(path, "%s/.term/socket", getenv("HOME")); X unlink(path); X args[(j=0)] = "./term"; X args[++j] = "-s"; X args[++j] = "off"; X for (i = 1; i < argc; ++i) X if (!strcmp(argv[i],"-1")) { X args[0] = argv[++i]; X j = -i; X use_defaults = 0; X }else if (!strcmp(argv[i],"--local")) { X j--; X }else if (!strcmp(argv[i],"--remote")||!strcmp(argv[i],"-2")) { X i++; X j -= 2; X }else { X args[i+j] = argv[i]; X } X args[i+j] = NULL; X sleep(1); X dup2(soc[0], 0); X dup2(soc[0], 1); X i = open("local.log", O_RDWR | O_CREAT | O_TRUNC , 0666); X if (i < 0) { X perror("Open"); X exit(1); X } X dup2(i, 2); X fprintf(stderr,"Executing (%d): %s",getpid(),args[0]); X for (i=1;args[i] != NULL; ++i) fprintf(stderr," %s",args[i]); X fprintf(stderr,"\n"); X sleep(1); X execv(args[0], args); X perror("local execv failed"); X exit(1); X } X if (!(childb=fork())) { X sprintf(path, "%s/.term/sockettest", getenv("HOME")); X unlink(path); X args[(j=0)] = "./term"; X args[++j] = "-r"; X args[++j] = "-s"; X args[++j] = "off"; X for (i = 1; i < argc; ++i) X if (!strcmp(argv[i],"-2")) { X args[0] = argv[++i]; X j = -i; X use_defaults = 0; X }else if (!strcmp(argv[i],"--remote")) { X j--; X }else if (!strcmp(argv[i],"--local")||!strcmp(argv[i],"-1")) { X i++; X j -= 2; X }else { X args[i+j] = argv[i]; X } X if (use_defaults) args[i+(j++)] = "test"; X args[i+j] = NULL; X dup2(soc[1], 0); X dup2(soc[1], 1); X i = open("remote.log", O_RDWR | O_CREAT | O_TRUNC , 0666); X if (i < 0) { X perror("Open"); X exit(1); X } X dup2(i, 2); X fprintf(stderr,"Executing (%d): %s",getpid(),args[0]); X for (i=1;args[i] != NULL; ++i) fprintf(stderr," %s",args[i]); X fprintf(stderr,"\n"); X execv(args[0], args); X perror("remote execv failed"); X exit(1); X } X signal(SIGCHLD, killall); X signal(SIGTERM, killall); X signal(SIGHUP, killall); X signal(SIGQUIT, killall); X signal(SIGTERM, killall); X pause(); X exit(0); X } X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/termtest.c' && chmod 0644 'term-2.2.5/termtest.c' || echo 'restore of term-2.2.5/termtest.c failed' shar_count="`wc -c < 'term-2.2.5/termtest.c'`" test 3619 -eq "$shar_count" || echo "term-2.2.5/termtest.c: original size 3619, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/tmon.c ============== if test -f 'term-2.2.5/tmon.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/tmon.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/tmon.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/tmon.c' && X/* X>From hendrick@edmund.cs.andrews.edu Tue Dec 29 10:02:07 1992 XReturn-Path: XReceived: from edmund.cs.andrews.edu by tartarus.uwa.edu.au (5.65c/SMI-4.1) X id AA07713; Tue, 29 Dec 1992 10:02:02 +0800 XReceived: by edmund.cs.andrews.edu (5.57/Ultrix3.0-C) X id AA11714; Mon, 28 Dec 92 21:01:39 -0500 XFrom: hendrick@edmund.cs.andrews.edu (John Hendrickson) XMessage-Id: <9212290201.AA11714@edmund.cs.andrews.edu> XSubject: tmon XTo: oreillym XDate: Mon, 28 Dec 92 21:01:37 EST XX-Mailer: ELM [version 2.3 PL11] XStatus: O X*/ X X#define I_CTYPE X#define I_MEMORY X#define I_TIMES X#define I_TTY X#define I_TYPE X#define I_SIGNAL X#define I_SYS X#define I_STAT X#define I_PARAM X#include "includes.h" X#include "client.h" X X#ifndef HZ X#define HZ_ENV Xstatic int HZ=60; X#endif X Xstatic int termsrv; /* server */ X X#define NULLS ((char *)0) Xint LI, /* One less than screen length in termcap entry */ X CO; /* Screen width */ X X#ifdef ONE_CLIENT X# define main tmon X#else Xint term_debug = 0; X#endif X X Xstatic char tc[2048]; /* termcap buffer */ Xstatic char tbuf[128], PC, *CF, *CL, *CM, *CN, *SO, *SE; X Xchar *tgetstr (); Xchar *tgoto (); Xint tgetent (); Xint tgetnum (); Xchar *getenv (); Xvoid tputs(); X X#define Tgetstr(code) (char *)((s = (char *)tgetstr(code,&p)) ? s : "") X X/* initialize termcap stuff */ Xstatic void get_ttype() X{ X char *ttytype; X char *p = tbuf; X char *s; X X if ((ttytype = getenv("TERM")) == NULLS) { X printf ("TERM not set\n"); X exit(6); X } X if (tgetent(tc, ttytype) != 1) { X printf("Can't load %s", ttytype); X exit(7); X } X LI = tgetnum("li") - 1; X CO = tgetnum("co"); X if ((s=Tgetstr("pc")) == NULLS) X PC = '\0'; X else X PC = (char)*s; X X X CL = Tgetstr("cl"); /* clear screen */ X CM = Tgetstr("cm"); /* move cursor sequence */ X SE = Tgetstr("se"); /* standout mode off */ X SO = Tgetstr("so"); /* standout mode on */ X CF = Tgetstr("vi"); /* cursor off string */ X CN = Tgetstr("ve"); /* cursor on string */ X} X Xstatic void putchr ( c ) Xchar c; X{ X fputc ( c, stdout ); X} X Xstatic void cls() { tputs(CL,LI,putchr); } X Xstatic void cur_on() { tputs(CN,1,putchr); } X Xstatic void cur_off() { tputs(CF,1,putchr); } X Xstatic void ttgoto(row, col) Xint row, col; X{ X tputs(tgoto(CM, col, row),1,putchr); X} X Xstatic void drawline(row, col, len) Xint row, col, len; X{ X ttgoto(row, col); X fputc('+', stdout); X while (len--) X fputc('-', stdout); X fputc('+', stdout); X} X Xstatic void theend(int sig) { X ttgoto ( 24, 0 ); X fflush(stdout); X terminal_restore(0,0); X cur_on(); X exit(sig<0 ? 1 : 0); X} X Xstatic void STAT(int local, int st) { X if (send_command(termsrv, C_STATS, local, "%d",st)< 0) { X ttgoto(23,0); X printf("C_STATS command failed. Abort."); X theend(-1); X } X} X Xstatic void get_compression_stats(int ser, int pos) { X long lcomp; X long d1=0, d2=0; X STAT ( ser, -2 ); X sscanf ( command_result, "%ld %ld", &d1, &d2); X if (d1 != 0) X lcomp = ((d1 - d2) * 100) / d1; X else X lcomp = 0; X ttgoto ( 2, pos); X printf ( "%4ld %%", lcomp ); X} X Xstatic int get_buffer_stats( int ser, int pos ) { X unsigned d1=0, d2=0; X int i=4, count=0; X STAT (ser, -1); X while (command_result && *command_result) { X int k=0; X for (k=0;isspace(command_result[k]) && command_result[k];k++); X for (;!isspace(command_result[k]) && command_result[k];k++); X for (;isspace(command_result[k]) && command_result[k];k++); X for (;!isspace(command_result[k]) && command_result[k];k++); X for (;isspace(command_result[k]) && command_result[k];k++); X if (sscanf(command_result, "%u %u", &d1, &d2) < 2) break; X count++; X if (i == 20) { X printf ( "..." ); X }else if (i < 20) { X if (d2) { X ttgoto (i++, pos); X printf ( "%3u: %3u %3u", count, d1, d2 ); X } X if (! command_result[k]) break; X command_result = &command_result[k]; X } X } X return count; X} X Xint main(int argc, char *argv[]) X{ X struct timeval timeout; X int i, x, y, rhist[33],ahist[33],ihist[33],ohist[33]; X unsigned long last_recv=0, last_ack=0, last_in=0, last_out=0, d1, d2, d3, d4; X unsigned int scale=0, timer=5, window_size=0; X unsigned long packet_timeout; X unsigned int max_cps; X int stim, ttim; X fd_set reads; X char line[35]; X float dtim; X struct tms Tbuf; X X timeout.tv_sec = 0; X timeout.tv_usec = 0; X X#ifdef HZ_ENV X { X char *hz = getenv ("HZ"); X if (hz) X HZ = atoi(hz); X } X#endif X /* set_nonblock(0); */ X priority = 3; X client_options(argc, argv,"",NULL); X X get_ttype (); X termsrv = connect_server(term_server); X terminal_save(0); X signal(SIGHUP, theend); X signal(SIGINT, theend); X signal(SIGQUIT, theend); X signal(SIGTERM, theend); X signal(SIGPIPE, theend); X terminal_raw(0); X cur_off(); X STAT ( 1, -5); X X sscanf(command_result,"%u %d %lu",&max_cps,&window_size,&packet_timeout); X scale = max_cps + 10; X X STAT ( 1, -3); X sscanf ( command_result, "%lu %lu %lu %lu", &last_recv, &last_ack, X &last_in, &last_out ); X stim=times(&Tbuf); X /* STAT ( 1, -8); */ X /* cooked_out = atoi(command_result); */ X X memset ( line, 0, sizeof (line) ); X memset ( rhist, 0, sizeof (rhist) ); X memset ( ahist, 0, sizeof (ahist) ); X memset ( ihist, 0, sizeof (ihist) ); X memset ( ohist, 0, sizeof (ohist) ); X X cls (); X printf ( "TERM link monitor" ); X X ttgoto ( 2, 1 ); X printf ( "local %s", str_version(VERSION)); X ttgoto ( 2, 41); X printf ( "remote %s", str_version(remote_term_version)); X X for (i=3;i<22;i++){ ttgoto(i,1); putchr('|'); } X for (i=3;i<22;i++){ ttgoto(i,41); putchr('|'); } X for (i=3;i<22;i++){ ttgoto(i,35); putchr('|'); } X for (i=3;i<22;i++){ ttgoto(i,75); putchr('|'); } X drawline ( 3,1,33 ); X drawline ( 3,41,33 ); X drawline ( 21,1,33 ); X drawline ( 21,41,33 ); X X while ( 1 ) X { X get_compression_stats(1, 30); X get_compression_stats(0, 70); X X STAT ( 1, -5); X sscanf(command_result,"%u %d %lu",&max_cps,&window_size,&packet_timeout); X ttgoto ( 0, 28 ); X printf ( "SCALE :%6u (cps)", scale-10); X ttgoto ( 0, 56 ); X printf ( "window : %4u", window_size); X ttgoto ( 1, 56 ); X printf ( "timeout: %4lu", packet_timeout); X X STAT ( 1, -3); X sscanf ( command_result, "%lu %lu %lu %lu", &d1, &d2, &d3, &d4); X X for (i=1;i<33;i++) { X rhist[i-1]=rhist[i]; X ahist[i-1]=ahist[i]; X ihist[i-1]=ihist[i]; X ohist[i-1]=ohist[i]; X } X ttim=times(&Tbuf); X dtim=((float)(ttim-stim) * HZ ) / 10000.0; X stim=ttim; X X ttgoto(2, 60); X X if (! last_recv) last_recv=d1; X if (! last_ack) last_ack=d2; X if (! last_in) last_in=d3; X if (! last_out) last_out=d4; X rhist[32]=(d1-last_recv)/dtim; X ahist[32]=(d2-last_ack)/dtim; X ihist[32]=(d3-last_in)/dtim; X ohist[32]=(d4-last_out)/dtim; X if(ihist[32]>scale) scale = ihist[32]+112; X if(ohist[32]>scale) scale = ohist[32]+112; X i=scale/18; X for (y=20;y>3;y--) { X for (x=0;x<33;x++) { X if ( rhist[x] > i ) X line[x]='#'; X else if ( ihist[x] > i ) X line[x]='.'; X else X line[x]=' '; X } X ttgoto(y,2); X printf ( "%s", line ); X i += (scale/18); X } X X i=scale/18; X for (y=20;y>3;y--) { X for (x=0;x<33;x++) X if ( ahist[x] > i ) X line[x]='#'; X else if ( ohist[x] > i ) X line[x]='.'; X else X line[x]=' '; X ttgoto(y,42); X printf ( "%s", line ); X i += (scale/18); X } X X ttgoto ( 22, 1 ); X printf ( "Incoming: %6lu (cps) %9lu k",(unsigned long)((d1-last_recv)/dtim),d1/1024); X ttgoto ( 22, 41 ); X printf ( "Outgoing: %6lu (cps) %9lu k\n",(unsigned long)((d2-last_ack)/dtim),d2/1024); X last_recv=d1;last_ack=d2;last_in=d3;last_out=d4; X X i = get_buffer_stats(1, 3); X ttgoto (1,1); X printf("Local: %u",i); X i = get_buffer_stats(0, 43); X ttgoto (1,41); X printf("Remote: %u",i); X X ttgoto(24, 0); X fflush(stdout); X while (1) { X timeout.tv_sec = timer; X timeout.tv_usec = 0; X FD_ZERO ( &reads ); X FD_SET ( 0, &reads ); X select ( 1, &reads, 0, 0, &timeout); X if ( FD_ISSET ( 0, &reads ) ) { X read(0, line, 1); X if ((tolower(*line) == 'q')||(*line == '\003')) X theend(0); X } X else break; X } X } X} X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/tmon.c' && chmod 0644 'term-2.2.5/tmon.c' || echo 'restore of term-2.2.5/tmon.c failed' shar_count="`wc -c < 'term-2.2.5/tmon.c'`" test 8032 -eq "$shar_count" || echo "term-2.2.5/tmon.c: original size 8032, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/trdate.c ============== if test -f 'term-2.2.5/trdate.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/trdate.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/trdate.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/trdate.c' && X/* X * trdate/trdated X * X * A term client to set the local time to the remote time. X * Can be run once as trdate or as a daemon trdated X * X * (C) 1994 Kevin Lentin (kevinl@cs.monash.edu.au) X * X */ X X#define I_ERRNO X#define I_SYS X#define I_STRING X#include "includes.h" X X#include "client.h" X X#define STAT(local, st) \ X if (send_command(s, C_STATS, local, "%d",st)< 0) { \ X fprintf(stderr,"C_STATS command failed. Abort.\n"); \ X exit(1); \ X } X X#define VERBOSE if(verbose)printf X Xlong delay = 300; X Xstatic int local_options ( char opt, char *term_optarg ) X{ X switch(opt) X { X case 'd' : X printf("optarg=%s\n", term_optarg); X delay = atoi(term_optarg); X if (delay < 10) { X fprintf(stderr, "Minimum delay is 10 seconds\n"); X return -1; X } X VERBOSE("Delay set to %ld seconds\n", delay); X break; X default: X return -1; X } X return 0; X} X X#ifdef ONE_CLIENT X# define main trdate X#endif Xint main(int argc, char *argv[]) X{ X int s; X int first; X int daemon = 0; X struct timeval t1,t2,t; X long diff; X long sec, usec; X char args[10]; X X strcpy(args,"v"); X if (argv[0][strlen(argv[0])-1] == 'd') { X daemon = 1; X strcat(args,"d:"); X } X X priority = 10; /* We want immediate results */ X first = client_options(argc,argv,args, local_options); X if (first == -1 || first > argc) X exit (1); X setbuf(stderr, 0); X X while (1) { X if ((s = socket_connect_server(-1,term_server)) <0) X { X /* Move above later */ X if (daemon) { X sleep(delay); X continue; /* Continues the while */ X } X fprintf(stderr,"Term: %s\n",command_result); X close(s); X exit(1); X } X gettime(&t1); X VERBOSE("Our time is: %ld %ld\n", (long)t1.tv_sec, X (long)t1.tv_usec); X STAT(0,-9); X VERBOSE("Got result:%s:\n", command_result); X sscanf(command_result, "%ld %ld", &sec, &usec); X t.tv_sec = sec; X t.tv_usec = usec; X gettime(&t2); X VERBOSE("Our time is: %ld %ld\n", (long)t2.tv_sec, X (long)t2.tv_usec); X diff = (t2.tv_sec - t1.tv_sec) * 1000000 + t2.tv_usec - t1.tv_usec; X VERBOSE("Diff = %ld\n", diff); X t.tv_usec += diff; X t.tv_sec += (t.tv_usec / 1000000); X t.tv_usec %= 1000000; X X VERBOSE("Setting time to: %ld %ld\n", (long)t.tv_sec, X (long)t.tv_usec); X settime(&t); X X close(s); X if (!daemon) X break; X sleep(delay); X } X exit(0); X} SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/trdate.c' && chmod 0644 'term-2.2.5/trdate.c' || echo 'restore of term-2.2.5/trdate.c failed' shar_count="`wc -c < 'term-2.2.5/trdate.c'`" test 2253 -eq "$shar_count" || echo "term-2.2.5/trdate.c: original size 2253, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/trshell.c ============== if test -f 'term-2.2.5/trshell.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/trshell.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/trshell.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/trshell.c' && X/* X * A client for term. X */ X#define I_SYS X#define I_IOCTL X#define I_TTY X#define I_SIGNAL X#include "includes.h" X#include "client.h" X X#ifdef ONE_CLIENT X# define main trsh X#else Xint term_debug = 0; X#endif X Xint term_client_number = -1; Xint s; Xint simple = 0; X Xchar * pathtail(char*); X Xstatic int local_options ( char opt, char *term_optarg ) X{ X switch(opt) X { X case 's' : X simple = 1; X break; X default: X return -1; X } X return 0; X} X X/* tty clean up and exit */ Xvoid quit(int ret) X{ X set_block(s); X set_block(0); X set_block(1); X X if (!simple && isatty(0)) X { X terminal_restore(0,0); X terminal_restore(1,0); X } X X exit (ret); X} X X /* In case of sudden death, do some */ X /* minimal clean up. */ Xvoid sig_quit(int dummy) X{ X quit(1); X} X X#ifdef USE_SIGWINCH Xvoid resizer(int foo) X{ X#ifdef TIOCGWINSZ X struct winsize ws; X if (ioctl(0, TIOCGWINSZ, &ws) >= 0) X#else /* TIOCGWINSZ */ X#ifdef TIOCGSIZE X struct ttysize ts; X if (ioctl(0, TIOCGSIZE, &ts) >= 0) X#endif X#endif X { X int s = connect_server(term_server); X if (s<0) return; X#ifdef TIOCGWINSZ X send_command(s, C_RESIZE, 0, "%d %d %d %d %d", term_client_number, X ws.ws_row, ws.ws_col, ws.ws_ypixel, ws.ws_xpixel); X#else /* TIOCGWINSZ */ X#ifdef TIOCGSIZE X send_command(s, C_RESIZE, 0, "%d %d %d %d %d", term_client_number, X ts.ts_lines, ts.ts_cols, ts.ts_yyy, ts.ts_xxx); X#endif X#endif X close(s); X } X signal(SIGWINCH, resizer); X} X#endif /* USE_SIGWINCH */ X Xint main(int argc, char *argv[]) { X int s, first; X char * f; X X X priority = 10; /* The scale is -20 to +20, higher is faster */ X X first = client_options(argc,argv,"s", local_options); X if (first >= argc){ X simple = 0; X signal(SIGPIPE, SIG_IGN); /* Maybe this will make non-simple mode work */ X }; X X use_term_command(PRIVILEGED); X X s = socket_connect_server(-1,term_server); X if (s < 0 ) { X fprintf(stderr, "Term: %s\n", command_result); X exit(1); X } X X if (send_command(s, C_STATS, 1, "%d", -6)<0) { X fprintf(stderr, "FATAL: Failed to get client number.\n"); X fprintf(stderr, "Reason given: %s\n", command_result); X exit(1); X } X X#ifdef USE_SIGWINCH X term_client_number = atoi(command_result); X if (term_client_number < 0) X fprintf(stderr, "Can't get client number: SIGWINCH not supported.\n"); X#endif X X f=build_arg(&argv[first]); X if(f==NULL) f="\0"; X X if (send_command(s, simple ? C_EXEC : C_PTYEXEC, 0, "%s", f) < 0) { X fprintf(stderr, "FATAL: Failed to exec remote command\n"); X fprintf(stderr, "Reason given: %s\n", command_result); X exit(1); X }; X if(argv[first]!=NULL) free(f); X send_command(s, C_DUMB, 1, 0); X X#ifdef USE_SIGWINCH X if (!simple && isatty(0)) X resizer(0); X#endif X X terminal_save(0); X X signal(SIGHUP, sig_quit); X signal(SIGINT, sig_quit); X signal(SIGQUIT, sig_quit); X signal(SIGPIPE, sig_quit); X if (!simple && isatty(0)) X { X terminal_raw(0); X terminal_raw(1); X } X set_nonblock(0); X set_nonblock(1); X set_nonblock(s); X X do_select_loop(s, 0, 1); X X quit (0); X exit(0); X} X X X/* my function. X * char * pathtail( char * path ) X * takes a path and returns a pointer to the last element in it X * assumes path separator is '/' X * assumes '\0' terminated path. X * X * note: returns a pointer to the string that was input. X * note: returns NULL if path == NULL. X * X * X * by croutons. 29 Nov 1992 X */ X Xchar * pathtail(char * p) X{ X int i; X X if ( ! p ) { X return NULL; X } X X for (i = 0; p[i] != '\0'; i++); X for (i--; i >= 0 && p[i] != '/'; i--); X return &p[i+1]; X} SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/trshell.c' && chmod 0644 'term-2.2.5/trshell.c' || echo 'restore of term-2.2.5/trshell.c failed' shar_count="`wc -c < 'term-2.2.5/trshell.c'`" test 3530 -eq "$shar_count" || echo "term-2.2.5/trshell.c: original size 3530, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/udpredir.c ============== if test -f 'term-2.2.5/udpredir.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/udpredir.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/udpredir.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/udpredir.c' && X/* udpredir.c - redirect udp sockets over term X * Danny Gasparovski u923168@student.canberra.edu.au X * X * C_USOCK both ends, C_UBIND local end, X * then hang around forever (until we get killed) X * so that the UDP clients don't die. X */ X X#define I_STRING X#define I_INET X#define I_SYS X#define I_IOCTL X#define I_SIGNAL X X#include "includes.h" X X#define MAXREDIR 32 X Xint S = -1; Xchar *sockaddr_to_str(struct sockaddr *,int trans); X Xstatic void sig_ignore(int dummy) { X signal(SIGPIPE, sig_ignore); X} X X/* do the redirecting */ X Xstatic int do_udp_redir(unsigned short localport, struct sockaddr *r_addr) { X int s,client; X X if (S < 0) return -1; X X /* create new client */ X if( (s = socket_connect_server(-1,term_server)) <0) { X fprintf(stderr,"Term: %s\n", command_result); X return -1; X } X else if( send_command(s, C_STATS, 1, "%d", -6) < 0) { X fprintf(stderr,"Term C_STATS: %s\n", command_result); X close(s); X return -1; X } X client = atoi(command_result); X X /* C_USOCK it */ X if(send_command(S,C_USOCK,0,"%d %d",client, X (UDP_T_SENDSTRIPHDR|UDP_T_SENDIGNOREHDR))<0) { X fprintf(stderr,"Term C_USOCK: %s\n", command_result); X close(s); X return -1; X } X else if(send_command(S,C_USOCK,1,"%d %d",client,(UDP_T_RECADDHDR))<0) { X fprintf(stderr,"Term C_USOCK: %s\n", command_result); X close(s); X return -1; X } X close(s); X X /* bind local USOCK to read the "from" port */ X if( send_command(S, C_UBIND, 1, "%d %d", client, localport) <0) { X fprintf(stderr,"Term C_UBIND: %s\n", command_result); X return -1; X } X X /* set up UDP parameters on remote to reflect the "to" port */ X if( send_command(S, C_UDPSET, 0, "%d :%s", client, sockaddr_to_str(r_addr,0)) <0) { X fprintf(stderr,"Term C_UDPSET: %s\n", command_result); X return -1; X } X X /* all seemed to succeed */ X return 0; X} X X Xstatic void check_usage(int n) { X X if ( n < 2 ) { X fprintf ( stderr, "Usage: udpredir [options] { <[host:]remoteport>}\n" ); X exit(1); X } X} X X#ifdef ONE_CLIENT X# define main tudpredir X#endif X Xint main(int argc, char **argv) { X Xstruct sockaddr_in r_addr; Xint first,i; Xchar *ptr=NULL; Xstruct hostent *hh; Xfd_set in, out, except; X X signal(SIGPIPE, sig_ignore); X X if( (first = client_options(argc,argv,"",NULL)) <0) X exit(1); X check_usage(argc - first); X X if( (S=socket_connect_server(-1,term_server)) <0) { X fprintf(stderr,"Term: %s\n", command_result); X exit(1); X } X X /* parse args */ X for (i = 0; i < MAXREDIR && first < argc;first += 2) { X check_usage(argc - first); X fprintf(stderr, "Redirecting %s to %s\n", argv[first], argv[first+1] ); X X r_addr.sin_family = AF_INET; X X ptr = strchr(argv[first+1],':'); X if(ptr == NULL) { X r_addr.sin_addr.s_addr = inet_addr("127.0.0.254"); X r_addr.sin_port = atoi(argv[first+1]); X } else { X char *host = NULL; X r_addr.sin_port = atoi(++ptr); /* get port */ X if( r_addr.sin_port <= 0) { X fprintf(stderr,"Bad port number %u.\n", r_addr.sin_port); X exit(1); X } X host = (char *) malloc( sizeof(char) * ( strlen(argv[first+1]) + 1) ); X strcpy(host,argv[first+1]); X ptr = strchr(host,':'); X *ptr = '\0'; X if ((hh = term_gethostbyname(host)) == NULL) exit(1); X if (host) free(host); X memcpy(&r_addr.sin_addr, hh->h_addr, hh->h_length); X } X X /* ok, got everything, redirect it */ X if( do_udp_redir((unsigned short)atoi(argv[first]), X (struct sockaddr *)&r_addr) <0) exit(1); X } X X FD_ZERO(&in); X FD_ZERO(&out); X FD_ZERO(&except); X X if (S != 0) close(0); X if (S != 1) close(1); X if (S != 2) close(2); X X /* We should wait until term exits. */ X /* This doesn't seem to work, I'm not sure why... */ X do { X FD_SET(S,&in); X FD_SET(S,&except); X select(1, &in, &out, &except, 0); X } while ( ! (FD_ISSET(S,&except) || FD_ISSET(S,&in)) ); X X close(S); X exit(0); X} X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/udpredir.c' && chmod 0644 'term-2.2.5/udpredir.c' || echo 'restore of term-2.2.5/udpredir.c failed' shar_count="`wc -c < 'term-2.2.5/udpredir.c'`" test 3897 -eq "$shar_count" || echo "term-2.2.5/udpredir.c: original size 3897, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/upload.c ============== if test -f 'term-2.2.5/upload.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/upload.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/upload.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/upload.c' && X/* X * A client for term. Hacked about by Jeff Grills, bashed a little here and X * there by me. Mostly formatting changes + a few error condition X * changes. X * [-u] (unlink) by Darren Drake (drd@gnu.ai.mit.edu) X * File checksumming by Olaf Titz (olaf@bigred.ka.sub.org) X */ X X/* If the remote file exists, tupload tries to checks if it can resume X * with the following conditions: X * X * - Either the remote file is read only or it is the same size as the X * local X * - The remote file is not larger than the local file. X * - The local file has not been edited, touched, or otherwise modified. X * - The remote and local checksums match. X * (bcr@physics.purdue.edu) X */ X X#define I_IOCTL X#define I_SYS X#define I_STRING X#define I_STAT X#define I_TIME X#define I_LIMITS X#define DEBUG X X#include "includes.h" X#include "client.h" X X#ifdef ONE_CLIENT X# define main tupload X#else Xint term_debug = 0; X#endif X Xint force = 0; Xint unlinkmode = 0; Xint literal_filename = 0; X Xstruct stat st; X X/*---------------------------------------------------------------------------*/ X Xstatic int local_options ( char opt, char *optarg ) X{ X switch(opt) X { X case 'f' : X force = 1; X break; X case 'q' : X verbose = 0; X break; X case 'u': X unlinkmode = 1; X break; X case 'l': X literal_filename = 1; X break; X default: X return -1; X } X return 0; X} X/*---------------------------------------------------------------------------*/ X X#define CPS_WINDOW 4 X#define PRIME_WRITE_SIZE 509 X Xdouble upload_delta_timeval(struct timeval *a, struct timeval *b) X{ X return (a->tv_sec + a->tv_usec/1000000.0) - X (b->tv_sec + b->tv_usec/1000000.0); X} X Xint main(int argc, char *argv[]) X{ X /* From client.c */ X extern int lcompression, rcompression; X /* locals for upload. */ X struct Buffer buffer; X char *cutpath, *file, *remote, path[255], filename[255]; X int term, fd, first, stdin_used, type, perms, i, lcksum, rcksum; X int filesent, j=0, fullperms=0; X long ret, remote_size, bytesent, total_bytesent, bytesent_base; X long dumpsize, cpsbytes, write_len; X double cps = 0; X struct timeval total_starttime, total_stoptime, starttime, lasttime, nowtime; X double etime, total_etime = 0; X double recent_cpsbytes[CPS_WINDOW], recent_etime[CPS_WINDOW]; X int cps_count, done; X fd_set writes; X int permissions; X long atime = 0, mtime = 0, rmtime = 0; X X term = -1; X fd = -1; X first = -1; X stdin_used = 0; X priority = -5; /* The scale is -20 to 20 with higher being better */ X verbose = 1; X bytesent = 0; X total_bytesent = 0; X gettime(&total_starttime); X filesent = 0; X path[0] = '\0'; X lcompression = rcompression = 0; X buffer.start = buffer.end = buffer.size = buffer.alloced = 0; X buffer.data = NULL; X X /* Handle the options. We use the standard client argument handling */ X /* to do this. Options peculiar to upload are 'f' for force, q for */ X /* quiet, and v for verbose, u for unlink */ X if ( ((first = client_options(argc,argv,"fquvl",local_options)) == -1) X || (first >= argc) ) { X fprintf(stderr, X "Usage: upload [-f] [-q] [-u] [-v] [-r] [-c] [-p ] " X " [... ] [remote dir]\n"); X exit(1); X } X X use_term_command(PRIVILEGED); X X /* Make sure the buffer is non-zero in */ X /* size. */ X add_to_buffer(&buffer, 0); X get_from_buffer(&buffer); X X#ifdef linux X term = socket(AF_INET, SOCK_STREAM, 0); X#else X term = -1; X#endif X if ((term = socket_connect_server(term, term_server)) < 0) { X fprintf(stderr,"Term: %s\n", command_result); X exit(1); X } X X /* check the last arg to see if it's a dir, and if so, */ X /* that's the path we send to. */ X if ((first < argc) && (send_command(term, C_STAT, 0, "%s", X argv[argc-1]) >= 0)) { X sscanf(command_result, "%ld %d %d", &remote_size, &type, &perms); X X /* check if it's a dir, and writable. */ X if (type == 1) { X strcpy(path, argv[--argc]); X if ( ! (i = strlen(path))) { X fprintf(stderr, "\tFatal. Zero length path passed.\n"); X exit(1); X } X if ( path[i - 1] != '/' ) { X path[i] = '/'; X path[i+1] = '\0'; X } X } X } X X /* should check here for a file to send. enforce command line. */ X /* or, maybe no args should mean take from stdin. */ X /* but then, what's the output file name? -q */ X X while ( first < argc ) { X X /* close the input file if it was left open */ X if (fd > 0) { X close(fd); X fd = -1; X } X X /* get the filename to send.*/ X file = argv[first++]; X X if ( (first+1 < argc) && X (! strcmp(argv[first],"-as")|| !strcmp(argv[first],"--as")) ) { X remote = argv[first+1]; X first += 2; X } X else { X /* leave the filename alone */ X remote = file; X X /* remove the pathname for the outgoing file */ X if (!literal_filename) { X for ( cutpath = remote; *cutpath; cutpath++ ) X if ( ( *cutpath == '/' ) && ( *(cutpath+1) ) ) X remote = cutpath + 1; X } X } X X /* prepend the specified path, if there is one. */ X if ( *path ) { X strcpy(filename, path); X strcat(filename, remote); X remote = filename; X } X X if ( verbose > 0 ) X if ( file == remote ) X fprintf(stderr, "sending %s\n",file); X else X fprintf(stderr, "sending %s as %s\n", file, remote ); X X /* open input file, or use stdin. The stdin is a bit of a kludge */ X /* but it can be useful. */ X fd = -1; X if ( strcmp(file, "-") ) X fd = open(file, O_RDONLY); X else X /* try to use stdin's file descriptor */ X if ( stdin_used++ ) { X fprintf(stderr, "\tSkipped : can only take input from stdin once\n"); X j=1; X continue; X } X else X fd = 0; X X if (fd < 0) { X fprintf(stderr, "\tSkipped : can't open local file\n"); X j=1; X continue; X } X X /* get some info on the local file. We need to know the file */ X /* size at the very least. */ X X if (fd) { X stat(file, &st); X X if ( st.st_mode & S_IFDIR ) { X fprintf(stderr,"\tSkipping directory.\n"); X continue; X } X permissions = (int) st.st_mode & 0777; X atime = (long) st.st_atime; X mtime = (long) st.st_mtime; X }else { X int current_umask = umask(0); X umask(current_umask); X permissions = 0666 & ~current_umask; X atime = mtime = 0; X } X X /* see if the file exists to be resumed. Done by asking term to */ X /* stat the file on the remote end. */ X remote_size = 0; X if (remote_term_version>=20164) { X i = send_command(term, C_STAT, 0, "\n%ld\n%s", 0, remote); X }else X i = send_command(term, C_STAT, 0, "%s", remote); X if (i >= 0) { X gettime(&nowtime); X if (force && remote_term_version < 20164) X fprintf(stderr,"\tWarning, overwriting file on remote host\n"); X else X if (!fd) { X if (force) { X fprintf(stderr,"\tWarning, overwriting file on remote host\n"); X }else { X fprintf(stderr,"\tCannot resume from stdin\n"); X j=1; X continue; X } X }else { X X /* Ok. The remote file exists. lets check a few things here.. */ X fullperms = 0; rcksum = 0; X if (sscanf(command_result,"%ld %*d %*d %*d %ld %o %u", X &remote_size, &rmtime, &fullperms, &rcksum) < 1) { X remote_size = 0; X } X /* The permissions on the remote file have been changed. */ X if (fullperms & 0333) { X if (force) { X remote_size = (remote_size != (long)st.st_size) ? 0 : remote_size; X }else { X fprintf(stderr, "\tSkipping, remote file has write/execute permission\n"); X j=1; X continue; X } X } X X /* Local file has been changed since last upload. */ X if ((remote_size || ! force) && (rmtime) && (rmtime+nowtime.tv_sec < mtime)) { X if (force) { X remote_size = 0; X }else { X fprintf(stderr,"\tSkipping, the local file has been modified\n"); X j = 0; X continue; X } X } X X /* remote file is same size. Identical? */ X if ( (remote_size || ! force) && remote_size == (long)st.st_size ) { X if (! force) fprintf(stderr,"\tRemote file is same size as local"); X if (rcksum) { X lcksum = file_crc(file, (long)st.st_size); X if (lcksum) { X if (lcksum==rcksum) { X if (force && verbose > 1) fprintf(stderr, X "\tSame size local and remote file"); X else X fprintf(stderr, ", checksums do match"); X /* Same file - set mode right */ X /* For old versions this will be ignored anyways... */ X if (send_command(term, C_CHMOD, 0, "%o %ld %ld\n%s", X permissions, X (atime) ? (atime - (long)nowtime.tv_sec) : 0, X (mtime) ? (mtime - (long)nowtime.tv_sec) : 0, X remote) && (! force || verbose > 1)) X fprintf(stderr, ", setting file mode"); X if (!force || verbose > 1) fprintf(stderr, "\n"); X continue; X }else if (force) { X remote_size = 0; X }else { X fprintf(stderr, ", checksums do not match, skipping\n"); X j=1; X continue; X } X } X }else if (force) { X remote_size = 0; X } else { X fprintf(stderr, ", skipping\n"); X j=1; X continue; X } X } X /* remote file is larger than current file. Skip this.*/ X else if ( remote_size && remote_size > (long)st.st_size ) { X if (force) { X remote_size = 0; X }else { X fprintf(stderr,"\tSkipping, remote file is larger than local\n"); X j=1; X continue; X } X } X /* Remote is a different shorter file. Skip */ X else if ((remote_size || ! force) && rcksum) { X lcksum = file_crc(file, remote_size); X if ((lcksum) && (rcksum!=lcksum)) { X if (force) { X remote_size = 0; X }else { X fprintf(stderr, "\tSkipping, remote file differs from beginning of local\n"); X j=1; X continue; X } X } X } X X if (force && ! remote_size) X fprintf(stderr,"\tWarning, overwriting file on remote host\n"); X else X fprintf(stderr, "\tAttempting to restart upload from %ld\n", X remote_size); X } X } X X if (remote_size) { X /* open file on the remote end. We use C_OPEN instead of */ X /* C_UPLOAD as we don't want to truncate the file. */ X X if (remote_term_version >= 20057) { X if (send_command(term, C_OPEN, 0, "%ld %o\n%s", X remote_size, 0400, remote) < 0) { X fprintf(stderr,"\tSkipped : Couldn't open remote file, %s\n", X command_result); X j=1; X continue; X } X }else { /* With older versions we had to send multiple commands :-( */ X if (send_command(term, C_OPEN, 0, "%s", remote) < 0) { X fprintf(stderr,"\tSkipped : Couldn't open remote file, %s\n", X command_result); X j=1; X continue; X } X /* do the remote file seek. */ X if (send_command(term, C_SEEK, 0, "%ld", remote_size) < 0) { X fprintf(stderr, "\tSkipped, remote seek failed, %s\n", X command_result); X j=1; X continue; X } X } X /* do the local file seek */ X if (lseek(fd, (off_t)remote_size, 0) < (off_t)0) { X fprintf(stderr, "\tSkipped, local seek failed, "); X perror("Reason given"); X j=1; X continue; X } X }else { X /* it's a new file. Use C_UPLOAD to open, and possibly creat, */ X /* or truncate it. */ X if (remote_term_version >= 20057) { X if (send_command(term, C_UPLOAD, 0, "0 %o\n%s", 0400, remote) < 0) { X fprintf(stderr,"\tSkipped : Couldn't open remote file, %s\n", X command_result); X j=1; X continue; X } X }else { X if (send_command(term, C_UPLOAD, 0, "%s", remote) < 0) { X fprintf(stderr,"\tSkipped : Couldn't open remote file, %s\n", X command_result); X j=1; X continue; X } X } X } X X /* dump the file over the socket. We handle this by using C_DUMP */ X /* commands to escape the data. */ X if (verbose > 1) { X gettime(&starttime); X lasttime = starttime; X } X bytesent = 0; X bytesent_base = 0; X cpsbytes = 0; X dumpsize = 0; X cps_count = 0; X done = 0; X for (i = 0; i < CPS_WINDOW; ++i) { X recent_cpsbytes[i] = 0; X recent_etime[i] = 0; X } X filesent++; X do { X if (buffer.size < PIPE_BUFFER) { X ret = (long)(read_into_buff(fd, &buffer,0)); X if (ret < 0) break; X if (ret > 0 && buffer.size < PIPE_BUFFER) continue; X } X if (buffer.size == 0) X done = 1; X else { X if (dumpsize < 0) { X fprintf(stderr, "\tAborted, dumpsize %ld < 0\n", dumpsize); X j=1; X break; X } X if (dumpsize == 0) { X if (send_command(term, C_DUMP, 1, "%d", buffer.size) < 0) { X fprintf(stderr, "\tAborted, couldn't turn off command" X " processing, %s\n", command_result ); X j=1; X break; X } X dumpsize = buffer.size; X } X set_nonblock(term); X termerrno = 0; X write_len = dumpsize < PRIME_WRITE_SIZE ? dumpsize : PRIME_WRITE_SIZE; X ret = (long) write_from_buff_async(term, &buffer, write_len); X if (ret <= 0 && termerrno) { X fprintf(stderr, "\tError writing to term server. Exiting..\n"); X exit(1); X } X X bytesent += ret; X total_bytesent += ret; X remote_size += ret; X cpsbytes += ret; X dumpsize -= ret; X if (write_len == ret && cpsbytes < 65536) /* guarantee some output */ X continue; X if (cpsbytes == 0) X continue; /* non-blocking lossage or some such */ X } X X gettime(&nowtime); X if ( (verbose > 2)) { X X /* Compute CPS as follows. We only get here when we were unable X to write all the data in the buffer, which means that we have X stuffed the pipe full. We use PRIME_WRITE_SIZE so that it X will be very uncommon for a write to complete fully at the X exact end of the pipe. For the first second of uploading, X we ignore CPS, since we don't know the depth of the pipe X to term. From then on, each CPS value is placed in a X CPS_WINDOW-sized buffer and the average of the buffer is X used as the CPS value. */ X X etime = upload_delta_timeval(&nowtime, &lasttime); X X lasttime = nowtime; X if (upload_delta_timeval(&nowtime, &starttime) < 1) { X cps = 0; X bytesent_base = bytesent; /* use to adjust ETA */ X } else { X recent_cpsbytes[cps_count] = cpsbytes; X recent_etime[cps_count] = etime; X if (++cps_count >= CPS_WINDOW) X cps_count = 0; X for (i = 0, cps = 0, etime = 0; i < CPS_WINDOW; ++i) { X cps += recent_cpsbytes[i]; X etime += recent_etime[i]; X } X if (etime > 0) X cps /= etime; X else X cps = 0; X } X X if ( fd && (st.st_size) ) { X long perc; X X perc = (remote_size*100) / (long)st.st_size; X if (cps) X fprintf(stderr, "\r\t%ld of %ld (%ld%%), current CPS %.0f. ETA: %.1f TT: %.1f ", X remote_size, (long)st.st_size, perc, X cps, (st.st_size-remote_size+bytesent_base)/cps, X st.st_size/cps); X else X fprintf(stderr, "\r\t%ld of %ld (%ld%%) ", X remote_size, (long)st.st_size, perc); X } X else if (!fd) { X if (cps) X fprintf(stderr, "\r\t%ld, current CPS %.0f. ", remote_size, cps ); X else X fprintf(stderr, "\r\t%ld ", remote_size); X } X X fflush(stderr); X cpsbytes = 0; X } X X if (done) X break; X X /* Wait until we can write again before we try reading any more */ X FD_ZERO(&writes); X FD_SET(term, &writes); X set_block(term); X select(term+1, NULL, &writes, NULL, (struct timeval *)NULL); X } while (1); X X /* give them cps ratings */ X if (verbose > 1) { X gettime(&nowtime); X etime = upload_delta_timeval(&nowtime, &starttime); X total_etime += etime; X if (etime == 0) X etime = 0.01; X fprintf(stderr, "\r\t%ld bytes sent in %.1f seconds;" X " CPS = %.0f ", X bytesent, etime, bytesent/((etime < 0.5) ? 0.5 : etime)); X } X X /* Close the file */ X send_command(term, C_CLCLOSE, 0, 0); X send_command(term, C_WAIT, 0, 0); /* We must delay, to allow the file to */ X /* to close before we send C_CHMOD */ X send_command(term, C_CHMOD, 0, "%o %ld %ld\n%s", permissions, X (atime) ? (atime - (long)nowtime.tv_sec) : 0, X (mtime) ? (mtime - (long)nowtime.tv_sec) : 0, remote); X X /* check the remote file after send */ X if (remote_term_version>=20164) { X i = send_command(term, C_STAT, 0, "\n%ld\n%s", 0, remote); X fprintf(stderr, "CRC "); X } X else X i = send_command(term, C_STAT, 0, "%s", remote); X if (i >= 0) { X long l=0; X rcksum = 0; X if(sscanf(command_result,"%ld %*d %*d %*d %*d %*o %u", X &l, &rcksum)<1) X l = 0; X if (( fd && (l != (long)st.st_size) ) || X ( (!fd) && (l != bytesent) )) { X fprintf(stderr, "F\n\tRemote file is a different size from local after" X " upload!\n\t(r=%ld,l=%ld)\n", l, st.st_size); X j=1; X continue; X } X if (fd && rcksum) { X lcksum = file_crc(file, (long)st.st_size); X if (lcksum && (lcksum!=rcksum)) { X fprintf(stderr, "F\n\tRemote and local file checksums don't match" X " after upload!\n"); X j=1; X continue; X } else { X fprintf(stderr, "OK"); X } X } X /* unlink files if we wanna remove them after *successful* send */ X if(fd && unlinkmode) { X if((unlink(file))&&(verbose>1)) { X fprintf(stderr,"\n\tUnable to remove sent file\n"); X j=1; X }else { X fprintf(stderr,"\n\tSent file removed.\n"); X } X } else fprintf(stderr, "\n"); X } X else { X fprintf(stderr,"\n\t%s",command_result); X fprintf(stderr,"\n\tcouldn't stat remote file after upload. Please" X " check it.\n"); X j=1; X } X } X X /* give them global cps rating */ X if ( (verbose > 1) && (filesent > 1) ) { X gettime(&total_stoptime); X etime = upload_delta_timeval(&total_stoptime, &total_starttime); X if (etime == 0) X etime = 0.01; X fprintf(stderr, "%ld total bytes sent in %.1f seconds; overall CPS %.0f\n", X total_bytesent, etime, total_bytesent/((etime < 0.5) ? 0.5 : etime)); X } X X exit(j); X} X X SHAR_EOF $shar_touch -am 1028144694 'term-2.2.5/upload.c' && chmod 0644 'term-2.2.5/upload.c' || echo 'restore of term-2.2.5/upload.c failed' shar_count="`wc -c < 'term-2.2.5/upload.c'`" test 18550 -eq "$shar_count" || echo "term-2.2.5/upload.c: original size 18550, current size $shar_count" rm -f _sharnew.tmp fi # ============= term-2.2.5/utils.c ============== if test -f 'term-2.2.5/utils.c' && test X"$1" != X"-c"; then echo 'x - skipping term-2.2.5/utils.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting term-2.2.5/utils.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'term-2.2.5/utils.c' && X#define I_IOCTL X#define I_ERRNO X#define I_TYPES X#define I_STAT X#define I_STRING X#define I_CTYPE X#define I_INET X#define I_LIMITS X#define I_STROPT X#define I_POLL X#include "includes.h" X X#include "debug.h" X X#define BUFF_INC_SIZE 1024 X#define MAX_BUFF 32767 X Xchar *term_strherror(int); X Xint termerrno = 0; X Xint share = -1; X X/*------------------------------------------------------------------------*/ X/* Do a partial read into the buffer. */ Xstatic int do_read_into_buff(int fd, struct Buffer *b, int size) { X int r = 0, t; X X X X if (!size || size > b->alloced - 1 - b->size) X size = b->alloced - 1 - b->size; X X termerrno = 0; X t = b->alloced - b->start; X if (t > size) t = size; X#ifdef SVR3 /* System Vr3 doesn't restart system calls */ X while ((r = read(fd, b->data + b->start, t)) == -1 && errno == EINTR); X#else X r = read(fd, b->data + b->start, t); X#endif X if (r <= 0) { X if (!r) termerrno = 1; X else X#ifndef SVR4 X if (errno != ERR_BLOCK) X#endif /* SVR4 */ X termerrno = errno + 1; X return r; X } X DEBUG_LL(stderr, "%s: d_r_i_b: read1 from %d (%d) did %d\n", X term_server, fd, t, r); X X b->start += r; X b->size += r; X SANITY(b->start <= b->alloced); X if (b->start == b->alloced) X b->start = 0; X size -= r; X if (!size || b->start != 0) return r; X X t = b->alloced - b->start; X if (t > size) t = size; X X#ifdef SVR3 /* System Vr3 doesn't restart system calls */ X while ((t = read(fd, b->data + b->start, t)) == -1 && errno == EINTR); X#else X t = read(fd, b->data + b->start, t); X#endif X if (t <= 0) { X if (!t) termerrno = 1; X else if(errno != ERR_BLOCK) X termerrno = errno+1; X return r; X } X DEBUG_LL(stderr, "%s: d_r_i_b: read2 from %d (%d) did %d\n", X term_server, fd, t, t); X X b->start += t; X b->size += t; X if (b->start == b->alloced) X b->start = 0; X size -= t; X r += t; X return r; X} X Xstatic int inc_buffer(struct Buffer *b, int do_move) { X if( (b->data == NULL) || (b->alloced == 0)) { X if( (b->data = (un_char *)malloc((1+BUFF_INC_SIZE)*sizeof(un_char))) == NULL){ X perror("Term: malloc()"); X return -1; X } X b->alloced = BUFF_INC_SIZE + 1; X b->size=0; X }else if(b->alloced >= MAX_BUFF) { X DEBUG_UDP(stderr,"%s:%s",term_server,"Term: max buffer\n"); X return -1; X }else if ((b->data = (un_char *)realloc(b->data, sizeof(un_char)* X (((b->alloced+BUFF_INC_SIZE) < 0 || (b->alloced+BUFF_INC_SIZE > MAX_BUFF))) ? SHAR_EOF : || echo 'restore of term-2.2.5/utils.c failed' fi echo 'End of archive part 8' echo 'File term-2.2.5/utils.c is continued in part 9' echo 9 > _sharseq.tmp exit 0