summaryrefslogblamecommitdiffstats
path: root/c/src/libnetworking/pppd/pppmain.c
blob: 4ba37a945f909f56510797c5e4ac0eea76ab49d3 (plain) (tree)
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314








































                                                                      


                       


                               




























                                                                        


                                          


































                                                                                           




                                                        
                                  


                                                   
                                             
      















































                                                
     
                            
      

                              
     
                    
      




























































































































































                                                                                                                    
                                                                                  
























                                                                       
                                                                              





                                          
                                                                             



































                                                                                                 
                                                               











                                                                      
                                                                    




















                                                                                                       
                                                                  





































































































































































































































































































































                                                                                         


                                                  








                                                              
     





                                                                                                                 
      










                                           
                                                           








































































































                                                                                                     

                          


























                                                  
      
























































































































































































































































































































































































                                                                                
/*
 * main.c - Point-to-Point Protocol main module
 *
 * Copyright (c) 1989 Carnegie Mellon University.
 * 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 Carnegie Mellon University.  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.
 */

#ifndef lint
/* static char rcsid[] = "$Id$"; */
#endif

#include <stdio.h>
#include <ctype.h>
/* #include <stdlib.h> */
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <netdb.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#include <rtems.h>
#include <rtems/rtems_bsdnet.h>

/* #include <stbconfig.h> */
#include "pppd.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#include "upap.h"
#include "chap.h"
#include "ccp.h"
#include "pathnames.h"
#include "patchlevel.h"

#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif

#if defined(SUNOS4)
extern char *strerror();
#endif

#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif							/* IPX_CHANGE */
#ifdef AT_CHANGE
#include "atcp.h"
#endif

void SetStatusInfo(int state, char * text, int res);

/* prototypes for routines in this file */
int connect_script(int fd);

/* interface vars */
char ifname[32];				/* Interface name */
int interfunit;					/* Interface unit number */

char *progname;					/* Name of this program */
char hostname[MAXNAMELEN] = "dcna";	/* Our hostname */
static char default_devnam[MAXPATHLEN];		/* name of default device */
/*static pid_t pid;	*/			/* Our pid */
static uid_t uid;				/* Our real user-id */
static int conn_running;		/* we have a [dis]connector running */

int ttyfd = -1;					/* Serial port file descriptor */
mode_t tty_mode = -1;			/* Original access permissions to tty */
int baud_rate;					/* Actual bits/second for serial device */
int hungup;						/* terminal has been hung up */
int privileged;					/* we're running as real uid root */
int need_holdoff;				/* need holdoff period before restarting */
int detached;					/* have detached from terminal */

int phase;						/* where the link is at */
int kill_link;
int open_ccp_flag;

char **script_env;				/* Env. variable values for scripts */
int s_env_nalloc;				/* # words avail at script_env */

u_char outpacket_buf[PPP_MRU + PPP_HDRLEN];		/* buffer for outgoing packet */
u_char inpacket_buf[PPP_MRU + PPP_HDRLEN];	/* buffer for incoming packet */



char *no_ppp_msg = "lack of PPP\n";

/* Prototypes for procedures local to this file. */
static void cleanup(void);
static void close_tty __P((void));
static void get_input __P((void));
static void calltimeout __P((void));
static struct timeval *timeleft __P((struct timeval *));
static void holdoff_end __P((void *));
static void reap_kids __P((void));
/* XXX currently unused */
#if 0
static int device_script __P((char *[], int, int));
static void pr_log __P((void *, char *,...));
#endif

extern char *ttyname __P((int));
extern char *getlogin __P((void));
int main __P((int, char *[]));





/*
 * PPP Data Link Layer "protocol" table.
 * One entry per supported protocol.
 * The last entry must be NULL.
 */
struct protent *protocols[] =
{
	&lcp_protent,
	&pap_protent,
	&chap_protent,
#ifdef CBCP_SUPPORT
	&cbcp_protent,
#endif
	&ipcp_protent,
	&ccp_protent,
#ifdef IPX_CHANGE
	&ipxcp_protent,
#endif
#ifdef AT_CHANGE
	&atcp_protent,
#endif
	NULL
};

extern int connect_stb();


extern int disconnect_stb();


extern struct in_addr rtems_bsdnet_nameserver[];
extern int rtems_bsdnet_nameserver_count;
extern int __res_init(void);

int pppdmain(argc, argv)
int argc;
char *argv[];
{
	int i;
#if 0
	struct timeval timo;
#endif
	struct protent *protp;
	struct stat statbuf;
#if 0
    	char t[100];
#endif


	phase = PHASE_INITIALIZE;

	strcpy(default_devnam, "/dev/modem");
	strcpy(devnam, "/dev/modem");

	script_env = NULL;

/*    if (gethostname(hostname, MAXNAMELEN) < 0 ) {
   die(1);
   }
 */
	hostname[MAXNAMELEN - 1] = 0;

	uid = 0;
	privileged = uid == 0;

	/*
	 * Initialize to the standard option set, then parse, in order,
	 * the system options file, the user's options file,
	 * the tty's options file, and the command line arguments.
	 */
	for (i = 0; (protp = protocols[i]) != NULL; ++i)
		(*protp->init) (0);



#if 1
	if (!ppp_available()) {
		exit(1);
	}
#endif
	/*
	 * Check that the options given are valid and consistent.
	 */
	sys_check_options();
	auth_check_options();
	for (i = 0; (protp = protocols[i]) != NULL; ++i)
		if (protp->check_options != NULL)
			(*protp->check_options) ();

	/*
	 * If the user has specified the default device name explicitly,
	 * pretend they hadn't.
	 */
	if (!default_device && strcmp(devnam, default_devnam) == 0)
		default_device = 1;
	if (default_device)
		nodetach = 1;

	/*
	 * Initialize system-dependent stuff and magic number package.
	 */
	sys_init();
	magic_init();

	/*
	 * Detach ourselves from the terminal, if required,
	 * and identify who is running us.
	 */

/*
	syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
	     VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
*/


	for (;;) {
#if 0 /* FIXME: how do we synchonize? */

/* !!! here should be done some kind of synchronization - I did it following way ... */
/* GlobalSystemStatus is set of different things shared between different tasks ... */
#if 0
/* XXX PPPConfiguration */
	GlobalSystemStatus * volatile stat;
	stat=LockSTBSystemParam();
	stat->ConnectionStatus = NotConnected;
	UnlockSTBSystemParam();
#endif


		while (1) {
			rtems_event_set events;
			int status;

#if 0
/* XXX PPPConfiguration */
			stat=LockSTBSystemParam();
			status=stat->WantConnection;
			UnlockSTBSystemParam();
			
			if (status == Connect) break;
#endif
			rtems_event_receive(RTEMS_EVENT_1, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events);
		}
#if 0
/* XXX PPPConfiguration */
	stat=LockSTBSystemParam();
/* 	stat->WantConnection=DontConnect; */
	stat->ConnectionStatus = Connecting;

/* Here you can change default nameserver ... */
	rtems_bsdnet_nameserver[0].s_addr=inet_addr(stat->DNS);
	rtems_bsdnet_nameserver_count=1;
	UnlockSTBSystemParam();
#endif
/* initialize DNS services here */
	 SetStatusInfo(0, "Connecting...",0);

	__res_init();
#endif /* FIXME */
		/*
		 * Open the serial device and set it up to be the ppp interface.
		 * First we open it in non-blocking mode so we can set the
		 * various termios flags appropriately.  If we aren't dialling
		 * out and we want to use the modem lines, we reopen it later
		 * in order to wait for the carrier detect signal from the modem.
		 */
		while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
			if (errno != EINTR)
				syslog(LOG_ERR, "Failed to open %s: %m", devnam);

			if (!persist || errno != EINTR)
				goto fail;
		}

		hungup = 0;
		kill_link = 0;

		/*
		 * Do the equivalent of `mesg n' to stop broadcast messages.
		 */
		tty_mode = statbuf.st_mode;

		/* run connection script */
		/*
		 * Set line speed, flow control, etc.
		 * On most systems we set CLOCAL for now so that we can talk
		 * to the modem before carrier comes up.  But this has the
		 * side effect that we might miss it if CD drops before we
		 * get to clear CLOCAL below.  On systems where we can talk
		 * successfully to the modem with CLOCAL clear and CD down,
		 * we can clear CLOCAL at this point.
		 */
		set_up_tty(ttyfd, 1);

		/* drop dtr to hang up in case modem is off hook */
		setdtr(ttyfd, FALSE);
		sleep(1);
		setdtr(ttyfd, TRUE);
	    {
/* Make a call ... */
#if 0
/* XXX PPPConfiguration */
	    	char t[100];
			stat=LockSTBSystemParam();
			sprintf(t,"Calling the number %s ...",stat->Phone_Number);
			UnlockSTBSystemParam();	    	
	    	SetStatusInfo(0, t,0);
#endif
	    }
	    

		if ((i=connect_script(ttyfd)) >0) {
#if 0
/* here go error messages ... */
		static char *error_msgs[]={ "Bad script", "IO Error"
		 	"Timeout", "Busy", "No dialtone", "No carrier",
			"No answer", "No answer from server" };
			setdtr(ttyfd, FALSE);
	    	sprintf(t,"Communication error: %s",error_msgs[i-1]);
		syslog(LOG_ERR, "Connect script failed");
	    	SetStatusInfo(0, t,1);
#endif
			goto fail;
		}
	
		else
		if (i<0)
		{
#if 0
	    	char t[100];
			sprintf(t,"Connecting the Internet at %d baud...",-i);
		    SetStatusInfo(0, t,0);
#endif
		}
		else
		{
#if 0
			    SetStatusInfo(0, "Connecting the Internet...",0);
#endif
		}
		syslog(LOG_INFO, "Serial connection established.");

		sleep(1);				/* give it time to set up its terminal */

		/* set line speed, flow control, etc.; clear CLOCAL if modem option */
		set_up_tty(ttyfd, 0);

		/* reopen tty if necessary to wait for carrier */

		/* run welcome script, if any */
/*  if (welcomer && welcomer[0]) {
   if (device_script(welcomer, 21, ttyfd) < 0)
   syslog(LOG_WARNING, "Welcome script failed");
   }
 */
		/* set up the serial device as a ppp interface */
		establish_ppp(ttyfd);

/*  syslog(LOG_INFO, "Using interface ppp%d", interfunit);  */
		(void) sprintf(ifname, "ppp%d", interfunit);

		/*
		 * Start opening the connection and wait for
		 * incoming events (reply, timeout, etc.).
		 */
/*   syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); */

		rtems_bsdnet_semaphore_obtain();

		lcp_lowerup(0);
		lcp_open(0);			/* Start protocol */

		rtems_bsdnet_semaphore_release();
#if 0
        SetStatusInfo(0, "Internet connection established.",1);
#endif
		for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD;) {
#if 0
			wait_input(timeleft(&timo));
#endif
			calltimeout();
			get_input();
#if 0
/* XXX PPPConfiguration */
			stat=LockSTBSystemParam();
			if (stat->WantConnection==DontConnect) {
				stat->ConnectionStatus = NotConnected;
			    SetStatusInfo(0, "Disconnecting ...",0);
				lcp_close(0, "");
				kill_link = 0;
			}
			UnlockSTBSystemParam();
#endif
			if (open_ccp_flag) {
				if (phase == PHASE_NETWORK) {
					ccp_fsm[0].flags = OPT_RESTART;		/* clears OPT_SILENT */
					(*ccp_protent.open) (0);
				}
				open_ccp_flag = 0;
			}
		}
		/*
		 * If we may want to bring the link up again, transfer
		 * the ppp unit back to the loopback.  Set the
		 * real serial device back to its normal mode of operation.
		 */
		clean_check();
		disestablish_ppp(ttyfd);
#if 0
	    SetStatusInfo(0, "Broken the internet connection.",1);
#endif
		/*
		 * Run disconnector script, if requested.
		 * XXX we may not be able to do this if the line has hung up!
		 */
/*  if (disconnector && !hungup) {
   set_up_tty(ttyfd, 1);
   if (device_script(disconnector, ttyfd, ttyfd) < 0) {
   syslog(LOG_WARNING, "disconnect script failed");
   } else {
   syslog(LOG_INFO, "Serial link disconnected.");
   }
   }
 */
	  fail:
#if 0
/* XXX PPPConfiguration */
		stat=LockSTBSystemParam();
		stat->ConnectionStatus = NotConnected;
		stat->WantConnection=DontConnect;
		UnlockSTBSystemParam();
#endif
		if (ttyfd >= 0)
			close_tty();



	}

	return 0;
}

/*
 * detach - detach us from the controlling terminal.
 */
void detach()
{
}

/*
 * holdoff_end - called via a timeout when the holdoff period ends.
 */

static void holdoff_end(arg)
void *arg;
{
	phase = PHASE_DORMANT;
}

/*
 * get_input - called when incoming data is available.
 */
static void get_input()
{
	int len, i;
	u_char *p;
	u_short protocol;
	struct protent *protp;

	p = inpacket_buf;			/* point to beginning of packet buffer */

	len = read_packet(inpacket_buf);
	if (len < 0)
		return;

	if (len == 0) {
#if 0
/* XXX PPPConfiguration */
		GlobalSystemStatus * volatile stat;
#endif
/*   syslog(LOG_NOTICE, "Modem hangup"); */
		hungup = 1;
#if 0
/* XXX PPPConfiguration */
		stat=LockSTBSystemParam();
		stat->ConnectionStatus = NotConnected;
		UnlockSTBSystemParam();
#endif

		lcp_lowerdown(0);		/* serial link is no longer available */
		link_terminated(0);
		return;
	}
/*	if ((debug))
		log_packet(p, len, "rcvd ", LOG_DEBUG);
*/

	if (len < PPP_HDRLEN) {
/*
		if (debug)
			MAINDEBUG((LOG_INFO, "io(): Received short packet."));
*/
		return;
	}
/* We need to modify internal network structures here */
	rtems_bsdnet_semaphore_obtain();

	p += 2;						/* Skip address and control */
	GETSHORT(protocol, p);
	len -= PPP_HDRLEN;

	/*
	 * Toss all non-LCP packets unless LCP is OPEN.
	 */
	if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
		MAINDEBUG((LOG_INFO,
			   "get_input: Received non-LCP packet when LCP not open."));
		rtems_bsdnet_semaphore_release();
		return;
	}
	/*
	 * Until we get past the authentication phase, toss all packets
	 * except LCP, LQR and authentication packets.
	 */
	if (phase <= PHASE_AUTHENTICATE
		&& !(protocol == PPP_LCP || protocol == PPP_LQR
			 || protocol == PPP_PAP || protocol == PPP_CHAP)) {

		rtems_bsdnet_semaphore_release();
		return;
	}
	/*
	 * Upcall the proper protocol input routine.
	 */
	for (i = 0; (protp = protocols[i]) != NULL; ++i) {
		if (protp->protocol == protocol && protp->enabled_flag) {
			(*protp->input) (0, p, len);
			rtems_bsdnet_semaphore_release();
			return;
		}
		if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
			&& protp->datainput != NULL) {
			(*protp->datainput) (0, p, len);
			rtems_bsdnet_semaphore_release();
			return;
		}
	}

	lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
	rtems_bsdnet_semaphore_release();
}


/*
 * quit - Clean up state and exit (with an error indication).
 */
void quit()
{
	die(1);
}

/*
 * die - like quit, except we can specify an exit status.
 */
void die(status)
int status;
{
	cleanup();
}

/*
 * cleanup - restore anything which needs to be restored before we exit
 */
/* ARGSUSED */
static void cleanup()
{
	sys_cleanup();

	if (ttyfd >= 0)
		close_tty();

}

/*
 * close_tty - restore the terminal device and close it.
 */
static void close_tty()
{
	disestablish_ppp(ttyfd);

	/* drop dtr to hang up */
	setdtr(ttyfd, FALSE);
	/*
	 * This sleep is in case the serial port has CLOCAL set by default,
	 * and consequently will reassert DTR when we close the device.
	 */
	sleep(1);

	restore_tty(ttyfd);
	close(ttyfd);
	ttyfd = -1;
}


struct callout {
	struct timeval c_time;
	void *c_arg;
	void (*c_func) __P((void *));
	struct callout *c_next;
};

static struct callout *callout = NULL;
static struct timeval timenow;

/*
 * timeout - Schedule a timeout.
 *
 * Note that this timeout takes the number of seconds, NOT hz (as in
 * the kernel).
 */
void my_timeout(func, arg, time)
void (*func) __P((void *));
void *arg;
int time;
{
	struct callout *newp, *p, **pp;

	MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
			   (long) func, (long) arg, time));
	/*
	 * Allocate timeout.
	 */
	if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
/*  syslog(LOG_ERR, "Out of memory in timeout()!"); */
		die(1);
	}
	newp->c_arg = arg;
	newp->c_func = func;
	gettimeofday(&timenow, NULL);
	newp->c_time.tv_sec = timenow.tv_sec + time;
	newp->c_time.tv_usec = timenow.tv_usec;
	/*
	 * Find correct place and link it in.
	 */
	for (pp = &callout; (p = *pp); pp = &p->c_next)
		if (newp->c_time.tv_sec < p->c_time.tv_sec
			|| (newp->c_time.tv_sec == p->c_time.tv_sec
				&& newp->c_time.tv_usec < p->c_time.tv_sec))
			break;
	newp->c_next = p;
	*pp = newp;
}

/*
 * untimeout - Unschedule a timeout.
 */

void untimeout(func, arg)
void (*func) __P((void *));
void *arg;
{
	struct callout **copp, *freep;

	MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));

	for (copp = &callout; (freep = *copp); copp = &freep->c_next)
		if (freep->c_func == func && freep->c_arg == arg) {
			*copp = freep->c_next;
			(void) free((char *) freep);
			break;
		}
}


/*
 * calltimeout - Call any timeout routines which are now due.
 */
static void calltimeout()
{
	struct callout *p;

	while (callout != NULL) {
		p = callout;

		if (gettimeofday(&timenow, NULL) < 0) {
			die(1);
		}
		if (!(p->c_time.tv_sec < timenow.tv_sec
			  || (p->c_time.tv_sec == timenow.tv_sec
				  && p->c_time.tv_usec <= timenow.tv_usec)))
			break;				/* no, it's not time yet */

		callout = p->c_next;
		(*p->c_func) (p->c_arg);

		free((char *) p);
	}
}


/*
 * timeleft - return the length of time until the next timeout is due.
 */
static struct timeval *
 timeleft(tvp)
struct timeval *tvp;
{
	if (callout == NULL)
		return NULL;

	gettimeofday(&timenow, NULL);
	tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
	tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
	if (tvp->tv_usec < 0) {
		tvp->tv_usec += 1000000;
		tvp->tv_sec -= 1;
	}
	if (tvp->tv_sec < 0)
		tvp->tv_sec = tvp->tv_usec = 0;

	return tvp;
}


/*
 * term - Catch SIGTERM signal and SIGINT signal (^C/del).
 *
 * Indicates that we should initiate a graceful disconnect and exit.
 */
static void term(sig)
int sig;
{
	/*    persist = 0; *//* don't try to restart */
	kill_link = 1;
}

