void shm_do_delete(shm_info_t *info) { int nframes,n; llist_unlink((llist_t *) info); nframes = info->info.shm_segsz / PHYSMM_PAGE_SIZE; for (n = 0; n < nframes; n++) physmm_free_frame(info->frames[n]); heapmm_free(info->frames, sizeof(physaddr_t) * nframes); heapmm_free(info, sizeof(shm_info_t)); }
LumieraConfigitem lumiera_config_lookup_remove (LumieraConfigLookup self, LumieraConfigitem item) { TRACE (configlookup_dbg, "%s", item->line); REQUIRE (!llist_is_empty (&item->lookup), "item is not in a lookup"); if (llist_is_single (&item->lookup)) { /* last item in lookup, remove it from the splay tree */ LumieraConfigLookupentry entry = LLIST_TO_STRUCTP (llist_next (&item->lookup), lumiera_config_lookupentry, configitems); llist_unlink (&item->lookup); psplay_delete_node (&self->tree, (PSplaynode)entry); } else { /* more than this item present in hash, just unlink this item */ llist_unlink (&item->lookup); } return item; }
void msg_do_delete(msg_info_t *info) { llist_t *_m; sysv_msg_t *m; llist_unlink((llist_t *) info); for (_m = llist_remove_last(&(info->msgs)); _m != NULL; _m = llist_remove_last(&(info->msgs))) { m = (sysv_msg_t *) _m; heapmm_free(m->mtext, m->msize); heapmm_free(m, sizeof(sysv_msg_t)); } semaphore_free(info->rwaitsem); semaphore_free(info->swaitsem); heapmm_free(info, sizeof(msg_info_t)); }
/** * Close the session associated with a particular socket. * Called from the HTTPD logic when a fatal error or EOF occurs. * * @param[in] session Session */ static void hio_socket_close(session_t *session) { SOCK_CLOSE(session->s); if (session->ioid != NULL_IOID) { RemoveInput(session->ioid); } if (session->toid != NULL_IOID) { RemoveTimeOut(session->toid); } #if defined(_WIN32) /*[*/ CloseHandle(session->event); #endif /*]*/ vb_free(&session->pending.result); llist_unlink(&session->link); Free(session); n_sessions--; }
/** * New inbound data for an httpd connection. * * @param[in] fd socket file descriptor * @param[in] id I/O ID */ void hio_socket_input(iosrc_t fd, ioid_t id) { session_t *session; char buf[1024]; ssize_t nr; session = NULL; FOREACH_LLIST(&sessions, session, session_t *) { if (session->ioid == id) { break; } } FOREACH_LLIST_END(&sessions, session, session_t *); if (session == NULL) { vtrace("httpd mystery input\n"); return; } /* Move this session to the front of the list. */ llist_unlink(&session->link); llist_insert_before(&session->link, sessions.next); session->idle = 0; if (session->toid != NULL_IOID) { RemoveTimeOut(session->toid); session->toid = NULL_IOID; } nr = recv(session->s, buf, sizeof(buf), 0); if (nr <= 0) { const char *ebuf; bool harmless = false; if (nr < 0) { if (socket_errno() == SE_EWOULDBLOCK) { harmless = true; } ebuf = lazyaf("recv error: %s", socket_errtext()); vtrace("httpd %s%s\n", ebuf, harmless? " (harmless)": ""); } else { ebuf = "session EOF"; } if (!harmless) { httpd_close(session->dhandle, ebuf); hio_socket_close(session); } } else { httpd_status_t rv; rv = httpd_input(session->dhandle, buf, nr); if (rv < 0) { httpd_close(session->dhandle, "protocol error"); hio_socket_close(session); } else if (rv == HS_PENDING) { /* Stop input on this socket. */ RemoveInput(session->ioid); session->ioid = NULL_IOID; } else if (session->toid == NULL_IOID) { /* Leave input enabled and start the timeout. */ session->toid = AddTimeOut(IDLE_MAX * 1000, hio_timeout); } } }
int chat_main(int argc UNUSED_PARAM, char **argv) { int record_fd = -1; bool echo = 0; // collection of device replies which cause unconditional termination llist_t *aborts = NULL; // inactivity period int timeout = DEFAULT_CHAT_TIMEOUT; // maximum length of abort string #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN size_t max_abort_len = 0; #else #define max_abort_len MAX_ABORT_LEN #endif #if ENABLE_FEATURE_CHAT_TTY_HIFI struct termios tio0, tio; #endif // directive names enum { DIR_HANGUP = 0, DIR_ABORT, #if ENABLE_FEATURE_CHAT_CLR_ABORT DIR_CLR_ABORT, #endif DIR_TIMEOUT, DIR_ECHO, DIR_SAY, DIR_RECORD, }; // make x* functions fail with correct exitcode xfunc_error_retval = ERR_IO; // trap vanilla signals to prevent process from being killed suddenly bb_signals(0 + (1 << SIGHUP) + (1 << SIGINT) + (1 << SIGTERM) + (1 << SIGPIPE) , signal_handler); #if ENABLE_FEATURE_CHAT_TTY_HIFI tcgetattr(STDIN_FILENO, &tio); tio0 = tio; cfmakeraw(&tio); tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); #endif #if ENABLE_FEATURE_CHAT_SWALLOW_OPTS getopt32(argv, "vVsSE"); argv += optind; #else argv++; // goto first arg #endif // handle chat expect-send pairs while (*argv) { // directive given? process it int key = index_in_strings( "HANGUP\0" "ABORT\0" #if ENABLE_FEATURE_CHAT_CLR_ABORT "CLR_ABORT\0" #endif "TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0" , *argv ); if (key >= 0) { // cache directive value char *arg = *++argv; // OFF -> 0, anything else -> 1 bool onoff = (0 != strcmp("OFF", arg)); // process directive if (DIR_HANGUP == key) { // turn SIGHUP on/off signal(SIGHUP, onoff ? signal_handler : SIG_IGN); } else if (DIR_ABORT == key) { // append the string to abort conditions #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN size_t len = strlen(arg); if (len > max_abort_len) max_abort_len = len; #endif llist_add_to_end(&aborts, arg); #if ENABLE_FEATURE_CHAT_CLR_ABORT } else if (DIR_CLR_ABORT == key) { // remove the string from abort conditions // N.B. gotta refresh maximum length too... #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN max_abort_len = 0; #endif for (llist_t *l = aborts; l; l = l->link) { #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN size_t len = strlen(l->data); #endif if (!strcmp(arg, l->data)) { llist_unlink(&aborts, l); continue; } #if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN if (len > max_abort_len) max_abort_len = len; #endif } #endif } else if (DIR_TIMEOUT == key) { // set new timeout // -1 means OFF timeout = atoi(arg) * 1000; // 0 means default // >0 means value in msecs if (!timeout) timeout = DEFAULT_CHAT_TIMEOUT; } else if (DIR_ECHO == key) { // turn echo on/off // N.B. echo means dumping device input/output to stderr echo = onoff; } else if (DIR_RECORD == key) { // turn record on/off // N.B. record means dumping device input to a file // close previous record_fd if (record_fd > 0) close(record_fd); // N.B. do we have to die here on open error? record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1; } else if (DIR_SAY == key) { // just print argument verbatim // TODO: should we use full_write() to avoid unistd/stdio conflict? bb_error_msg("%s", arg); } // next, please! argv++; // ordinary expect-send pair! } else { //----------------------- // do expect //----------------------- int expect_len; size_t buf_len = 0; size_t max_len = max_abort_len; struct pollfd pfd; #if ENABLE_FEATURE_CHAT_NOFAIL int nofail = 0; #endif char *expect = *argv++; // sanity check: shall we really expect something? if (!expect) goto expect_done; #if ENABLE_FEATURE_CHAT_NOFAIL // if expect starts with - if ('-' == *expect) { // swallow - expect++; // and enter nofail mode nofail++; } #endif #ifdef ___TEST___BUF___ // test behaviour with a small buffer # undef COMMON_BUFSIZE # define COMMON_BUFSIZE 6 #endif // expand escape sequences in expect expect_len = unescape(expect, &expect_len /*dummy*/); if (expect_len > max_len) max_len = expect_len; // sanity check: // we should expect more than nothing but not more than input buffer // TODO: later we'll get rid of fixed-size buffer if (!expect_len) goto expect_done; if (max_len >= COMMON_BUFSIZE) { exitcode = ERR_MEM; goto expect_done; } // get reply pfd.fd = STDIN_FILENO; pfd.events = POLLIN; while (!exitcode && poll(&pfd, 1, timeout) > 0 && (pfd.revents & POLLIN) ) { #define buf bb_common_bufsiz1 llist_t *l; ssize_t delta; // read next char from device if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) { // dump device input if RECORD fname if (record_fd > 0) { full_write(record_fd, buf+buf_len, 1); } // dump device input if ECHO ON if (echo > 0) { // if (buf[buf_len] < ' ') { // full_write(STDERR_FILENO, "^", 1); // buf[buf_len] += '@'; // } full_write(STDERR_FILENO, buf+buf_len, 1); } buf_len++; // move input frame if we've reached higher bound if (buf_len > COMMON_BUFSIZE) { memmove(buf, buf+buf_len-max_len, max_len); buf_len = max_len; } } // N.B. rule of thumb: values being looked for can // be found only at the end of input buffer // this allows to get rid of strstr() and memmem() // TODO: make expect and abort strings processed uniformly // abort condition is met? -> bail out for (l = aborts, exitcode = ERR_ABORT; l; l = l->link, ++exitcode) { size_t len = strlen(l->data); delta = buf_len-len; if (delta >= 0 && !memcmp(buf+delta, l->data, len)) goto expect_done; } exitcode = ERR_OK; // expected reply received? -> goto next command delta = buf_len - expect_len; if (delta >= 0 && !memcmp(buf+delta, expect, expect_len)) goto expect_done; #undef buf } /* while (have data) */ // device timed out or unexpected reply received exitcode = ERR_TIMEOUT; expect_done: #if ENABLE_FEATURE_CHAT_NOFAIL // on success and when in nofail mode // we should skip following subsend-subexpect pairs if (nofail) { if (!exitcode) { // find last send before non-dashed expect while (*argv && argv[1] && '-' == argv[1][0]) argv += 2; // skip the pair // N.B. do we really need this?! if (!*argv++ || !*argv++) break; } // nofail mode also clears all but IO errors (or signals) if (ERR_IO != exitcode) exitcode = ERR_OK; } #endif // bail out unless we expected successfully if (exitcode) break; //----------------------- // do send //----------------------- if (*argv) { #if ENABLE_FEATURE_CHAT_IMPLICIT_CR int nocr = 0; // inhibit terminating command with \r #endif char *loaded = NULL; // loaded command size_t len; char *buf = *argv++; // if command starts with @ // load "real" command from file named after @ if ('@' == *buf) { // skip the @ and any following white-space trim(++buf); buf = loaded = xmalloc_xopen_read_close(buf, NULL); } // expand escape sequences in command len = unescape(buf, &nocr); // send command alarm(timeout); pfd.fd = STDOUT_FILENO; pfd.events = POLLOUT; while (len && !exitcode && poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLOUT) ) { #if ENABLE_FEATURE_CHAT_SEND_ESCAPES // "\\d" means 1 sec delay, "\\p" means 0.01 sec delay // "\\K" means send BREAK char c = *buf; if ('\\' == c) { c = *++buf; if ('d' == c) { sleep(1); len--; continue; } if ('p' == c) { usleep(10000); len--; continue; } if ('K' == c) { tcsendbreak(STDOUT_FILENO, 0); len--; continue; } buf--; } if (safe_write(STDOUT_FILENO, buf, 1) != 1) break; len--; buf++; #else len -= full_write(STDOUT_FILENO, buf, len); #endif } /* while (can write) */ alarm(0); // report I/O error if there still exists at least one non-sent char if (len) exitcode = ERR_IO; // free loaded command (if any) if (loaded) free(loaded); #if ENABLE_FEATURE_CHAT_IMPLICIT_CR // or terminate command with \r (if not inhibited) else if (!nocr) xwrite(STDOUT_FILENO, "\r", 1); #endif // bail out unless we sent command successfully if (exitcode) break; } /* if (*argv) */ } } /* while (*argv) */ #if ENABLE_FEATURE_CHAT_TTY_HIFI tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0); #endif return exitcode; }
int last_main(int argc UNUSED_PARAM, char **argv) { struct utmpx ut; const char *filename = _PATH_WTMP; llist_t *zlist; off_t pos; time_t start_time; time_t boot_time; time_t down_time; int file; smallint going_down; smallint boot_down; /*opt =*/ getopt32(argv, "Wf:" /* "H" */, &filename); #ifdef BUT_UTIL_LINUX_LAST_HAS_NO_SUCH_OPT if (opt & LAST_OPT_H) { /* Print header line */ if (opt & LAST_OPT_W) { printf(HEADER_FORMAT, HEADER_LINE_WIDE); } else { printf(HEADER_FORMAT, HEADER_LINE); } } #endif file = xopen(filename, O_RDONLY); { /* in case the file is empty... */ struct stat st; fstat(file, &st); start_time = st.st_ctime; } time(&down_time); going_down = 0; boot_down = NORMAL; /* 0 */ zlist = NULL; boot_time = 0; /* get file size, rounding down to last full record */ pos = xlseek(file, 0, SEEK_END) / sizeof(ut) * sizeof(ut); for (;;) { pos -= (off_t)sizeof(ut); if (pos < 0) { /* Beyond the beginning of the file boundary => * the whole file has been read. */ break; } xlseek(file, pos, SEEK_SET); xread(file, &ut, sizeof(ut)); /* rewritten by each record, eventially will have * first record's ut_tv.tv_sec: */ start_time = ut.ut_tv.tv_sec; switch (get_ut_type(&ut)) { case SHUTDOWN_TIME: down_time = ut.ut_tv.tv_sec; boot_down = DOWN; going_down = 1; break; case RUN_LVL: if (is_runlevel_shutdown(&ut)) { down_time = ut.ut_tv.tv_sec; going_down = 1; boot_down = DOWN; } break; case BOOT_TIME: strcpy(ut.ut_line, "system boot"); show_entry(&ut, REBOOT, down_time); boot_down = CRASH; going_down = 1; break; case DEAD_PROCESS: if (!ut.ut_line[0]) { break; } /* add_entry */ llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); break; case USER_PROCESS: { int show; if (!ut.ut_line[0]) { break; } /* find_entry */ show = 1; { llist_t *el, *next; for (el = zlist; el; el = next) { struct utmpx *up = (struct utmpx *)el->data; next = el->link; if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) { if (show) { show_entry(&ut, NORMAL, up->ut_tv.tv_sec); show = 0; } llist_unlink(&zlist, el); free(el->data); free(el); } } } if (show) { int state = boot_down; if (boot_time == 0) { state = LOGGED; /* Check if the process is alive */ if ((ut.ut_pid > 0) && (kill(ut.ut_pid, 0) != 0) && (errno == ESRCH)) { state = GONE; } } show_entry(&ut, state, boot_time); } /* add_entry */ llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); break; } } if (going_down) { boot_time = ut.ut_tv.tv_sec; llist_free(zlist, free); zlist = NULL; going_down = 0; } } if (ENABLE_FEATURE_CLEAN_UP) { llist_free(zlist, free); } printf("\nwtmp begins %s", ctime(&start_time)); if (ENABLE_FEATURE_CLEAN_UP) close(file); fflush_stdout_and_exit(EXIT_SUCCESS); }
ssize_t _sys_msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg) { size_t readsz; msg_info_t *info; sysv_msg_t *msg; assert(msgp != NULL); msgsz += sizeof(long int); info = msg_get_by_id(msqid); if (!info) { syscall_errno = EINVAL; return -1; } if (!ipc_have_permissions(&(info->info.msg_perm), IPC_PERM_READ)) { syscall_errno = EACCES; return -1; } if (info->del) { syscall_errno = EIDRM; return -1; } msg = (sysv_msg_t *) llist_iterate_select(&(info->msgs), &msg_recv_iterator, (void *) msgtyp); if (!msg) { if (msgflg & IPC_NOWAIT) { syscall_errno = ENOMSG; return -1; } info->refs++; while (!msg) { if (semaphore_idown(info->rwaitsem)) { info->refs--; if (info->del && !info->refs) msg_do_delete(info); syscall_errno = EINTR; return -1; } if (info->del) { info->refs--; if (!info->refs) msg_do_delete(info); syscall_errno = EIDRM; return -1; } msg = (sysv_msg_t *) llist_iterate_select(&(info->msgs), &msg_recv_iterator, (void *) msgtyp); } } if (msg->msize > msgsz) { if (msgflg & MSG_NOERROR) readsz = msgsz; else { info->refs--; syscall_errno = E2BIG; return -1; } } else readsz = msg->msize; llist_unlink((llist_t *) msg); info->info.msg_qnum--; info->used_bytes -= msg->msize; info->refs--; memcpy(msgp, msg->mtext, readsz); heapmm_free(msg->mtext, msg->msize); heapmm_free(msg, sizeof(sysv_msg_t)); info->info.msg_lrpid = scheduler_current_task->pid; info->info.msg_rtime = (time_t) system_time; semaphore_up(info->swaitsem); return (ssize_t) (readsz - sizeof(long int)); }