This is tip.c in view mode; [Download] [Up]
char *tipx_rev = "x1.21"; #define PATCHLEVEL 1 /* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* * Modifications by Warren Tucker <wht%n4hgf.uucp@emory.mathcs.emory.edu> * for eight-bit transparent pass through and file transfer protocols * are unencumbered in any way. They are yours, ours, everybody's, nobody's. */ /*+:EDITS:*/ /*:05-08-1990-15:05-wht@n4hgf-rawthru */ /*:05-08-1990-15:00-wht@n4hgf-move tip.c original to tip-orig.c */ #ifndef lint char copyright[] = "@(#) Copyright(c) 1983 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ /* * tip - UNIX link to other systems * tip [-psv] [-speed] system-name [data] * or * cu phone-number [-s speed] [-l line] [-a acu] */ #include <sys/types.h> #include <stdlib.h> #include <sys/ioctl.h> #include "tip.h" uid_t getuid(void); uid_t geteuid(void); gid_t getgid(void); gid_t getegid(void); int setreuid(); int getuucpuid(void); void cumain(); char *strncpy(); int hunt(); int uu_unlock(); void vinit(void); int ioctl(); int pipe(); int fork(void); void tipin(void); void tipout(void); int kill(); int setregid(); int sleep(unsigned int seconds); void setscript(void); int read(int fd, char *buf, int nbytes); int write(int fd, char *buf, int nbytes); int escape(void); /* * Baud rate mapping table */ int bauds[] = { 0,50,75,110,134,150,200,300,600, 1200,1800,2400,4800,9600,19200,38400,-1 }; #ifdef TIPX int rawthru = 0; char *rawthru_msg = "\r\n--> raw tip: 3 ~ rapidly for ~ equivalent\r\n"; char *no_rawthru_msg = "\r\n--> normal tip: 1 ~ == ~\r\n"; extern char opened_tty[]; #endif int page; int disc = OTTYDISC; /* tip normally runs this way */ void intprompt(); void timeout(); char *login(); char *sname(); char PNbuf[256]; /* This limits the size of a number */ struct sgttyb ttyarg; #ifdef TIPX typedef struct b_to_br { char *baud_rate; int B_code; } B_TO_BR; B_TO_BR speeds[] = /* ordered to put less common rates later in table */ { /* and the vagaries of baud rates above 9600 "handled" */ "2400", B2400, "1200", B1200, "9600", B9600, #if defined(B19200) "19200",B19200, #endif #if defined(B38400) "38400",B38400, #endif "4800", B4800, "300", B300, "110", B110, "600", B600, "75", B75, "50", B50, "HUP", B0, "EXTA", EXTA, "EXTB", EXTB, (char *)0,0 }; #endif /* TIPX */ /*+------------------------------------------------------------------------- B_to_baud_rate(code) - convert CBAUD B_ code to baud rate string --------------------------------------------------------------------------*/ #ifdef TIPX char * B_to_baud_rate(code) int code; { register int n; for(n=0; speeds[n].baud_rate; n++) if(speeds[n].B_code == code) return(speeds[n].baud_rate); return("-----"); } /* end of B_to_baud_rate */ #endif /* TIPX */ int main(argc,argv) int argc; char *argv[]; { int uuid; char *system = NOSTR; char *data = NOSTR; register int i; register char *p; char sbuf[12]; uid = getuid(); gid = getgid(); euid = geteuid(); /* should be root */ egid = getegid(); uuid = getuucpuid(); if(equal(sname(argv[0]),"cu")) { setreuid(uid,uuid); cumode = 1; cumain(argc,argv); goto cucommon; } if(argc < 2) { /** fprintf(stderr,"usage: tip [-psv] [-speed] [system-name] [data]\n"); **/ fprintf(stderr,"usage: tip [-v] [-speed] [system-name] [data]\n"); exit(1); } for(; argc > 1; argv++,argc--) { if(argv[1][0] != '-') { if(system) data = argv[1]; else system = argv[1]; } else switch(argv[1][1]) { /*** case 'p': page++; break; case 's': slip++; break; ***/ case 'v': vflag++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': BR = atoi(&argv[1][1]); break; default: fprintf(stderr,"tip: %s, unknown option\n",argv[1]); break; } } /** if(!isatty(0) && !slip && !page) { fprintf(stderr,"tip: warning: input is not a tty\n"); } if(slip) { setreuid(euid,uuid); uid = 0; } else { setreuid(uid,uuid); } euid = uuid; **/ if(system == NOSTR) goto notnumber; if(isalpha(*system)) goto notnumber; /* * System name is really a phone number... * Copy the number then stomp on the original (in case the number * is private, we don't want 'ps' or 'w' to find it). */ if(strlen(system) > sizeof PNbuf - 1) { fprintf(stderr,"tip: phone number too long (max = %d bytes)\n", sizeof PNbuf - 1); exit(1); } strncpy( PNbuf,system,sizeof PNbuf - 1 ); for(p = system; *p; p++) *p = '\0'; PN = PNbuf; (void)sprintf(sbuf,"tip%d",BR); system = sbuf; notnumber: signal(SIGINT,cleanup); signal(SIGQUIT,cleanup); signal(SIGHUP,cleanup); signal(SIGTERM,cleanup); signal(SIGPIPE,cleanup); if((i = hunt(system)) == 0) { printf("all ports busy\n"); exit(3); } if(i == -1) { printf("link down\n"); (void)uu_unlock(uucplock); exit(3); } setbuf(stdout,NULL); loginit(); /* * Kludge, their's no easy way to get the initialization * in the right order, so force it here */ if((PH = getenv("PHONES")) == NOSTR) PH = "/etc/phones"; vinit(); /* init variables */ setparity("none"); /* set the parity table */ if((i = speed(number(value(BAUDRATE)))) == 0) { printf("tip: bad baud rate %d\n",number(value(BAUDRATE))); (void)uu_unlock(uucplock); exit(3); } /*** if(slip) { if(SA == NOSTR) { printf("tip: local addr not set\n"); uu_unlock(uucplock); exit(3); } if(DA == NOSTR) { printf("tip: destination addr not set\n"); uu_unlock(uucplock); exit(3); } if(SM == NOSTR) { printf("tip: slip netmask not set\n"); uu_unlock(uucplock); exit(3); } } ***/ /* * Now that we have the logfile and the ACU open * return to the real uid and gid. These things will * be closed on exit. Swap real and effective uid's * so we can get the original permissions back * for removing the uucp lock. */ user_uid(); /* in the case of slip, we are now priviliged */ /* * Hardwired connections require the * line speed set before they make any transmissions * (this is particularly true of things like a DF03-AC) */ if(HW) ttysetup(i); if(p = lconnect()) { printf("\07%s\n[EOT]\n",p); daemon_uid(); (void)uu_unlock(uucplock); exit(1); } if(!HW) ttysetup(i); /**** if(LS != NOSTR) { fprintf(stderr,"\07[Logging in...]\r\n"); if(p = login()) { printf("\07%s\n[EOT]\n",p); daemon_uid(); (void)uu_unlock(uucplock); exit(1); } } if(page) { i = sendpage(data); daemon_uid(); (void)uu_unlock(uucplock); exit(i); } if(slip) { i = runslip(); daemon_uid(); (void)uu_unlock(uucplock); exit(i); } ***/ cucommon: /* * From here down the code is shared with * the "cu" version of tip. */ ioctl(0,TIOCGETP,(char *)&defarg); ioctl(0,TIOCGETC,(char *)&defchars); ioctl(0,TIOCGLTC,(char *)&deflchars); ioctl(0,TIOCGETD,(char *)&odisc); arg = defarg; #ifdef TIPX arg.sg_flags = CBREAK; #else arg.sg_flags = ANYP | CBREAK; #endif tchars = defchars; tchars.t_intrc = tchars.t_quitc = -1; ltchars = deflchars; ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc = ltchars.t_lnextc = -1; raw(); pipe(fildes); pipe(repdes); signal(SIGALRM,timeout); /* * Everything's set up now: * connection established (hardwired or dialup) * line conditioned (baud rate, mode, etc.) * internal data structures (variables) * so, fork one process for local side and one for remote. */ #ifdef TIPX printf("tipx (tip 4.3 mod by wht@n4hgf %s.%02d) connected to %s\r\n", tipx_rev,PATCHLEVEL,opened_tty); fputs("Copyright (c) 1983 The Regents of the University of California.\r\n", stdout); printf("line speed = %s, tandem = %s\r\n", B_to_baud_rate(ttyarg.sg_ospeed), (ttyarg.sg_flags & TANDEM) ? "yes" : "no"); #else printf(cumode ? "Connected\r\n" : "\07connected\r\n"); #endif if(pid = fork()) tipin(); else tipout(); /*NOTREACHED*/ return(0); } void cleanup() { daemon_uid(); (void)uu_unlock(uucplock); if(pid) { (void) kill(pid,SIGTERM); unraw(); } else if(odisc) ioctl(0,TIOCSETD,(char *)&odisc); exit(0); } /* * Muck with user ID's. We are setuid to the owner of the lock * directory when we start. user_uid() reverses real and effective * ID's after startup, to run with the user's permissions. * daemon_uid() switches back to the privileged uid for unlocking. * Finally, to avoid running a shell with the wrong real uid, * shell_uid() sets real and effective uid's to the user's real ID. */ static int uidswapped; void user_uid(void) { if(uidswapped == 0) { setregid(egid,gid); setreuid(euid,uid); uidswapped = 1; } } void daemon_uid(void) { if(uidswapped) { setreuid(uid,euid); setregid(gid,egid); uidswapped = 0; } } void shell_uid(void) { setreuid(uid,uid); setregid(gid,gid); } /* * put the controlling keyboard into raw mode */ void raw(void) { ioctl(0,TIOCSETP,&arg); ioctl(0,TIOCSETC,&tchars); ioctl(0,TIOCSLTC,<chars); ioctl(0,TIOCSETD,(char *)&disc); } /* * return keyboard to normal mode */ void unraw(void) { ioctl(0,TIOCSETD,(char *)&odisc); ioctl(0,TIOCSETP,(char *)&defarg); ioctl(0,TIOCSETC,(char *)&defchars); ioctl(0,TIOCSLTC,(char *)&deflchars); } static jmp_buf promptbuf; /* * Print string ``s'', then read a string * in from the terminal. Handles signals & allows use of * normal erase and kill characters. */ int prompt(s,p) char *s; char *p; { register char *b = p; void (*oint)(),(*oquit)(); stoprompt = 0; oint = signal(SIGINT,intprompt); oquit = signal(SIGQUIT,SIG_IGN); unraw(); printf("%s",s); if(setjmp(promptbuf) == 0) while((*p = getchar()) != EOF && *p != '\n') p++; *p = '\0'; raw(); signal(SIGINT,oint); signal(SIGQUIT,oint); return(stoprompt || p == b); } /* * Interrupt service routine during prompting */ void intprompt(void) { signal(SIGINT,SIG_IGN); stoprompt = 1; printf("\r\n"); longjmp(promptbuf,1); } /* * ****TIPIN TIPIN**** */ void tipin(void) { char gch,bol = 1; /* * Kinda klugey here... * check for scripting being turned on from the .tiprc file, * but be careful about just using setscript(), as we may * send a SIGEMT before tipout has a chance to set up catching * it; so wait a second, then setscript() */ if(boolean(value(SCRIPT))) { sleep(1); setscript(); } #ifdef TIPX if(!rawthru) goto NORMAL_TIP2; RAWTHRU_TIP: printf(rawthru_msg); while(1) { long count; char chbuf[4]; read(0,&gch,1); if((gch == character(value(ESCAPE)))) { sleep(1); ioctl(0,FIONREAD,&count); if(count == 2) { /* might have raw mode escape */ read(0,chbuf,2); if((chbuf[0] == character(value(ESCAPE))) && (chbuf[1] == character(value(ESCAPE)))) { printf("rawthru%s",ctrl(chbuf[0])); if(!(gch = escape())) { if(!rawthru) { bol = 1; goto NORMAL_TIP; } continue; } } else { gch = character(value(ESCAPE)); write(FD,&gch,1); write(FD,chbuf,2); continue; } } } write(FD,&gch,1); } NORMAL_TIP: printf(no_rawthru_msg); NORMAL_TIP2: #endif /* TIPX */ while(1) { gch = getchar()&0177; if((gch == character(value(ESCAPE))) && bol) { if(!(gch = escape())) #ifdef TIPX { if(rawthru) goto RAWTHRU_TIP; continue; } #else /* TIPX */ continue; #endif /* TIPX */ } else if(!cumode && gch == character(value(RAISECHAR))) { boolean(value(RAISE)) = !boolean(value(RAISE)); continue; } else if(gch == '\r') { bol = 1; pwrite(FD,&gch,1); if(boolean(value(HALFDUPLEX))) printf("\r\n"); continue; } else if(!cumode && gch == character(value(FORCE))) gch = getchar()&0177; bol = any(gch,value(EOL)); if(boolean(value(RAISE)) && islower(gch)) gch = toupper(gch); pwrite(FD,&gch,1); if(boolean(value(HALFDUPLEX))) printf("%c",gch); } } /* * Escape handler -- * called on recognition of ``escapec'' at the beginning of a line */ int escape(void) { register char gch; register esctable_t *p; char c = character(value(ESCAPE)); extern esctable_t etable[]; gch = (getchar()&0177); for(p = etable; p->e_char; p++) if(p->e_char == gch) { if((p->e_flags&PRIV) && uid) continue; #ifdef TIPX if(!rawthru) #endif printf("%s",ctrl(c)); (*p->e_func)(gch); return(0); } /* ESCAPE ESCAPE forces ESCAPE */ if(c != gch) pwrite(FD,&c,1); return(gch); } int speed(n) int n; { register int *p; for(p = bauds; *p != -1; p++) if(*p == n) return(p - bauds); return(0); } int any(c,p) register char c,*p; { while(p && *p) if(*p++ == c) return(1); return(0); } int size(s) register char *s; { register int i = 0; while(s && *s++) i++; return(i); } char * interp(s) register char *s; { static char buf[256]; register char *p = buf,c,*q; while(c = *s++) { for(q = "\nn\rr\tt\ff\033E\bb"; *q; q++) if(*q++ == c) { *p++ = '\\'; *p++ = *q; goto next; } if(c < 040) { *p++ = '^'; *p++ = c + 'A'-1; } else if(c == 0177) { *p++ = '^'; *p++ = '?'; } else *p++ = c; next: ; } *p = '\0'; return(buf); } char * ctrl(c) char c; { static char s[3]; if(c < 040 || c == 0177) { s[0] = '^'; s[1] = c == 0177 ? '?' : c+'A'-1; s[2] = '\0'; } else { s[0] = c; s[1] = '\0'; } return(s); } /* * Help command */ void help(c) char c; { register esctable_t *p; extern esctable_t etable[]; printf("%c\r\n",c); for(p = etable; p->e_char; p++) { if((p->e_flags&PRIV) && uid) continue; printf("%2s",ctrl(character(value(ESCAPE)))); printf("%-2s %c %s\r\n",ctrl(p->e_char), p->e_flags&EXP ? '*': ' ',p->e_help); } } /* * Set up the "remote" tty's state */ void ttysetup(speed) int speed; { unsigned bits = LDECCTQ; ttyarg.sg_ispeed = ttyarg.sg_ospeed = speed; ttyarg.sg_flags = RAW; if(boolean(value(TAND))) ttyarg.sg_flags |= TANDEM; /*** if(boolean(value(DTRHUP))) { ioctl(FD,TIOCSDTR,0); ioctl(FD,TIOCHPCL,0); } ***/ ioctl(FD,TIOCSETP,(char *)&ttyarg); ioctl(FD,TIOCLBIS,(char *)&bits); } /* * Return "simple" name from a file name, * strip leading directories. */ char * sname(s) register char *s; { register char *p = s; while(*s) if(*s++ == '/') p = s; return(p); } static char partab[0200]; /* * Do a write to the remote machine with the correct parity. * We are doing 8 bit wide output, so we just generate a character * with the right parity and output it. */ void pwrite(fd,buf,n) int fd; char *buf; register int n; { register int i; register char *bp; extern int errno; extern void tip_abort(); #ifdef TIPX extern int rawthru; if(rawthru) { write(fd,buf,n); return; } #endif /* TIPX */ bp = buf; for(i = 0; i < n; i++) { *bp = partab[(*bp) & 0177]; bp++; } if(write(fd,buf,n) < 0) { if(errno == EIO) tip_abort("Lost carrier."); /* this is questionable */ perror("write"); } } /* * Build a parity table with appropriate high-order bit. */ void setparity(defparity) char *defparity; { register int i; char *parity; extern char evenpartab[]; if(value(PARITY) == NOSTR) value(PARITY) = defparity; parity = value(PARITY); for(i = 0; i < 0200; i++) partab[i] = evenpartab[i]; if(equal(parity,"even")) return; if(equal(parity,"odd")) { for(i = 0; i < 0200; i++) partab[i] ^= 0200; /* reverse bit 7 */ return; } if(equal(parity,"none") || equal(parity,"zero")) { for(i = 0; i < 0200; i++) partab[i] &= ~0200; /* turn off bit 7 */ return; } if(equal(parity,"one")) { for(i = 0; i < 0200; i++) partab[i] |= 0200; /* turn on bit 7 */ return; } fprintf(stderr,"%s: unknown parity value\n",PA); fflush(stderr); } /* The uid could be determined by stat()-ing ACULOG */ int getuucpuid(void) { struct passwd *pw; if((pw = getpwnam("uucp")) == NULL) { fprintf(stderr,"tip: unable to get uucp uid\n"); exit(1); } return(pw->pw_uid); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.