int modem_fd; /* FIXME: should not be global... */
int connect_script(int fd)
{
#if 0 /* FIXME: This is WinNT special */
	char program[256] = "TIMEOUT@10@@CLIENT@CLIENTSERVER";
#else
	char program[256] = { 0 };
#endif
#if 0
/* XXX PPPConfiguration */
	GlobalSystemStatus * volatile stat;
#endif
#if 0
/* Connect scripts are almost the same as in Linux Chat ... */
	static char *scripts[] =
	{
		"TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@",
		"TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@@ppp@@Username:@%s@Password:@%s@"
	};
#endif
	modem_fd = fd;
#if 0
/* XXX PPPConfiguration */
	stat=LockSTBSystemParam();	
	if (strcmp("",stat->PPP_User))
	{
		stat->provider=Poland_TPSA;
	}
	else
		stat->provider=DumbLogin;
	switch (stat->provider) {
	case Poland_TPSA:       /* TPSA - Polish Telecom */
		sprintf(program, scripts[1], stat->Phone_Number, stat->PPP_User, stat->PPP_Password);
		break;
	default:
		sprintf(program, scripts[0], stat->Phone_Number);

	}
	UnlockSTBSystemParam();
#endif
	conn_running = 0;

	return chatmain(program);
}


/*
 * run-program - execute a program with given arguments,
 * but don't wait for it.
 * If the program can't be executed, logs an error unless
 * must_exist is 0 and the program file doesn't exist.
 */
int run_program(prog, args, must_exist)
char *prog;
char **args;
int must_exist;
{

	return 0;
}


/*
 * reap_kids - get status from any dead child processes,
 * and log a message for abnormal terminations.
 */
static void reap_kids()
{
}


/*
 * log_packet - format a packet and log it.
 */

char line[256];
char *linep;

/*#define log_packet(p, len, prefix, level) */
void log_packet(p, len, prefix, level)
u_char *p;
int len;
char *prefix;
int level;
{
	strcpy(line, prefix);
	linep = line + strlen(line);
/*	format_packet(p, len, pr_log, NULL); */
/*    if (linep != line)
   syslog(level, "%s", line);
 */
}

/*
 * format_packet - make a readable representation of a packet,
 * calling `printer(arg, format, ...)' to output it.
 */
/*#define format_packet(p, len, printer, arg) */

void format_packet(p, len, printer, arg)
u_char *p;
int len;
void (*printer) __P((void *, char *,...));
void *arg;
{
/*
	int i, n;
	u_short proto;
	struct protent *protp;

	if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
		p += 2;
		GETSHORT(proto, p);
		len -= PPP_HDRLEN;
		for (i = 0; (protp = protocols[i]) != NULL; ++i)
			if (proto == protp->protocol)
				break;
		if (protp != NULL) {
			printer(arg, "[%s", protp->name);
			n = (*protp->printpkt) (p, len, printer, arg);
			printer(arg, "]");
			p += n;
			len -= n;
		} else {
			printer(arg, "[proto=0x%x]", proto);
		}
	}
*/
/*    for (; len > 0; --len) {
   GETCHAR(x, p);
   printer(arg, " %.2x", x);
   }
 */
}



/* XXX currently unused */
#if 0
static void
pr_log __V((void *arg, char *fmt,...))
{
	int n;
	va_list pvar;
	char buf[256];

#if __STDC__
	va_start(pvar, fmt);
#else
	void *arg;
	char *fmt;
	va_start(pvar);
	arg = va_arg(pvar, void *);
	fmt = va_arg(pvar, char *);
#endif

	n = vfmtmsg(buf, sizeof(buf), fmt, pvar);
	va_end(pvar);

	if (linep + n + 1 > line + sizeof(line)) {
/*  syslog(LOG_DEBUG, "%s", line); */
		linep = line;
	}
	strcpy(linep, buf);
	linep += n;
}
#endif

/*
 * print_string - print a readable representation of a string using
 * printer.
 */
/*#define print_string(p, len, printer, arg) */

void print_string(p, len, printer, arg)
char *p;
int len;
void (*printer) __P((void *, char *,...));
void *arg;
{
	int c;

	printer(arg, "\"");
	for (; len > 0; --len) {
		c = *p++;
		if (' ' <= c && c <= '~') {
			if (c == '\\' || c == '"')
				printer(arg, "\\");
			printer(arg, "%c", c);
		} else {
			switch (c) {
			case '\n':
				printer(arg, "\\n");
				break;
			case '\r':
				printer(arg, "\\r");
				break;
			case '\t':
				printer(arg, "\\t");
				break;
			default:
				printer(arg, "\\%.3o", c);
			}
		}
	}
	printer(arg, "\"");
}


