⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c++

📁 好东东。linux下面的文件节点、文件状态的变化监听代码
💻 C++
字号:
//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.//  This program is free software; you can redistribute it and/or modify it//  under the terms of version 2 of the GNU General Public License as//  published by the Free Software Foundation.////  This program is distributed in the hope that it would be useful, but//  WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any//  license provided herein, whether implied or otherwise, is limited to//  this program in accordance with the express provisions of the GNU//  General Public License.  Patent licenses, if any, provided herein do not//  apply to combinations of this program with other product or programs, or//  any other product whatsoever.  This program is distributed without any//  warranty that the program is delivered free of the rightful claim of any//  third person by way of infringement or the like.  See the GNU General//  Public License for more details.////  You should have received a copy of the GNU General Public License along//  with this program; if not, write the Free Software Foundation, Inc., 59//  Temple Place - Suite 330, Boston MA 02111-1307, USA.#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <sys/stat.h>#if HAVE_SYSSGI#include <sys/syssgi.h>#endif#include <unistd.h>#include <ctype.h>#include <limits.h>#include "Activity.h"#include "Listener.h"#include "Log.h"#include "Pollster.h"#include "Scheduler.h"#include "Cred.h"#include "Interest.h"const char *program_name;//  These are options which are read from the configuration file & the//  command line.struct config_opts{    config_opts();    const char *config_file;  // do not free this    char *untrusted_user;    int pollster_interval;  // in seconds    int activity_timeout;   // in seconds    bool disable_pollster;    bool local_only;    bool xtab_verification;    bool disable_audit;    bool disable_mac;    bool insecure_compat;    bool debugging;};#define CFG_INSECURE_COMPAT "insecure_compatibility"#define CFG_LOCAL_ONLY "local_only"#define CFG_XTAB_VERIFICATION "xtab_verification"#define CFG_UNTRUSTED_USER "untrusted_user"#define CFG_IDLE_TIMEOUT "idle_timeout"#define CFG_NFS_POLLING_INTERVAL "nfs_polling_interval"static void parse_config(config_opts &opts);static void parse_config_line(config_opts &opts, int line,                              const char *k, const char *v);static bool is_true(const char *str);static const char *basename2(const char *p){    const char *tail = p;    while (*p)	if (*p++ == '/' && *p && *p != '/')	    tail = p;    return tail;}void usage(){   fprintf(stderr,	    "fam, version %s\n"	    "Use: %s [ -f | -d | -v ] [ -l | -t seconds ] [ -T seconds ] \\\n"	    "\t\t\t\t[ -p prog.vers ] [ -L ] [ -c config_file ] [-C]\n",	    VERSION, program_name);    fprintf(stderr, "\t-f\t\tstay in foreground\n");    fprintf(stderr, "\t-d\t\tdebug\n");    fprintf(stderr, "\t-v\t\tverbose\n");    fprintf(stderr, "\t-l\t\tno polling\n");    fprintf(stderr, "\t-t seconds\tset polling interval (default 6 s)\n");    fprintf(stderr, "\t-T seconds\tset inactive timeout (default 5 s)\n");    fprintf(stderr, "\t-p prog.vers\tset RPC program number and version\n");    fprintf(stderr, "\t-L\t\tlocal only (ignore remote requests)\n");    fprintf(stderr, "\t-c config_file\tpath to alternate configuration file\n");    fprintf(stderr, "\t\t\t  (default is %s)\n", CONFIG_ETC_CONFIG_PATH);    fprintf(stderr, "\t-C\t\tinsecure compatibility\n");    fprintf(stderr, "\n");    exit(1);}int main(int argc, char *argv[]){#if HAVE_SGI_NOHANG    // This keeps down nfs mounts from hanging fam.  System calls on    // down nfs mounts fail with errno == ETIMEDOUT.  We don't do this    // if we're running diskless because we don't want fam to crash    // because a page fault timed out.    char buf[20];    if (sgikopt("diskless", buf, sizeof buf) == 0	&& strcmp(buf, "0") == 0) {	syssgi(SGI_NOHANG, 1);    }#endif    config_opts opts;    //  If fd 0 is a socket, we figure we were started by inetd.    struct stat st;    fstat(0, &st);    bool started_by_inetd = S_ISSOCK(st.st_mode);    unsigned long program = Listener::FAMPROG, version = Listener::FAMVERS;    program_name = basename2(argv[0]);    Log::name(program_name);    if (!started_by_inetd)	Log::foreground();    //  Run through the command-line args once, looking for debugging flags    //  and config-file flags.  (We want to check those before we parse the    //  config file, and we want to parse the config file before reading other    //  command-line args which might override its contents.)    int i;    for (i = 1; i < argc; i++)    {        if (argv[i][0] != '-' || !argv[i][1] || argv[i][2]) continue;        switch (argv[i][1])        {        case 'c':            if(++i >= argc) usage();            opts.config_file = argv[i];            break;	case 'f':	    opts.debugging = true;	    break;	case 'd':	    Log::debug();	    opts.debugging = true;	    break;	case 'v':	    Log::info();	    opts.debugging = true;	    break;        }    }    if (getuid() != 0)    {   Log::error("must be superuser");	exit(1);    }    parse_config(opts);    //  Now run through the command-line arguments again.    for (i = 1; i < argc; i++)    {   if (argv[i][0] != '-' || !argv[i][1] || argv[i][2])	    usage();	switch (argv[i][1])	{	    char *p, *q;	    unsigned secs;	case 'f':	case 'd':	case 'v':            //  handled above.	    break;	case 'l':	    opts.disable_pollster = true;	    break;	case 'p':	    if (++i >= argc)		usage();	    p = strchr(argv[i], '.');	    if (p)	    {	*p++ = '\0';		version = strtoul(p, &q, 10);                if (p == q) usage();	    }	    program = strtoul(argv[i], &q, 10);            if (argv[i] == q) usage();	    break;	case 't':	    if (i + 1 >= argc)		usage();	    secs = strtoul(argv[++i], &p, 10);	    if (*p)		usage();	    if (secs == 0)		Log::error("illegal poll interval 0");	    else		opts.pollster_interval = secs;	    break;	case 'T':	    if (i + 1 >= argc)		usage();	    secs = strtoul(argv[++i], &p, 10);	    if (*p)		usage();	    opts.activity_timeout = secs;	    break;	case 'L':	    opts.local_only = true;	    break;	case 'C':	    opts.insecure_compat = true;            opts.xtab_verification = false;            Log::info("Running with -C (" CFG_INSECURE_COMPAT                      ") command-line option");	    break;        case 'c':            //  handled above.            ++i;            break;	default:	    usage();	}    }    //  Apply the various options.    if (opts.local_only && started_by_inetd) {        Log::error("Warning!  Started by inetd, so -L (" CFG_LOCAL_ONLY                   ") option is being ignored!");        opts.local_only = false;    }    if (opts.disable_audit) Log::disable_audit();    if (opts.disable_mac) Cred::disable_mac();    if (opts.insecure_compat) Cred::enable_insecure_compat();    if (opts.untrusted_user) Cred::set_untrusted_user(opts.untrusted_user);    else {        Log::error("Fatal misconfiguration!  No " CFG_UNTRUSTED_USER                   " found in %s!", opts.config_file);        exit(1);    }    Pollster::interval(opts.pollster_interval);    Activity::timeout(opts.activity_timeout);    if (opts.disable_pollster) Pollster::disable();    if (!opts.local_only) {        Interest::enable_xtab_verification(opts.xtab_verification);    }    Log::audit(true, "fam starting SAT with process name \"%s\"",                     program_name);    if (!started_by_inetd)    {#if HAVE_DAEMONIZE	if (!opts.debugging)	{   _daemonize(0, -1, -1, -1);	    Log::background();	}#else#  if HAVE_DAEMON	if (!opts.debugging)	{   daemon(0, 0);	    Log::background();	}#  endif#endif    }    (void) signal(SIGPIPE, SIG_IGN);#if HAVE_SGI_NOHANG    // Ignore SIGCHLD because we run nfsunhang to unhang down nfs    // mounts, and we don't care about the exit status of nfsunhang    // (since we poll anyway) and we don't want to create zombies.    (void) signal(SIGCHLD, SIG_IGN);#endif    new Listener(started_by_inetd, opts.local_only, program, version);    Scheduler::loop();    return 0;}static voidparse_config(config_opts &opts){    FILE *cfg = fopen(opts.config_file, "r");    if(cfg == NULL)    {        Log::error("Couldn't open config file \"%s\"!", opts.config_file);        usage();        return;    }    char buf[PATH_MAX + 64];    char *bp;    int lineno = 0;    while(fgets(buf, sizeof(buf), cfg))    {        ++lineno;        bp = buf;        while(isspace(*bp)) ++bp;        if ((*bp == '\0') || (*bp == '#') || (*bp == '!')) continue;        if (bp[strlen(bp) - 1] != '\n')        {            Log::error("config file %s line %d is too long, and is "                       "being ignored!", opts.config_file, lineno);            --lineno;            continue;        }        bp[strlen(bp) - 1] = '\0';  // whap newline        //  split line at "=", strip whitespace from ends of both pieces        char *vp = strchr(bp, '=');        if(vp == NULL)        {            Log::error("config file %s line %d seems dain bramaged (no \"=\"), "                       "and is being ignored.", opts.config_file, lineno);            continue;        }        *vp++ = '\0';        while (isspace(*vp)) ++vp;        char *end = bp + strlen(bp) - 1;        while (isspace(*end) && (end >= bp)) *end-- = '\0';        end = vp + strlen(vp) - 1;        while (isspace(*end) && (end >= vp)) *end-- = '\0';        Log::debug("read %s line %d: \"%s\" = \"%s\"",                   opts.config_file, lineno, bp, vp);        parse_config_line(opts, lineno, bp, vp);    }    fclose(cfg);}static voidparse_config_line(config_opts &opts, int lineno, const char *key, const char *val){    char *p;    unsigned secs;    if(!strcmp(key, CFG_UNTRUSTED_USER))    {        if (!opts.untrusted_user) opts.untrusted_user = strdup(val);        else Log::error("config file %s line %d: ignoring duplicate %s",                        opts.config_file, lineno, key);    }    else if(!strcmp(key, CFG_LOCAL_ONLY))    {        opts.local_only = is_true(val);    }    else if(!strcmp(key, CFG_IDLE_TIMEOUT))    {	secs = strtoul(val, &p, 10);	if (*p)	{	    Log::error("config file %s line %d: ignoring invalid value for %s",	    		opts.config_file, lineno, key);	}	else	{	    opts.activity_timeout = secs;	}    }    else if(!strcmp(key, CFG_NFS_POLLING_INTERVAL))    {	secs = strtoul(val, &p, 10);	if (*p || secs == 0)	{	    Log::error("config file %s line %d: ignoring invalid value for %s",		       opts.config_file, lineno, key);	}	else	{	    opts.pollster_interval = secs;	}    }    else if(!strcmp(key, CFG_XTAB_VERIFICATION))    {        opts.xtab_verification = is_true(val);        if(opts.xtab_verification && opts.insecure_compat)        {            opts.xtab_verification = false;            Log::error("config file %s line %d: ignoring %s because "                       CFG_INSECURE_COMPAT " is set",                       opts.config_file, lineno, key);        }    }    else if(!strcmp(key, CFG_INSECURE_COMPAT))    {        opts.insecure_compat = is_true(val);//ehh... it would be nice to handle this a little better.//        if(opts.insecure_compat && opts.xtab_verification)//        {//            opts.xtab_verification = false;//            Log::error("config file %s line %d: %s overrides "//                       CFG_XTAB_VERIFICATION,//                       opts.config_file, lineno, key);//        }    }    else if(!strcmp(key, "disable_audit"))    {        opts.disable_audit = is_true(val);    }    else if(!strcmp(key, "disable_mac"))    {        opts.disable_mac = is_true(val);    }    else    {        Log::error("config file %s line %d: unrecognized key \"%s\"",                    opts.config_file, lineno, key);    }}config_opts::config_opts(){    memset(this, 0, sizeof(config_opts));    config_file = CONFIG_ETC_CONFIG_PATH;    untrusted_user = NULL;    pollster_interval = 6;    activity_timeout = 5;    disable_pollster = false;    local_only = false;    xtab_verification = true;#ifdef HAVE_AUDIT    disable_audit = (sysconf(_SC_AUDIT) != 1);#else    disable_audit = true;#endif#ifdef HAVE_MAC    disable_mac = ((sysconf(_SC_MAC) != 1) || (sysconf(_SC_IP_SECOPTS) != 1));#else    disable_mac = true;#endif    insecure_compat = false;    debugging = false;}static boolis_true(const char *val){    if (!strcasecmp(val, "false") ||        !strcasecmp(val, "no")  ||        !strcmp(val, "0"))    {        return false;    }    return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -