+static int
+sd_openlog(vfs_context_t ctx)
+{
+ int error = 0;
+ struct timeval tv;
+
+ /* Open shutdown log */
+ if ((error = vnode_open(PROC_SHUTDOWN_LOG, (O_CREAT | FWRITE | O_NOFOLLOW), 0644, 0, &sd_logvp, ctx))) {
+ printf("Failed to open %s: error %d\n", PROC_SHUTDOWN_LOG, error);
+ sd_logvp = NULLVP;
+ return error;
+ }
+
+ vnode_setsize(sd_logvp, (off_t)0, 0, ctx);
+
+ /* Write a little header */
+ microtime(&tv);
+ sd_log(ctx, "Process shutdown log. Current time is %lu (in seconds).\n\n", tv.tv_sec);
+
+ return 0;
+}
+
+static int
+sd_closelog(vfs_context_t ctx)
+{
+ int error = 0;
+ if (sd_logvp != NULLVP) {
+ VNOP_FSYNC(sd_logvp, MNT_WAIT, ctx);
+ error = vnode_close(sd_logvp, FWRITE, ctx);
+ }
+
+ return error;
+}
+
+static void
+sd_log(vfs_context_t ctx, const char *fmt, ...)
+{
+ int resid, log_error, len;
+ char logbuf[100];
+ va_list arglist;
+
+ /* If the log isn't open yet, open it */
+ if (sd_logvp == NULLVP) {
+ if (sd_openlog(ctx) != 0) {
+ /* Couldn't open, we fail out */
+ return;
+ }
+ }
+
+ va_start(arglist, fmt);
+ len = vsnprintf(logbuf, sizeof(logbuf), fmt, arglist);
+ log_error = vn_rdwr(UIO_WRITE, sd_logvp, (caddr_t)logbuf, len, sd_log_offset,
+ UIO_SYSSPACE, IO_UNIT | IO_NOAUTH, vfs_context_ucred(ctx), &resid, vfs_context_proc(ctx));
+ if (log_error == EIO || log_error == 0) {
+ sd_log_offset += (len - resid);
+ }
+
+ va_end(arglist);
+
+}
+
+static int
+sd_filt1(proc_t p, void * args)
+{
+ proc_t self = current_proc();
+ struct sd_filterargs * sf = (struct sd_filterargs *)args;
+ int delayterm = sf-> delayterm;
+ int shutdownstate = sf->shutdownstate;
+
+ if (((p->p_flag&P_SYSTEM) != 0) || (p->p_ppid == 0)
+ ||(p == self) || (p->p_stat == SZOMB)
+ || (p->p_shutdownstate != shutdownstate)
+ ||((delayterm == 0) && ((p->p_lflag& P_LDELAYTERM) == P_LDELAYTERM))
+ || ((p->p_sigcatch & sigmask(SIGTERM))== 0)) {
+ return(0);
+ }
+ else
+ return(1);
+}
+
+
+static int
+sd_callback1(proc_t p, void * args)
+{
+ struct sd_iterargs * sd = (struct sd_iterargs *)args;
+ int signo = sd->signo;
+ int setsdstate = sd->setsdstate;
+ int countproc = sd->countproc;
+
+ proc_lock(p);
+ p->p_shutdownstate = setsdstate;
+ if (p->p_stat != SZOMB) {
+ proc_unlock(p);
+ if (countproc != 0) {
+ proc_list_lock();
+ p->p_listflag |= P_LIST_EXITCOUNT;
+ proc_shutdown_exitcount++;
+ proc_list_unlock();
+ }
+
+ psignal(p, signo);
+ if (countproc != 0)
+ sd->activecount++;
+ } else {
+ proc_unlock(p);
+ }
+
+ return PROC_RETURNED;
+}
+
+static int
+sd_filt2(proc_t p, void * args)
+{
+ proc_t self = current_proc();
+ struct sd_filterargs * sf = (struct sd_filterargs *)args;
+ int delayterm = sf-> delayterm;
+ int shutdownstate = sf->shutdownstate;
+
+ if (((p->p_flag&P_SYSTEM) != 0) || (p->p_ppid == 0)
+ ||(p == self) || (p->p_stat == SZOMB)
+ || (p->p_shutdownstate == shutdownstate)
+ ||((delayterm == 0) && ((p->p_lflag& P_LDELAYTERM) == P_LDELAYTERM))) {
+ return(0);
+ }
+ else
+ return(1);
+}
+
+static int
+sd_callback2(proc_t p, void * args)
+{
+ struct sd_iterargs * sd = (struct sd_iterargs *)args;
+ int signo = sd->signo;
+ int setsdstate = sd->setsdstate;
+ int countproc = sd->countproc;
+
+ proc_lock(p);
+ p->p_shutdownstate = setsdstate;
+ if (p->p_stat != SZOMB) {
+ proc_unlock(p);
+ if (countproc != 0) {
+ proc_list_lock();
+ p->p_listflag |= P_LIST_EXITCOUNT;
+ proc_shutdown_exitcount++;
+ proc_list_unlock();
+ }
+ psignal(p, signo);
+ if (countproc != 0)
+ sd->activecount++;
+ } else {
+ proc_unlock(p);
+ }