📄 mmcmgr.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 + -