to myself 的分类学习日志

做自己想做的事
posts - 232, comments - 6, trackbacks - 0, articles - 0
example 1:
https://github.com/paulran/test/blob/master/c%2B%2B/sample-server/src/AppMain.cpp




example 2:
/******************************************************************************
 *
 * worker-ping.c - Nagios Core 4 worker to handle ping checke
 *
 * Program: Nagios Core
 * License: GPL
 *
 * First Written:   01-03-2013 (start of development)
 *
 * Description:
 *
 * License:
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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 to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 ****************************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>


#define    OK       0   /**< Indicates successful function call */
#define ERROR   -2   /**< Non-successful function call */

#ifdef FALSE
#undef FALSE
#endif
#define FALSE 0 /**< Not true */

#ifdef TRUE
#undef TRUE
#endif
#define TRUE (!FALSE) /**< Not false */


/******************* LOGGING TYPES ********************/
#define NSLOG_RUNTIME_ERROR        1
#define NSLOG_RUNTIME_WARNING        2

#define NSLOG_VERIFICATION_ERROR    4
#define NSLOG_VERIFICATION_WARNING    8

#define NSLOG_CONFIG_ERROR        16
#define NSLOG_CONFIG_WARNING        32

#define NSLOG_PROCESS_INFO        64
#define NSLOG_EVENT_HANDLER        128

int logit(int data_type, int display, const char *fmt, )
{
    va_list ap;
    char buf[1024];
    int result;

    va_start(ap, fmt);
    result = vsprintf(buf, fmt, ap);
    va_end(ap);

    if (result >= 0) {
        printf(buf);
    }
    return result;
}


/* Local macro definitions */
#define PING_WORKER_VERSION "0.2"
#define PING_WORKER_MODIFICATION_DATE "02-Feb-13"

#define PW_OK        0
#define PW_ERROR    1

/* Local function declarations */
int            daemon_init( void);
int            drop_privileges( char *, char *);
void        print_license( void);
void        print_usage( char *);
void        print_version( void);
void        parse_worker_command_line( intchar **, char **, int *, char **,
                    char **, char **);
static int    worker( const char *);


const char *lock_file = "/tmp/nagios.lock";


/* Everything starts here */
int main( int argc, char **argv, char **env) {
    int daemon_mode = FALSE;
    char *worker_socket;
    char *worker_user = ( char *)0;
    char *worker_group = ( char *)0;

    if( FALSE == daemon_mode) {
        printf( "Greetings from the ping worker.\n");
    }

    parse_worker_command_line( argc, argv, env, &daemon_mode, &worker_socket,
            &worker_user, &worker_group);

    if( FALSE == daemon_mode) {
        print_version();
        printf( "Worker socket is %s.\n", worker_socket);
    }

    /* drop privileges */
    if( drop_privileges( worker_user, worker_group) == PW_ERROR) {
        fprintf( stderr, "Failed to drop privileges. Aborting.\n");
        exit( 1);
    }

    if( TRUE == daemon_mode) {
        if( daemon_init() == ERROR) {
            fprintf( stderr,
                    "Bailing out due to failure to daemonize. (PID=%d)\n",
                    ( int)getpid());
            exit( 1);
        }
    }

    /* Enter the worker code */
    if( worker( worker_socket)) {
        exit( 1);
    }

    if (daemon_mode == TRUE) {
        unlink(lock_file);
    }
}

void parse_worker_command_line( int argc, char **argv, char **env,
        int *daemon_mode, char **worker_socket, char **worker_user,
        char **worker_group) {
    int c = 0;
    int display_usage = FALSE;
    int display_license = FALSE;

#ifdef HAVE_GETOPT_H
    int option_index = 0;
    static struct option long_options[] = {
        { "help", no_argument, 0, 'h'},
        { "version", no_argument, 0, 'V'},
        { "license", no_argument, 0, 'V'},
        { "daemon", no_argument, 0, 'd'},
        { "worker", required_argument, 0, 'W'},
        { "user", required_argument, 0, 'u'},
        { "group", required_argument, 0, 'g'},
        { 0, 0, 0, 0}
    };
#define getopt( argc, argv, o) getopt_long( argc, argv, o, long_options, &option_index)
#endif

    /* get all command line arguments */
    while( 1) {
        c = getopt( argc, argv, "+:hVdW:u:g:");

        if( -1 == c || EOF == c) break;

        switch( c) {

            case '?': /* usage */
            case 'h':
                display_usage = TRUE;
                break;

            case 'V': /* version */
                display_license = TRUE;
                break;

            case 'd': /* daemon mode */
                *daemon_mode = TRUE;
                break;

            case 'W':
                *worker_socket = optarg;
                break;

            case 'u':
                *worker_user = optarg;
                break;

            case 'g':
                *worker_group = optarg;
                break;

            case ':':
                printf( "Missing argument for command line option '%c'.\n\n",
                        optopt);
                print_usage( argv[ 0]);
                exit( 1);
                break;

            default:
                printf( "Unknown command line option '%c'.\n\n", c);
                print_usage( argv[ 0]);
                exit( 1);
                break;
        }
    }

    if( TRUE == display_license) {
        print_version();
        print_license();
        exit( 0);
    }

    if( TRUE == display_usage) {
        print_usage( argv[ 0]);
        exit( 0);
    }

}

