📄 devfsd.c
字号:
free_config (); *event_mask = 0; return; } if (num_args < 2) { SYSLOG (LOG_ERR, "bad config line: \"%s\"\n", line); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } if ( (strcasecmp (when, "INCLUDE") == 0) || (strcasecmp (when, "OPTIONAL_INCLUDE") == 0) ) { st_expr_expand (name, STRING_LENGTH, name, get_variable, NULL, NULL); read_config (name, (toupper (when[0]) == 'I') ? FALSE : TRUE, event_mask); return; } if (strcasecmp (when, "RESTORE") == 0) { do_restore ( name, strlen (name) ); return; } if (num_args < 3) { SYSLOG (LOG_ERR, "bad config line: \"%s\"\n", line); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } if ( ( new = malloc (sizeof *new) ) == NULL ) { SYSLOG (LOG_ERR, "error allocating\n"); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } memset (new, 0, sizeof *new); for (count = 0; event_types[count].config_name != NULL; ++count) { if (strcasecmp (when, event_types[count].config_name) != 0) continue; new->action.when = event_types[count].type; break; } if (event_types[count].config_name == NULL) { SYSLOG (LOG_ERR, "bad WHEN in config line: \"%s\"\n", line); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } if (strcasecmp (what, "PERMISSIONS") == 0) { char *ptr; new->action.what = AC_PERMISSIONS; /* Get user and group */ if ( ( ptr = strchr (p[0], '.') ) == NULL ) { SYSLOG (LOG_ERR, "missing '.' character in: \"%s\"\n", p[0]); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } *ptr++ = '\0'; new->u.permissions.uid = get_uid (p[0]); new->u.permissions.gid = get_gid (ptr); /* Get mode */ new->u.permissions.mode = get_mode (p[1]); } else if (strcasecmp (what, "MODLOAD") == 0) new->action.what = AC_MODLOAD; else if (strcasecmp (what, "EXECUTE") == 0) { new->action.what = AC_EXECUTE; num_args -= 3; if (strstr (p[0], "modprobe") != NULL) { /* Bitch and moan */ SYSLOG (LOG_NOTICE, "Use MODLOAD action instead of EXECUTE modprobe!\n"); exit (1); } for (count = 0; count < num_args; ++count) { if ( ( new->u.execute.argv[count] = strdup (p[count]) ) == NULL ) { SYSLOG (LOG_ERR, "error allocating\n"); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } } new->u.execute.argv[num_args] = NULL; } else if ( (strcasecmp (what, "MFUNCTION") == 0) || (strcasecmp (what, "CFUNCTION") == 0) ) { new->action.what = (strcasecmp (what, "MFUNCTION") == 0) ? AC_MFUNCTION : AC_CFUNCTION; num_args -= 3; if (num_args < 2) { SYSLOG (LOG_ERR, "missing path and function in \"%s\"\n",line); exit (1); } if ( ( new->u.function.so = get_shared_object (p[0]) ) == NULL ) { SYSLOG (LOG_ERR, "error loading: \"%s\"\t%s\n", p[0], dlerror () ); exit (1); } new->u.function.func.m = dlsym_nofail (p[0], new->u.function.so->handle, p[1]); --num_args; for (count = 0; count < num_args; ++count) { if ( ( new->u.function.argv[count] = strdup (p[count + 1]) ) == NULL ) { SYSLOG (LOG_ERR, "error allocating\n"); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } } new->u.function.argv[num_args] = NULL; } else if (strcasecmp (what, "COPY") == 0) { new->action.what = AC_COPY; num_args -= 3; if (num_args != 2) { SYSLOG (LOG_ERR, "missing path and function in \"%s\"\n", line); exit (1); } if ( ( new->u.copy.source = strdup (p[0]) ) == NULL ) { SYSLOG (LOG_ERR, "error allocating source string\n"); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } if ( ( new->u.copy.destination = strdup (p[1]) ) == NULL ) { SYSLOG (LOG_ERR, "error allocating destination string\n"); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } } else if (strcasecmp (what, "IGNORE") == 0) new->action.what = AC_IGNORE; else if (strcasecmp (what, "MKOLDCOMPAT") == 0) new->action.what = AC_MKOLDCOMPAT; else if (strcasecmp (what, "MKNEWCOMPAT") == 0) new->action.what = AC_MKNEWCOMPAT; else if (strcasecmp (what, "RMOLDCOMPAT") == 0) new->action.what = AC_RMOLDCOMPAT; else if (strcasecmp (what, "RMNEWCOMPAT") == 0) new->action.what = AC_RMNEWCOMPAT; else { SYSLOG (LOG_ERR, "bad WHAT in config line: \"%s\"\n", line); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } if ( ( err = regcomp (&new->preg, name, REG_EXTENDED) ) != 0 ) { regerror (err, &new->preg, tmp, STRING_LENGTH); SYSLOG (LOG_ERR, "error compiling regexp: \"%s\"\t%s\n", name,tmp); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } *event_mask |= 1 << new->action.when; new->next = NULL; if (first_config == NULL) first_config = new; else last_config->next = new; last_config = new;} /* End Function process_config_line */static void *dlsym_nofail (const char *file, void *handle, char *symbol){ void *result = dlsym (handle, symbol); if (result == NULL) { SYSLOG (LOG_ERR, "symbol: \"%s\" not found in %s\n", symbol, file); exit (1); } return (result);} /* End Function dlsym_nofail */static void load_libnsl (void){#ifdef LIBNSL /* It comes from a shared object */ void *libnsl_handle; libnsl_handle = dlopen (LIBNSL, RTLD_LAZY); if (libnsl_handle == NULL) { SYSLOG ( LOG_ERR, "read map: unable to open %s: %s", LIBNSL, dlerror() ); exit (1); } my_yp_all = dlsym_nofail (LIBNSL, libnsl_handle, "yp_all"); my_yp_get_default_domain = dlsym_nofail (LIBNSL, libnsl_handle, "yp_get_default_domain");#else /* It's built-in the C library */ my_yp_all = yp_all; my_yp_get_default_domain = yp_get_default_domain;#endif} /* End Function load_libnsl */static int process_yp_line (int instatus, char *inkey, int inkeylen, char *inval, int invallen, char *indata){ if (instatus != YP_TRUE) return (instatus); if (invallen > 0) process_config_line (inval, (unsigned long *) indata); return (0);} /* End Function process_yp_line */static flag do_servicing (int fd, unsigned long event_mask)/* [SUMMARY] Service devfs changes until a signal is received. <fd> The open control file. <event_mask> The event mask. [RETURNS] TRUE if SIGHUP was caught, else FALSE.*/{ ssize_t bytes; struct devfsd_notify_struct info; unsigned long tmp_event_mask; /* Tell devfs what events we care about */ tmp_event_mask = event_mask; /* May need to trap inode creates to watch for syslogd(8) starting */ if (!syslog_is_open && !no_syslog) { tmp_event_mask |= 1 << DEVFSD_NOTIFY_CREATE; } if (ioctl (fd, DEVFSDIOC_SET_EVENT_MASK, tmp_event_mask) != 0) { SYSLOG (LOG_ERR, "error setting event mask\t%s\n", ERRSTRING); exit (1); } while (!caught_signal) { errno = 0; bytes = read (fd, (char *) &info, sizeof info); if (caught_signal) break; /* Must test for this first */ if (errno == EINTR) continue; /* Yes, the order is important */ if (bytes < 1) break; /* Special trap for "/dev/log" creation */ if (!syslog_is_open && !no_syslog && (info.type == DEVFSD_NOTIFY_CREATE) && (strcmp (info.devname, "log") == 0) ) { /* Open syslog, now that "/dev/log" exists */ do_open_syslog (); if (ioctl (fd, DEVFSDIOC_SET_EVENT_MASK, event_mask) != 0) { SYSLOG (LOG_ERR, "error setting event mask\t%s\n", ERRSTRING); exit (1); } } service_name (&info); } if (caught_signal) { flag c_sighup = caught_sighup; caught_signal = FALSE; caught_sighup = FALSE; return (c_sighup); } SYSLOG (LOG_ERR, "Error reading control file\t%s\n", ERRSTRING); exit (1);} /* End Function do_servicing */static void service_name (const struct devfsd_notify_struct *info)/* [SUMMARY] Service a single devfs change. <info> The devfs change. [RETURNS] Nothing.*/{ unsigned int n; regmatch_t mbuf[MAX_SUBEXPR]; struct config_entry_struct *entry; if (info->overrun_count > 0) SYSLOG (LOG_ERR, "%u events have been lost!\n", info->overrun_count); if (trace_level > 2) fprintf (stderr, "Looking for \"%s\" (%d)\n", info->devname, info->type); /* Discard lookups on "/dev/log" and "/dev/initctl" */ if (info->type == DEVFSD_NOTIFY_LOOKUP) { if ( (strcmp (info->devname, "log") == 0) || (strcmp (info->devname, "initctl") == 0) ) return; } for (entry = first_config; entry != NULL; entry = entry->next) { if (trace_level > 3) fprintf (stderr, "\t\tProcess \"%s\" (%d)\n", info->devname, entry->action.when); /* First check if action matches the type, then check if name matches */ if (info->type != entry->action.when) continue; if (regexec (&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0) continue; for (n = 0; (n < MAX_SUBEXPR) && (mbuf[n].rm_so != -1); ++n); switch (entry->action.what) { case AC_PERMISSIONS: action_permissions (info, entry); break; case AC_MODLOAD: action_modload (info, entry); break; case AC_EXECUTE: action_execute (info, entry, mbuf, n); break; case AC_MFUNCTION: case AC_CFUNCTION: action_call_function (info, entry, mbuf, n); break; case AC_COPY: action_copy (info, entry, mbuf, n); break; case AC_IGNORE: return; /*break;*/ case AC_MKOLDCOMPAT: case AC_MKNEWCOMPAT: case AC_RMOLDCOMPAT: case AC_RMNEWCOMPAT: action_compat (info, entry->action.what); break; default: SYSLOG (LOG_ERR, "Unknown action type: %u\n", entry->action.what); exit (1); /*break;*/ } }} /* End Function service_name */static void action_permissions (const struct devfsd_notify_struct *info, const struct config_entry_struct *entry)/* [SUMMARY] Update permissions for a device entry. <info> The devfs change. <entry> The config file entry. [RETURNS] Nothing.*/{ mode_t new_mode; struct stat statbuf; if (stat (info->devname, &statbuf) != 0) { SYSLOG (LOG_ERR, "error stat(2)ing: \"%s\"\t%s\n", info->devname, ERRSTRING); return; } new_mode = (statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT); if (trace_level > 2) fprintf (stderr, "\tupdate permissions for \"%s\" from %05o to %05o, user.group from %d.%d to %d.%d\n", info->devname, info->mode, new_mode, info->uid, info->gid, entry->u.permissions.uid, entry->u.permissions.gid); if (new_mode != statbuf.st_mode) { if (chmod (info->devname, new_mode) != 0) { SYSLOG (LOG_ERR, "error changing mode for: \"%s\"\t%s\n", info->devname, ERRSTRING); return; } if (trace_level > 2) fprintf (stderr,"Set permission %05o on \"%s\"\n", new_mode, info->devname); } if ( (entry->u.permissions.uid != statbuf.st_uid) || (entry->u.permissions.gid != statbuf.st_gid) ) { if (chown (info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0) { SYSLOG (LOG_ERR, "error changing owner for: \"%s\"\t%s\n", info->devname, ERRSTRING); return; } if (trace_level > 2) fprintf (stderr, "Set user.group %d.%d on \"%s\"\n", entry->u.permissions.uid, entry->u.permissions.gid, info->devname); }} /* End Function action_permissions */static void action_modload (const struct devfsd_notify_struct *info, const struct config_entry_struct *entry)/* [SUMMARY] Load a module. <info> The devfs change. <entry> The config file entry. [RETURNS] Nothing.*/{ char *argv[6]; char device[STRING_LENGTH]; char *env[4] = {"HOME=/", "TERM=linux", /* Safe mode environment */ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL}; static int (*modprobe) (int argc, char **argv) = NULL; static flag first_time = TRUE; if (first_time) { void *lib; first_time = FALSE; if ( ( lib = dlopen ("/lib/modutils.so", RTLD_NOW) ) != NULL ) { if ( ( modprobe = dlsym (lib, "modprobe") ) == NULL ) SYSLOG(LOG_ERR, "/lib/modutils.so doesn't contain modprobe()"); } else if (trace_level > 1) fprintf (stderr, "/lib/modutils.so load failure: %s\n",dlerror() ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -