Beispiel #1
0
/*----------------------------------------------------------------------+*/
SPC_Channel_Ptr open_pty_channel_object(SPC_Channel_Ptr channel,
					int iomode,
					XeString hostname)
/*----------------------------------------------------------------------+*/
{

  Wire *tmpwire, *newwire;
  SPC_Channel_Ptr result;
  
  call_parent_method(channel, open, (channel, iomode, hostname), result);

  if(result==SPC_ERROR)
    return(SPC_ERROR);

  /* We know that we are going to use one of STDIN, STDOUT, or STDERR
     (or else we would be a NOIO channel), so allocate at least one
     pty pair */

  if(!(tmpwire=getpty(NULL)))
    return(SPC_ERROR);

  if (IS_SPCIO_STDIN(iomode)) {
    channel->wires[STDIN]=tmpwire;
  }
  
  if (IS_SPCIO_STDOUT(iomode)) {
    channel->wires[STDOUT]=tmpwire;
  }
  
  if (IS_SPCIO_SEPARATE(iomode)) {
    if(!(newwire=getpty(tmpwire))) {
      spc_close(tmpwire->fd[MASTER_SIDE]);
      free_wire(tmpwire);
      return(SPC_ERROR);
    } else
      tmpwire=newwire;
  }
  
  if (IS_SPCIO_STDERR(iomode)) {
    channel->wires[STDERR]=tmpwire;
  }
  
  channel->wire_list=tmpwire;
  
  /* set up the channel file descriptors */

  channel->file_descs[STDIN]  = (channel->wires[STDIN]) ->fd[MASTER_SIDE];
  channel->file_descs[STDOUT] = (channel->wires[STDOUT])->fd[MASTER_SIDE];
  channel->file_descs[STDERR] = (channel->wires[STDERR])->fd[MASTER_SIDE];

  for(tmpwire=channel->wire_list; tmpwire; tmpwire=tmpwire->next) {
    init_termio(&tmpwire->master_termio);
    init_termio(&tmpwire->slave_termio);
  }
  
  return(channel);

}
bool
SpawningUploadClient::SpawnCommand()
{
	char ptypath[20];
	char ttypath[20];
	//XXX: should use a system-provided TerminalCommand class
	BString shellcmd = "exec";
	const char *args[] = { "/bin/sh", "-c", NULL, NULL };
	fPty = getpty(ptypath, ttypath);
	if (fPty < 0)
		return B_ERROR;

	shellcmd << " 0<" << ttypath;
	shellcmd << " 1>" << ttypath;
	shellcmd += " 2>&1";
	shellcmd << " ; ";
	shellcmd << "export TTY=" << ttypath << "; "; // BeOS hack
	shellcmd << "export LC_ALL=C; export LANG=C; ";
	shellcmd << "exec ";
	shellcmd << fCommand.c_str();
printf("spawning: '%s'\n", shellcmd.String());
	args[2] = shellcmd.String();
	fCommandPid = load_image(3, args, (const char **)environ);
	if (fCommandPid < 0)
		return false;
	resume_thread(fCommandPid);
	return true;
}
Beispiel #3
0
int
openpty(int *master, int *slave, char *name, struct termios *term, struct winsize *winsz)
{
  if (getpty(master, slave, name) == -1)
  {
    return (-1);
  }
  if (term)
  {
    (void) tcsetattr(*slave, TCSANOW, term);
  }
  if (winsz)
  {
    (void) ioctl(*slave, TIOCSWINSZ, winsz);
  }

  return (0);
}
Beispiel #4
0
	/* We rely on that there is space in the buffer for now.  */
	char *b = ts->buf2 + ts->rdidx2;
	*b++ = IAC;
	*b++ = command;
	*b++ = option;
	ts->rdidx2 += 3;
	ts->size2 += 3;
}


static struct tsession *
#ifdef CONFIG_FEATURE_TELNETD_INETD
make_new_session(void)
#else /* CONFIG_FEATURE_TELNETD_INETD */
make_new_session(int sockfd)
#endif /* CONFIG_FEATURE_TELNETD_INETD */
{
	struct termios termbuf;
	int pty, pid;
	char tty_name[32];
	struct tsession *ts = malloc(sizeof(struct tsession) + BUFSIZE * 2);

	ts->buf1 = (char *)(&ts[1]);
	ts->buf2 = ts->buf1 + BUFSIZE;

#ifdef CONFIG_FEATURE_TELNETD_INETD
	ts->sockfd_read = 0;
	ts->sockfd_write = 1;
#else /* CONFIG_FEATURE_TELNETD_INETD */
	ts->sockfd = sockfd;
#endif /* CONFIG_FEATURE_TELNETD_INETD */

	ts->rdidx1 = ts->wridx1 = ts->size1 = 0;
	ts->rdidx2 = ts->wridx2 = ts->size2 = 0;

#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
	/* initialize it with the timeout value*/
	ts->timeout_time = time(NULL) + TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */	

	/* Got a new connection, set up a tty and spawn a shell.  */

	pty = getpty(tty_name);

	if (pty < 0) {
		syslog(LOG_ERR, "All network ports in use!");
		return 0;
	}

	if (pty > maxfd)
		maxfd = pty;

	ts->ptyfd = pty;

	/* Make the telnet client understand we will echo characters so it
	 * should not do it locally. We don't tell the client to run linemode,
	 * because we want to handle line editing and tab completion and other
	 * stuff that requires char-by-char support.
	 */

	send_iac(ts, DO, TELOPT_ECHO);
	send_iac(ts, DO, TELOPT_NAWS);
	send_iac(ts, DO, TELOPT_LFLOW);
	send_iac(ts, WILL, TELOPT_ECHO);
	send_iac(ts, WILL, TELOPT_SGA);


	if ((pid = fork()) < 0) {
		syslog(LOG_ERR, "Can`t forking");
	}
	if (pid == 0) {
		/* In child, open the child's side of the tty.  */
		int i;

		for(i = 0; i <= maxfd; i++)
			close(i);
		/* make new process group */
		setsid();

		if (open(tty_name, O_RDWR /*| O_NOCTTY*/) < 0) {
			syslog(LOG_ERR, "Could not open tty");
			exit(1);
			}
		dup(0);
		dup(0);

		tcsetpgrp(0, getpid());

		/* The pseudo-terminal allocated to the client is configured to operate in
		 * cooked mode, and with XTABS CRMOD enabled (see tty(4)).
		 */

		tcgetattr(0, &termbuf);
		termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
		termbuf.c_oflag |= ONLCR|XTABS;
		termbuf.c_iflag |= ICRNL;
		termbuf.c_iflag &= ~IXOFF;
		/*termbuf.c_lflag &= ~ICANON;*/
		tcsetattr(0, TCSANOW, &termbuf);

		print_login_issue(issuefile, NULL);

		/* exec shell, with correct argv and env */
		execv(loginpath, (char *const *)argv_init);

		/* NOT REACHED */
		syslog(LOG_ERR, "execv error");
		exit(1);
	}

	ts->shell_pid = pid;

	return ts;
}
Beispiel #5
0
static struct tsession *
make_new_session(int sockfd)
{
	struct termios termbuf;
	int pty, pid;
	static char tty_name[32];
	struct tsession *ts = (struct tsession *)malloc(sizeof(struct tsession));
	int t1, t2;
#ifdef USE_ISSUE
	FILE *fp;
	int chr;
#endif
	ts->buf1 = (char *)malloc(BUFSIZE);
	ts->buf2 = (char *)malloc(BUFSIZE);

	ts->sockfd = sockfd;

	ts->rdidx1 = ts->wridx1 = ts->size1 = 0;
	ts->rdidx2 = ts->wridx2 = ts->size2 = 0;

	/* Got a new connection, set up a tty and spawn a shell.  */

	pty = getpty(tty_name);

	if (pty < 0) {
		fprintf(stderr, "All network ports in use!\n");
		return 0;
	}

	if (pty > maxfd)
		maxfd = pty;

	ts->ptyfd = pty;

	/* Make the telnet client understand we will echo characters so it 
	 * should not do it locally. We don't tell the client to run linemode,
	 * because we want to handle line editing and tab completion and other
	 * stuff that requires char-by-char support.
	 */

	send_iac(ts, DO, TELOPT_ECHO);
	send_iac(ts, DO, TELOPT_LFLOW);
	send_iac(ts, WILL, TELOPT_ECHO);
	send_iac(ts, WILL, TELOPT_SGA);


	if ((pid = fork()) < 0) {
		perror("fork");
	}
	if (pid == 0) {
		/* In child, open the child's side of the tty.  */
		int i, t;

		for(i = 0; i <= maxfd; i++)
			close(i);

		/* make new process group */
		if (setsid() < 0)
			perror_msg_and_die("setsid");
		t = open(tty_name, O_RDWR | O_NOCTTY);
		//t = open(tty_name, O_RDWR);
		if (t < 0)
			perror_msg_and_die("Could not open tty");

		t1 = dup(0);
		t2 = dup(1);

		tcsetpgrp(0, getpid());
		if (ioctl(t, TIOCSCTTY, NULL)) {
			perror_msg_and_die("could not set controlling tty");
		} 
   
		/* The pseudo-terminal allocated to the client is configured to operate in
		 * cooked mode, and with XTABS CRMOD enabled (see tty(4)).
		 */

		tcgetattr(t, &termbuf);
		termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
		termbuf.c_oflag |= ONLCR|XTABS;
		termbuf.c_iflag |= ICRNL;
		termbuf.c_iflag &= ~IXOFF;
		/* termbuf.c_lflag &= ~ICANON; */
		tcsetattr(t, TCSANOW, &termbuf);

		DEBUG_OUT("stdin, stdout, stderr: %d %d %d\n", t, t1, t2);
#ifdef USE_ISSUE
		/* Display ISSUE_FILE */
		if ((fp = fopen(ISSUE_FILE, "r")) != NULL) {
			DEBUG_OUT(" Open & start display %s\n", ISSUE_FILE);
			while ((chr=fgetc(fp)) != EOF) { 
				if (chr == '\n') fputc('\r', stdout);
				fputc(chr, stdout);
			}
			fclose(fp);
		}
#endif
		/* exec shell, with correct argv and env */
		execv(loginpath, argv_init);

	        /* NOT REACHED */
		perror_msg_and_die("execv");
	}

	ts->shell_pid = pid;

	return ts;
}
Beispiel #6
0
static struct tsession *
make_new_session(
		USE_FEATURE_TELNETD_STANDALONE(int sock_r, int sock_w)
		SKIP_FEATURE_TELNETD_STANDALONE(void)
) {
	const char *login_argv[2];
	struct termios termbuf;
	int fd, pid;
	char tty_name[32];
	struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);

	ts->buf1 = (char *)(&ts[1]);
	ts->buf2 = ts->buf1 + BUFSIZE;

	/* Got a new connection, set up a tty. */
	fd = getpty(tty_name, 32);
	if (fd < 0) {
		bb_error_msg("all terminals in use");
		return NULL;
	}
	if (fd > maxfd) maxfd = fd;
	ndelay_on(ts->ptyfd = fd);
#if ENABLE_FEATURE_TELNETD_STANDALONE
	if (sock_w > maxfd) maxfd = sock_w;
	if (sock_r > maxfd) maxfd = sock_r;
	ndelay_on(ts->sockfd_write = sock_w);
	ndelay_on(ts->sockfd_read = sock_r);
#else
	ts->sockfd_write = 1;
	/* xzalloc: ts->sockfd_read = 0; */
	ndelay_on(0);
Beispiel #7
0
/*
 * Get a pty, scan input lines.
 */
static void
doit(struct sockaddr_in *who)
{
	const char *host;
#ifndef REALLY_SMALL_TELNETD
	struct hostent *hp;
#endif
	int level;
	char user_name[256];

	/*
	 * Find an available pty to use.
	 */
#ifndef	convex
	pty = getpty();
	if (pty < 0)
		fatal(net, "All network ports in use");
#else
	for (;;) {
		char *lp;
		extern char *line, *getpty();

		if ((lp = getpty()) == NULL)
			fatal(net, "Out of ptys");

		if ((pty = open(lp, 2)) >= 0) {
			strcpy(line,lp);
			line[5] = 't';
			break;
		}
	}
#endif

#ifndef REALLY_SMALL_TELNETD
	/* get name of connected client */
	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
		who->sin_family);
	if (hp)
		host = hp->h_name;
	else
#endif
		host = inet_ntoa(who->sin_addr);

#ifndef REALLY_SMALL_TELNETD
	/*
	 * We must make a copy because Kerberos is probably going
	 * to also do a gethost* and overwrite the static data...
	 */
	strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
	remote_host_name[sizeof(remote_host_name)-1] = 0;
	host = remote_host_name;

	{
		struct hostent *h;
		gethostname(host_name, sizeof(host_name));
		h = gethostbyname(host_name);
		if (h) {
		    strncpy(host_name, h->h_name, sizeof(host_name));
		    host_name[sizeof(host_name)-1] = 0;
		}
	}
#endif

#if	defined(AUTHENTICATE) || defined(ENCRYPT)
	auth_encrypt_init(host_name, host, "TELNETD", 1);
#endif

	init_env();
	/*
	 * get terminal type.
	 */
	*user_name = 0;
	level = getterminaltype(user_name);
#ifdef ENV
	setenv("TERM", terminaltype ? terminaltype : "network", 1);
#endif

	/*
	 * Start up the login process on the slave side of the terminal
	 */
#ifndef	convex
	startslave(host, level, user_name);

	telnet(net, pty);  /* begin server processing */
#else
	telnet(net, pty, host);
#endif
	/*NOTREACHED*/
}  /* end of doit */
Beispiel #8
0
void send_commands(int fildes, char * file)
{
    FILE * fp;
    char * line = NULL;

    fp = fopen(file, "r");
    if (!fp) {
        perror("Failed to open commands file");
        exit(EXIT_FAILURE);
    }

    while (1) {
        char input;
        size_t n, len;
        fd_set rfds;
        struct timeval timeout = { .tv_sec = 5, .tv_usec = 0, };
        int retval;

        FD_ZERO(&rfds);
        FD_SET(fildes, &rfds);

        retval = select(fildes + 1, &rfds, NULL, NULL, &timeout);
        if (retval == -1 || retval == 0) {
            pty_timeout = 1;
            break;
        }
        if (read(fildes, &input, sizeof(char)) <= 0)
            break;
        write(STDOUT_FILENO, &input, sizeof(char));

        if (input == '#' && (len = getline(&line, &n, fp)) != -1) {
            line[len - 1] = '\r';
            write(fildes, line, len);
            if (!strcmp(line, "exit\r"))
                break;
        } else if (len == -1) {
            break;
        }
    }

    free(line);
    fclose(fp);
}

int main(int argc, char * argv[])
{
    int pty[2];
    pid_t pid;

    if (argc < 3) {
        printf("Usage: %s FILE args\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (getpty(pty)) {
        fprintf(stderr, "Failed to get pty\n");
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid == -1) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        struct termios new_term;

        close(pty[0]); /* Close the master side */
        cfmakeraw(&new_term);
        tcsetattr(pty[1], TCSANOW, &new_term);
        close(0);
        close(1);
        dup(pty[1]);
        dup(pty[1]);

        if (execvp(argv[2], argv + 2))
            perror("Exec failed");

        exit(EXIT_FAILURE);
    }

    close(pty[1]); /* Close the slave side */
    send_commands(pty[0], argv[1]);
    kill(pid, SIGINT);
    wait(NULL);
    close(pty[0]);

    return (pty_timeout) ? EXIT_FAILURE : 0;
}
Beispiel #9
0
int script_main(int argc ATTRIBUTE_UNUSED, char **argv)
{
	int opt;
	int mode;
	int child_pid;
	int attr_ok; /* NB: 0: ok */
	int winsz_ok;
	int pty;
	char pty_line[GETPTY_BUFSIZE];
	struct termios tt, rtt;
	struct winsize win;
	const char *fname = "typescript";
	const char *shell;
	char shell_opt[] = "-i";
	char *shell_arg = NULL;

#if ENABLE_GETOPT_LONG
	static const char getopt_longopts[] ALIGN1 =
		"append\0"  No_argument       "a"
		"command\0" Required_argument "c"
		"flush\0"   No_argument       "f"
		"quiet\0"   No_argument       "q"
		;

	applet_long_options = getopt_longopts;
#endif
	opt_complementary = "?1"; /* max one arg */
	opt = getopt32(argv, "ac:fq", &shell_arg);
	//argc -= optind;
	argv += optind;
	if (argv[0]) {
		fname = argv[0];
	}
	mode = O_CREAT|O_TRUNC|O_WRONLY;
	if (opt & 1) {
		mode = O_CREAT|O_APPEND|O_WRONLY;
	}
	if (opt & 2) {
		shell_opt[1] = 'c';
	}
	if (!(opt & 8)) { /* not -q */
		printf("Script started, file is %s\n", fname);
	}
	shell = getenv("SHELL");
	if (shell == NULL) {
		shell = DEFAULT_SHELL;
	}

	pty = getpty(pty_line);
	if (pty < 0) {
		bb_perror_msg_and_die("can't get pty");
	}

	/* get current stdin's tty params */
	attr_ok = tcgetattr(0, &tt);
	winsz_ok = ioctl(0, TIOCGWINSZ, (char *)&win);

	rtt = tt;
	cfmakeraw(&rtt);
	rtt.c_lflag &= ~ECHO;
	tcsetattr(0, TCSAFLUSH, &rtt);

	/* "script" from util-linux exits when child exits,
	 * we wouldn't wait for EOF from slave pty
	 * (output may be produced by grandchildren of child) */
	signal(SIGCHLD, handle_sigchld);

	/* TODO: SIGWINCH? pass window size changes down to slave? */

	child_pid = vfork();
	if (child_pid < 0) {
		bb_perror_msg_and_die("vfork");
	}

	if (child_pid) {
		/* parent */
#define buf bb_common_bufsiz1
		struct pollfd pfd[2];
		struct pollfd *ppfd = pfd;
		int outfd, count, loop;

		outfd = xopen(fname, mode);
		pfd[0].fd = 0;
		pfd[0].events = POLLIN;
		pfd[1].fd = pty;
		pfd[1].events = POLLIN;
		ndelay_on(pty); /* this descriptor is not shared, can do this */
		/* ndelay_on(0); - NO, stdin can be shared! Pity :( */

		/* copy stdin to pty master input,
		 * copy pty master output to stdout and file */
		/* TODO: don't use full_write's, use proper write buffering */
		while (fd_count) {
			/* not safe_poll! we want SIGCHLD to EINTR poll */
			poll(ppfd, fd_count, -1);
			if (pfd[0].revents) {
				count = safe_read(0, buf, sizeof(buf));
				if (count <= 0) {
					/* err/eof: don't read anymore */
					pfd[0].revents = 0;
					ppfd++;
					fd_count--;
				} else {
					full_write(pty, buf, count);
				}
			}
			if (pfd[1].revents) {
				errno = 0;
				count = safe_read(pty, buf, sizeof(buf));
				if (count <= 0 && errno != EAGAIN) {
					/* err/eof: don't read anymore */
					pfd[1].revents = 0;
					fd_count--;
				}
				if (count > 0) {
					full_write(1, buf, count);
					full_write(outfd, buf, count);
					if (opt & 4) { /* -f */
						fsync(outfd);
					}
				}
			}
		}
		/* If loop was exited because SIGCHLD handler set fd_count to 0,
		 * there still can be some buffered output. But not loop forever:
		 * we won't pump orphaned grandchildren's output indefinitely.
		 * Testcase: running this in script:
		 *      exec dd if=/dev/zero bs=1M count=1
		 * must have "1+0 records in, 1+0 records out" captured too.
		 * (util-linux's script doesn't do this. buggy :) */
		loop = 999;
		/* pty is in O_NONBLOCK mode, we exit as soon as buffer is empty */
		while (--loop && (count = safe_read(pty, buf, sizeof(buf))) > 0) {
			full_write(1, buf, count);
			full_write(outfd, buf, count);
		}

		if (attr_ok == 0)
			tcsetattr(0, TCSAFLUSH, &tt);
		if (!(opt & 8)) /* not -q */
			printf("Script done, file is %s\n", fname);
		return EXIT_SUCCESS;
	}

	/* child: make pty slave to be input, output, error; run shell */
	close(pty); /* close pty master */
	/* open pty slave to fd 0,1,2 */
	close(0);               
	xopen(pty_line, O_RDWR); /* uses fd 0 */
	xdup2(0, 1);
	xdup2(0, 2);
	/* copy our original stdin tty's parameters to pty */
	if (attr_ok == 0)
		tcsetattr(0, TCSAFLUSH, &tt);
	if (winsz_ok == 0)
		ioctl(0, TIOCSWINSZ, (char *)&win);
	/* set pty as a controlling tty */
	setsid();
	ioctl(0, TIOCSCTTY, 0 /* 0: don't forcibly steal */);

	/* signal(SIGCHLD, SIG_DFL); - exec does this for us */
	execl(shell, shell, shell_opt, shell_arg, NULL);
	bb_simple_perror_msg_and_die(shell);
}
Beispiel #10
0
/*
 * Get a pty, scan input lines.
 */
static void
doit(struct sockaddr_in *who)
{
	const char *host;
	struct hostent *hp;
	int level;
	char user_name[256];
	char portnum[8];

	/*
	 * Find an available pty to use.
	 */
	pty = getpty();
	if (pty < 0)
		fatal(net, "All network ports in use");

	/* get name of connected client */
	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
		who->sin_family);
	if (hp)
		host = hp->h_name;
	else
		host = inet_ntoa(who->sin_addr);

	/*
	 * We must make a copy because Kerberos is probably going
	 * to also do a gethost* and overwrite the static data...
	 */
	{
		int i;
		strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
		remote_host_name[sizeof(remote_host_name)-1] = 0;

		/* Disallow funnies. */
		for (i=0; remote_host_name[i]; i++) {
		    if (remote_host_name[i]<=32 || remote_host_name[i]>126) 
			remote_host_name[i] = '?';
		}
	}
	host = remote_host_name;

	/* Get local host name */
	{
		struct hostent *h;
		gethostname(host_name, sizeof(host_name));
		h = gethostbyname(host_name);
		if (h) {
		    strncpy(host_name, h->h_name, sizeof(host_name));
		    host_name[sizeof(host_name)-1] = 0;
		}
	}

#if	defined(AUTHENTICATE) || defined(ENCRYPT)
	auth_encrypt_init(host_name, host, "TELNETD", 1);
#endif

	init_env();
	/*
	 * get terminal type.
	 */
	*user_name = 0;
	level = getterminaltype(user_name);
	setenv("HOME", "/opt/mud/plogin",1);
	setenv("TERM", terminaltype ? terminaltype : "network", 1);

	/* TODO list stuff provided by Laszlo Vecsey <*****@*****.**> */

	/*
	 * Set REMOTEHOST environment variable
	 */
	setproctitle("%s", host);

	sprintf(portnum, "%d", ntohs(who->sin_port));

	setenv("REMOTEADDR", inet_ntoa(who->sin_addr), 1);
	setenv("REMOTEHOST", host, 1);
	setenv("REMOTEPORT", portnum, 1);

	/*
	 * Start up the login process on the slave side of the terminal
	 */
	startslave(host, level, user_name);

	telnet(net, pty);  /* begin server processing */

	/*NOTREACHED*/
}  /* end of doit */
Beispiel #11
0
/*
 * Get a pty, scan input lines.
 */
static void
doit(struct sockaddr *who, socklen_t who_len)
{
	char *host;
	int level;
	char user_name[256];
	int i;
	struct addrinfo hints, *res;

	/*
	 * Find an available pty to use.
	 */
	pty = getpty();
	if (pty < 0)
		fatalperror(net, "getpty");

	/* get name of connected client */
	if (getnameinfo(who, who_len, remote_host_name,
			sizeof(remote_host_name), 0, 0, 
			numeric_hosts ? NI_NUMERICHOST : 0)) {
		syslog(LOG_ERR, "doit: getnameinfo: %m");
		*remote_host_name = 0;
        }

	/* Disallow funnies. */
	for (i=0; remote_host_name[i]; i++) {
	    if (remote_host_name[i]<=32 || remote_host_name[i]>126) 
		remote_host_name[i] = '?';
	}
	host = remote_host_name;

	/* Get local host name */
	gethostname(host_name, sizeof(host_name));
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_CANONNAME;
	if ((i = getaddrinfo(host_name, 0, &hints, &res)))
		syslog(LOG_WARNING, "doit: getaddrinfo: %s", gai_strerror(i));
	else {
		strncpy(host_name, res->ai_canonname, sizeof(host_name)-1);
		host_name[sizeof(host_name)-1] = 0;
	}

#if	defined(AUTHENTICATE) || defined(ENCRYPT)
	auth_encrypt_init(host_name, host, "TELNETD", 1);
#endif

	init_env();
	/*
	 * get terminal type.
	 */
	*user_name = 0;
	level = getterminaltype(user_name);
	setenv("TERM", terminaltype ? terminaltype : "network", 1);

	/* TODO list stuff provided by Laszlo Vecsey <*****@*****.**> */

#ifdef USE_SSL
	if (debug) {
	    fprintf(stderr,"doit - ALIVE\n");
	    fflush(stderr);
	    sleep(2);
	}
#endif /* USE_SSL */


	/*
	 * Set REMOTEHOST environment variable
	 */
	setproctitle("%s", host);
	setenv("REMOTEHOST", host, 0);

#ifdef USE_SSL
	if (debug) {
	    fprintf(stderr,"doit - starting telnet protocol itself\n");
	    fflush(stderr);
	    sleep(2);
	}
#endif /* USE_SSL */

	/*
	 * Start up the login process on the slave side of the terminal
	 */
	startslave(host, level, user_name);

	telnet(net, pty);  /* begin server processing */

	/*NOTREACHED*/
}  /* end of doit */