📄 start-stop-daemon.c
字号:
if (parse_signal (signal_str, &signal_nr) != 0) { badusage ("--signal takes a numeric argument or name of signal (KILL, INTR, ...)"); } } } if (start == stop) #ifndef SunOS badusage("need one of --start or --stop"); #else badusage("need one of -S (start) or -K (stop)"); #endif if (!execname && !pidfile && !userspec) badusage("need at least one of --exec, --pidfile or --user"); if (!startas) startas = execname; if (start && !startas) badusage("--start needs --exec or --startas"); if (mpidfile && pidfile == NULL) badusage("--make-pidfile is only relevant with --pidfile"); if (background && !start) badusage("--background is only relevant with --start");}#if defined(OSLinux)static intpid_is_exec(int pid, const struct stat *esb){ struct stat sb; char buf[32]; sprintf(buf, "/proc/%d/exe", pid); if (stat(buf, &sb) != 0) return 0; return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);}static intpid_is_user(int pid, int uid){ struct stat sb; char buf[32]; sprintf(buf, "/proc/%d", pid); if (stat(buf, &sb) != 0) return 0; return ((int) sb.st_uid == uid);}static intpid_is_cmd(int pid, const char *name){ char buf[32]; FILE *f; int c; sprintf(buf, "/proc/%d/stat", pid); f = fopen(buf, "r"); if (!f) return 0; while ((c = getc(f)) != EOF && c != '(') ; if (c != '(') { fclose(f); return 0; } /* this hopefully handles command names containing ')' */ while ((c = getc(f)) != EOF && c == *name) name++; fclose(f); return (c == ')' && *name == '\0');}#endif /* OSLinux */#if defined(OSHURD)static intpid_is_user(int pid, int uid){ struct stat sb; char buf[32]; struct proc_stat *pstat; sprintf(buf, "/proc/%d", pid); if (stat(buf, &sb) != 0) return 0; return (sb.st_uid == uid); pstat = proc_stat_list_pid_proc_stat (procset, pid); if (pstat == NULL) fatal ("Error getting process information: NULL proc_stat struct"); proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_OWNER_UID); return (pstat->owner_uid == uid);}static intpid_is_cmd(int pid, const char *name){ struct proc_stat *pstat; pstat = proc_stat_list_pid_proc_stat (procset, pid); if (pstat == NULL) fatal ("Error getting process information: NULL proc_stat struct"); proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_ARGS); return (!strcmp (name, pstat->args));}#endif /* OSHURD */#if defined(SunOS)/*Lots of lovely system dependant functions for Solaris. I used to like theidea of proc, but now I'm not so sure. It feels to much like a kludge.*//*pid_is_user, takes the pid and a uid, normally ours, but can be someoneelses, to allow you to identify the process' owner. returns zero on success,and either true or the uid of the owner on failure (this may be undefined,or I may be misremembering.*/static intpid_is_user(int pid, int uid){ struct stat sb; char buf[32]; sprintf(buf, "/proc/%d", pid); if (stat(buf, &sb) != 0) return 0; /*I can stat it so it seems to be mine...*/ return ((int) sb.st_uid == uid);}/*pid_is_cmd, takes a pid, and a string representing the process' (supposed)name. Compares the process' supposed name with the name reported by thesystem. Returns zero on failure, and nonzero on success.*/static intpid_is_cmd(int pid, const char *name){ char buf[32]; FILE *f; psinfo_t pid_info; sprintf(buf, "/proc/%d/psinfo", pid); f = fopen(buf, "r"); if (!f) return 0; fread(&pid_info,sizeof(psinfo_t),1,f); return (!strcmp(name,pid_info.pr_fname));}#endif /*SunOS*/#ifdef FreeBSDstatic int pid_is_user(int pid, int uid){ struct stat sb; char buf[32]; sprintf(buf, "/proc/%d", pid); if (stat(buf, &sb) != 0) return 0; return ((int) sb.st_uid == uid);}static intpid_is_cmd(int pid, const char *name){ char buf[32]; FILE *f; int c; sprintf(buf, "/proc/%d/stat", pid); f = fopen(buf, "r"); if (!f) return 0; while ((c = getc(f)) != EOF && c != '(') ; if (c != '(') { fclose(f); return 0; } /* this hopefully handles command names containing ')' */ while ((c = getc(f)) != EOF && c == *name) name++; fclose(f); return (c == ')' && *name == '\0');}#endif /*FreeBSD*/static voidcheck(int pid){#if defined(OSLinux) if (execname && !pid_is_exec(pid, &exec_stat))#elif defined(OSHURD) /* I will try this to see if it works */ if (execname && !pid_is_cmd(pid, execname))#endif return; if (userspec && !pid_is_user(pid, user_id)) return; if (cmdname && !pid_is_cmd(pid, cmdname)) return; push(&found, pid);}static voiddo_pidfile(const char *name){ FILE *f; int pid; f = fopen(name, "r"); if (f) { if (fscanf(f, "%d", &pid) == 1) check(pid); fclose(f); }}/* WTA: this needs to be an autoconf check for /proc/pid existance. */#if defined(OSLinux) || defined (SunOS) || defined(FreeBSD)static voiddo_procinit(void){ DIR *procdir; struct dirent *entry; int foundany, pid; procdir = opendir("/proc"); if (!procdir) fatal("opendir /proc: %s", strerror(errno)); foundany = 0; while ((entry = readdir(procdir)) != NULL) { if (sscanf(entry->d_name, "%d", &pid) != 1) continue; foundany++; check(pid); } closedir(procdir); if (!foundany) fatal("nothing in /proc - not mounted?");}#endif /* OSLinux */#if defined(OSHURD)error_tcheck_all (void *ptr){ struct proc_stat *pstat = ptr; check (pstat->pid); return (0);}static voiddo_psinit(void) error_t err; err = ps_context_create (getproc (), &context); if (err) error (1, err, "ps_context_create"); err = proc_stat_list_create (context, &procset); if (err) error (1, err, "proc_stat_list_create"); err = proc_stat_list_add_all (procset, 0, 0); if (err) error (1, err, "proc_stat_list_add_all"); /* Check all pids */ ihash_iterate (context->procs, check_all);}#endif /* OSHURD *//* return 1 on failure */static intdo_stop(void){ char what[1024]; struct pid_list *p; int retval = 0; if (cmdname) strcpy(what, cmdname); else if (execname) strcpy(what, execname); else if (pidfile) sprintf(what, "process in pidfile `%s'", pidfile); else if (userspec) sprintf(what, "process(es) owned by `%s'", userspec); else fatal("internal error, please report"); if (!found) { if (quietmode <= 0) printf("No %s found running; none killed.\n", what); exit(exitnodo); } for (p = found; p; p = p->next) { if (testmode) printf("Would send signal %d to %d.\n", signal_nr, p->pid); else if (kill(p->pid, signal_nr) == 0) push(&killed, p->pid); else { printf("%s: warning: failed to kill %d: %s\n", progname, p->pid, strerror(errno)); retval += exitnodo; } } if (quietmode < 0 && killed) { printf("Stopped %s (pid", what); for (p = killed; p; p = p->next) printf(" %d", p->pid); printf(").\n"); } return retval;}intmain(int argc, char **argv){ progname = argv[0]; parse_options(argc, argv); argc -= optind; argv += optind; if (execname && stat(execname, &exec_stat)) fatal("stat %s: %s", execname, strerror(errno)); if (userspec && sscanf(userspec, "%d", &user_id) != 1) { struct passwd *pw; pw = getpwnam(userspec); if (!pw) fatal("user `%s' not found\n", userspec); user_id = pw->pw_uid; } if (changegroup && sscanf(changegroup, "%d", &runas_gid) != 1) { struct group *gr = getgrnam(changegroup); if (!gr) fatal("group `%s' not found\n", changegroup); runas_gid = gr->gr_gid; } if (changeuser && sscanf(changeuser, "%d", &runas_uid) != 1) { struct passwd *pw = getpwnam(changeuser); if (!pw) fatal("user `%s' not found\n", changeuser); runas_uid = pw->pw_uid; if (changegroup == NULL) { /* pass the default group of this user */ changegroup = ""; /* just empty */ runas_gid = pw->pw_gid; } } if (pidfile) do_pidfile(pidfile); else do_procinit(); if (stop) { int i = do_stop(); if (i) { if (quietmode <= 0) printf("%d pids were not killed\n", i); exit(1); } exit(0); } if (found) { if (quietmode <= 0) printf("%s already running.\n", execname); exit(exitnodo); } if (testmode) { printf("Would start %s ", startas); while (argc-- > 0) printf("%s ", *argv++); if (changeuser != NULL) { printf(" (as user %s[%d]", changeuser, runas_uid); if (changegroup != NULL) printf(", and group %s[%d])", changegroup, runas_gid); else printf(")"); } if (changeroot != NULL) printf(" in directory %s", changeroot); printf(".\n"); exit(0); } if (quietmode < 0) printf("Starting %s...\n", startas); *--argv = startas; if (changeroot != NULL) { if (chdir(changeroot) < 0) fatal("Unable to chdir() to %s", changeroot); if (chroot(changeroot) < 0) fatal("Unable to chroot() to %s", changeroot); } if (changeuser != NULL) { if (setgid(runas_gid)) fatal("Unable to set gid to %d", runas_gid); if (initgroups(changeuser, runas_gid)) fatal("Unable to set initgroups() with gid %d", runas_gid); if (setuid(runas_uid)) fatal("Unable to set uid to %s", changeuser); } if (background) { /* ok, we need to detach this process */ int i, fd; if (quietmode < 0) printf("Detatching to start %s...", startas); i = fork(); if (i<0) { fatal("Unable to fork.\n"); } if (i) { /* parent */ if (quietmode < 0) printf("done.\n"); exit(0); } /* child continues here */ /* now close all extra fds */ for (i=getdtablesize()-1; i>=0; --i) close(i); /* change tty */ fd = open("/dev/tty", O_RDWR); ioctl(fd, TIOCNOTTY, 0); close(fd); chdir("/"); umask(022); /* set a default for dumb programs */#ifndef FreeBSD setpgrp(); /* set the process group */#else setpgrp(0, runas_gid); /* set the process group */#endif fd=open("/dev/null", O_RDWR); /* stdin */ dup(fd); /* stdout */ dup(fd); /* stderr */ } if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */ FILE *pidf = fopen(pidfile, "w"); pid_t pidt = getpid(); if (pidf == NULL) fatal("Unable to open pidfile `%s' for writing: %s", pidfile, strerror(errno)); fprintf(pidf, "%d\n", (int)pidt); fclose(pidf); } execv(startas, argv); fatal("Unable to start %s: %s", startas, strerror(errno));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -