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

📄 utils.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2004 Kannel Group   * Copyright (c) 1998-2001 WapIT Ltd.    * 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 end-user documentation included with the redistribution,  *    if any, must include the following acknowledgment:  *       "This product includes software developed by the  *        Kannel Group (http://www.kannel.org/)."  *    Alternately, this acknowledgment may appear in the software itself,  *    if and wherever such third-party acknowledgments normally appear.  *  * 4. The names "Kannel" and "Kannel Group" must not be used to  *    endorse or promote products derived from this software without  *    prior written permission. For written permission, please   *    contact org@kannel.org.  *  * 5. Products derived from this software may not be called "Kannel",  *    nor may "Kannel" appear in their name, without prior written  *    permission of the Kannel Group.  *  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 KANNEL GROUP OR ITS 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.  * ====================================================================  *  * This software consists of voluntary contributions made by many  * individuals on behalf of the Kannel Group.  For more information on   * the Kannel Group, please see <http://www.kannel.org/>.  *  * Portions of this software are based upon software originally written at   * WapIT Ltd., Helsinki, Finland for the Kannel project.   */ /* * utils.c - generally useful, non-application specific functions for Gateway * */#include "gw-config.h" #include <ctype.h>#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <termios.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#include <fcntl.h>#include <pwd.h>#include <grp.h>#include "gwlib.h"/* pid of child process when parachute is used */static pid_t child_pid = -1;/* saved child signal handlers */static struct sigaction child_actions[32];/* just a flag that child signal handlers are stored */static int child_actions_init = 0;/* our pid file name */static char *pid_file = NULL;static volatile sig_atomic_t parachute_shutdown = 0;static void parachute_sig_handler(int signum){    info(0, "Signal %d received, forward to child pid (%ld)", signum, (long) child_pid);    /* we do not handle any signal, just forward these to child process */    if (child_pid != -1 && getpid() != child_pid)        kill(child_pid, signum);    /* if signal received and no child there, terminating */    switch(signum) {        case SIGTERM:        case SIGINT:        case SIGABRT:            if (child_pid == -1)                exit(0);            else                parachute_shutdown = 1;    }}static void parachute_init_signals(int child){    struct sigaction sa;    if (child_actions_init && child) {        sigaction(SIGTERM, &child_actions[SIGTERM], NULL);        sigaction(SIGQUIT, &child_actions[SIGQUIT], NULL);        sigaction(SIGINT,  &child_actions[SIGINT], NULL);        sigaction(SIGABRT, &child_actions[SIGABRT], NULL);        sigaction(SIGHUP,  &child_actions[SIGHUP], NULL);        sigaction(SIGALRM, &child_actions[SIGALRM], NULL);        sigaction(SIGUSR1, &child_actions[SIGUSR1], NULL);        sigaction(SIGUSR2, &child_actions[SIGUSR2], NULL);        sigaction(SIGPIPE, &child_actions[SIGPIPE], NULL);    }    else if (!child && !child_actions_init) {        sa.sa_flags = 0;        sigemptyset(&sa.sa_mask);        sa.sa_handler = parachute_sig_handler;        sigaction(SIGTERM, &sa, &child_actions[SIGTERM]);        sigaction(SIGQUIT, &sa, &child_actions[SIGQUIT]);        sigaction(SIGINT,  &sa, &child_actions[SIGINT]);        sigaction(SIGABRT, &sa, &child_actions[SIGABRT]);        sigaction(SIGHUP,  &sa, &child_actions[SIGHUP]);        sigaction(SIGALRM, &sa, &child_actions[SIGALRM]);        sigaction(SIGUSR1, &sa, &child_actions[SIGUSR1]);        sigaction(SIGUSR2, &sa, &child_actions[SIGUSR2]);        sa.sa_handler = SIG_IGN;        sigaction(SIGPIPE, &sa, &child_actions[SIGPIPE]);        sigaction(SIGTTOU, &sa, NULL);        sigaction(SIGTTIN, &sa, NULL);        sigaction(SIGTSTP, &sa, NULL);        child_actions_init = 1;    }    else        panic(0, "Child process signal handlers not initialized before.");}static int is_executable(const char *filename){    struct stat buf;    if (stat(filename, &buf)) {        error(errno, "Error while stat of file `%s'", filename);        return 0;    }    if (!S_ISREG(buf.st_mode) && !S_ISLNK(buf.st_mode)) {        error(0, "File `%s' is not a regular file.", filename);        return 0;    }    /* others has exec permission */    if (S_IXOTH & buf.st_mode) return 1;    /* group has exec permission */    if ((S_IXGRP & buf.st_mode) && buf.st_gid == getgid())        return 1;    /* owner has exec permission */    if ((S_IXUSR & buf.st_mode) && buf.st_uid == getuid())        return 1;    return 0;}/* * become daemon. * returns 0 for father process; 1 for child process */static int become_daemon(void){    int fd;    if (getppid() != 1) {       signal(SIGTTOU, SIG_IGN);       signal(SIGTTIN, SIG_IGN);       signal(SIGTSTP, SIG_IGN);       if (fork())          return 0;       setsid();    }    close(STDIN_FILENO);    close(STDOUT_FILENO);    close(STDERR_FILENO);    fd = open("/dev/null", O_RDWR); /* stdin */    if (fd == -1)        panic(errno, "Could not open `/dev/null'");    dup(fd); /* stdout */    dup(fd); /* stderr */    chdir("/");    return 1;}#define PANIC_SCRIPT_MAX_LEN 4096static PRINTFLIKE(2,3) void execute_panic_script(const char *panic_script, const char *format, ...){    char *args[3];    char buf[PANIC_SCRIPT_MAX_LEN + 1];    va_list ap;    va_start(ap, format);    vsnprintf(buf, PANIC_SCRIPT_MAX_LEN, format, ap);    va_end(ap);    if (fork())       return;    close(STDIN_FILENO);    close(STDOUT_FILENO);    close(STDERR_FILENO);    args[0] = (char*) panic_script;    args[1] = buf;    args[2] = NULL;    execv(args[0], args);}static void parachute_start(const char *myname, const char *panic_script) {    time_t last_start = 0, last_panic = 0;    long respawn_count = 0;    int status;    if (panic_script && !is_executable(panic_script))        panic(0, "Panic script `%s' is not executable for us.", panic_script);    /* setup sighandler */    parachute_init_signals(0);    for (;;) {        if (respawn_count > 0 && difftime(time(NULL), last_start) < 10) {            error(0, "Child process died too fast, disabling for 30 sec.");            gwthread_sleep(30.0);        }        if (!(child_pid = fork())) { /* child process */            parachute_init_signals(1); /* reset sighandlers */	    return;        }	else if (child_pid < 0) {	    error(errno, "Could not start child process! Will retry in 5 sec.");	    gwthread_sleep(5.0);            continue;	}	else { /* father process */	    time(&last_start);            info(0, "Child process with PID (%ld) started.", (long) child_pid);            do {                if (waitpid(child_pid, &status, 0) == child_pid) {                    /* check here why child terminated */                   if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {                       info(0, "Child process exited gracefully, exit...");                       gwlib_shutdown();                       exit(0);                   }                   else if (WIFEXITED(status)) {                       error(0, "Caught child PID (%ld) which died with return code %d",                           (long) child_pid, WEXITSTATUS(status));                       child_pid = -1;                   }                   else if (WIFSIGNALED(status)) {                       error(0, "Caught child PID (%ld) which died due to signal %d",                           (long) child_pid, WTERMSIG(status));                       child_pid = -1;                   }                }                else if (errno != EINTR) {                    error(errno, "Error while waiting of child process.");                }            } while(child_pid > 0);            if (parachute_shutdown) {                /* may only happens if child process crashed while shutdown */                info(0, "Child process crashed while shutdown. Exiting due to signal...");                info(0, "Going into gwlib_shutdown...");                gwlib_shutdown();                info(0, "gwlib_shutdown done... Bye bye...");                exit(WIFEXITED(status) ? WEXITSTATUS(status) : 0);            }            /* check whether it's panic while start */            if (respawn_count == 0 && difftime(time(NULL), last_start) < 2) {                info(0, "Child process crashed while starting. Exiting...");                info(0, "Going into gwlib_shutdown...");                gwlib_shutdown();                info(0, "gwlib_shutdown done... Bye bye...");                exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);            }            respawn_count++;            if (panic_script && myname && difftime(time(NULL), last_panic) > 300) {                time(&last_panic);                debug("kannel", 0, "Executing panic script: %s %s %ld", panic_script, myname, respawn_count);                execute_panic_script(panic_script, "%s %ld", myname, respawn_count);            }            /* sleep a while to get e.g. sockets released */            gwthread_sleep(5.0);	}    }}static void write_pid_file(void){    int fd;    FILE *file;    if (!pid_file)        return;    fd = open(pid_file, O_WRONLY|O_NOCTTY|O_TRUNC|O_CREAT|O_EXCL, 0644);    if (fd == -1)        panic(errno, "Could not open pid-file `%s'", pid_file);    file = fdopen(fd, "w");    if (!file)        panic(errno, "Could not open file-stream `%s'", pid_file);    fprintf(file, "%ld\n", (long) getpid());    fclose(file);}static void remove_pid_file(void){    if (!pid_file)        return;    /* ensure we don't called from child process */    if (child_pid == 0)        return;    if (-1 == unlink(pid_file))        error(errno, "Could not unlink pid-file `%s'", pid_file);}static int change_user(const char *user){    struct passwd *pass;    if (!user)        return -1;    pass = getpwnam(user);    if (!pass) {        error(0, "Could not find a user `%s' in system.", user);        return -1;    }    if (-1 == setgid(pass->pw_gid)) {        error(errno, "Could not change group id from %ld to %ld.", (long) getgid(), (long) pass->pw_gid);        return -1;    }    if (initgroups(user, -1) == -1) {        error(errno, "Could not set supplementary group ID's.");    }        if (-1 == setuid(pass->pw_uid)) {        error(errno, "Could not change user id from %ld to %ld.", (long) getuid(), (long) pass->pw_uid);        return -1;    }    return 0;}/* * new datatype functions */MultibyteInt get_variable_value(Octet *source, int *len){    MultibyteInt retval = 0;        for(*len=1;; (*len)++, source++) {	retval = retval * 0x80 + (*source & 0x7F);	if (*source < 0x80)  /* if the continue-bit (high bit) is not set */	    break;    }    return retval;}int write_variable_value(MultibyteInt value, Octet *dest){    int i, loc = 0;    Octet revbuffer[20];	/* we write it backwards */        for (;;) {	revbuffer[loc++] = (value & 0x7F) + 0x80;		if (value >= 0x80)	    value = value >> 7;	else	    break;    }    for(i=0; i < loc; i++)		/* reverse the buffer */	dest[i] = revbuffer[loc-i-1];        dest[loc-1] &= 0x7F;	/* remove trailer-bit from last */

⌨️ 快捷键说明

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