tmp.c
来源:互联网 发布:python while循环终止 编辑:程序博客网 时间:2024/06/06 02:32
/*
* main.c - Point-to-Point Protocol main module
*
* Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Copyright (c) 1999-2004 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: main.c,v 1.156 2008/06/23 11:47:18 paulus Exp $"
#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 <utmp.h>
#include <pwd.h>
#include <setjmp.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 <netinet/in.h>
#include <arpa/inet.h>
#include "pppd.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#ifdef INET6
#include "ipv6cp.h"
#endif
#include "upap.h"
#include "chap-new.h"
#include "eap.h"
#include "ccp.h"
#include "ecp.h"
#include "pathnames.h"
#ifdef USE_TDB
#include "tdb.h"
#endif
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif /* IPX_CHANGE */
#ifdef AT_CHANGE
#include "atcp.h"
#endif
static const char rcsid[] = RCSID;
/* interface vars */
char ifname[32]; /* Interface name */
int ifunit; /* Interface unit number */
struct channel *the_channel;
char *progname; /* Name of this program */
char hostname[MAXNAMELEN]; /* Our hostname */
static char pidfilename[MAXPATHLEN]; /* name of pid file */
static char linkpidfile[MAXPATHLEN]; /* name of linkname pid file */
char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
uid_t uid; /* Our real user-id */
struct notifier *pidchange = NULL;
struct notifier *phasechange = NULL;
struct notifier *exitnotify = NULL;
struct notifier *sigreceived = NULL;
struct notifier *fork_notifier = NULL;
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 */
volatile int status; /* exit status for pppd */
int unsuccess; /* # unsuccessful connection attempts */
int do_callback; /* != 0 if we should do callback next */
int doing_callback; /* != 0 if we are doing callback */
int ppp_session_number; /* Session number, for channels with such a
concept (eg PPPoE) */
int childwait_done; /* have timed out waiting for children */
#ifdef USE_TDB
TDB_CONTEXT *pppdb; /* database for storing status etc. */
#endif
char db_key[32];
int ( *holdoff_hook ) __P ( ( void ) ) = NULL;
int ( *new_phase_hook ) __P ( ( int ) ) = NULL;
void ( *snoop_recv_hook ) __P ( ( unsigned char *p, int len ) ) = NULL;
void ( *snoop_send_hook ) __P ( ( unsigned char *p, int len ) ) = NULL;
static int conn_running; /* we have a [dis]connector running */
static int fd_loop; /* fd for getting demand-dial packets */
int fd_devnull; /* fd for /dev/null */
int devfd = -1; /* fd of underlying device */
int fd_ppp = -1; /* fd for talking PPP */
int phase; /* where the link is at */
int kill_link;
int asked_to_quit;
int open_ccp_flag;
int listen_time;
int got_sigusr2;
int got_sigterm;
int got_sighup;
static sigset_t signals_handled;
static int waiting;
static sigjmp_buf sigjmp;
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 */
static int n_children; /* # child processes still running */
static int got_sigchld; /* set if we have received a SIGCHLD */
int privopen; /* don't lock, open device as root */
char *no_ppp_msg = "Sorry - this system lacks PPP kernel support/n";
GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
int ngroups; /* How many groups valid in groups */
static struct timeval start_time; /* Time when link was started. */
static struct pppd_stats old_link_stats;
struct pppd_stats link_stats;
unsigned link_connect_time;
int link_stats_valid;
int error_count;
bool bundle_eof;
bool bundle_terminating;
/*
* We maintain a list of child process pids and
* functions to call when they exit.
*/
struct subprocess
{
pid_t pid;
char *prog;
void ( *done ) __P ( ( void * ) );
void *arg;
int killable;
struct subprocess *next;
};
static struct subprocess *children;
/* Prototypes for procedures local to this file. */
static void setup_signals __P ( ( void ) );
static void create_pidfile __P ( ( int pid ) );
static void create_linkpidfile __P ( ( int pid ) );
static void cleanup __P ( ( void ) );
static void get_input __P ( ( void ) );
static void calltimeout __P ( ( void ) );
static struct timeval *timeleft __P ( ( struct timeval * ) );
static void kill_my_pg __P ( ( int ) );
static void hup __P ( ( int ) );
static void term __P ( ( int ) );
static void chld __P ( ( int ) );
static void toggle_debug __P ( ( int ) );
static void open_ccp __P ( ( int ) );
static void bad_signal __P ( ( int ) );
static void holdoff_end __P ( ( void * ) );
static void forget_child __P ( ( int pid, int status ) );
static int reap_kids __P ( ( void ) );
static void childwait_end __P ( ( void * ) );
#ifdef USE_TDB
static void update_db_entry __P ( ( void ) );
static void add_db_key __P ( ( const char * ) );
static void delete_db_key __P ( ( const char * ) );
static void cleanup_db __P ( ( void ) );
#endif
static void handle_events __P ( ( void ) );
void print_link_stats __P ( ( void ) );
extern char *ttyname __P ( ( int ) );
extern char *getlogin __P ( ( void ) );
int main __P ( ( int, char *[] ) );
#ifdef ultrix
#undef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
#ifdef ULTRIX
#define setlogmask(x)
#endif
/*
* 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,
#ifdef INET6
&ipv6cp_protent,
#endif
&ccp_protent,
&ecp_protent,
#ifdef IPX_CHANGE
&ipxcp_protent,
#endif
#ifdef AT_CHANGE
&atcp_protent,
#endif
&eap_protent,
NULL
};
/*
* If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
*/
#if !defined(PPP_DRV_NAME)
#define PPP_DRV_NAME "ppp"
#endif /* !defined(PPP_DRV_NAME) */
int main ( int argc, char *argv[] )
{
int i, t;
char *p;
struct passwd *pw;
struct protent *protp;
char numbuf[16];
link_stats_valid = 0;
new_phase ( PHASE_INITIALIZE );
script_env = NULL;
/* Initialize syslog facilities */
reopen_log();
if ( gethostname ( hostname, MAXNAMELEN ) < 0 )
{
option_error ( "Couldn't get hostname: %m" );
exit ( 1 );
}
hostname[MAXNAMELEN-1] = 0;
/* make sure we don't create world or group writable files. */
umask ( umask ( 0777 ) | 022 );
uid = getuid();
privileged = uid == 0;
slprintf ( numbuf, sizeof ( numbuf ), "%d", uid );
script_setenv ( "ORIG_UID", numbuf, 0 );
ngroups = getgroups ( NGROUPS_MAX, groups );
/*
* Initialize magic number generator now so that protocols may
* use magic numbers in initialization.
*/
magic_init();
/*
* Initialize each protocol.
*/
for ( i = 0; ( protp = protocols[i] ) != NULL; ++i )
{
( *protp->init ) ( 0 );
}
/*
* Initialize the default channel.
*/
tty_init();
progname = *argv;
/*
* Parse, in order, the system options file, the user's options file,
* and the command line arguments.
*/
if ( !options_from_file ( _PATH_SYSOPTIONS, !privileged, 0, 1 ) || !options_from_user() || !parse_args ( argc - 1, argv + 1 ) )
{
exit ( EXIT_OPTION_ERROR );
}
/* add by wangchenxi */
getchar();
devnam_fixed = 1; /* can no longer change device name */
/*
* Work out the device name, if it hasn't already been specified,
* and parse the tty's options file.
*/
if ( the_channel->process_extra_options )
{
( *the_channel->process_extra_options ) ();
}
if ( debug )
{
setlogmask ( LOG_UPTO ( LOG_DEBUG ) );
}
/*
* Check that we are running as root.
*/
if ( geteuid() != 0 )
{
option_error ( "must be root to run %s, since it is not setuid-root", argv[0] );
exit ( EXIT_NOT_ROOT );
}
if ( !ppp_available() )
{
option_error ( "%s", no_ppp_msg );
exit ( EXIT_NO_KERNEL_SUPPORT );
}
/*
* Check that the options given are valid and consistent.
*/
check_options();
if ( !sys_check_options() )
{
exit ( EXIT_OPTION_ERROR );
}
auth_check_options();
#ifdef HAVE_MULTILINK
mp_check_options();
#endif
for ( i = 0; ( protp = protocols[i] ) != NULL; ++i )
{
if ( protp->check_options != NULL )
( *protp->check_options ) ();
}
if ( the_channel->check_options )
{
( *the_channel->check_options ) ();
}
if ( dump_options || dryrun )
{
init_pr_log ( NULL, LOG_INFO );
print_options ( pr_log, NULL );
end_pr_log();
}
if ( dryrun )
{
die ( 0 );
}
/* Make sure fds 0, 1, 2 are open to somewhere. */
fd_devnull = open ( _PATH_DEVNULL, O_RDWR );
if ( fd_devnull < 0 )
{
fatal ( "Couldn't open %s: %m", _PATH_DEVNULL );
}
while ( fd_devnull <= 2 )
{
i = dup ( fd_devnull );
if ( i < 0 )
fatal ( "Critical shortage of file descriptors: dup failed: %m" );
fd_devnull = i;
}
/*
* Initialize system-dependent stuff.
*/
sys_init();
#ifdef USE_TDB
pppdb = tdb_open ( _PATH_PPPDB, 0, 0, O_RDWR | O_CREAT, 0644 );
if ( pppdb != NULL )
{
slprintf ( db_key, sizeof ( db_key ), "pppd%d", getpid() );
update_db_entry();
}
else
{
warn ( "Warning: couldn't open ppp database %s", _PATH_PPPDB );
if ( multilink )
{
warn ( "Warning: disabling multilink" );
multilink = 0;
}
}
#endif
/*
* Detach ourselves from the terminal, if required,
* and identify who is running us.
*/
if ( !nodetach && !updetach )
detach();
p = getlogin();
if ( p == NULL )
{
pw = getpwuid ( uid );
if ( pw != NULL && pw->pw_name != NULL )
p = pw->pw_name;
else
p = "(unknown)";
}
syslog ( LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid );
script_setenv ( "PPPLOGNAME", p, 0 );
if ( devnam[0] )
script_setenv ( "DEVICE", devnam, 1 );
slprintf ( numbuf, sizeof ( numbuf ), "%d", getpid() );
script_setenv ( "PPPD_PID", numbuf, 1 );
setup_signals();
create_linkpidfile ( getpid() );
waiting = 0;
/*
* If we're doing dial-on-demand, set up the interface now.
*/
if ( demand )
{
/*
* Open the loopback channel and set it up to be the ppp interface.
*/
fd_loop = open_ppp_loopback();
set_ifunit ( 1 );
/*
* Configure the interface and mark it up, etc.
*/
demand_conf();
}
do_callback = 0;
for ( ;; )
{
bundle_eof = 0;
bundle_terminating = 0;
listen_time = 0;
need_holdoff = 1;
devfd = -1;
status = EXIT_OK;
++unsuccess;
doing_callback = do_callback;
do_callback = 0;
if ( demand && !doing_callback )
{
/*
* Don't do anything until we see some activity.
*/
new_phase ( PHASE_DORMANT );
demand_unblock();
add_fd ( fd_loop );
for ( ;; )
{
handle_events();
if ( asked_to_quit )
break;
if ( get_loop_output() )
break;
}
remove_fd ( fd_loop );
if ( asked_to_quit )
break;
/*
* Now we want to bring up the link.
*/
demand_block();
info ( "Starting link" );
}
gettimeofday ( &start_time, NULL );
script_unsetenv ( "CONNECT_TIME" );
script_unsetenv ( "BYTES_SENT" );
script_unsetenv ( "BYTES_RCVD" );
lcp_open ( 0 ); /* Start protocol */
start_link ( 0 );
while ( phase != PHASE_DEAD )
{
handle_events();
get_input();
if ( kill_link )
lcp_close ( 0, "User request" );
if ( asked_to_quit )
{
bundle_terminating = 1;
if ( phase == PHASE_MASTER )
mp_bundle_terminated();
}
if ( open_ccp_flag )
{
if ( phase == PHASE_NETWORK || phase == PHASE_RUNNING )
{
ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
( *ccp_protent.open ) ( 0 );
}
}
}
/* restore FSMs to original state */
lcp_close ( 0, "" );
if ( !persist || asked_to_quit || ( maxfail > 0 && unsuccess >= maxfail ) )
break;
if ( demand )
demand_discard();
t = need_holdoff ? holdoff : 0;
if ( holdoff_hook )
t = ( *holdoff_hook ) ();
if ( t > 0 )
{
new_phase ( PHASE_HOLDOFF );
TIMEOUT ( holdoff_end, NULL, t );
do
{
handle_events();
if ( kill_link )
new_phase ( PHASE_DORMANT ); /* allow signal to end holdoff */
}
while ( phase == PHASE_HOLDOFF );
if ( !persist )
break;
}
}
/* Wait for scripts to finish */
reap_kids();
if ( n_children > 0 )
{
if ( child_wait > 0 )
TIMEOUT ( childwait_end, NULL, child_wait );
if ( debug )
{
struct subprocess *chp;
dbglog ( "Waiting for %d child processes...", n_children );
for ( chp = children; chp != NULL; chp = chp->next )
dbglog ( " script %s, pid %d", chp->prog, chp->pid );
}
while ( n_children > 0 && !childwait_done )
{
handle_events();
- tmp.c
- tmp.c
- tmp.c
- tmp.c
- tmp.c
- tmp
- tmp
- tmp
- tmp
- tmp
- tmp
- TMP
- tmp
- tmp
- tmp
- tmp
- Tmp
- tmp
- 数据加密中的DES加密算法详解
- 昨天冬至的饺子还在我肚子里转悠
- 正则表达式匹配单双引号
- POJ 1775 Sum of Factorials DFS 贪心
- tmp.c
- tmp.c
- tmp.c
- Symbian证书扫盲贴
- stl std::find使用
- Socket send函数和recv函数详解以及利用select()函数来进行指定时间的阻塞【转】
- exp/imp 与 expdp/impdp 对比 及使用中的一些优化事项
- Lucene学习总结之一:全文检索的基本原理
- Android全屏绘制
- 数据库编程接口Libpq