Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414)
Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can
arrange to use the same source file name in sfimage, without having to export over the original
Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need
for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.
/*
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnetd.h"
#ifdef __SYMBIAN32__
#include "dummy.h"
extern void mini_inetd (int port);
#endif
#ifndef __SYMBIAN32__
__RCSID("$Heimdal: telnetd.c,v 1.69.6.1 2004/03/22 18:17:25 lha Exp $"
"$NetBSD: telnetd.c,v 1.3 2004/04/02 14:59:47 lha Exp $");
#endif
#ifdef _SC_CRAY_SECURE_SYS
#include <sys/sysv.h>
#include <sys/secdev.h>
#include <sys/secparm.h>
#include <sys/usrv.h>
int secflag;
char tty_dev[16];
struct secdev dv;
struct sysv sysv;
struct socksec ss;
#endif /* _SC_CRAY_SECURE_SYS */
#ifdef AUTHENTICATION
int auth_level = 0;
#endif
#ifdef __SYMBIAN32__
#ifdef __WINSCW__
#pragma warn_unusedarg off
#endif
#endif
extern int utmp_len;
int registerd_host_only = 0;
/**moved from roken.h**/
#define roken_getservbyname(x,y) getservbyname(x,y)
#define roken_openlog(a,b,c) openlog(a,b,c)
#define roken_getsockname(a,b,c) getsockname(a,b,c)
#undef NOERROR
#ifdef STREAMSPTY
# include <stropts.h>
# include <termios.h>
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif /* HAVE_SYS_UIO_H */
#ifdef HAVE_SYS_STREAM_H
#include <sys/stream.h>
#endif
#ifdef _AIX
#include <sys/termio.h>
#endif
# ifdef HAVE_SYS_STRTTY_H
# include <sys/strtty.h>
# endif
# ifdef HAVE_SYS_STR_TTY_H
# include <sys/str_tty.h>
# endif
/* make sure we don't get the bsd version */
/* what is this here for? solaris? /joda */
# ifdef HAVE_SYS_TTY_H
# include "/usr/include/sys/tty.h"
# endif
# ifdef HAVE_SYS_PTYVAR_H
# include <sys/ptyvar.h>
# endif
/*
* Because of the way ptyibuf is used with streams messages, we need
* ptyibuf+1 to be on a full-word boundary. The following wierdness
* is simply to make that happen.
*/
long ptyibufbuf[BUFSIZ/sizeof(long)+1];
char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
char *ptyip = ((char *)&ptyibufbuf[1])-1;
char ptyibuf2[BUFSIZ];
unsigned char ctlbuf[BUFSIZ];
struct strbuf strbufc, strbufd;
int readstream(int, char*, int);
#else /* ! STREAMPTY */
/*
* I/O data buffers,
* pointers, and counters.
*/
char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
char ptyibuf2[BUFSIZ];
#endif /* ! STREAMPTY */
int hostinfo = 1; /* do we print login banner? */
#ifdef _CRAY
extern int newmap; /* nonzero if \n maps to ^M^J */
int lowpty = 0, highpty; /* low, high pty numbers */
#endif /* CRAY */
int debug = 1;
int keepalive = 1;
char *progname;
static void usage (void);
/*
* The string to pass to getopt(). We do it this way so
* that only the actual options that we support will be
* passed off to getopt().
*/
char valid_opts[] = "Bd:hklnS:u:UL:y"
#ifdef AUTHENTICATION
"a:X:z"
#endif
#ifdef DIAGNOSTICS
"D:"
#endif
#ifdef _CRAY
"r:"
#endif
;
static void doit(struct sockaddr*, int);
#ifdef ENCRYPTION
extern int des_check_key;
#endif
extern int getConnectionUp(void);
int
main(int argc, char **argv)
{
struct sockaddr_storage __ss;
struct sockaddr *sa = (struct sockaddr *)&__ss;
int on = 1;
socklen_t sa_size;
int ch;
#if defined(IPPROTO_IP) && defined(IP_TOS)
int tos = -1;
#endif
#ifdef ENCRYPTION
des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */
#endif
pfrontp = pbackp = ptyobuf;
netip = netibuf;
nfrontp = nbackp = netobuf;
#ifdef __SYMBIAN32__
if( getConnectionUp() < 0) exit(1);
#endif
setprogname(argv[0]);
progname = *argv;
#ifdef ENCRYPTION
nclearto = 0;
#endif
#ifdef _CRAY
/*
* Get number of pty's before trying to process options,
* which may include changing pty range.
*/
highpty = getnpty();
#endif /* CRAY */
if (argc == 2 && strcmp(argv[1], "--version") == 0) {
#ifndef __SYMBIAN32__
print_version(NULL);
#endif //__SYMBIAN32__
exit(0);
}
while ((ch = getopt(argc, argv, valid_opts)) != -1) {
switch(ch) {
#ifdef AUTHENTICATION
case 'a':
/*
* Check for required authentication level
*/
if (strcmp(optarg, "debug") == 0) {
auth_debug_mode = 1;
} else if (strcasecmp(optarg, "none") == 0) {
auth_level = 0;
} else if (strcasecmp(optarg, "otp") == 0) {
auth_level = 0;
require_otp = 1;
} else if (strcasecmp(optarg, "other") == 0) {
auth_level = AUTH_OTHER;
} else if (strcasecmp(optarg, "user") == 0) {
auth_level = AUTH_USER;
} else if (strcasecmp(optarg, "valid") == 0) {
auth_level = AUTH_VALID;
} else if (strcasecmp(optarg, "off") == 0) {
/*
* This hack turns off authentication
*/
auth_level = -1;
} else {
fprintf(stderr,
"telnetd: unknown authorization level for -a\n");
}
break;
#endif /* AUTHENTICATION */
case 'B': /* BFTP mode is not supported any more */
break;
case 'd':
if (strcmp(optarg, "ebug") == 0) {
debug++;
break;
}
usage();
/* NOTREACHED */
break;
#ifdef DIAGNOSTICS
case 'D':
/*
* Check for desired diagnostics capabilities.
*/
if (!strcmp(optarg, "report")) {
diagnostic |= TD_REPORT|TD_OPTIONS;
} else if (!strcmp(optarg, "exercise")) {
diagnostic |= TD_EXERCISE;
} else if (!strcmp(optarg, "netdata")) {
diagnostic |= TD_NETDATA;
} else if (!strcmp(optarg, "ptydata")) {
diagnostic |= TD_PTYDATA;
} else if (!strcmp(optarg, "options")) {
diagnostic |= TD_OPTIONS;
} else {
usage();
/* NOT REACHED */
}
break;
#endif /* DIAGNOSTICS */
case 'h':
hostinfo = 0;
break;
case 'k': /* Linemode is not supported any more */
case 'l':
break;
case 'n':
keepalive = 0;
break;
#ifdef _CRAY
case 'r':
{
char *strchr();
char *c;
/*
* Allow the specification of alterations
* to the pty search range. It is legal to
* specify only one, and not change the
* other from its default.
*/
c = strchr(optarg, '-');
if (c) {
*c++ = '\0';
highpty = atoi(c);
}
if (*optarg != '\0')
lowpty = atoi(optarg);
if ((lowpty > highpty) || (lowpty < 0) ||
(highpty > 32767)) {
usage();
/* NOT REACHED */
}
break;
}
#endif /* CRAY */
case 'S':
#ifdef HAVE_PARSETOS
if ((tos = parsetos(optarg, "tcp")) < 0)
fprintf(stderr, "%s%s%s\n",
"telnetd: Bad TOS argument '", optarg,
"'; will try to use default TOS");
#else
fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
"-S flag not supported\n");
#endif
break;
case 'u': {
char *eptr;
utmp_len = strtol(optarg, &eptr, 0);
if (optarg == eptr)
fprintf(stderr, "telnetd: unknown utmp len (%s)\n", optarg);
break;
}
case 'U':
registerd_host_only = 1;
break;
#ifdef AUTHENTICATION
case 'X':
/*
* Check for invalid authentication types
*/
auth_disable_name(optarg);
break;
#endif
case 'y':
no_warn = 1;
break;
#ifdef AUTHENTICATION
case 'z':
log_unauth = 1;
break;
#endif /* AUTHENTICATION */
case 'L':
new_login = optarg;
break;
default:
fprintf(stderr, "telnetd: %c: unknown option\n", ch);
/* FALLTHROUGH */
case '?':
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (debug) {
int port = 0;
struct servent *sp;
if (argc > 1) {
usage ();
} else if (argc == 1) {
sp = (struct servent*)roken_getservbyname (*argv, "tcp");
if (sp)
port = sp->s_port;
else
port = htons(atoi(*argv));
} else {
#ifdef __SYMBIAN32__
port = htons(atoi("23"));
#else
#ifdef KRB5
port = krb5_getportbyname (NULL, "telnet", "tcp", 23);
#else
port = k_getportbyname("telnet", "tcp", htons(23));
#endif
#endif //__SYMBIAN32__
}
mini_inetd (port);
} else if (argc > 0) {
usage();
/* NOT REACHED */
}
#ifdef _SC_CRAY_SECURE_SYS
secflag = sysconf(_SC_CRAY_SECURE_SYS);
/*
* Get socket's security label
*/
if (secflag) {
socklen_t szss = sizeof(ss);
int sock_multi;
socklen_t szi = sizeof(int);
memset(&dv, 0, sizeof(dv));
if (getsysv(&sysv, sizeof(struct sysv)) != 0)
fatalperror(net, "getsysv");
/*
* Get socket security label and set device values
* {security label to be set on ttyp device}
*/
#ifdef SO_SEC_MULTI /* 8.0 code */
if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
(void *)&ss, &szss) < 0) ||
(getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
(void *)&sock_multi, &szi) < 0))
fatalperror(net, "getsockopt");
else {
dv.dv_actlvl = ss.ss_actlabel.lt_level;
dv.dv_actcmp = ss.ss_actlabel.lt_compart;
if (!sock_multi) {
dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
dv.dv_valcmp = dv.dv_actcmp;
} else {
dv.dv_minlvl = ss.ss_minlabel.lt_level;
dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
}
dv.dv_devflg = 0;
}
#else /* SO_SEC_MULTI */ /* 7.0 code */
if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
(void *)&ss, &szss) >= 0) {
dv.dv_actlvl = ss.ss_slevel;
dv.dv_actcmp = ss.ss_compart;
dv.dv_minlvl = ss.ss_minlvl;
dv.dv_maxlvl = ss.ss_maxlvl;
dv.dv_valcmp = ss.ss_maxcmp;
}
#endif /* SO_SEC_MULTI */
}
#endif /* _SC_CRAY_SECURE_SYS */
roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
sa_size = sizeof (__ss);
if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) {
fprintf(stderr, "%s: ", progname);
perror("getpeername");
_exit(1);
}
if (keepalive &&
setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
(void *)&on, sizeof (on)) < 0) {
#ifndef __SYMBIAN32__
syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
#endif
;
}
#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
{
# ifdef HAVE_GETTOSBYNAME
struct tosent *tp;
if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
tos = tp->t_tos;
# endif
if (tos < 0)
tos = 020; /* Low Delay bit */
if (tos
&& sa->sa_family == AF_INET
&& (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
(void *)&tos, sizeof(tos)) < 0)
&& (errno != ENOPROTOOPT) )
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
}
#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
net = STDIN_FILENO;
doit(sa, sa_size);
/* NOTREACHED */
return 0;
} /* end of main */
static void
usage(void)
{
fprintf(stderr, "Usage: telnetd");
#ifdef AUTHENTICATION
fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t");
#endif
fprintf(stderr, " [-debug]");
#ifdef DIAGNOSTICS
fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
#endif
#ifdef AUTHENTICATION
fprintf(stderr, " [-edebug]");
#endif
fprintf(stderr, " [-h]");
fprintf(stderr, " [-L login]");
fprintf(stderr, " [-n]");
#ifdef _CRAY
fprintf(stderr, " [-r[lowpty]-[highpty]]");
#endif
fprintf(stderr, "\n\t");
#ifdef HAVE_GETTOSBYNAME
fprintf(stderr, " [-S tos]");
#endif
#ifdef AUTHENTICATION
fprintf(stderr, " [-X auth-type] [-y] [-z]");
#endif
fprintf(stderr, " [-u utmp_hostname_length] [-U]");
fprintf(stderr, " [port]\n");
exit(1);
}
/*
* getterminaltype
*
* Ask the other end to send along its terminal type and speed.
* Output is the variable terminaltype filled in.
*/
static unsigned char ttytype_sbbuf[] = {
IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
};
int
getterminaltype(char *name, size_t name_sz)
{
int retval = -1;
settimer(baseline);
#ifdef AUTHENTICATION
/*
* Handle the Authentication option before we do anything else.
*/
send_do(TELOPT_AUTHENTICATION, 1);
while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
ttloop();
if (his_state_is_will(TELOPT_AUTHENTICATION)) {
retval = auth_wait(name, name_sz);
}
#endif
#ifdef ENCRYPTION
send_will(TELOPT_ENCRYPT, 1);
send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */
#endif
send_do(TELOPT_TTYPE, 1);
send_do(TELOPT_TSPEED, 1);
send_do(TELOPT_XDISPLOC, 1);
send_do(TELOPT_NEW_ENVIRON, 1);
send_do(TELOPT_OLD_ENVIRON, 1);
while (
#ifdef ENCRYPTION
his_do_dont_is_changing(TELOPT_ENCRYPT) ||
#endif
his_will_wont_is_changing(TELOPT_TTYPE) ||
his_will_wont_is_changing(TELOPT_TSPEED) ||
his_will_wont_is_changing(TELOPT_XDISPLOC) ||
his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
ttloop();
}
#ifdef ENCRYPTION
/*
* Wait for the negotiation of what type of encryption we can
* send with. If autoencrypt is not set, this will just return.
*/
if (his_state_is_will(TELOPT_ENCRYPT)) {
encrypt_wait();
}
#endif
if (his_state_is_will(TELOPT_TSPEED)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
telnet_net_write (sb, sizeof sb);
DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
}
if (his_state_is_will(TELOPT_XDISPLOC)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
telnet_net_write (sb, sizeof sb);
DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
}
if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
telnet_net_write (sb, sizeof sb);
DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
}
else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
telnet_net_write (sb, sizeof sb);
DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
}
if (his_state_is_will(TELOPT_TTYPE)) {
telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
sizeof ttytype_sbbuf - 2););
}
if (his_state_is_will(TELOPT_TSPEED)) {
while (sequenceIs(tspeedsubopt, baseline))
ttloop();
}
if (his_state_is_will(TELOPT_XDISPLOC)) {
while (sequenceIs(xdisplocsubopt, baseline))
ttloop();
}
if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
while (sequenceIs(environsubopt, baseline))
ttloop();
}
if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
while (sequenceIs(oenvironsubopt, baseline))
ttloop();
}
if (his_state_is_will(TELOPT_TTYPE)) {
char first[256], last[256];
while (sequenceIs(ttypesubopt, baseline))
ttloop();
/*
* If the other side has already disabled the option, then
* we have to just go with what we (might) have already gotten.
*/
if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
strlcpy(first, terminaltype, sizeof(first));
for(;;) {
/*
* Save the unknown name, and request the next name.
*/
strlcpy(last, terminaltype, sizeof(last));
_gettermname();
if (terminaltypeok(terminaltype))
break;
if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
his_state_is_wont(TELOPT_TTYPE)) {
/*
* We've hit the end. If this is the same as
* the first name, just go with it.
*/
if (strncmp(first, terminaltype, sizeof(first)) == 0)
break;
/*
* Get the terminal name one more time, so that
* RFC1091 compliant telnets will cycle back to
* the start of the list.
*/
_gettermname();
if (strncmp(first, terminaltype, sizeof(first)) != 0)
strcpy(terminaltype, first);
break;
}
}
}
}
return(retval);
} /* end of getterminaltype */
void
_gettermname(void)
{
/*
* If the client turned off the option,
* we can't send another request, so we
* just return.
*/
if (his_state_is_wont(TELOPT_TTYPE))
return;
settimer(baseline);
telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
sizeof ttytype_sbbuf - 2););
while (sequenceIs(ttypesubopt, baseline))
ttloop();
}
int
terminaltypeok(char *s)
{
return 1;
}
char host_name[MAXHOSTNAMELEN];
char remote_host_name[MAXHOSTNAMELEN];
char remote_utmp_name[MAXHOSTNAMELEN];
static int
getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen,
int flags)
{
int ret;
struct addrinfo *ai, *a;
char servbuf[NI_MAXSERV];
struct addrinfo hints;
if (host == NULL)
return EAI_NONAME;
if (serv == NULL) {
serv = servbuf;
servlen = sizeof(servbuf);
}
ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
flags | NI_NUMERICSERV);
if (ret)
goto fail;
memset (&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
ret = getaddrinfo (host, serv, &hints, &ai);
if (ret)
goto fail;
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_addrlen == salen
&& memcmp (a->ai_addr, sa, salen) == 0) {
freeaddrinfo (ai);
return 0;
}
}
freeaddrinfo (ai);
fail:
if (flags & NI_NAMEREQD)
return EAI_NONAME;
ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
flags | NI_NUMERICSERV | NI_NUMERICHOST);
return ret;
}
#ifdef __SYMBIAN32__
//replace the ocurrences of \n with \n\r.
//caller should free the memory
char* add_return(char* source)
{
int occur=0, len=0, tokens=0, occurbk=0;
char *token, *ret;
if(NULL==source || !(len=strlen(source)))
return NULL;
ret=(char*)calloc(len+1, sizeof(char));
strcpy(ret, source);
occur=source[len-1]=='\n'? 1:0;
if(len>1 && source[0]=='\n')
occur+=1;
//find the no. of occurrences of \n
token=strtok(source, "\n");
while(token)
{
token=strtok(NULL, "\n");
tokens++;
}
occurbk=occur=tokens>1?tokens+occur-1: occur;
if(occur<=0)
{
return ret;
}
//start replacing with \n\r
/* start moving from end of the string.
* If the no. of occurences of \n is n(n set), then move the nth set
* to n bytes forward and n-1th set to n-1 bytes forward and similarly
* for the rest until it reaches the first set.
*/
ret=(char*)realloc(ret, (sizeof(char)*(len+occur+1)));
if(ret)
{
int counter=len-1;
while(occur>0 && counter>0)
{
while(ret[counter]!='\n')
{
ret[counter+occur]=ret[counter];
counter--;
}
ret[counter+occur-1]='\n';
ret[counter+occur]='\r';
counter--;
occur--;
}
ret[len+occurbk]='\0'; //terminate the entire string
}
return ret;
}
void readinput(char* line_o, int* length, int size)
{
char read_c;
if(!line_o || !length)
return;
*length=0;
read(net, &read_c, 1);
while(read_c!='\n') //read the command from client
{
if(*length==size-1)
break;
if(read_c=='\r')
{
read(net, &read_c, 1);
line_o[(*length)++]='\n';
break;
}
write(net, &read_c, 1);
line_o[(*length)++]=read_c;
read(net, &read_c, 1);
}
line_o[*length]='\0';
}
#endif
/*
* Get a pty, scan input lines.
*/
static void
doit(struct sockaddr *who, int who_len)
{
#ifndef __SYMBIAN32__
int level;
int ptynum;
int error;
char user_name[256];
/*
* Find an available pty to use.
*/
ourpty = getpty(&ptynum);
if (ourpty < 0)
fatal(net, "All network ports in use");
#ifdef _SC_CRAY_SECURE_SYS
/*
* set ttyp line security label
*/
if (secflag) {
char slave_dev[16];
snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum);
if (setdevs(tty_dev, &dv) < 0)
fatal(net, "cannot set pty security");
snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum);
if (setdevs(slave_dev, &dv) < 0)
fatal(net, "cannot set tty security");
}
#endif /* _SC_CRAY_SECURE_SYS */
error = getnameinfo_verified (who, who_len,
remote_host_name,
sizeof(remote_host_name),
NULL, 0,
registerd_host_only ? NI_NAMEREQD : 0);
if (error)
fatal(net, "Couldn't resolve your address into a host name.\r\n\
Please contact your net administrator");
gethostname(host_name, sizeof (host_name));
strlcpy (remote_utmp_name, remote_host_name, sizeof(remote_utmp_name));
/* Only trim if too long (and possible) */
if (strlen(remote_utmp_name) > utmp_len) {
char *domain = strchr(host_name, '.');
char *p = strchr(remote_utmp_name, '.');
if (domain != NULL && p != NULL && (strcmp(p, domain) == 0))
*p = '\0'; /* remove domain part */
}
/*
* If hostname still doesn't fit utmp, use ipaddr.
*/
if (strlen(remote_utmp_name) > utmp_len) {
error = getnameinfo (who, who_len,
remote_utmp_name,
sizeof(remote_utmp_name),
NULL, 0,
NI_NUMERICHOST);
if (error)
fatal(net, "Couldn't get numeric address\r\n");
}
#ifdef AUTHENTICATION
auth_encrypt_init(host_name, remote_host_name, "TELNETD", 1);
#endif
init_env();
/*
* get terminal type.
*/
*user_name = 0;
level = getterminaltype(user_name, sizeof(user_name));
setenv("TERM", terminaltype ? terminaltype : "network", 1);
#ifdef _SC_CRAY_SECURE_SYS
if (secflag) {
if (setulvl(dv.dv_actlvl) < 0)
fatal(net,"cannot setulvl()");
if (setucmp(dv.dv_actcmp) < 0)
fatal(net, "cannot setucmp()");
}
#endif /* _SC_CRAY_SECURE_SYS */
#endif //__SYMBIAN32__
/* begin server processing */
my_telnet();
/*NOTREACHED*/
} /* end of doit */
#ifdef __SYMBIAN32__
#define PASSKEY_MAXLEN 8
static
int clientAuthentication(char* dev_key)
{
char* get_key="Enter Key: ";
fd_set read_fds;
struct timeval tv;
char client_buf[PASSKEY_MAXLEN+1];
char read_c;
int buf_len=0;
if(dev_key==NULL)
return 1;
write(net, get_key, strlen(get_key));
FD_ZERO(&read_fds);
FD_SET(net, &read_fds);
tv.tv_sec = 60;
tv.tv_usec = 0;
//exit if nothing is read for 60 secs
if(select(net+1, &read_fds, NULL, NULL, &tv)==0)
{
char* login_timout="Authentication Failure:\
timeout\n";
write(1, login_timout, strlen(login_timout));
exit(1);
}
if(FD_ISSET(net, &read_fds))
{
while(buf_len < PASSKEY_MAXLEN)
{
read(net, &read_c, 1); //read from socket fd
switch(read_c)
{
case '\n':
goto jump_out;
case '\b':
//ignore previous character.
write(net, "\b", 1);
if(buf_len > 0)
buf_len--;
case '\r':
break;
default:
//let all other keys be part of the passkey.
write(net, "*", 1);
client_buf[buf_len++]=read_c;
break;
}
}
jump_out:
//pass key max length has reached or '\r\n' is entered.
write(net, "\r\n", 2);
client_buf[buf_len]='\0';
}
if(strcmp(dev_key, client_buf)==0)
return 0;
return 1;
}
static char key[PASSKEY_MAXLEN+1];
char* deviceAuthentication()
{
fd_set read_fds;
struct timeval tv;
int console_fd=open("CON:", O_RDWR);
const char* login_key="Enter Key: ";
FD_ZERO(&read_fds);
FD_SET(console_fd, &read_fds);
if(console_fd!=-1)
{
write(console_fd, login_key, strlen(login_key));
tv.tv_sec = 60;
tv.tv_usec = 0;
//exit if nothing is read for 60 secs
if(select(console_fd+1, &read_fds, NULL, NULL, &tv)==0)
{
char* login_timout="Authentication Failure:\
timeout\n";
write(1, login_timout, strlen(login_timout));
exit(1);
}
if(FD_ISSET(console_fd, &read_fds))
{
char read_c;
int buf_len=0;
char key_buf[PASSKEY_MAXLEN+1];
setecho(console_fd, '*'); //turn off the echo
while(buf_len < PASSKEY_MAXLEN)
{
read(console_fd, &read_c, 1);
switch(read_c)
{
case '\n':
if(buf_len==0)
continue;
else
goto jump_out;
case '\b':
//ignore previous character...
if(buf_len > 0)
buf_len--;
break;
default:
//let all other keys be part of the passkey...
key_buf[buf_len++]=read_c;
break;
}
}
jump_out:
setecho(console_fd, 1); //turn on the echo
key_buf[buf_len]='\0';
if(buf_len > 0 && buf_len <= PASSKEY_MAXLEN)
strcpy(key, key_buf);
close(console_fd);
return key;
}
}
else
{
char* console_err="Authentication Failure:\
console not supported\n";
write(1, console_err, strlen(console_err));
exit(1);
}
return NULL;
}
#endif
/* output contents of /etc/issue.net, or /etc/issue */
#ifndef __SYMBIAN32__
static void
show_issue(void)
{
FILE *f;
char buf[128];
f = fopen(SYSCONFDIR "/issue.net", "r");
if(f == NULL)
f = fopen(SYSCONFDIR "/issue", "r");
if(f){
while(fgets(buf, sizeof(buf)-2, f)){
strcpy(buf + strcspn(buf, "\r\n"), "\r\n");
writenet((unsigned char*)buf, strlen(buf));
}
fclose(f);
}
}
#endif //__SYMBIAN32__
/*
* Main loop. Select from pty and network, and
* hand data to telnet receiver finite state machine.
*/
void
my_telnet()
{
int on = 1;
#ifndef __SYMBIAN32__
char *he;
char *IM;
int nfd;
time_t timeout;
#endif
int startslave_called = 0;
int fds[3],pid;
/*
* Initialize the slc mapping table.
*/
get_slc_defaults();
/*
* Do some tests where it is desireable to wait for a response.
* Rather than doing them slowly, one at a time, do them all
* at once.
*/
if (my_state_is_wont(TELOPT_SGA))
send_will(TELOPT_SGA, 1);
/*
* Is the client side a 4.2 (NOT 4.3) system? We need to know this
* because 4.2 clients are unable to deal with TCP urgent data.
*
* To find out, we send out a "DO ECHO". If the remote system
* answers "WILL ECHO" it is probably a 4.2 client, and we note
* that fact ("WILL ECHO" ==> that the client will echo what
* WE, the server, sends it; it does NOT mean that the client will
* echo the terminal input).
*/
send_do(TELOPT_ECHO, 1);
#ifdef __SYMBIAN32__
if (my_state_is_wont(TELOPT_ECHO))
send_will(TELOPT_ECHO, 1);
#endif
/*
* Send along a couple of other options that we wish to negotiate.
*/
send_do(TELOPT_NAWS, 1);
send_will(TELOPT_STATUS, 1);
flowmode = 1; /* default flow control state */
restartany = -1; /* uninitialized... */
send_do(TELOPT_LFLOW, 1);
/*
* Spin, waiting for a response from the DO ECHO. However,
* some REALLY DUMB telnets out there might not respond
* to the DO ECHO. So, we spin looking for NAWS, (most dumb
* telnets so far seem to respond with WONT for a DO that
* they don't understand...) because by the time we get the
* response, it will already have processed the DO ECHO.
* Kludge upon kludge.
*/
while (his_will_wont_is_changing(TELOPT_NAWS))
ttloop();
/*
* But...
* The client might have sent a WILL NAWS as part of its
* startup code; if so, we'll be here before we get the
* response to the DO ECHO. We'll make the assumption
* that any implementation that understands about NAWS
* is a modern enough implementation that it will respond
* to our DO ECHO request; hence we'll do another spin
* waiting for the ECHO option to settle down, which is
* what we wanted to do in the first place...
*/
if (his_want_state_is_will(TELOPT_ECHO) &&
his_state_is_will(TELOPT_NAWS)) {
while (his_will_wont_is_changing(TELOPT_ECHO))
ttloop();
}
/*
* On the off chance that the telnet client is broken and does not
* respond to the DO ECHO we sent, (after all, we did send the
* DO NAWS negotiation after the DO ECHO, and we won't get here
* until a response to the DO NAWS comes back) simulate the
* receipt of a will echo. This will also send a WONT ECHO
* to the client, since we assume that the client failed to
* respond because it believes that it is already in DO ECHO
* mode, which we do not want.
*/
if (his_want_state_is_will(TELOPT_ECHO)) {
DIAG(TD_OPTIONS,
{output_data("td: simulating recv\r\n");
});
willoption(TELOPT_ECHO);
}
/*
* Finally, to clean things up, we turn on our echo. This
* will break stupid 4.2 telnets out of local terminal echo.
*/
if (my_state_is_wont(TELOPT_ECHO))
send_will(TELOPT_ECHO, 1);
#ifndef __SYMBIAN32__ //below are not required...
#ifdef TIOCPKT
#ifdef STREAMSPTY
if (!really_stream)
#endif
/*
* Turn on packet mode
*/
ioctl(p, TIOCPKT, (char *)&on);
#endif
/*
* Call telrcv() once to pick up anything received during
* terminal type negotiation, 4.2/4.3 determination, and
* linemode negotiation.
*/
telrcv();
ioctl(f, FIONBIO, (char *)&on);
ioctl(p, FIONBIO, (char *)&on);
#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
(void *)&on, sizeof on);
#endif /* defined(SO_OOBINLINE) */
#ifdef SIGTSTP
#ifndef __SYMBIAN32__
signal(SIGTSTP, SIG_IGN);
#endif
#endif
#ifdef SIGTTOU
/*
* Ignoring SIGTTOU keeps the kernel from blocking us
* in ttioct() in /sys/tty.c.
*/
#ifndef __SYMBIAN32__
signal(SIGTTOU, SIG_IGN);
#endif
#endif
#ifndef __SYMBIAN32__
signal(SIGCHLD, cleanup);
#endif
#ifdef TIOCNOTTY
{
int t;
t = open(_PATH_TTY, O_RDWR);
if (t >= 0) {
ioctl(t, TIOCNOTTY, (char *)0);
close(t);
}
}
#endif
show_issue();
/*
* Show banner that getty never gave.
*
* We put the banner in the pty input buffer. This way, it
* gets carriage return null processing, etc., just like all
* other pty --> client data.
*/
if (getenv("USER"))
hostinfo = 0;
IM = DEFAULT_IM;
he = 0;
edithost(he, host_name);
if (hostinfo && *IM)
putf(IM, ptyibuf2);
if (pcc)
strncat(ptyibuf2, ptyip, pcc+1);
ptyip = ptyibuf2;
pcc = strlen(ptyip);
DIAG(TD_REPORT, {
output_data("td: Entering processing loop\r\n");
});
nfd = ((f > p) ? f : p) + 1;
timeout = time(NULL) + 5;
for (;;) {
fd_set ibits, obits, xbits;
int c;
/* wait for encryption to be turned on, but don't wait
indefinitely */
#ifndef __SYMBIAN32__
if(!startslave_called && (/*!encrypt_delay() || */timeout > time(NULL))){
startslave_called = 1;
startslave(host, utmp_host, level, autoname);
}
#endif
if (ncc < 0 && pcc < 0)
break;
FD_ZERO(&ibits);
FD_ZERO(&obits);
FD_ZERO(&xbits);
if (f >= FD_SETSIZE
|| p >= FD_SETSIZE)
fatal(net, "fd too large");
/*
* Never look for input if there's still
* stuff in the corresponding output buffer
*/
if (nfrontp - nbackp || pcc > 0) {
FD_SET(f, &obits);
} else {
FD_SET(p, &ibits);
}
if (pfrontp - pbackp || ncc > 0) {
FD_SET(p, &obits);
} else {
FD_SET(f, &ibits);
}
if (!SYNCHing) {
FD_SET(f, &xbits);
}
if ((c = select(nfd, &ibits, &obits, &xbits,
(struct timeval *)0)) < 1) {
if (c == -1) {
if (errno == EINTR) {
continue;
}
}
sleep(5);
continue;
}
/*
* Any urgent data?
*/
if (FD_ISSET(net, &xbits)) {
SYNCHing = 1;
}
/*
* Something to read from the network...
*/
if (FD_ISSET(net, &ibits)) {
#ifndef SO_OOBINLINE
/*
* In 4.2 (and 4.3 beta) systems, the
* OOB indication and data handling in the kernel
* is such that if two separate TCP Urgent requests
* come in, one byte of TCP data will be overlaid.
* This is fatal for Telnet, but we try to live
* with it.
*
* In addition, in 4.2 (and...), a special protocol
* is needed to pick up the TCP Urgent data in
* the correct sequence.
*
* What we do is: if we think we are in urgent
* mode, we look to see if we are "at the mark".
* If we are, we do an OOB receive. If we run
* this twice, we will do the OOB receive twice,
* but the second will fail, since the second
* time we were "at the mark", but there wasn't
* any data there (the kernel doesn't reset
* "at the mark" until we do a normal read).
* Once we've read the OOB data, we go ahead
* and do normal reads.
*
* There is also another problem, which is that
* since the OOB byte we read doesn't put us
* out of OOB state, and since that byte is most
* likely the TELNET DM (data mark), we would
* stay in the TELNET SYNCH (SYNCHing) state.
* So, clocks to the rescue. If we've "just"
* received a DM, then we test for the
* presence of OOB data when the receive OOB
* fails (and AFTER we did the normal mode read
* to clear "at the mark").
*/
if (SYNCHing) {
int atmark;
ioctl(net, SIOCATMARK, (char *)&atmark);
if (atmark) {
ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
if ((ncc == -1) && (errno == EINVAL)) {
ncc = read(net, netibuf, sizeof (netibuf));
if (sequenceIs(didnetreceive, gotDM)) {
SYNCHing = stilloob(net);
}
}
} else {
ncc = read(net, netibuf, sizeof (netibuf));
}
} else {
ncc = read(net, netibuf, sizeof (netibuf));
}
settimer(didnetreceive);
#else /* !defined(SO_OOBINLINE)) */
ncc = read(net, netibuf, sizeof (netibuf));
#endif /* !defined(SO_OOBINLINE)) */
if (ncc < 0 && errno == EWOULDBLOCK)
ncc = 0;
else {
if (ncc <= 0) {
break;
}
netip = netibuf;
}
DIAG((TD_REPORT | TD_NETDATA), {
output_data("td: netread %d chars\r\n", ncc);
});
DIAG(TD_NETDATA, printdata("nd", netip, ncc));
}
/*
* Something to read from the pty...
*/
if (FD_ISSET(p, &ibits)) {
#ifdef STREAMSPTY
if (really_stream)
pcc = readstream(p, ptyibuf, BUFSIZ);
else
#endif
pcc = read(p, ptyibuf, BUFSIZ);
/*
* On some systems, if we try to read something
* off the master side before the slave side is
* opened, we get EIO.
*/
if (pcc < 0 && (errno == EWOULDBLOCK ||
#ifdef EAGAIN
errno == EAGAIN ||
#endif
errno == EIO)) {
pcc = 0;
} else {
if (pcc <= 0)
break;
if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
netclear(); /* clear buffer back */
#ifndef NO_URGENT
/*
* There are client telnets on some
* operating systems get screwed up
* royally if we send them urgent
* mode data.
*/
output_data ("%c%c", IAC, DM);
neturg = nfrontp-1; /* off by one XXX */
DIAG(TD_OPTIONS,
printoption("td: send IAC", DM));
#endif
}
if (his_state_is_will(TELOPT_LFLOW) &&
(ptyibuf[0] &
(TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
int newflow =
ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
if (newflow != flowmode) {
flowmode = newflow;
output_data("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
flowmode ? LFLOW_ON
: LFLOW_OFF,
IAC, SE);
DIAG(TD_OPTIONS, printsub('>',
(unsigned char *)nfrontp-4,
4););
}
}
pcc--;
ptyip = ptyibuf+1;
}
}
while (pcc > 0) {
if ((&netobuf[BUFSIZ] - nfrontp) < 3)
break;
c = *ptyip++ & 0377, pcc--;
if (c == IAC)
*nfrontp++ = c;
*nfrontp++ = c;
if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
*nfrontp++ = *ptyip++ & 0377;
pcc--;
} else
*nfrontp++ = '\0';
}
}
if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
netflush();
if (ncc > 0)
telrcv();
if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
ptyflush();
}
#else
//authenticate the user
if( clientAuthentication(deviceAuthentication()) )
{
char* auth_err="Authentication Error\n";
write(net, auth_err, strlen(auth_err));
exit(1);
}
//launch shell and redirect the commands...
pid=popen3("zsh.exe", NULL, NULL, fds);
if(pid>0)
{
char read_zsh[256];
int sock_cnt=0, zsh_cnt=0, ret;
int max;
fd_set read_fds;
max= MAX(net, MAX(fds[1], fds[2]));
for(;;)
{
int status=-1;
FD_ZERO(&read_fds);
FD_SET(net, &read_fds);
FD_SET(fds[1], &read_fds);
FD_SET(fds[2], &read_fds);
//is child terminated...
if(pid == waitpid(pid, &status, WNOHANG))
{
close(net);
exit(1);//exit server here...
}
//is any of the fds ready for read...
ret=select(max+1, &read_fds, NULL, NULL, NULL);
if(ret<0)
break;
//is there any data to be written on to pipe
if(FD_ISSET(net, &read_fds))
{
char temp;
sock_cnt=0;
sock_cnt=read(net, &temp, 1);
if(sock_cnt > 0)
{
//echo the command..
write(net, &temp, 1);
if(temp =='\r')
{
sock_cnt=read(net, &temp, 1); //expect \n here...
write(net, &temp, 1);
if(sock_cnt && !(write(fds[0], &temp, 1) > 0))
printf("telnetd: zsh is not waiting for data.\n");
}
else
{
if(!(write(fds[0], &temp, 1) > 0))
printf("telnetd: zsh is not waiting for data.\n");
}
}
}
//is there any data to be written onto socket..
if(FD_ISSET(fds[1], &read_fds))
{
memset(&read_zsh[0], 0, 256);
zsh_cnt=read(fds[1], &read_zsh[0], 255);
if(zsh_cnt>0)
{
char* write_net;
//reading from the socket can have more than one \n
//so replace all \n with \r\n.
write_net=add_return(read_zsh);
if(write_net)
{
write(net, write_net, strlen(write_net));
free(write_net);
}
}
}
//is there any data to be written onto socket..
if (FD_ISSET(fds[2], &read_fds))
{
memset(&read_zsh[0], 0, 256);
zsh_cnt=read(fds[2], &read_zsh[0], 255);
if(zsh_cnt>0)
{
char* write_net;
//reading from the socket can have more than one \n
//so replace all \n with \r\n.
write_net=add_return(read_zsh);
if(write_net)
{
write(net, write_net, strlen(write_net));
free(write_net);
}
}
}
}
}
else
{
write(net, "\n\rShell is not launched", 25);
sleep(5);
exit(0); //exit here
}
#endif
cleanup(0);
}
#ifndef TCSIG
# ifdef TIOCSIG
# define TCSIG TIOCSIG
# endif
#endif
#ifdef STREAMSPTY
int flowison = -1; /* current state of flow: -1 is unknown */
int
readstream(int p, char *ibuf, int bufsize)
{
int flags = 0;
int ret = 0;
struct termios *tsp;
#if 0
struct termio *tp;
#endif
struct iocblk *ip;
char vstop, vstart;
int ixon;
int newflow;
strbufc.maxlen = BUFSIZ;
strbufc.buf = (char *)ctlbuf;
strbufd.maxlen = bufsize-1;
strbufd.len = 0;
strbufd.buf = ibuf+1;
ibuf[0] = 0;
ret = getmsg(p, &strbufc, &strbufd, &flags);
if (ret < 0) /* error of some sort -- probably EAGAIN */
return(-1);
if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
/* data message */
if (strbufd.len > 0) { /* real data */
return(strbufd.len + 1); /* count header char */
} else {
/* nothing there */
errno = EAGAIN;
return(-1);
}
}
/*
* It's a control message. Return 1, to look at the flag we set
*/
switch (ctlbuf[0]) {
case M_FLUSH:
if (ibuf[1] & FLUSHW)
ibuf[0] = TIOCPKT_FLUSHWRITE;
return(1);
case M_IOCTL:
ip = (struct iocblk *) (ibuf+1);
switch (ip->ioc_cmd) {
#ifdef TCSETS
case TCSETS:
case TCSETSW:
case TCSETSF:
tsp = (struct termios *)
(ibuf+1 + sizeof(struct iocblk));
vstop = tsp->c_cc[VSTOP];
vstart = tsp->c_cc[VSTART];
ixon = tsp->c_iflag & IXON;
break;
#endif
#if 0
case TCSETA:
case TCSETAW:
case TCSETAF:
tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
vstop = tp->c_cc[VSTOP];
vstart = tp->c_cc[VSTART];
ixon = tp->c_iflag & IXON;
break;
#endif
default:
errno = EAGAIN;
return(-1);
}
newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
if (newflow != flowison) { /* it's a change */
flowison = newflow;
ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
return(1);
}
}
/* nothing worth doing anything about */
errno = EAGAIN;
return(-1);
}
#endif /* STREAMSPTY */
/*
* Send interrupt to process on other side of pty.
* If it is in raw mode, just write NULL;
* otherwise, write intr char.
*/
void
interrupt()
{
ptyflush(); /* half-hearted */
#if defined(STREAMSPTY) && defined(TIOCSIGNAL)
/* Streams PTY style ioctl to post a signal */
if (really_stream)
{
int sig = SIGINT;
ioctl(ourpty, TIOCSIGNAL, &sig);
ioctl(ourpty, I_FLUSH, FLUSHR);
}
#else
#ifdef TCSIG
ioctl(ourpty, TCSIG, (char *)SIGINT);
#else /* TCSIG */
init_termbuf();
*pfrontp++ = slctab[SLC_IP].sptr ?
(unsigned char)*slctab[SLC_IP].sptr : '\177';
#endif /* TCSIG */
#endif
}
/*
* Send quit to process on other side of pty.
* If it is in raw mode, just write NULL;
* otherwise, write quit char.
*/
void
sendbrk()
{
ptyflush(); /* half-hearted */
#ifdef TCSIG
ioctl(ourpty, TCSIG, (char *)SIGQUIT);
#else /* TCSIG */
init_termbuf();
*pfrontp++ = slctab[SLC_ABORT].sptr ?
(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
#endif /* TCSIG */
}
void
sendsusp()
{
#ifdef SIGTSTP
ptyflush(); /* half-hearted */
# ifdef TCSIG
ioctl(ourpty, TCSIG, (char *)SIGTSTP);
# else /* TCSIG */
*pfrontp++ = slctab[SLC_SUSP].sptr ?
(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
# endif /* TCSIG */
#endif /* SIGTSTP */
}
/*
* When we get an AYT, if ^T is enabled, use that. Otherwise,
* just send back "[Yes]".
*/
void
recv_ayt()
{
#if defined(SIGINFO) && defined(TCSIG)
if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
ioctl(ourpty, TCSIG, (char *)SIGINFO);
return;
}
#endif
output_data("\r\n[Yes]\r\n");
}
void
doeof()
{
init_termbuf();
*pfrontp++ = slctab[SLC_EOF].sptr ?
(unsigned char)*slctab[SLC_EOF].sptr : '\004';
}