void print_license( void) {
    printf( "\nThis program is free software; you can redistribute it and/or modify\n");
    printf( "it under the terms of the GNU General Public License version 2 as\n");
    printf( "published by the Free Software Foundation.\n\n");
    printf( "This program is distributed in the hope that it will be useful,\n");
    printf( "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
    printf( "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
    printf( "GNU General Public License for more details.\n\n");
    printf( "You should have received a copy of the GNU General Public License\n");
    printf( "along with this program; if not, write to the Free Software\n");
    printf( "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
}

void print_usage( char *program_name) {
    printf( "\nUsage: %s [-?|-h|--help] [-V|--version] [-d]\n", program_name);
    printf( "        -W /path/to/socket -u user -g group\n");
    printf( "\n");
    printf( "Options:\n");
    printf( "\n");
    printf( "  -d, --daemon                 Starts the ping worker in daemon mode,\n");
    printf( "                               instead of as a foreground process\n");
    printf( "  -W, --worker /path/to/socket Act as a worker for an already running daemon\n");
    printf( "  -u, --user user              Drop priviliges to the specified user\n");
    printf( "  -g, --group group            Drop priviliges to the specified user\n");
    printf( "\n");
    printf( "Visit the Nagios website at http://www.nagios.org/ for bug fixes, new\n");
    printf( "releases, online documentation, FAQs, information on subscribing to\n");
    printf( "the mailing lists, and commercial support options for Nagios.\n");
    printf( "\n");
}

void print_version( void) {
    printf( "\nNagios Core 4 Ping Worker %s\n", PING_WORKER_VERSION);
    printf( "Copyright (c) 2013-present Nagios Core Development Team\n");
    printf( "        and Community Contributors\n");
    printf( "Last Modified: %s\n", PING_WORKER_MODIFICATION_DATE);
    printf( "License: GPL\n");
    printf( "Website: http://www.nagios.org\n");
}

static int worker( const char *path)
{
    // to do something.
    return 0;
}

int drop_privileges( char *user, char *group) {
    uid_t uid = -1;
    gid_t gid = -1;
    struct group *grp = NULL;
    struct passwd *pw = NULL;
    int result = PW_OK;

    /* only drop privileges if we're running as root, so we don't
        interfere with being debugged while running as some random user 
*/
    if( getuid() != 0) {
        return PW_OK;
    }

    /* set effective group ID */
    if( NULL != group) {

        /* see if this is a group name */
        if( strspn( group, "0123456789") < strlen( group)) {
            grp = ( struct group *)getgrnam( group);
            if( NULL != grp) {
                gid = ( gid_t)(grp->gr_gid);
            }
            else {
                fprintf( stderr,
                    "Warning: Could not get group entry for '%s'\n", group);
            }
        }

        /* else we were passed the GID */
        else {
            gid = ( gid_t)atoi( group);
        }

        /* set effective group ID if other than current EGID */
        if( gid != getegid()) {
            if( setgid( gid) == -1) {
                fprintf( stderr, "Warning: Could not set effective GID=%d\n",
                        ( int)gid);
                result = PW_ERROR;
            }
        }
    }

    /* set effective user ID */
    if( NULL != user) {

        /* see if this is a user name */
        if( strspn( user, "0123456789") < strlen( user)) {
            pw = ( struct passwd *)getpwnam( user);
            if( NULL != pw) {
                uid = ( uid_t)(pw->pw_uid);
            }
            else {
                fprintf( stderr,
                        "Warning: Could not get passwd entry for '%s'\n", user);
            }
        }

        /* else we were passed the UID */
        else {
            uid = ( uid_t)atoi( user);
        }

#ifdef HAVE_INITGROUPS

        if( uid != geteuid()) {

            /* initialize supplementary groups */
            if( initgroups( user, gid) == -1) {
                if( EPERM == errno) {
                    fprintf( stderr, "Warning: Unable to change supplementary "
                            "groups using initgroups() -- I hope you know what "
                            "you're doing\n");
                }
                else {
                    fprintf( stderr, "Warning: Possibly root user failed "
                            "dropping privileges with initgroups()\n");
                    return PW_ERROR;
                }
            }
        }
#endif
        if( setuid( uid) == -1) {
            fprintf( stderr, "Warning: Could not set effective UID=%d\n",
                    ( int)uid);
            result = PW_ERROR;
        }
    }

    return result;
}

int daemon_init( void) {
    pid_t pid = -1;
    int pidno = 0;
    int lockfile = 0;
    int val = 0;
    char buf[256];
    struct flock lock;
    char *homedir = NULL;

#ifdef RLIMIT_CORE
    struct rlimit limit;
#endif

    /* change working directory. scuttle home if we're dumping core */
    homedir = getenv( "HOME");
#ifdef DAEMON_DUMPS_CORE
    if( NULL != homedir) {
        chdir( homedir);
    }
    else {
#endif
        chdir( "/");
#ifdef DAEMON_DUMPS_CORE
    }
#endif

    umask( S_IWGRP | S_IWOTH);

    /* close existing stdin, stdout, stderr */
    close( 0);
    close( 1);
    close( 2);

    /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */
    /* re-open stdin, stdout, stderr with known values */
    open( "/dev/null", O_RDONLY);
    open( "/dev/null", O_WRONLY);
    open( "/dev/null", O_WRONLY);

#ifdef USE_LOCKFILE
    lockfile = open( lock_file,
            O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);

    if( lockfile < 0) {
        logit( NSLOG_RUNTIME_ERROR, TRUE, "Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno));
        logit( NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to errors encountered while attempting to daemonize (PID=%d)", (int)getpid());

        exit( 1);
    }

    /* see if we can read the contents of the lockfile */
    if(( val = read( lockfile, buf, ( size_t)10)) < 0) {
        logit(NSLOG_RUNTIME_ERROR, TRUE, "Lockfile exists but cannot be read");
        exit( 1);
    }

    /* we read something - check the PID */
    if( val > 0) {
        if(( val = sscanf( buf, "%d", &pidno)) < 1) {
            logit( NSLOG_RUNTIME_ERROR, TRUE, "Lockfile '%s' does not contain a valid PID (%s)", lock_file, buf);
            exit( 1);
        }
    }

    /* check for SIGHUP */
    if( val == 1 && ( pid = ( pid_t)pidno) == getpid()) {
        close( lockfile);
        return OK;
    }
#endif

    /* exit on errors */
    if(( pid = fork()) < 0) {
        return( PW_ERROR);
    }

    /* parent process goes away.. */
    else if((int)pid != 0) {
        exit( 0);
    }

    /* child continues */

    /* child becomes session leader */
    setsid();

#ifdef USE_LOCKFILE
    /* place a file lock on the lock file */
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;
    if( fcntl( lockfile, F_SETLK, &lock) < 0) {
        if( EACCES == errno || EAGAIN == errno) {
            fcntl( lockfile, F_GETLK, &lock);
            logit( NSLOG_RUNTIME_ERROR, TRUE, "Lockfile '%s' looks like its already held by another instance of Nagios (PID %d).  Bailing out", lock_file, (int)lock.l_pid);
            }
        else {
            logit(NSLOG_RUNTIME_ERROR, TRUE, "Cannot lock lockfile '%s': %s. Bailing out", lock_file, strerror(errno));

        }
        exit( 1);
    }
#endif

    /* prevent daemon from dumping a core file */
#if defined( RLIMIT_CORE) && defined( DAEMON_DUMPS_CORE)
    getrlimit( RLIMIT_CORE, &limit);
    limit.rlim_cur = 0;
    setrlimit( RLIMIT_CORE, &limit);
#endif

#ifdef USE_LOCKFILE
    /* write PID to lockfile */
    lseek( lockfile, 0, SEEK_SET);
    ftruncate( lockfile, 0);
    sprintf( buf, "%d\n", ( int)getpid());
    write( lockfile, buf, strlen( buf));

    /* make sure lock file stays open while program is executing */
    val = fcntl( lockfile, F_GETFD, 0);
    val |= FD_CLOEXEC;
    fcntl( lockfile, F_SETFD, val);
#endif

    return PW_OK;
}
  • 说明:
  1. 程序由Nagios源码nagios-4.1.0rc1\worker\ping\worker-ping.c改写而成。
  2. 程序运行过程中,通过一直保有一个约定文件的文件锁来排除同时运行多个相同的程序。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理