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

📄 mmcmgr.c

📁 一个基于armlinux的管理精灵进程
💻 C
字号:
/*======================================================================

    MMC Card Manager daemon

    mmcmgr.c 1.183 2003/02/27 07:11:45

    The contents of this file are subject to the Mozilla Public
    License Version 1.1 (the "License"); you may not use this file
    except in compliance with the License. You may obtain a copy of
    the License at http://www.mozilla.org/MPL/

    Software distributed under the License is distributed on an "AS
    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
    implied. See the License for the specific language governing
    rights and limitations under the License.

    The initial developer of the original code is David A. Hinds
    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.

    Alternatively, the contents of this file may be used under the
    terms of the GNU General Public License version 2 (the "GPL"), in
    which case the provisions of the GPL are applicable instead of the
    above.  If you wish to allow the use of your version of this file
    only under the terms of the GPL and not to allow others to use
    your version of this file under the MPL, indicate your decision
    by deleting the provisions above and replace them with the notice
    and other provisions required by the GPL.  If you do not delete
    the provisions above, a recipient may use your version of this
    file under either the MPL or the GPL.
    
======================================================================*/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/file.h>


#define MAX_SOCKS 1
static int g_fd = -1;
static int sockets;
/*====================================================================*/

static int execute(char *msg, char *cmd)
{
    int ret;
    FILE *f;
    char line[256];

    syslog(LOG_INFO, "executing: '%s'", cmd);
    strcat(cmd, " 2>&1");
    f = popen(cmd, "r");
    while (fgets(line, 255, f)) {
	line[strlen(line)-1] = '\0';
	syslog(LOG_INFO, "+ %s", line);
    }
    ret = pclose(f);
    if (WIFEXITED(ret)) {
	if (WEXITSTATUS(ret))
	    syslog(LOG_INFO, "%s exited with status %d",
		   msg, WEXITSTATUS(ret));
	return WEXITSTATUS(ret);
    } else
	syslog(LOG_INFO, "%s exited on signal %d",
	       msg, WTERMSIG(ret));
    return -1;
}

/*====================================================================*/

/*====================================================================*/

static void fork_now(void)
{
    int ret;
    if ((ret = fork()) > 0)
	_exit(0);
    if (ret == -1)
	syslog(LOG_ERR, "forking: %m");
    if (setsid() < 0)
	syslog(LOG_ERR, "detaching from tty: %m");
}    

/*====================================================================*/

/* most recent signal */
static int caught_signal = 0;

static void catch_signal(int sig)
{
    caught_signal = sig;
    if (signal(sig, catch_signal) == SIG_ERR)
	syslog(LOG_INFO, "signal(%d): %m", sig);
}

static void handle_signal(void)
{
    int i;
    char umount[64] = "umount /mnt/mmc";

    switch (caught_signal) {
    case SIGTERM:
    case SIGINT:
	execute("mmcmgr terminated, umount file system", umount);
	exit(0);
	break;
    case SIGHUP:
	break;
#ifdef SIGPWR
    case SIGPWR:
	break;
#endif
    }
}

/*********************************************** 
 * BEGIN: routines for char device "mmc_event" *
 ***********************************************/
static int major = 0;

/* find a device's major number from /proc/devices */
static int lookup_dev(char *name)
{
    FILE *f;
    int n;
    char s[32], t[32];

    f = fopen("/proc/devices", "r");
    if (f == NULL)
            return -errno;
    while (fgets(s, 32, f) != NULL) {
        if (sscanf(s, "%d %s", &n, t) == 2)
        if (strcmp(name, t) == 0)
            break;
    }
    fclose(f);
    if (strcmp(name, t) == 0)
        return n;
    else
        return -ENODEV;
}

/* make a device node with the dev_t(major<<8 | minor),
 * then open it and return the file descriptor. 
 */
int open_dev(dev_t dev, int mode)
{
    /* here we provides some optional paths for the device node */
    static char *paths[] = {
        "/var/lib/mmc", "/var/run", "/dev", "/tmp", NULL
	};
    static int nd = 0;
    char **p, fn[64];
    int fd;

    int o_mode = (mode & S_IWRITE) ? O_RDWR : O_RDONLY;
    /* look for a path we can make the node file */
    for (p = paths; *p; p++) {
        sprintf(fn, "%s/mmc-node", *p);
        if (mknod(fn, mode, dev) == 0) {
            fd = open(fn, o_mode);
            if (fd < 0)
                fd = open(fn, O_NONBLOCK|o_mode);
            unlink(fn);
            if (fd >= 0)
                return fd;
            if (errno == ENODEV)
                break;
        }

    }
    return -1;
}

/* give it the minor(sock) number and access mode */
int open_sock(int sock, int mode)
{
	dev_t dev = (major<<8) + sock;
        return open_dev(dev, mode);
}

/* main routine for init "mmc_event" device:
 * 1. lookup_dev()
 * 	find the major of the device from /proc/devices
 * 2. open_sock()
 * 	create a node with the major and minor(0)
 * 3. assign the fd to global variable g_fd
 */
static int init_sockets(void)
{
    int fd, i;

    major = lookup_dev("mmc_event");
    if (major < 0) {
            if (major == -ENODEV)
                syslog(LOG_ERR, "no pcmcia driver in /proc/devices");
            else
                syslog(LOG_ERR, "could not open /proc/devices: %m");
            exit(EXIT_FAILURE);
    }
    for (fd = -1, i = 0; i < MAX_SOCKS; i++) {
        fd = open_sock(i, S_IFCHR|S_IREAD|S_IWRITE);
        if (fd < 0) break;
        g_fd = fd;
    }
    if ((fd < 0) && (errno != ENODEV) && (errno != ENOENT))
        syslog(LOG_ERR, "open_sock(socket %d) failed: %m", i);
    sockets = i;
    if (sockets == 0) {
        if (errno == ENODEV)
             syslog(LOG_ERR, "no sockets found!");
        else if (errno == EBUSY)
             syslog(LOG_ERR, "another cardmgr is already running?");
        return -1;
    } else
        syslog(LOG_INFO, "watching %d sockets", sockets);

    return 0;
}
/********************************************* 
 * END: routines for char device "mmc_event" *
 *********************************************/

/*====================================================================*/
static char *pidfile = "/var/run/mmcmgr.pid";

static void write_pid(void)
{
    FILE *f;
    f = fopen(pidfile, "w");
    if (f == NULL)
        syslog(LOG_WARNING, "could not open %s: %m", pidfile);
    else {
        fprintf(f, "%d\n", getpid());
        fclose(f);
    }
}

/* 
 * int main(int argc, char *argv[])
 *   1. init_sockets()
 * 	open "mmc_event" device and store the file descriptor in g_fd.
 *   2. fork_now()
 * 	run as a daemon
 *   3. write_pid()
 * 	store its process id in /var/run/mmcmgr.pid
 *   4. FD_ZERO(&fds) and FD_SET(g_fd, &fds)
 * 	init a fd_set structure for slelect, which monitors the g_fd.
 *   5. select()
 * 	monitoring g_fd for an event, sleep on g_fd when it is empty.
 *   6. read() and switch(event)
 * 	read an event and execute mount/umount.
 * one more thing, we use handle_signal to serve a system signal issued
 * when we sleep on g_fd.
 */
int main(int argc, char *argv[])
{
    int i, max_fd, ret;
    fd_set fds;
    unsigned int event = 0;
    char mount[128] = "mount -t vfat /dev/mmca1 /mnt/mmc";
    char umount[64] = "umount /mnt/mmc";

    putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin");

    /* open the "mmc_event" device */
    if (init_sockets() != 0)
	    exit(EXIT_FAILURE);

    /* daemonlize */
    fork_now();
    syslog(LOG_INFO, "mmcmgr starting, version is 1.0");

    write_pid();
    if (signal(SIGHUP, catch_signal) == SIG_ERR)
	syslog(LOG_ERR, "signal(SIGHUP): %m");
    if (signal(SIGTERM, catch_signal) == SIG_ERR)
	syslog(LOG_ERR, "signal(SIGTERM): %m");
    if (signal(SIGINT, catch_signal) == SIG_ERR)
	syslog(LOG_ERR, "signal(SIGINT): %m");
#ifdef SIGPWR
    if (signal(SIGPWR, catch_signal) == SIG_ERR)
	syslog(LOG_ERR, "signal(SIGPWR): %m");
#endif

    if ( g_fd == -1 ) {
	syslog(LOG_ERR, "open(): %m");
	exit(EXIT_FAILURE);
    }
    max_fd = g_fd;
    for (;;) {
	FD_ZERO(&fds);
	FD_SET(g_fd, &fds);

	/* wait for an event on the devcie */
	while ((ret = select(max_fd+1, &fds, NULL, NULL, NULL)) < 0) {
	    if (errno == EINTR) {
		handle_signal();
	    } else {
		syslog(LOG_ERR, "select(): %m");
		exit(EXIT_FAILURE);
	    }
	}

	if (!FD_ISSET(g_fd, &fds))
	    continue;
	ret = read(g_fd, &event, 4);
	if ((ret == -1) && (errno != EAGAIN))
	    syslog(LOG_INFO, "read(%d): %m\n", i);
	/* deal with the event returned */
	switch (event) {
		case 0:
			execute("removed!", umount);
			break;	
		case 1:
			execute("inserted!", mount);
			break;
	}

    } /* repeat */
    return 0;
}

⌨️ 快捷键说明

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