17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include <libsec.h>
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier #include "../ip/telnet.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier /* console state (for consctl) */
107dd7cddfSDavid du Colombier typedef struct Consstate Consstate;
117dd7cddfSDavid du Colombier struct Consstate{
127dd7cddfSDavid du Colombier int raw;
137dd7cddfSDavid du Colombier int hold;
147dd7cddfSDavid du Colombier };
157dd7cddfSDavid du Colombier Consstate *cons;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier int notefd; /* for sending notes to the child */
187dd7cddfSDavid du Colombier int noproto; /* true if we shouldn't be using the telnet protocol */
197dd7cddfSDavid du Colombier int trusted; /* true if we need not authenticate - current user
207dd7cddfSDavid du Colombier is ok */
217dd7cddfSDavid du Colombier int nonone = 1; /* don't allow none logins */
229a747e4fSDavid du Colombier int noworldonly; /* only noworld accounts */
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier enum
259a747e4fSDavid du Colombier {
269a747e4fSDavid du Colombier Maxpath= 256,
279a747e4fSDavid du Colombier Maxuser= 64,
289a747e4fSDavid du Colombier Maxvar= 32,
299a747e4fSDavid du Colombier };
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier /* input and output buffers for network connection */
327dd7cddfSDavid du Colombier Biobuf netib;
337dd7cddfSDavid du Colombier Biobuf childib;
349a747e4fSDavid du Colombier char remotesys[Maxpath]; /* name of remote system */
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier int alnum(int);
377dd7cddfSDavid du Colombier int conssim(void);
387dd7cddfSDavid du Colombier int fromchild(char*, int);
397dd7cddfSDavid du Colombier int fromnet(char*, int);
407dd7cddfSDavid du Colombier int termchange(Biobuf*, int);
417dd7cddfSDavid du Colombier int termsub(Biobuf*, uchar*, int);
427dd7cddfSDavid du Colombier int xlocchange(Biobuf*, int);
437dd7cddfSDavid du Colombier int xlocsub(Biobuf*, uchar*, int);
447dd7cddfSDavid du Colombier int challuser(char*);
457dd7cddfSDavid du Colombier int noworldlogin(char*);
4674f16c81SDavid du Colombier void* share(ulong);
477dd7cddfSDavid du Colombier int doauth(char*);
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier #define TELNETLOG "telnet"
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier void
logit(char * fmt,...)527dd7cddfSDavid du Colombier logit(char *fmt, ...)
537dd7cddfSDavid du Colombier {
547dd7cddfSDavid du Colombier va_list arg;
559a747e4fSDavid du Colombier char buf[8192];
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier va_start(arg, fmt);
589a747e4fSDavid du Colombier vseprint(buf, buf + sizeof(buf) / sizeof(*buf), fmt, arg);
597dd7cddfSDavid du Colombier va_end(arg);
607dd7cddfSDavid du Colombier syslog(0, TELNETLOG, "(%s) %s", remotesys, buf);
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier void
getremote(char * dir)647dd7cddfSDavid du Colombier getremote(char *dir)
657dd7cddfSDavid du Colombier {
667dd7cddfSDavid du Colombier int fd, n;
679a747e4fSDavid du Colombier char remfile[Maxpath];
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier sprint(remfile, "%s/remote", dir);
707dd7cddfSDavid du Colombier fd = open(remfile, OREAD);
717dd7cddfSDavid du Colombier if(fd < 0)
727dd7cddfSDavid du Colombier strcpy(remotesys, "unknown2");
737dd7cddfSDavid du Colombier n = read(fd, remotesys, sizeof(remotesys)-1);
747dd7cddfSDavid du Colombier if(n>0)
757dd7cddfSDavid du Colombier remotesys[n-1] = 0;
767dd7cddfSDavid du Colombier else
777dd7cddfSDavid du Colombier strcpy(remotesys, remfile);
787dd7cddfSDavid du Colombier close(fd);
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier void
main(int argc,char * argv[])827dd7cddfSDavid du Colombier main(int argc, char *argv[])
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier char buf[1024];
857dd7cddfSDavid du Colombier int fd;
869a747e4fSDavid du Colombier char user[Maxuser];
877dd7cddfSDavid du Colombier int tries = 0;
887dd7cddfSDavid du Colombier int childpid;
897dd7cddfSDavid du Colombier int n, eofs;
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier memset(user, 0, sizeof(user));
927dd7cddfSDavid du Colombier ARGBEGIN {
937dd7cddfSDavid du Colombier case 'n':
947dd7cddfSDavid du Colombier opt[Echo].local = 1;
957dd7cddfSDavid du Colombier noproto = 1;
967dd7cddfSDavid du Colombier break;
977dd7cddfSDavid du Colombier case 'p':
987dd7cddfSDavid du Colombier noproto = 1;
997dd7cddfSDavid du Colombier break;
1007dd7cddfSDavid du Colombier case 'a':
1017dd7cddfSDavid du Colombier nonone = 0;
1027dd7cddfSDavid du Colombier break;
1037dd7cddfSDavid du Colombier case 't':
1047dd7cddfSDavid du Colombier trusted = 1;
1059a747e4fSDavid du Colombier strncpy(user, getuser(), sizeof(user)-1);
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier case 'u':
1087dd7cddfSDavid du Colombier strncpy(user, ARGF(), sizeof(user)-1);
1097dd7cddfSDavid du Colombier break;
1107dd7cddfSDavid du Colombier case 'd':
1117dd7cddfSDavid du Colombier debug = 1;
1127dd7cddfSDavid du Colombier break;
1139a747e4fSDavid du Colombier case 'N':
1149a747e4fSDavid du Colombier noworldonly = 1;
1159a747e4fSDavid du Colombier break;
1167dd7cddfSDavid du Colombier } ARGEND
1177dd7cddfSDavid du Colombier
1187dd7cddfSDavid du Colombier if(argc)
1197dd7cddfSDavid du Colombier getremote(argv[argc-1]);
1207dd7cddfSDavid du Colombier else
1217dd7cddfSDavid du Colombier strcpy(remotesys, "unknown");
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier /* options we need routines for */
1247dd7cddfSDavid du Colombier opt[Term].change = termchange;
1257dd7cddfSDavid du Colombier opt[Term].sub = termsub;
1267dd7cddfSDavid du Colombier opt[Xloc].sub = xlocsub;
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier /* setup default telnet options */
1297dd7cddfSDavid du Colombier if(!noproto){
1307dd7cddfSDavid du Colombier send3(1, Iac, Will, opt[Echo].code);
1317dd7cddfSDavid du Colombier send3(1, Iac, Do, opt[Term].code);
1327dd7cddfSDavid du Colombier send3(1, Iac, Do, opt[Xloc].code);
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier /* shared data for console state */
1367dd7cddfSDavid du Colombier cons = share(sizeof(Consstate));
1377dd7cddfSDavid du Colombier if(cons == 0)
1387dd7cddfSDavid du Colombier fatal("shared memory", 0, 0);
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier /* authenticate and create new name space */
1417dd7cddfSDavid du Colombier Binit(&netib, 0, OREAD);
1427dd7cddfSDavid du Colombier if (!trusted){
1437dd7cddfSDavid du Colombier while(doauth(user) < 0)
1447dd7cddfSDavid du Colombier if(++tries == 5){
1459a747e4fSDavid du Colombier logit("failed as %s: %r", user);
1469a747e4fSDavid du Colombier print("authentication failure:%r\r\n");
1477dd7cddfSDavid du Colombier exits("authentication");
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier logit("logged in as %s", user);
1517dd7cddfSDavid du Colombier putenv("service", "con");
1527dd7cddfSDavid du Colombier
1537dd7cddfSDavid du Colombier /* simulate /dev/consctl and /dev/cons using pipes */
1547dd7cddfSDavid du Colombier fd = conssim();
1557dd7cddfSDavid du Colombier if(fd < 0)
1567dd7cddfSDavid du Colombier fatal("simulating", 0, 0);
1577dd7cddfSDavid du Colombier Binit(&childib, fd, OREAD);
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier /* start a shell in a different process group */
1607dd7cddfSDavid du Colombier switch(childpid = rfork(RFPROC|RFNAMEG|RFFDG|RFNOTEG)){
1617dd7cddfSDavid du Colombier case -1:
1627dd7cddfSDavid du Colombier fatal("fork", 0, 0);
1637dd7cddfSDavid du Colombier case 0:
1647dd7cddfSDavid du Colombier close(fd);
1657dd7cddfSDavid du Colombier fd = open("/dev/cons", OREAD);
1667dd7cddfSDavid du Colombier dup(fd, 0);
1677dd7cddfSDavid du Colombier close(fd);
1687dd7cddfSDavid du Colombier fd = open("/dev/cons", OWRITE);
1697dd7cddfSDavid du Colombier dup(fd, 1);
1707dd7cddfSDavid du Colombier dup(fd, 2);
1717dd7cddfSDavid du Colombier close(fd);
1727dd7cddfSDavid du Colombier segdetach(cons);
173f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-il", nil);
1747dd7cddfSDavid du Colombier fatal("/bin/rc", 0, 0);
1757dd7cddfSDavid du Colombier default:
1767dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", childpid);
1777dd7cddfSDavid du Colombier notefd = open(buf, OWRITE);
1787dd7cddfSDavid du Colombier break;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier /* two processes to shuttle bytes twixt children and network */
1827dd7cddfSDavid du Colombier switch(fork()){
1837dd7cddfSDavid du Colombier case -1:
1847dd7cddfSDavid du Colombier fatal("fork", 0, 0);
1857dd7cddfSDavid du Colombier case 0:
1867dd7cddfSDavid du Colombier eofs = 0;
1877dd7cddfSDavid du Colombier for(;;){
1887dd7cddfSDavid du Colombier n = fromchild(buf, sizeof(buf));
1897dd7cddfSDavid du Colombier if(n <= 0){
1907dd7cddfSDavid du Colombier if(eofs++ > 2)
1917dd7cddfSDavid du Colombier break;
1927dd7cddfSDavid du Colombier continue;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier eofs = 0;
1957dd7cddfSDavid du Colombier if(write(1, buf, n) != n)
1967dd7cddfSDavid du Colombier break;
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier break;
1997dd7cddfSDavid du Colombier default:
2007dd7cddfSDavid du Colombier while((n = fromnet(buf, sizeof(buf))) >= 0)
2017dd7cddfSDavid du Colombier if(write(fd, buf, n) != n)
2027dd7cddfSDavid du Colombier break;
2037dd7cddfSDavid du Colombier break;
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier
2067dd7cddfSDavid du Colombier /* kill off all server processes */
2077dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", getpid());
2087dd7cddfSDavid du Colombier fd = open(buf, OWRITE);
2097dd7cddfSDavid du Colombier write(fd, "die", 3);
2107dd7cddfSDavid du Colombier exits(0);
2117dd7cddfSDavid du Colombier }
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier void
prompt(char * p,char * b,int n,int raw)2147dd7cddfSDavid du Colombier prompt(char *p, char *b, int n, int raw)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier char *e;
2177dd7cddfSDavid du Colombier int i;
2187dd7cddfSDavid du Colombier int echo;
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier echo = opt[Echo].local;
2217dd7cddfSDavid du Colombier if(raw)
2227dd7cddfSDavid du Colombier opt[Echo].local = 0;
2237dd7cddfSDavid du Colombier print("%s: ", p);
2247dd7cddfSDavid du Colombier for(e = b+n; b < e;){
2257dd7cddfSDavid du Colombier i = fromnet(b, e-b);
2267dd7cddfSDavid du Colombier if(i <= 0)
2277dd7cddfSDavid du Colombier exits("fromnet: hungup");
2287dd7cddfSDavid du Colombier b += i;
2297dd7cddfSDavid du Colombier if(*(b-1) == '\n' || *(b-1) == '\r'){
2307dd7cddfSDavid du Colombier *(b-1) = 0;
2317dd7cddfSDavid du Colombier break;
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier if(raw)
2357dd7cddfSDavid du Colombier opt[Echo].local = echo;
2367dd7cddfSDavid du Colombier }
2377dd7cddfSDavid du Colombier
2387dd7cddfSDavid du Colombier /*
2397dd7cddfSDavid du Colombier * challenge user
2407dd7cddfSDavid du Colombier */
2417dd7cddfSDavid du Colombier int
challuser(char * user)2427dd7cddfSDavid du Colombier challuser(char *user)
2437dd7cddfSDavid du Colombier {
2449a747e4fSDavid du Colombier char nchall[64];
2459a747e4fSDavid du Colombier char response[64];
2469a747e4fSDavid du Colombier Chalstate *ch;
2479a747e4fSDavid du Colombier AuthInfo *ai;
2487dd7cddfSDavid du Colombier
2497dd7cddfSDavid du Colombier if(strcmp(user, "none") == 0){
2507dd7cddfSDavid du Colombier if(nonone)
2517dd7cddfSDavid du Colombier return -1;
2529a747e4fSDavid du Colombier newns("none", nil);
2537dd7cddfSDavid du Colombier return 0;
2547dd7cddfSDavid du Colombier }
2559a747e4fSDavid du Colombier if((ch = auth_challenge("proto=p9cr role=server user=%q", user)) == nil)
2567dd7cddfSDavid du Colombier return -1;
2579a747e4fSDavid du Colombier snprint(nchall, sizeof nchall, "challenge: %s\r\nresponse", ch->chal);
2587dd7cddfSDavid du Colombier prompt(nchall, response, sizeof response, 0);
2599a747e4fSDavid du Colombier ch->resp = response;
2609a747e4fSDavid du Colombier ch->nresp = strlen(response);
2619a747e4fSDavid du Colombier ai = auth_response(ch);
2629a747e4fSDavid du Colombier auth_freechal(ch);
2633ff48bf5SDavid du Colombier if(ai == nil){
2643ff48bf5SDavid du Colombier rerrstr(response, sizeof response);
2653ff48bf5SDavid du Colombier print("!%s\n", response);
2667dd7cddfSDavid du Colombier return -1;
2673ff48bf5SDavid du Colombier }
2689a747e4fSDavid du Colombier if(auth_chuid(ai, nil) < 0)
2699a747e4fSDavid du Colombier return -1;
2707dd7cddfSDavid du Colombier return 0;
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier /*
2737dd7cddfSDavid du Colombier * use the in the clear apop password to change user id
2747dd7cddfSDavid du Colombier */
2757dd7cddfSDavid du Colombier int
noworldlogin(char * user)2767dd7cddfSDavid du Colombier noworldlogin(char *user)
2777dd7cddfSDavid du Colombier {
2787dd7cddfSDavid du Colombier char password[256];
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier prompt("password", password, sizeof(password), 1);
2817dd7cddfSDavid du Colombier if(login(user, password, "/lib/namespace.noworld") < 0)
2827dd7cddfSDavid du Colombier return -1;
2839a747e4fSDavid du Colombier rfork(RFNOMNT); /* sandbox */
2847dd7cddfSDavid du Colombier return 0;
2857dd7cddfSDavid du Colombier }
2867dd7cddfSDavid du Colombier
2877dd7cddfSDavid du Colombier int
doauth(char * user)2887dd7cddfSDavid du Colombier doauth(char *user)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier if(*user == 0)
2919a747e4fSDavid du Colombier prompt("user", user, Maxuser, 0);
2927dd7cddfSDavid du Colombier if(noworld(user))
2937dd7cddfSDavid du Colombier return noworldlogin(user);
2949a747e4fSDavid du Colombier if(noworldonly)
2959a747e4fSDavid du Colombier return -1;
2967dd7cddfSDavid du Colombier return challuser(user);
2977dd7cddfSDavid du Colombier
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier /*
3017dd7cddfSDavid du Colombier * Process some input from the child, add protocol if needed. If
3027dd7cddfSDavid du Colombier * the input buffer goes empty, return.
3037dd7cddfSDavid du Colombier */
3047dd7cddfSDavid du Colombier int
fromchild(char * bp,int len)3057dd7cddfSDavid du Colombier fromchild(char *bp, int len)
3067dd7cddfSDavid du Colombier {
3077dd7cddfSDavid du Colombier int c;
3087dd7cddfSDavid du Colombier char *start;
3097dd7cddfSDavid du Colombier
3107dd7cddfSDavid du Colombier for(start = bp; bp-start < len-1; ){
3117dd7cddfSDavid du Colombier c = Bgetc(&childib);
3127dd7cddfSDavid du Colombier if(c < 0){
3137dd7cddfSDavid du Colombier if(bp == start)
3147dd7cddfSDavid du Colombier return -1;
3157dd7cddfSDavid du Colombier else
3167dd7cddfSDavid du Colombier break;
3177dd7cddfSDavid du Colombier }
3187dd7cddfSDavid du Colombier if(cons->raw == 0 && c == '\n')
3197dd7cddfSDavid du Colombier *bp++ = '\r';
3207dd7cddfSDavid du Colombier *bp++ = c;
3217dd7cddfSDavid du Colombier if(Bbuffered(&childib) == 0)
3227dd7cddfSDavid du Colombier break;
3237dd7cddfSDavid du Colombier }
3247dd7cddfSDavid du Colombier return bp-start;
3257dd7cddfSDavid du Colombier }
3267dd7cddfSDavid du Colombier
3277dd7cddfSDavid du Colombier /*
3287dd7cddfSDavid du Colombier * Read from the network up to a '\n' or some other break.
3297dd7cddfSDavid du Colombier *
3307dd7cddfSDavid du Colombier * If in binary mode, buffer characters but don't
3317dd7cddfSDavid du Colombier *
3327dd7cddfSDavid du Colombier * The following characters are special:
3337dd7cddfSDavid du Colombier * '\r\n's and '\r's get turned into '\n's.
3347dd7cddfSDavid du Colombier * ^H erases the last character buffered.
3357dd7cddfSDavid du Colombier * ^U kills the whole line buffered.
3367dd7cddfSDavid du Colombier * ^W erases the last word
337*aef37788SDavid du Colombier * ^D causes a 0-length line to be returned.
3387dd7cddfSDavid du Colombier * Intr causes an "interrupt" note to be sent to the children.
3397dd7cddfSDavid du Colombier */
3407dd7cddfSDavid du Colombier #define ECHO(c) { *ebp++ = (c); }
3417dd7cddfSDavid du Colombier int
fromnet(char * bp,int len)3427dd7cddfSDavid du Colombier fromnet(char *bp, int len)
3437dd7cddfSDavid du Colombier {
3447dd7cddfSDavid du Colombier int c;
3457dd7cddfSDavid du Colombier char echobuf[1024];
3467dd7cddfSDavid du Colombier char *ebp;
3477dd7cddfSDavid du Colombier char *start;
3487dd7cddfSDavid du Colombier static int crnl;
3497dd7cddfSDavid du Colombier static int doeof;
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier /* simulate an EOF as a 0 length input */
3537dd7cddfSDavid du Colombier if(doeof){
3547dd7cddfSDavid du Colombier doeof = 0;
3557dd7cddfSDavid du Colombier return 0;
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier for(ebp = echobuf,start = bp; bp-start < len && ebp-echobuf < sizeof(echobuf); ){
3597dd7cddfSDavid du Colombier c = Bgetc(&netib);
3607dd7cddfSDavid du Colombier if(c < 0){
3617dd7cddfSDavid du Colombier if(bp == start)
3627dd7cddfSDavid du Colombier return -1;
3637dd7cddfSDavid du Colombier else
3647dd7cddfSDavid du Colombier break;
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier /* telnet protocol only */
3687dd7cddfSDavid du Colombier if(!noproto){
3697dd7cddfSDavid du Colombier /* protocol messages */
3707dd7cddfSDavid du Colombier switch(c){
3717dd7cddfSDavid du Colombier case Iac:
3727dd7cddfSDavid du Colombier crnl = 0;
3737dd7cddfSDavid du Colombier c = Bgetc(&netib);
3747dd7cddfSDavid du Colombier if(c == Iac)
3757dd7cddfSDavid du Colombier break;
3767dd7cddfSDavid du Colombier control(&netib, c);
3777dd7cddfSDavid du Colombier continue;
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier
3827dd7cddfSDavid du Colombier /* \r\n or \n\r become \n */
3837dd7cddfSDavid du Colombier if(c == '\r' || c == '\n'){
3847dd7cddfSDavid du Colombier if(crnl && crnl != c){
3857dd7cddfSDavid du Colombier crnl = 0;
3867dd7cddfSDavid du Colombier continue;
3877dd7cddfSDavid du Colombier }
3887dd7cddfSDavid du Colombier if(cons->raw == 0 && opt[Echo].local){
3897dd7cddfSDavid du Colombier ECHO('\r');
3907dd7cddfSDavid du Colombier ECHO('\n');
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier crnl = c;
3937dd7cddfSDavid du Colombier if(cons->raw == 0)
3947dd7cddfSDavid du Colombier *bp++ = '\n';
3957dd7cddfSDavid du Colombier else
3967dd7cddfSDavid du Colombier *bp++ = c;
3977dd7cddfSDavid du Colombier break;
3987dd7cddfSDavid du Colombier } else
3997dd7cddfSDavid du Colombier crnl = 0;
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier /* raw processing (each character terminates */
4027dd7cddfSDavid du Colombier if(cons->raw){
4037dd7cddfSDavid du Colombier *bp++ = c;
4047dd7cddfSDavid du Colombier break;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier /* in binary mode, there are no control characters */
4087dd7cddfSDavid du Colombier if(opt[Binary].local){
4097dd7cddfSDavid du Colombier if(opt[Echo].local)
4107dd7cddfSDavid du Colombier ECHO(c);
4117dd7cddfSDavid du Colombier *bp++ = c;
4127dd7cddfSDavid du Colombier continue;
4137dd7cddfSDavid du Colombier }
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier /* cooked processing */
4167dd7cddfSDavid du Colombier switch(c){
4177dd7cddfSDavid du Colombier case 0x00:
4187dd7cddfSDavid du Colombier if(noproto) /* telnet ignores nulls */
4197dd7cddfSDavid du Colombier *bp++ = c;
4207dd7cddfSDavid du Colombier continue;
4217dd7cddfSDavid du Colombier case 0x04:
4227dd7cddfSDavid du Colombier if(bp != start)
4237dd7cddfSDavid du Colombier doeof = 1;
4247dd7cddfSDavid du Colombier goto out;
4257dd7cddfSDavid du Colombier
4267dd7cddfSDavid du Colombier case 0x08: /* ^H */
4277dd7cddfSDavid du Colombier if(start < bp)
4287dd7cddfSDavid du Colombier bp--;
4297dd7cddfSDavid du Colombier if(opt[Echo].local)
4307dd7cddfSDavid du Colombier ECHO(c);
4317dd7cddfSDavid du Colombier break;
4327dd7cddfSDavid du Colombier
4337dd7cddfSDavid du Colombier case 0x15: /* ^U */
4347dd7cddfSDavid du Colombier bp = start;
4357dd7cddfSDavid du Colombier if(opt[Echo].local){
4367dd7cddfSDavid du Colombier ECHO('^');
4377dd7cddfSDavid du Colombier ECHO('U');
4387dd7cddfSDavid du Colombier ECHO('\r');
4397dd7cddfSDavid du Colombier ECHO('\n');
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier break;
4427dd7cddfSDavid du Colombier
4437dd7cddfSDavid du Colombier case 0x17: /* ^W */
4447dd7cddfSDavid du Colombier if (opt[Echo].local) {
4457dd7cddfSDavid du Colombier while (--bp >= start && !alnum(*bp))
4467dd7cddfSDavid du Colombier ECHO('\b');
4477dd7cddfSDavid du Colombier while (bp >= start && alnum(*bp)) {
4487dd7cddfSDavid du Colombier ECHO('\b');
4497dd7cddfSDavid du Colombier bp--;
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier bp++;
4527dd7cddfSDavid du Colombier }
4537dd7cddfSDavid du Colombier break;
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier case 0x7f: /* Del */
4567dd7cddfSDavid du Colombier write(notefd, "interrupt", 9);
45759cc4ca5SDavid du Colombier bp = start;
4587dd7cddfSDavid du Colombier break;
4597dd7cddfSDavid du Colombier
4607dd7cddfSDavid du Colombier default:
4617dd7cddfSDavid du Colombier if(opt[Echo].local)
4627dd7cddfSDavid du Colombier ECHO(c);
4637dd7cddfSDavid du Colombier *bp++ = c;
4647dd7cddfSDavid du Colombier }
4657dd7cddfSDavid du Colombier if(ebp != echobuf)
4667dd7cddfSDavid du Colombier write(1, echobuf, ebp-echobuf);
4677dd7cddfSDavid du Colombier ebp = echobuf;
4687dd7cddfSDavid du Colombier }
4697dd7cddfSDavid du Colombier out:
4707dd7cddfSDavid du Colombier if(ebp != echobuf)
4717dd7cddfSDavid du Colombier write(1, echobuf, ebp-echobuf);
4727dd7cddfSDavid du Colombier return bp - start;
4737dd7cddfSDavid du Colombier }
4747dd7cddfSDavid du Colombier
4757dd7cddfSDavid du Colombier int
termchange(Biobuf * bp,int cmd)4767dd7cddfSDavid du Colombier termchange(Biobuf *bp, int cmd)
4777dd7cddfSDavid du Colombier {
4787dd7cddfSDavid du Colombier char buf[8];
4797dd7cddfSDavid du Colombier char *p = buf;
4807dd7cddfSDavid du Colombier
4817dd7cddfSDavid du Colombier if(cmd != Will)
4827dd7cddfSDavid du Colombier return 0;
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier /* ask other side to send term type info */
4857dd7cddfSDavid du Colombier *p++ = Iac;
4867dd7cddfSDavid du Colombier *p++ = Sb;
4877dd7cddfSDavid du Colombier *p++ = opt[Term].code;
4887dd7cddfSDavid du Colombier *p++ = 1;
4897dd7cddfSDavid du Colombier *p++ = Iac;
4907dd7cddfSDavid du Colombier *p++ = Se;
4917dd7cddfSDavid du Colombier return iwrite(Bfildes(bp), buf, p-buf);
4927dd7cddfSDavid du Colombier }
4937dd7cddfSDavid du Colombier
4947dd7cddfSDavid du Colombier int
termsub(Biobuf * bp,uchar * sub,int n)4957dd7cddfSDavid du Colombier termsub(Biobuf *bp, uchar *sub, int n)
4967dd7cddfSDavid du Colombier {
4979a747e4fSDavid du Colombier char term[Maxvar];
4987dd7cddfSDavid du Colombier
4997dd7cddfSDavid du Colombier USED(bp);
5007dd7cddfSDavid du Colombier if(n-- < 1 || sub[0] != 0)
5017dd7cddfSDavid du Colombier return 0;
5027dd7cddfSDavid du Colombier if(n >= sizeof term)
5037dd7cddfSDavid du Colombier n = sizeof term;
5047dd7cddfSDavid du Colombier strncpy(term, (char*)sub, n);
5057dd7cddfSDavid du Colombier putenv("TERM", term);
5067dd7cddfSDavid du Colombier return 0;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier int
xlocchange(Biobuf * bp,int cmd)5107dd7cddfSDavid du Colombier xlocchange(Biobuf *bp, int cmd)
5117dd7cddfSDavid du Colombier {
5127dd7cddfSDavid du Colombier char buf[8];
5137dd7cddfSDavid du Colombier char *p = buf;
5147dd7cddfSDavid du Colombier
5157dd7cddfSDavid du Colombier if(cmd != Will)
5167dd7cddfSDavid du Colombier return 0;
5177dd7cddfSDavid du Colombier
5187dd7cddfSDavid du Colombier /* ask other side to send x display info */
5197dd7cddfSDavid du Colombier *p++ = Iac;
5207dd7cddfSDavid du Colombier *p++ = Sb;
5217dd7cddfSDavid du Colombier *p++ = opt[Xloc].code;
5227dd7cddfSDavid du Colombier *p++ = 1;
5237dd7cddfSDavid du Colombier *p++ = Iac;
5247dd7cddfSDavid du Colombier *p++ = Se;
5257dd7cddfSDavid du Colombier return iwrite(Bfildes(bp), buf, p-buf);
5267dd7cddfSDavid du Colombier }
5277dd7cddfSDavid du Colombier
5287dd7cddfSDavid du Colombier int
xlocsub(Biobuf * bp,uchar * sub,int n)5297dd7cddfSDavid du Colombier xlocsub(Biobuf *bp, uchar *sub, int n)
5307dd7cddfSDavid du Colombier {
5319a747e4fSDavid du Colombier char xloc[Maxvar];
5327dd7cddfSDavid du Colombier
5337dd7cddfSDavid du Colombier USED(bp);
5347dd7cddfSDavid du Colombier if(n-- < 1 || sub[0] != 0)
5357dd7cddfSDavid du Colombier return 0;
5367dd7cddfSDavid du Colombier if(n >= sizeof xloc)
5377dd7cddfSDavid du Colombier n = sizeof xloc;
5387dd7cddfSDavid du Colombier strncpy(xloc, (char*)sub, n);
5397dd7cddfSDavid du Colombier putenv("DISPLAY", xloc);
5407dd7cddfSDavid du Colombier return 0;
5417dd7cddfSDavid du Colombier }
5427dd7cddfSDavid du Colombier
5437dd7cddfSDavid du Colombier /*
5447dd7cddfSDavid du Colombier * create a shared segment. Make is start 2 meg higher than the current
5457dd7cddfSDavid du Colombier * end of process memory.
5467dd7cddfSDavid du Colombier */
5477dd7cddfSDavid du Colombier void*
share(ulong len)54874f16c81SDavid du Colombier share(ulong len)
5497dd7cddfSDavid du Colombier {
5507545821fSDavid du Colombier uchar *vastart;
5517dd7cddfSDavid du Colombier
5527545821fSDavid du Colombier vastart = sbrk(0);
55374f16c81SDavid du Colombier if(vastart == (void*)-1)
55474f16c81SDavid du Colombier return 0;
5557545821fSDavid du Colombier vastart += 2*1024*1024;
5567dd7cddfSDavid du Colombier
55774f16c81SDavid du Colombier if(segattach(0, "shared", vastart, len) == (void*)-1)
5587dd7cddfSDavid du Colombier return 0;
5597dd7cddfSDavid du Colombier
5607545821fSDavid du Colombier return vastart;
5617dd7cddfSDavid du Colombier }
5627dd7cddfSDavid du Colombier
5637dd7cddfSDavid du Colombier /*
5647dd7cddfSDavid du Colombier * bind a pipe onto consctl and keep reading it to
5657dd7cddfSDavid du Colombier * get changes to console state.
5667dd7cddfSDavid du Colombier */
5677dd7cddfSDavid du Colombier int
conssim(void)5687dd7cddfSDavid du Colombier conssim(void)
5697dd7cddfSDavid du Colombier {
5707dd7cddfSDavid du Colombier int i, n;
5717dd7cddfSDavid du Colombier int fd;
5727dd7cddfSDavid du Colombier int tries;
5737dd7cddfSDavid du Colombier char buf[128];
5747dd7cddfSDavid du Colombier char *field[10];
5757dd7cddfSDavid du Colombier
5767dd7cddfSDavid du Colombier /* a pipe to simulate the /dev/cons */
5777dd7cddfSDavid du Colombier if(bind("#|", "/mnt/cons/cons", MREPL) < 0)
5787dd7cddfSDavid du Colombier fatal("/dev/cons1", 0, 0);
5797dd7cddfSDavid du Colombier if(bind("/mnt/cons/cons/data1", "/dev/cons", MREPL) < 0)
5807dd7cddfSDavid du Colombier fatal("/dev/cons2", 0, 0);
5817dd7cddfSDavid du Colombier
5827dd7cddfSDavid du Colombier /* a pipe to simulate consctl */
5837dd7cddfSDavid du Colombier if(bind("#|", "/mnt/cons/consctl", MBEFORE) < 0
5847dd7cddfSDavid du Colombier || bind("/mnt/cons/consctl/data1", "/dev/consctl", MREPL) < 0)
5857dd7cddfSDavid du Colombier fatal("/dev/consctl", 0, 0);
5867dd7cddfSDavid du Colombier
5877dd7cddfSDavid du Colombier /* a process to read /dev/consctl and set the state in cons */
5887dd7cddfSDavid du Colombier switch(fork()){
5897dd7cddfSDavid du Colombier case -1:
5907dd7cddfSDavid du Colombier fatal("forking", 0, 0);
5917dd7cddfSDavid du Colombier case 0:
5927dd7cddfSDavid du Colombier break;
5937dd7cddfSDavid du Colombier default:
5947dd7cddfSDavid du Colombier return open("/mnt/cons/cons/data", ORDWR);
5957dd7cddfSDavid du Colombier }
5967dd7cddfSDavid du Colombier
5977dd7cddfSDavid du Colombier for(tries = 0; tries < 100; tries++){
5987dd7cddfSDavid du Colombier cons->raw = 0;
5997dd7cddfSDavid du Colombier cons->hold = 0;
6007dd7cddfSDavid du Colombier fd = open("/mnt/cons/consctl/data", OREAD);
6017dd7cddfSDavid du Colombier if(fd < 0)
6027dd7cddfSDavid du Colombier continue;
6037dd7cddfSDavid du Colombier tries = 0;
6047dd7cddfSDavid du Colombier for(;;){
6057dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)-1);
6067dd7cddfSDavid du Colombier if(n <= 0)
6077dd7cddfSDavid du Colombier break;
6087dd7cddfSDavid du Colombier buf[n] = 0;
6097dd7cddfSDavid du Colombier n = getfields(buf, field, 10, 1, " ");
6107dd7cddfSDavid du Colombier for(i = 0; i < n; i++){
6117dd7cddfSDavid du Colombier if(strcmp(field[i], "rawon") == 0) {
6127dd7cddfSDavid du Colombier if(debug) fprint(2, "raw = 1\n");
6137dd7cddfSDavid du Colombier cons->raw = 1;
6147dd7cddfSDavid du Colombier } else if(strcmp(field[i], "rawoff") == 0) {
6157dd7cddfSDavid du Colombier if(debug) fprint(2, "raw = 0\n");
6167dd7cddfSDavid du Colombier cons->raw = 0;
6177dd7cddfSDavid du Colombier } else if(strcmp(field[i], "holdon") == 0) {
6187dd7cddfSDavid du Colombier cons->hold = 1;
6197dd7cddfSDavid du Colombier if(debug) fprint(2, "raw = 1\n");
6207dd7cddfSDavid du Colombier } else if(strcmp(field[i], "holdoff") == 0) {
6217dd7cddfSDavid du Colombier cons->hold = 0;
6227dd7cddfSDavid du Colombier if(debug) fprint(2, "raw = 0\n");
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier }
6257dd7cddfSDavid du Colombier }
6267dd7cddfSDavid du Colombier close(fd);
6277dd7cddfSDavid du Colombier }
6287dd7cddfSDavid du Colombier exits(0);
6297dd7cddfSDavid du Colombier return -1;
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier
6327dd7cddfSDavid du Colombier int
alnum(int c)6337dd7cddfSDavid du Colombier alnum(int c)
6347dd7cddfSDavid du Colombier {
6357dd7cddfSDavid du Colombier /*
6367dd7cddfSDavid du Colombier * Hard to get absolutely right. Use what we know about ASCII
6377dd7cddfSDavid du Colombier * and assume anything above the Latin control characters is
6387dd7cddfSDavid du Colombier * potentially an alphanumeric.
6397dd7cddfSDavid du Colombier */
6407dd7cddfSDavid du Colombier if(c <= ' ')
6417dd7cddfSDavid du Colombier return 0;
6427dd7cddfSDavid du Colombier if(0x7F<=c && c<=0xA0)
6437dd7cddfSDavid du Colombier return 0;
6447dd7cddfSDavid du Colombier if(strchr("!\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", c))
6457dd7cddfSDavid du Colombier return 0;
6467dd7cddfSDavid du Colombier return 1;
6477dd7cddfSDavid du Colombier }
648