/*
 * novm - log an error message saying we ran out of memory, and die.
 */
void novm(msg)
char *msg;
{
/*    syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
 */ die(1);
}

/*
 * fmtmsg - format a message into a buffer.  Like sprintf except we
 * also specify the length of the output buffer, and we handle
 * %r (recursive format), %m (error message) and %I (IP address) formats.
 * Doesn't do floating-point formats.
 * Returns the number of chars put into buf.
 */
int
fmtmsg __V((char *buf, int buflen, char *fmt,...))
{
	va_list args;
	int n;

#if __STDC__
	va_start(args, fmt);
#else
	char *buf;
	int buflen;
	char *fmt;
	va_start(args);
	buf = va_arg(args, char *);
	buflen = va_arg(args, int);
	fmt = va_arg(args, char *);
#endif
	n = vfmtmsg(buf, buflen, fmt, args);
	va_end(args);
	return n;
}

/*
 * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
 */
#define OUTCHAR(c)	(buflen > 0? (--buflen, *buf++ = (c)): 0)
/*#define vfmtmsg(buf, buflen, fmt, args) */

int vfmtmsg(buf, buflen, fmt, args)
char *buf;
int buflen;
char *fmt;
va_list args;
{
/*    int c, i, n;
   int width, prec, fillch;
   int base, len, neg, quoted;
   unsigned long val = 0;
   char *str, *f, *buf0;
   unsigned char *p;
   char num[32];
   time_t t;
   static char hexchars[] = "0123456789abcdef";

   buf0 = buf;
   --buflen;
   while (buflen > 0) {
   for (f = fmt; *f != '%' && *f != 0; ++f)
   ;
   if (f > fmt) {
   len = f - fmt;
   if (len > buflen)
   len = buflen;
   memcpy(buf, fmt, len);
   buf += len;
   buflen -= len;
   fmt = f;
   }
   if (*fmt == 0)
   break;
   c = *++fmt;
   width = prec = 0;
   fillch = ' ';
   if (c == '0') {
   fillch = '0';
   c = *++fmt;
   }
   if (c == '*') {
   width = va_arg(args, int);
   c = *++fmt;
   } else {
   while (isdigit(c)) {
   width = width * 10 + c - '0';
   c = *++fmt;
   }
   }
   if (c == '.') {
   c = *++fmt;
   if (c == '*') {
   prec = va_arg(args, int);
   c = *++fmt;
   } else {
   while (isdigit(c)) {
   prec = prec * 10 + c - '0';
   c = *++fmt;
   }
   }
   }
   str = 0;
   base = 0;
   neg = 0;
   ++fmt;
   switch (c) {
   case 'd':
   i = va_arg(args, int);
   if (i < 0) {
   neg = 1;
   val = -i;
   } else
   val = i;
   base = 10;
   break;
   case 'o':
   val = va_arg(args, unsigned int);
   base = 8;
   break;
   case 'x':
   val = va_arg(args, unsigned int);
   base = 16;
   break;
   case 'p':
   val = (unsigned long) va_arg(args, void *);
   base = 16;
   neg = 2;
   break;
   case 's':
   str = va_arg(args, char *);
   break;
   case 'c':
   num[0] = va_arg(args, int);
   num[1] = 0;
   str = num;
   break;
   case 'm':
   str = strerror(errno);
   break;
   case 'I':
   str = ip_ntoa(va_arg(args, u_int32_t));
   break;
   case 'r':
   f = va_arg(args, char *);
   #ifndef __powerpc__
   n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
   #else

   n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
   #endif
   buf += n;
   buflen -= n;
   continue;
   case 't':
   break;
   case 'v':         
   case 'q':     
   quoted = c == 'q';
   p = va_arg(args, unsigned char *);
   if (fillch == '0' && prec > 0) {
   n = prec;
   } else {
   n = strlen((char *)p);
   if (prec > 0 && prec < n)
   n = prec;
   }
   while (n > 0 && buflen > 0) {
   c = *p++;
   --n;
   if (!quoted && c >= 0x80) {
   OUTCHAR('M');
   OUTCHAR('-');
   c -= 0x80;
   }
   if (quoted && (c == '"' || c == '\\'))
   OUTCHAR('\\');
   if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
   if (quoted) {
   OUTCHAR('\\');
   switch (c) {
   case '\t':   OUTCHAR('t');   break;
   case '\n':   OUTCHAR('n');   break;
   case '\b':   OUTCHAR('b');   break;
   case '\f':   OUTCHAR('f');   break;
   default:
   OUTCHAR('x');
   OUTCHAR(hexchars[c >> 4]);
   OUTCHAR(hexchars[c & 0xf]);
   }
   } else {
   if (c == '\t')
   OUTCHAR(c);
   else {
   OUTCHAR('^');
   OUTCHAR(c ^ 0x40);
   }
   }
   } else
   OUTCHAR(c);
   }
   continue;
   default:
   *buf++ = '%';
   if (c != '%')
   --fmt;       
   --buflen;
   continue;
   }
   if (base != 0) {
   str = num + sizeof(num);
   *--str = 0;
   while (str > num + neg) {
   *--str = hexchars[val % base];
   val = val / base;
   if (--prec <= 0 && val == 0)
   break;
   }
   switch (neg) {
   case 1:
   *--str = '-';
   break;
   case 2:
   *--str = 'x';
   *--str = '0';
   break;
   }
   len = num + sizeof(num) - 1 - str;
   } else {
   len = strlen(str);
   if (prec > 0 && len > prec)
   len = prec;
   }
   if (width > 0) {
   if (width > buflen)
   width = buflen;
   if ((n = width - len) > 0) {
   buflen -= n;
   for (; n > 0; --n)
   *buf++ = fillch;
   }
   }
   if (len > buflen)
   len = buflen;
   memcpy(buf, str, len);
   buf += len;
   buflen -= len;
   }
   *buf = 0;
   return buf - buf0;
 */
	return 0;
}


/*
 * script_setenv - set an environment variable value to be used
 * for scripts that we run (e.g. ip-up, auth-up, etc.)
 */
#define script_setenv(var, value)
/*
   void
   script_setenv(var, value)
   char *var, *value;
   {
   int vl = strlen(var);
   int i;
   char *p, *newstring;

   newstring = (char *) malloc(vl + strlen(value) + 2);
   if (newstring == 0)
   return;
   strcpy(newstring, var);
   newstring[vl] = '=';
   strcpy(newstring+vl+1, value);

   if (script_env != 0) {
   for (i = 0; (p = script_env[i]) != 0; ++i) {
   if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
   free(p);
   script_env[i] = newstring;
   return;
   }
   }
   } else {
   i = 0;
   script_env = (char **) malloc(16 * sizeof(char *));
   if (script_env == 0)
   return;
   s_env_nalloc = 16;
   }

   if (i + 1 >= s_env_nalloc) {
   int new_n = i + 17;
   char **newenv = (char **) realloc((void *)script_env,
   new_n * sizeof(char *));
   if (newenv == 0)
   return;
   script_env = newenv;
   s_env_nalloc = new_n;
   }

   script_env[i] = newstring;
   script_env[i+1] = 0;
   }

		    *//*
		      * script_unsetenv - remove a variable from the environment
		      * for scripts.
		    */
#define script_unsetenv(var)
/*
   void
   script_unsetenv(var)
   char *var;
   {
   int vl = strlen(var);
   int i;
   char *p;

   if (script_env == 0)
   return;
   for (i = 0; (p = script_env[i]) != 0; ++i) {
   if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
   free(p);
   while ((script_env[i] = script_env[i+1]) != 0)
   ++i;
   break;
   }
   }
   }
 */