int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "")) != -1) switch(ch) { case '?': default: usage(); } argc -= optind; argv += optind; switch(argc) { case 0: if (acct(NULL)) err(1, NULL); break; case 1: if (acct(*argv)) err(1, "%s", *argv); break; default: usage(); } exit(0); }
/* * 父进程等待子进程终止 * i为子进程pid,-1表示等待所有子进程 * t为语法树节点 */ void pwait(int i, int *t) { int p, e; int s; if(i != 0) for(;;) { times(&timeb); time(timeb.proct); p = wait(&s); if(p == -1) /* 等待失败 */ break; e = s&0177; /* 保留状态环境 */ if(mesg[e] != 0) { /* 子进程异常终止 */ if(p != i) { prn(p); prs(": "); } prs(mesg[e]); /* 打印对应的消息 */ if(s&0200) /* 内核奔溃 */ prs(" -- Core dumped"); } if(e != 0) err(""); /* 等待正常终止 */ if(i == p) { acct(t); break; } else acct(0); } }
static void setup(void) { int fd; tst_require_root(NULL); tst_tmpdir(); ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); fd = SAFE_CREAT(cleanup, TEST_FILE5, 0777); SAFE_CLOSE(cleanup, fd); if (acct(TEST_FILE5) == -1) { if (errno == ENOSYS) { tst_brkm(TCONF, cleanup, "BSD process accounting is not configured in " "this kernel"); } else { tst_brkm(TBROK | TERRNO, cleanup, "acct failed unexpectedly"); } } /* turn off acct, so we are in a known state */ if (acct(NULL) == -1) { if (errno == ENOSYS) { tst_brkm(TCONF, cleanup, "BSD process accounting is not configured in " "this kernel"); } else { tst_brkm(TBROK | TERRNO, cleanup, "acct(NULL) failed"); } } /* ELOOP SETTING */ SAFE_SYMLINK(cleanup, TEST_FILE6, "test_file_eloop2"); SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_FILE6); /* ENAMETOOLONG SETTING */ memset(nametoolong, 'a', PATH_MAX+1); /* EROFS SETTING */ tst_mkfs(NULL, device, fstype, NULL); SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); if (mount(device, "mntpoint", fstype, 0, NULL) < 0) { tst_brkm(TBROK | TERRNO, cleanup, "mount device:%s failed", device); } mount_flag = 1; /* Create a file in the file system, then remount it as read-only */ fd = SAFE_CREAT(cleanup, TEST_FILE8, 0644); SAFE_CLOSE(cleanup, fd); if (mount(device, "mntpoint", fstype, MS_REMOUNT | MS_RDONLY, NULL) < 0) { tst_brkm(TBROK | TERRNO, cleanup, "mount device:%s failed", device); } mount_flag = 1; }
static void setup(void) { int fd; tst_require_root(NULL); check_acct_in_kernel(); tst_tmpdir(); ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); fd = SAFE_CREAT(cleanup, TEST_FILE5, 0777); SAFE_CLOSE(cleanup, fd); if (acct(TEST_FILE5) == -1) tst_brkm(TBROK | TERRNO, cleanup, "acct failed unexpectedly"); /* turn off acct, so we are in a known state */ if (acct(NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "acct(NULL) failed"); /* ELOOP SETTING */ SAFE_SYMLINK(cleanup, TEST_FILE6, "test_file_eloop2"); SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_FILE6); /* ENAMETOOLONG SETTING */ memset(nametoolong, 'a', PATH_MAX+1); /* EROFS SETTING */ fs_type = tst_dev_fs_type(); device = tst_acquire_device(cleanup); if (!device) tst_brkm(TCONF, cleanup, "Failed to obtain block device"); tst_mkfs(cleanup, device, fs_type, NULL); SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); if (mount(device, "mntpoint", fs_type, 0, NULL) < 0) { tst_brkm(TBROK | TERRNO, cleanup, "mount device:%s failed", device); } mount_flag = 1; /* Create a file in the file system, then remount it as read-only */ fd = SAFE_CREAT(cleanup, TEST_FILE8, 0644); SAFE_CLOSE(cleanup, fd); if (mount(device, "mntpoint", fs_type, MS_REMOUNT | MS_RDONLY, NULL) < 0) { tst_brkm(TBROK | TERRNO, cleanup, "mount device:%s failed", device); } }
static void bootchart_finish() { unlink(LOG_STOPFILE); fclose(log_stat); fclose(log_disks); fclose(log_procs); acct(NULL); }
static void acct_verify(int i) { if (test_cases[i].setupfunc) test_cases[i].setupfunc(); TEST(acct(test_cases[i].filename)); if (test_cases[i].cleanfunc) test_cases[i].cleanfunc(); if (TEST_RETURN != -1) { tst_resm(TFAIL, "acct(%s) succeeded unexpectedly", test_cases[i].filename); return; } if (TEST_ERRNO == test_cases[i].exp_errno) { tst_resm(TPASS | TTERRNO, "acct failed as expected"); } else { tst_resm(TFAIL | TTERRNO, "acct failed unexpectedly; expected: %d - %s", test_cases[i].exp_errno, strerror(test_cases[i].exp_errno)); } }
void bootchart_finish( void ) { // unlink( LOG_STOPFILE ); file_buff_done(log_stat); file_buff_done(log_disks); file_buff_done(log_procs); acct(NULL); }
static void cleanup(void) { if (acct(NULL) == -1) tst_resm(TBROK | TERRNO, "acct(NULL) failed"); tst_rmdir(); }
int main(int argc, char *argv[]) { if (acct(RECORD_FILE) < 0) { perror(RECORD_FILE); return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* called to setup bootcharting */ int bootchart_init( void ) { int ret; char buff[4]; int timeout = 0, count = 0; buff[0] = 0; proc_read( LOG_STARTFILE, buff, sizeof(buff) ); if (buff[0] != 0) { timeout = atoi(buff); } else { /* when running with emulator, androidboot.bootchart=<timeout> * might be passed by as kernel parameters to specify the bootchart * timeout. this is useful when using -wipe-data since the /data * partition is fresh */ char cmdline[1024]; char* s; #define KERNEL_OPTION "androidboot.bootchart=" proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) ); s = strstr(cmdline, KERNEL_OPTION); if (s) { s += sizeof(KERNEL_OPTION)-1; timeout = atoi(s); } } if (timeout == 0) return 0; if (timeout > BOOTCHART_MAX_TIME_SEC) timeout = BOOTCHART_MAX_TIME_SEC; count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS; do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR); selinux_android_restorecon(LOG_ROOT, 0); file_buff_open(log_stat, LOG_STAT); file_buff_open(log_procs, LOG_PROCS); file_buff_open(log_disks, LOG_DISK); /* create kernel process accounting file */ { int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd >= 0) { close(fd); acct( LOG_ACCT ); } } log_header(); return count; }
static void check_acct_in_kernel(void) { /* check if acct is implemented in kernel */ if (acct(NULL) == -1) { if (errno == ENOSYS) { tst_brkm(TCONF, NULL, "BSD process accounting is not configured in " "this kernel"); } } }
int main() { InsecureAccount acct(12345, 321.98, "Luke Skywalker"); acct.deposit(6.23); /* Error! No matching function - hidden by deposit(double, int). */ acct.m_Balance += 6.23; /* Error! Member is protected, inaccessible. */ acct.Account::deposit(6.23); /* Hidden does not mean inaccessible. You can still access hidden public members via scope resolution. */ // ... more client code return 0; }
static void cleanup(void) { TEST_CLEANUP; if (acct(NULL) == -1) tst_resm(TBROK | TERRNO, "acct(NULL) failed"); if (mount_flag && umount("mntpoint") < 0) { tst_brkm(TBROK | TERRNO, NULL, "umount device:%s failed", device); } tst_rmdir(); }
int main(int argc, char *argv[]) { if (argc > 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) usageErr("%s [file]\n", argv[0]); if (acct(argv[1]) == -1) errExit("acct"); printf("Process accounting %s\n", (argv[1] == NULL) ? "disabled" : "enabled"); exit(EXIT_SUCCESS); }
static int bootchart_init() { int timeout = 0; std::string start; android::base::ReadFileToString(LOG_STARTFILE, &start); if (!start.empty()) { timeout = atoi(start.c_str()); } else { // When running with emulator, androidboot.bootchart=<timeout> // might be passed by as kernel parameters to specify the bootchart // timeout. this is useful when using -wipe-data since the /data // partition is fresh. std::string cmdline; const char* s; android::base::ReadFileToString("/proc/cmdline", &cmdline); #define KERNEL_OPTION "androidboot.bootchart=" if ((s = strstr(cmdline.c_str(), KERNEL_OPTION)) != NULL) { timeout = atoi(s + sizeof(KERNEL_OPTION) - 1); } } if (timeout == 0) return 0; if (timeout > BOOTCHART_MAX_TIME_SEC) timeout = BOOTCHART_MAX_TIME_SEC; int count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS; log_stat = fopen(LOG_STAT, "we"); if (log_stat == NULL) { return -1; } log_procs = fopen(LOG_PROCS, "we"); if (log_procs == NULL) { fclose(log_stat); return -1; } log_disks = fopen(LOG_DISK, "we"); if (log_disks == NULL) { fclose(log_stat); fclose(log_procs); return -1; } // Create kernel process accounting file. close(open(LOG_ACCT, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)); acct(LOG_ACCT); log_header(); return count; }
void priv_acct_cleanup(int asroot, int injail, struct test *test) { (void)acct(NULL); if (fpath1_initialized) { (void)unlink(fpath1); fpath1_initialized = 0; } if (fpath2_initialized) { (void)unlink(fpath2); fpath2_initialized = 0; } }
int main(int argc, char *argv[]) { struct passwd *pwent; setup(); /* EISDIR */ if (acct("/") == -1 && errno == EISDIR) tst_resm(TPASS, "Failed with EISDIR as expected"); else tst_brkm(TFAIL | TERRNO, cleanup, "didn't fail as expected; expected EISDIR"); /* EACCES */ if (acct("/dev/null") == -1 && errno == EACCES) tst_resm(TPASS, "Failed with EACCES as expected"); else tst_brkm(TFAIL | TERRNO, cleanup, "didn't fail as expected; expected EACCES"); /* ENOENT */ if (acct("/tmp/does/not/exist") == -1 && errno == ENOENT) tst_resm(TPASS, "Failed with ENOENT as expected"); else tst_brkm(TBROK | TERRNO, cleanup, "didn't fail as expected; expected ENOENT"); /* ENOTDIR */ if (acct("/etc/fstab/") == -1 && errno == ENOTDIR) tst_resm(TPASS, "Failed with ENOTDIR as expected"); else tst_brkm(TFAIL | TERRNO, cleanup, "didn't fail as expected; expected ENOTDIR"); /* EPERM */ sprintf(tmpbuf, "./%s.%d", TCID, getpid()); fd = SAFE_CREAT(cleanup, tmpbuf, 0777); SAFE_CLOSE(cleanup, fd); if (acct(tmpbuf) == -1) tst_brkm(TBROK | TERRNO, cleanup, "acct failed unexpectedly"); pwent = SAFE_GETPWNAM(cleanup, "nobody"); SAFE_SETEUID(cleanup, pwent->pw_uid); if (acct(tmpbuf) == -1 && errno == EPERM) tst_resm(TPASS, "Failed with EPERM as expected"); else tst_brkm(TBROK | TERRNO, cleanup, "didn't fail as expected; expected EPERM"); SAFE_SETEUID(cleanup, 0); SAFE_UNLINK(cleanup, tmpbuf); cleanup(); tst_exit(); }
void priv_acct_noopdisable(int asroot, int injail, struct test *test) { int error; error = acct(NULL); if (asroot && injail) expect("priv_acct_noopdisable(root, jail)", error, -1, EPERM); if (asroot && !injail) expect("priv_acct_noopdisable(root, !jail)", error, 0, 0); if (!asroot && injail) expect("priv_acct_noopdisable(!root, jail)", error, -1, EPERM); if (!asroot && !injail) expect("priv_acct_noopdisable(!root, !jail)", error, -1, EPERM); }
void priv_acct_rotate(int asroot, int injail, struct test *test) { int error; error = acct(fpath2); if (asroot && injail) expect("priv_acct_rotate(root, jail)", error, -1, EPERM); if (asroot && !injail) expect("priv_acct_rotate(root, !jail)", error, 0, 0); if (!asroot && injail) expect("priv_acct_rotate(!root, jail)", error, -1, EPERM); if (!asroot && !injail) expect("priv_acct_rotate(!root, !jail)", error, -1, EPERM); }
int priv_acct_setup(int asroot, int injail, struct test *test) { size_t len; int i; len = sizeof(i); if (sysctlbyname(SYSCTL_NAME, &i, &len, NULL, 0) < 0) { warn("priv_acct_setup: sysctlbyname(%s)", SYSCTL_NAME); return (-1); } if (i != 0) { warnx("sysctlbyname(%s) indicates accounting configured", SYSCTL_NAME); return (-1); } setup_file("priv_acct_setup: fpath1", fpath1, 0, 0, 0666); fpath1_initialized = 1; setup_file("priv_acct_setup: fpath2", fpath2, 0, 0, 0666); fpath2_initialized = 1; if (test->t_test_func == priv_acct_enable || test->t_test_func == priv_acct_noopdisable) { if (acct(NULL) != 0) { warn("priv_acct_setup: acct(NULL)"); return (-1); } } else if (test->t_test_func == priv_acct_disable || test->t_test_func == priv_acct_rotate) { if (acct(fpath1) != 0) { warn("priv_acct_setup: acct(\"%s\")", fpath1); return (-1); } } return (0); }
static void cleanup(void) { TEST_CLEANUP; if (acct(NULL) == -1) tst_resm(TWARN | TERRNO, "acct(NULL) failed"); if (mount_flag && umount("mntpoint") < 0) { tst_resm(TWARN | TERRNO, "umount device:%s failed", device); } if (device) tst_release_device(NULL, device); tst_rmdir(); }
void SailfishPlatform::telepathyResponse(const QString &account, const QString &contact, const QString &text) const { QDBusObjectPath acct(account); QVariantMap arg1,arg2; arg1.insert("message-type",0); arg2.insert("content-type",QString("text/plain")); arg2.insert("content",text); QDBusReply<QString> res = QDBusConnection::sessionBus().call( QDBusMessage::createMethodCall("org.freedesktop.Telepathy.ChannelDispatcher", "/org/freedesktop/Telepathy/ChannelDispatcher", "org.freedesktop.Telepathy.ChannelDispatcher.Interface.Messages.DRAFT", "SendMessage") << qVariantFromValue(acct) << contact << qVariantFromValue(QList<QVariantMap>({arg1,arg2})) << (quint32)0); if (res.isValid()) { if (res.value().isEmpty()) { qWarning() << "Unable to send response from" << account << "to" << contact << "with" << text; } else qDebug() << "Sent message under uuid" << res.value(); } else { qWarning() << res.error().message(); } }
MetadataItemPropertiesPanel::MetadataItemPropertiesPanel( MetadataItemPropertiesFrame* parent, MetadataItem* object) : wxPanel(parent, wxID_ANY), pageTypeM(ptSummary), objectM(object), htmlReloadRequestedM(false) { wxASSERT(object); mipPanels.push_back(this); html_window = new PrintableHtmlWindow(this, wxID_ANY); parent->SetTitle(object->getName_()); wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL ); bSizer2->Add(html_window, 1, wxEXPAND, 0 ); SetSizer( bSizer2 ); Layout(); wxAcceleratorEntry entries[4]; entries[0].Set(wxACCEL_CMD, (int) 'W', wxID_CLOSE_FRAME); entries[1].Set(wxACCEL_CMD, (int) 'R', wxID_REFRESH); // MSW only entries[2].Set(wxACCEL_CTRL, WXK_F4, wxID_CLOSE_FRAME); entries[3].Set(wxACCEL_NORMAL, WXK_F5, wxID_REFRESH); bool isMSW = (wxPlatformInfo::Get().GetOperatingSystemId() & wxOS_WINDOWS) != 0; wxAcceleratorTable acct(isMSW ? 4 : 2, entries); SetAcceleratorTable(acct); Connect(wxID_CLOSE_FRAME, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MetadataItemPropertiesPanel::OnCloseFrame)); Connect(wxID_ANY, wxEVT_COMMAND_HTML_CELL_HOVER, wxHtmlCellEventHandler(MetadataItemPropertiesPanel::OnHtmlCellHover)); Connect(wxID_REFRESH, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MetadataItemPropertiesPanel::OnRefresh)); // request initial rendering requestLoadPage(true); objectM->attachObserver(this, true); }
/* called to setup bootcharting */ void bootchart_init( void ) { int ret; char buff[4]; do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR); file_buff_open(log_stat, LOG_STAT); file_buff_open(log_procs, LOG_PROCS); file_buff_open(log_disks, LOG_DISK); /* create kernel process accounting file */ { int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd >= 0) { close(fd); acct( LOG_ACCT ); } } log_header(); gettimeofday(&start_time, 0); }
static void setup(void) { /* * XXX: FreeBSD says you must always be superuser, but Linux says you * need to have CAP_SYS_PACCT capability. * * Either way, it's better to do this to test out the EPERM * requirement. */ tst_require_root(NULL); tst_tmpdir(); /* turn off acct, so we are in a known state */ if (acct(NULL) == -1) { if (errno == ENOSYS) tst_brkm(TCONF, cleanup, "BSD process accounting is not configured in this " "kernel"); else tst_brkm(TBROK | TERRNO, cleanup, "acct(NULL) failed"); } }
/* * Return value: * 1 - exitlwps() failed, call (or continue) lwp_exit() * 0 - restarting init. Return through system call path */ int proc_exit(int why, int what) { kthread_t *t = curthread; klwp_t *lwp = ttolwp(t); proc_t *p = ttoproc(t); zone_t *z = p->p_zone; timeout_id_t tmp_id; int rv; proc_t *q; task_t *tk; vnode_t *exec_vp, *execdir_vp, *cdir, *rdir; sigqueue_t *sqp; lwpdir_t *lwpdir; uint_t lwpdir_sz; tidhash_t *tidhash; uint_t tidhash_sz; ret_tidhash_t *ret_tidhash; refstr_t *cwd; hrtime_t hrutime, hrstime; int evaporate; /* * Stop and discard the process's lwps except for the current one, * unless some other lwp beat us to it. If exitlwps() fails then * return and the calling lwp will call (or continue in) lwp_exit(). */ proc_is_exiting(p); if (exitlwps(0) != 0) return (1); mutex_enter(&p->p_lock); if (p->p_ttime > 0) { /* * Account any remaining ticks charged to this process * on its way out. */ (void) task_cpu_time_incr(p->p_task, p->p_ttime); p->p_ttime = 0; } mutex_exit(&p->p_lock); DTRACE_PROC(lwp__exit); DTRACE_PROC1(exit, int, why); /* * Will perform any brand specific proc exit processing, since this * is always the last lwp, will also perform lwp_exit and free brand * data */ if (PROC_IS_BRANDED(p)) { lwp_detach_brand_hdlrs(lwp); brand_clearbrand(p, B_FALSE); } /* * Don't let init exit unless zone_start_init() failed its exec, or * we are shutting down the zone or the machine. * * Since we are single threaded, we don't need to lock the * following accesses to zone_proc_initpid. */ if (p->p_pid == z->zone_proc_initpid) { if (z->zone_boot_err == 0 && zone_status_get(z) < ZONE_IS_SHUTTING_DOWN && zone_status_get(global_zone) < ZONE_IS_SHUTTING_DOWN && z->zone_restart_init == B_TRUE && restart_init(what, why) == 0) return (0); /* * Since we didn't or couldn't restart init, we clear * the zone's init state and proceed with exit * processing. */ z->zone_proc_initpid = -1; } lwp_pcb_exit(); /* * Allocate a sigqueue now, before we grab locks. * It will be given to sigcld(), below. * Special case: If we will be making the process disappear * without a trace because it is either: * * an exiting SSYS process, or * * a posix_spawn() vfork child who requests it, * we don't bother to allocate a useless sigqueue. */ evaporate = (p->p_flag & SSYS) || ((p->p_flag & SVFORK) && why == CLD_EXITED && what == _EVAPORATE); if (!evaporate) sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); /* * revoke any doors created by the process. */ if (p->p_door_list) door_exit(); /* * Release schedctl data structures. */ if (p->p_pagep) schedctl_proc_cleanup(); /* * make sure all pending kaio has completed. */ if (p->p_aio) aio_cleanup_exit(); /* * discard the lwpchan cache. */ if (p->p_lcp != NULL) lwpchan_destroy_cache(0); /* * Clean up any DTrace helper actions or probes for the process. */ if (p->p_dtrace_helpers != NULL) { ASSERT(dtrace_helpers_cleanup != NULL); (*dtrace_helpers_cleanup)(); } /* untimeout the realtime timers */ if (p->p_itimer != NULL) timer_exit(); if ((tmp_id = p->p_alarmid) != 0) { p->p_alarmid = 0; (void) untimeout(tmp_id); } /* * Remove any fpollinfo_t's for this (last) thread from our file * descriptors so closeall() can ASSERT() that they're all gone. */ pollcleanup(); if (p->p_rprof_cyclic != CYCLIC_NONE) { mutex_enter(&cpu_lock); cyclic_remove(p->p_rprof_cyclic); mutex_exit(&cpu_lock); } mutex_enter(&p->p_lock); /* * Clean up any DTrace probes associated with this process. */ if (p->p_dtrace_probes) { ASSERT(dtrace_fasttrap_exit_ptr != NULL); dtrace_fasttrap_exit_ptr(p); } while ((tmp_id = p->p_itimerid) != 0) { p->p_itimerid = 0; mutex_exit(&p->p_lock); (void) untimeout(tmp_id); mutex_enter(&p->p_lock); } lwp_cleanup(); /* * We are about to exit; prevent our resource associations from * being changed. */ pool_barrier_enter(); /* * Block the process against /proc now that we have really * acquired p->p_lock (to manipulate p_tlist at least). */ prbarrier(p); sigfillset(&p->p_ignore); sigemptyset(&p->p_siginfo); sigemptyset(&p->p_sig); sigemptyset(&p->p_extsig); sigemptyset(&t->t_sig); sigemptyset(&t->t_extsig); sigemptyset(&p->p_sigmask); sigdelq(p, t, 0); lwp->lwp_cursig = 0; lwp->lwp_extsig = 0; p->p_flag &= ~(SKILLED | SEXTKILLED); if (lwp->lwp_curinfo) { siginfofree(lwp->lwp_curinfo); lwp->lwp_curinfo = NULL; } t->t_proc_flag |= TP_LWPEXIT; ASSERT(p->p_lwpcnt == 1 && p->p_zombcnt == 0); prlwpexit(t); /* notify /proc */ lwp_hash_out(p, t->t_tid); prexit(p); p->p_lwpcnt = 0; p->p_tlist = NULL; sigqfree(p); term_mstate(t); p->p_mterm = gethrtime(); exec_vp = p->p_exec; execdir_vp = p->p_execdir; p->p_exec = NULLVP; p->p_execdir = NULLVP; mutex_exit(&p->p_lock); pr_free_watched_pages(p); closeall(P_FINFO(p)); /* Free the controlling tty. (freectty() always assumes curproc.) */ ASSERT(p == curproc); (void) freectty(B_TRUE); #if defined(__sparc) if (p->p_utraps != NULL) utrap_free(p); #endif if (p->p_semacct) /* IPC semaphore exit */ semexit(p); rv = wstat(why, what); acct(rv & 0xff); exacct_commit_proc(p, rv); /* * Release any resources associated with C2 auditing */ if (AU_AUDITING()) { /* * audit exit system call */ audit_exit(why, what); } /* * Free address space. */ relvm(); if (exec_vp) { /* * Close this executable which has been opened when the process * was created by getproc(). */ (void) VOP_CLOSE(exec_vp, FREAD, 1, (offset_t)0, CRED(), NULL); VN_RELE(exec_vp); } if (execdir_vp) VN_RELE(execdir_vp); /* * Release held contracts. */ contract_exit(p); /* * Depart our encapsulating process contract. */ if ((p->p_flag & SSYS) == 0) { ASSERT(p->p_ct_process); contract_process_exit(p->p_ct_process, p, rv); } /* * Remove pool association, and block if requested by pool_do_bind. */ mutex_enter(&p->p_lock); ASSERT(p->p_pool->pool_ref > 0); atomic_add_32(&p->p_pool->pool_ref, -1); p->p_pool = pool_default; /* * Now that our address space has been freed and all other threads * in this process have exited, set the PEXITED pool flag. This * tells the pools subsystems to ignore this process if it was * requested to rebind this process to a new pool. */ p->p_poolflag |= PEXITED; pool_barrier_exit(); mutex_exit(&p->p_lock); mutex_enter(&pidlock); /* * Delete this process from the newstate list of its parent. We * will put it in the right place in the sigcld in the end. */ delete_ns(p->p_parent, p); /* * Reassign the orphans to the next of kin. * Don't rearrange init's orphanage. */ if ((q = p->p_orphan) != NULL && p != proc_init) { proc_t *nokp = p->p_nextofkin; for (;;) { q->p_nextofkin = nokp; if (q->p_nextorph == NULL) break; q = q->p_nextorph; } q->p_nextorph = nokp->p_orphan; nokp->p_orphan = p->p_orphan; p->p_orphan = NULL; } /* * Reassign the children to init. * Don't try to assign init's children to init. */ if ((q = p->p_child) != NULL && p != proc_init) { struct proc *np; struct proc *initp = proc_init; boolean_t setzonetop = B_FALSE; if (!INGLOBALZONE(curproc)) setzonetop = B_TRUE; pgdetach(p); do { np = q->p_sibling; /* * Delete it from its current parent new state * list and add it to init new state list */ delete_ns(q->p_parent, q); q->p_ppid = 1; q->p_pidflag &= ~(CLDNOSIGCHLD | CLDWAITPID); if (setzonetop) { mutex_enter(&q->p_lock); q->p_flag |= SZONETOP; mutex_exit(&q->p_lock); } q->p_parent = initp; /* * Since q will be the first child, * it will not have a previous sibling. */ q->p_psibling = NULL; if (initp->p_child) { initp->p_child->p_psibling = q; } q->p_sibling = initp->p_child; initp->p_child = q; if (q->p_proc_flag & P_PR_PTRACE) { mutex_enter(&q->p_lock); sigtoproc(q, NULL, SIGKILL); mutex_exit(&q->p_lock); } /* * sigcld() will add the child to parents * newstate list. */ if (q->p_stat == SZOMB) sigcld(q, NULL); } while ((q = np) != NULL); p->p_child = NULL; ASSERT(p->p_child_ns == NULL); } TRACE_1(TR_FAC_PROC, TR_PROC_EXIT, "proc_exit: %p", p); mutex_enter(&p->p_lock); CL_EXIT(curthread); /* tell the scheduler that curthread is exiting */ /* * Have our task accummulate our resource usage data before they * become contaminated by p_cacct etc., and before we renounce * membership of the task. * * We do this regardless of whether or not task accounting is active. * This is to avoid having nonsense data reported for this task if * task accounting is subsequently enabled. The overhead is minimal; * by this point, this process has accounted for the usage of all its * LWPs. We nonetheless do the work here, and under the protection of * pidlock, so that the movement of the process's usage to the task * happens at the same time as the removal of the process from the * task, from the point of view of exacct_snapshot_task_usage(). */ exacct_update_task_mstate(p); hrutime = mstate_aggr_state(p, LMS_USER); hrstime = mstate_aggr_state(p, LMS_SYSTEM); p->p_utime = (clock_t)NSEC_TO_TICK(hrutime) + p->p_cutime; p->p_stime = (clock_t)NSEC_TO_TICK(hrstime) + p->p_cstime; p->p_acct[LMS_USER] += p->p_cacct[LMS_USER]; p->p_acct[LMS_SYSTEM] += p->p_cacct[LMS_SYSTEM]; p->p_acct[LMS_TRAP] += p->p_cacct[LMS_TRAP]; p->p_acct[LMS_TFAULT] += p->p_cacct[LMS_TFAULT]; p->p_acct[LMS_DFAULT] += p->p_cacct[LMS_DFAULT]; p->p_acct[LMS_KFAULT] += p->p_cacct[LMS_KFAULT]; p->p_acct[LMS_USER_LOCK] += p->p_cacct[LMS_USER_LOCK]; p->p_acct[LMS_SLEEP] += p->p_cacct[LMS_SLEEP]; p->p_acct[LMS_WAIT_CPU] += p->p_cacct[LMS_WAIT_CPU]; p->p_acct[LMS_STOPPED] += p->p_cacct[LMS_STOPPED]; p->p_ru.minflt += p->p_cru.minflt; p->p_ru.majflt += p->p_cru.majflt; p->p_ru.nswap += p->p_cru.nswap; p->p_ru.inblock += p->p_cru.inblock; p->p_ru.oublock += p->p_cru.oublock; p->p_ru.msgsnd += p->p_cru.msgsnd; p->p_ru.msgrcv += p->p_cru.msgrcv; p->p_ru.nsignals += p->p_cru.nsignals; p->p_ru.nvcsw += p->p_cru.nvcsw; p->p_ru.nivcsw += p->p_cru.nivcsw; p->p_ru.sysc += p->p_cru.sysc; p->p_ru.ioch += p->p_cru.ioch; p->p_stat = SZOMB; p->p_proc_flag &= ~P_PR_PTRACE; p->p_wdata = what; p->p_wcode = (char)why; cdir = PTOU(p)->u_cdir; rdir = PTOU(p)->u_rdir; cwd = PTOU(p)->u_cwd; ASSERT(cdir != NULL || p->p_parent == &p0); /* * Release resource controls, as they are no longer enforceable. */ rctl_set_free(p->p_rctls); /* * Decrement tk_nlwps counter for our task.max-lwps resource control. * An extended accounting record, if that facility is active, is * scheduled to be written. We cannot give up task and project * membership at this point because that would allow zombies to escape * from the max-processes resource controls. Zombies stay in their * current task and project until the process table slot is released * in freeproc(). */ tk = p->p_task; mutex_enter(&p->p_zone->zone_nlwps_lock); tk->tk_nlwps--; tk->tk_proj->kpj_nlwps--; p->p_zone->zone_nlwps--; mutex_exit(&p->p_zone->zone_nlwps_lock); /* * Clear the lwp directory and the lwpid hash table * now that /proc can't bother us any more. * We free the memory below, after dropping p->p_lock. */ lwpdir = p->p_lwpdir; lwpdir_sz = p->p_lwpdir_sz; tidhash = p->p_tidhash; tidhash_sz = p->p_tidhash_sz; ret_tidhash = p->p_ret_tidhash; p->p_lwpdir = NULL; p->p_lwpfree = NULL; p->p_lwpdir_sz = 0; p->p_tidhash = NULL; p->p_tidhash_sz = 0; p->p_ret_tidhash = NULL; /* * If the process has context ops installed, call the exit routine * on behalf of this last remaining thread. Normally exitpctx() is * called during thread_exit() or lwp_exit(), but because this is the * last thread in the process, we must call it here. By the time * thread_exit() is called (below), the association with the relevant * process has been lost. * * We also free the context here. */ if (p->p_pctx) { kpreempt_disable(); exitpctx(p); kpreempt_enable(); freepctx(p, 0); } /* * curthread's proc pointer is changed to point to the 'sched' * process for the corresponding zone, except in the case when * the exiting process is in fact a zsched instance, in which * case the proc pointer is set to p0. We do so, so that the * process still points at the right zone when we call the VN_RELE() * below. * * This is because curthread's original proc pointer can be freed as * soon as the child sends a SIGCLD to its parent. We use zsched so * that for user processes, even in the final moments of death, the * process is still associated with its zone. */ if (p != t->t_procp->p_zone->zone_zsched) t->t_procp = t->t_procp->p_zone->zone_zsched; else t->t_procp = &p0; mutex_exit(&p->p_lock); if (!evaporate) { p->p_pidflag &= ~CLDPEND; sigcld(p, sqp); } else { /* * Do what sigcld() would do if the disposition * of the SIGCHLD signal were set to be ignored. */ cv_broadcast(&p->p_srwchan_cv); freeproc(p); } mutex_exit(&pidlock); /* * We don't release u_cdir and u_rdir until SZOMB is set. * This protects us against dofusers(). */ if (cdir) VN_RELE(cdir); if (rdir) VN_RELE(rdir); if (cwd) refstr_rele(cwd); /* * task_rele() may ultimately cause the zone to go away (or * may cause the last user process in a zone to go away, which * signals zsched to go away). So prior to this call, we must * no longer point at zsched. */ t->t_procp = &p0; kmem_free(lwpdir, lwpdir_sz * sizeof (lwpdir_t)); kmem_free(tidhash, tidhash_sz * sizeof (tidhash_t)); while (ret_tidhash != NULL) { ret_tidhash_t *next = ret_tidhash->rth_next; kmem_free(ret_tidhash->rth_tidhash, ret_tidhash->rth_tidhash_sz * sizeof (tidhash_t)); kmem_free(ret_tidhash, sizeof (*ret_tidhash)); ret_tidhash = next; } thread_exit(); /* NOTREACHED */ }
int main(int argc, char *argv[]) { int c, i, fd; char *ptr; i = getdtablesize (); for (fd = 3; fd < i; fd++) close (fd); if (getpid () == 1) { for (fd = 0; fd < 3; fd++) close (fd); while (1) wait (NULL); /* Grim reaper never stops */ } sigsetmask (0); /* simpleinit(8) blocks all signals: undo for ALRM */ for (i = 1; i < NSIG; i++) signal (i, SIG_DFL); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #ifndef DEBUGGING if(setreuid (0, 0)) { fprintf(stderr, _("%s: Only root can shut a system down.\n"), argv[0]); exit(1); } #endif if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */ prog = argv[0]; if((ptr = strrchr(argv[0], '/'))) prog = ++ptr; /* All names (halt, reboot, fasthalt, fastboot, shutdown) refer to the same program with the same options, only the defaults differ. */ if(!strcmp("halt", prog)) { opt_reboot = 0; opt_quiet = 1; opt_fast = 0; timeout = 0; } else if(!strcmp("fasthalt", prog)) { opt_reboot = 0; opt_quiet = 1; opt_fast = 1; timeout = 0; } else if(!strcmp("reboot", prog)) { opt_reboot = 1; opt_quiet = 1; opt_fast = 0; timeout = 0; } else if(!strcmp("fastboot", prog)) { opt_reboot = 1; opt_quiet = 1; opt_fast = 1; timeout = 0; } else { /* defaults */ opt_reboot = 0; opt_quiet = 0; opt_fast = 0; timeout = 2*60; } c = 0; while(++c < argc) { if(argv[c][0] == '-') { for(i = 1; argv[c][i]; i++) { switch(argv[c][i]) { case 'C': opt_use_config_file = 1; break; case 'h': opt_reboot = 0; break; case 'r': opt_reboot = 1; break; case 'f': opt_fast = 1; break; case 'q': opt_quiet = 1; break; case 's': opt_single = 1; break; default: usage(); } } } else if(!strcmp("now", argv[c])) { timeout = 0; } else if(argv[c][0] == '+') { timeout = 60 * atoi(&argv[c][1]); } else if (isdigit(argv[c][0])) { char *colon; int hour = 0; int minute = 0; time_t tics; struct tm *tt; int now, then; if((colon = strchr(argv[c], ':'))) { *colon = '\0'; hour = atoi(argv[c]); minute = atoi(++colon); } else usage(); (void) time(&tics); tt = localtime(&tics); now = 3600 * tt->tm_hour + 60 * tt->tm_min; then = 3600 * hour + 60 * minute; timeout = then - now; if(timeout < 0) { fprintf(stderr, _("That must be tomorrow, " "can't you wait till then?\n")); exit(1); } } else { xstrncpy(message, argv[c], sizeof(message)); opt_msgset = 1; } } halt_action[0] = 0; /* No doubt we shall want to extend this some day and register a series of commands to be executed at various points during the shutdown sequence, and to define the number of milliseconds to sleep, etc. */ if (opt_use_config_file) { char line[256], *p; FILE *fp; /* Read and parse the config file */ halt_action[0] = '\0'; if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) { if (fgets (line, sizeof(line), fp) != NULL && strncasecmp (line, "HALT_ACTION", 11) == 0 && iswhitespace(line[11])) { p = index(line, '\n'); if (p) *p = 0; /* strip final '\n' */ p = line+11; while(iswhitespace(*p)) p++; strcpy(halt_action, p); } fclose (fp); } } if(!opt_quiet && !opt_msgset) { /* now ask for message, gets() is insecure */ int cnt = sizeof(message)-1; char *ptr; printf("Why? "); fflush(stdout); ptr = message; while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') { ptr++; } *ptr = '\0'; } else if (!opt_msgset) { strcpy(message, _("for maintenance; bounce, bounce")); } #ifdef DEBUGGING printf(_("timeout = %d, quiet = %d, reboot = %d\n"), timeout, opt_quiet, opt_reboot); #endif /* so much for option-processing, now begin termination... */ if(!(whom = getlogin()) || !*whom) whom = "ghost"; if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */ setpriority(PRIO_PROCESS, 0, PRIO_MIN); signal(SIGINT, int_handler); signal(SIGHUP, int_handler); signal(SIGQUIT, int_handler); signal(SIGTERM, int_handler); chdir("/"); if(timeout > 5*60) { sleep(timeout - 5*60); timeout = 5*60; } if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) { /* keep xgettext happy and leave \r\n outside strings */ WRCRLF; WR(_("The system is being shut down within 5 minutes")); WRCRLF; write(fd, message, strlen(message)); WRCRLF; WR(_("Login is therefore prohibited.")); WRCRLF; close(fd); } signal(SIGPIPE, SIG_IGN); if(timeout > 0) { wall(); sleep(timeout); } timeout = 0; wall(); sleep(3); /* now there's no turning back... */ signal(SIGINT, SIG_IGN); /* do syslog message... */ openlog(prog, LOG_CONS, LOG_AUTH); if (opt_reboot) syslog(LOG_NOTICE, _("rebooted by %s: %s"), whom, message); else syslog(LOG_NOTICE, _("halted by %s: %s"), whom, message); closelog(); if(opt_fast) if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0) close(fd); kill(1, SIGTSTP); /* tell init not to spawn more getty's */ write_wtmp(); if(opt_single) if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0) close(fd); sync(); signal(SIGTERM, SIG_IGN); if(fork() > 0) sleep(1000); /* the parent will die soon... */ setpgrp(); /* so the shell wont kill us in the fall */ #ifndef DEBUGGING /* a gentle kill of all other processes except init */ kill_mortals (SIGTERM); for (fd = 0; fd < 3; fd++) close (fd); stop_finalprog (); sleep (1); /* Time for saves to start */ kill (1, SIGTERM); /* Tell init to kill spawned gettys */ usleep (100000); /* Wait for gettys to die */ my_puts (""); /* Get past the login prompt */ system ("/sbin/initctl -r"); /* Roll back services */ syncwait (1); my_puts ("Sending SIGTERM to all remaining processes..."); kill (-1, SIGTERM); sleep (2); /* Default 2, some people need 5 */ kill (-1, SIGKILL); /* Now use brute force... */ /* turn off accounting */ acct(NULL); #endif /* RedHat and SuSE like to remove /etc/nologin. Perhaps the usual sequence is touch nologin; shutdown -h; fiddle with hardware; boot; fiddle with software; rm nologin and removing it here will be counterproductive. Let us see whether people complain. */ unlink(_PATH_NOLOGIN); /* Tell init(8) to exec so that the old inode may be freed cleanly if required. Need to sleep before remounting root read-only */ kill (1, SIGQUIT); sleep (1); /* Time for processes to die and close files */ syncwait (2); /* remove swap files and partitions using swapoff */ swap_off(); /* unmount disks... */ unmount_disks(); syncwait (1); if(opt_reboot) { my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ my_puts(_("\nWhy am I still alive after reboot?")); } else { my_puts(_("\nNow you can turn off the power...")); /* allow C-A-D now, [email protected], re-fixed 8-Jul-96 */ my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ sleep (1); /* Wait for devices to finish writing to media */ do_halt(halt_action); } /* NOTREACHED */ exit(0); /* to quiet gcc */ }
void *linux_bootchart_thread (void *ignored) { struct cfgnode *node; char *save_to = "/var/log/bootchart.tgz"; FILE *f; char try_acct = 1; signed int extra_wait = 0; if ((node = cfg_getnode ("configuration-bootchart-extra-waiting-time", NULL)) && node->value) { extra_wait = node->value; } char *buffer_ds = NULL; char *buffer_ps = NULL; char *buffer_st = NULL; while (!shutting_down && (linux_bootchart_have_thread || (extra_wait > 0))) { char *uptime = linux_bootchart_get_uptime(); if (linux_bootchart_process_accounting && try_acct) { if (acct ("/dev/kernel_pacct") == -1) try_acct = 1; } if (uptime) { buffer_ds = linux_bootchart_update_ds (buffer_ds, uptime); buffer_ps = linux_bootchart_update_ps (buffer_ps, uptime); buffer_st = linux_bootchart_update_st (buffer_st, uptime); free (uptime); uptime = NULL; } usleep (linux_bootchart_sleep_time); if (!linux_bootchart_have_thread) extra_wait -= linux_bootchart_sleep_time; } if ((node = cfg_getnode ("configuration-bootchart-save-to", NULL)) && node->svalue) { save_to = node->svalue; } if (coremode & einit_mode_sandbox) { save_to = "bootchart.tgz"; } mkdir ("/tmp/bootchart.einit", 0755); if (buffer_ds) { if ((f = fopen ("/tmp/bootchart.einit/proc_diskstats.log", "w"))) { fputs (buffer_ds, f); fclose (f); } free (buffer_ds); buffer_ds = NULL; } if (buffer_ps) { if ((f = fopen ("/tmp/bootchart.einit/proc_ps.log", "w"))) { fputs (buffer_ps, f); fclose (f); } free (buffer_ps); buffer_ps = NULL; } if (buffer_st) { if ((f = fopen ("/tmp/bootchart.einit/proc_stat.log", "w"))) { fputs (buffer_st, f); fclose (f); } free (buffer_st); buffer_st = NULL; } if (linux_bootchart_process_accounting) { char *r = readfile ("/dev/kernel_pacct"); if (r) { if ((f = fopen ("/tmp/bootchart.einit/kernel_pacct", "w"))) { fputs (r, f); fclose (f); } unlink ("/dev/kernel_pacct"); } acct(NULL); } if ((f = fopen ("/tmp/bootchart.einit/header", "w"))) { char *t, buffer[BUFFERSIZE]; time_t ti = time(NULL); /* we're emulating bootchartd-0.8/0.9's format... */ eputs ("version = 0.8\n", f); if (gethostname (buffer, BUFFERSIZE) == 0) { eprintf (f, "title = eINIT Boot Chart for %s, %s", buffer, ctime(&ti)); } else { eprintf (f, "title = eINIT Boot Chart, %s", ctime(&ti)); } fprintf (f, "system.uname = %s %s %s %s\n", osinfo.sysname, osinfo.release, osinfo.version, osinfo.machine); if ((t = readfile ("/etc/gentoo-release"))) { strtrim (t); eprintf (f, "system.release = %s\n", t); free (t); } else { eputs ("system.release = unknown\n", f); } if ((t = readfile ("/proc/cpuinfo"))) { char **r = str2set ('\n', t); char *n = NULL; int i; if (r) { for (i = 0; r[i]; i++) { if (strstr (r[i], "model name") == r[i]) { n = r[i]; break; } } if (n) eprintf (f, "system.cpu = %s\n", n); else eputs ("system.cpu = unknown\n", f); } free (t); } else { eputs ("system.cpu = unknown\n", f); } if ((t = readfile ("/proc/cmdline"))) { eprintf (f, "system.kernel.options = %s\n", t); free (t); } fclose (f); } char buffer[BUFFERSIZE]; if (coremode & einit_mode_sandbox) { esprintf (buffer, BUFFERSIZE, "export pwx=`pwd`; cd /tmp/bootchart.einit; tar czf \"${pwx}/%s\" *", save_to); } else { esprintf (buffer, BUFFERSIZE, "cd /tmp/bootchart.einit; tar czf %s *", save_to); } system (buffer); unlink_recursive ("/tmp/bootchart.einit/", 1); char *di = cfg_getstring ("configuration-bootchart-chart-directory", NULL); char *fo = cfg_getstring ("configuration-bootchart-chart-format", NULL); esprintf (buffer, BUFFERSIZE, "bootchart -o %s -f %s %s", di, fo, save_to); return NULL; }