void do_pending_atimers (void) { if (atimers) { block_atimers (); run_timers (); unblock_atimers (); } }
void do_pending_atimers (void) { if (pending_atimers) { BLOCK_ATIMERS; run_timers (); UNBLOCK_ATIMERS; } }
void do_pending_atimers (void) { if (atimers) { sigset_t oldset; block_atimers (&oldset); run_timers (); unblock_atimers (&oldset); } }
/* * Wait for some network data and process it. * * We have two variants of this function. One uses select() so that * it's compatible with WinSock 1. The other uses WSAEventSelect * and MsgWaitForMultipleObjects, so that we can consistently use * WSAEventSelect throughout; this enables us to also implement * ssh_sftp_get_cmdline() using a parallel mechanism. */ int ssh_sftp_loop_iteration(void) { if (p_WSAEventSelect == NULL) { fd_set readfds; int ret; unsigned long now = GETTICKCOUNT(), then; if (sftp_ssh_socket == INVALID_SOCKET) return -1; /* doom */ if (socket_writable(sftp_ssh_socket)) select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_WRITE); do { unsigned long next; long ticks; struct timeval tv, *ptv; if (run_timers(now, &next)) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; tv.tv_sec = ticks / 1000; tv.tv_usec = ticks % 1000 * 1000; ptv = &tv; } else { ptv = NULL; } FD_ZERO(&readfds); FD_SET(sftp_ssh_socket, &readfds); ret = p_select(1, &readfds, NULL, NULL, ptv); if (ret < 0) return -1; /* doom */ else if (ret == 0) now = next; else now = GETTICKCOUNT(); } while (ret == 0); select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ); return 0; } else { return do_eventsel_loop(INVALID_HANDLE_VALUE); } }
void alarm_signal_handler (int signo) { #ifndef SYNC_INPUT SIGNAL_THREAD_CHECK (signo); #endif pending_atimers = 1; #ifdef SYNC_INPUT pending_signals = 1; #else run_timers (); #endif }
static gint timer_trigger(gpointer data) { unsigned long now = GPOINTER_TO_LONG(data); unsigned long next, then; long ticks; /* * Destroy the timer we got here on. */ if (timer_id) { g_source_remove(timer_id); timer_id = 0; } /* * run_timers() may cause a call to timer_change_notify, in which * case a new timer will already have been set up and left in * timer_id. If it hasn't, and run_timers reports that some timing * still needs to be done, we do it ourselves. */ if (run_timers(now, &next) && !timer_id) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; timer_id = g_timeout_add(ticks, timer_trigger, LONG_TO_GPOINTER(next)); } /* * Returning FALSE means 'don't call this timer again', which * _should_ be redundant given that we removed it above, but just * in case, return FALSE anyway. */ return FALSE; }
void t_pgrid::run() { bool quit= false; setvbuf(stdout, 0, _IONBF, 0); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); SDL_WM_SetCaption("pgrid", "pgrid"); lastmillis= curmillis= SDL_GetTicks(); SDL_ShowCursor(0); SDL_EnableUNICODE(true); gui= new flux_gui(); bool guimouse= false; while(!quit) { lastframephystime= physicstime; lastmillis= curmillis; curmillis= SDL_GetTicks(); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: case SDL_KEYUP: { if(event.key.keysym.sym==SDLK_ESCAPE) quit= true; if(wnd_getkbdfocus()!=NOWND) { flux_keyboard_event(event.type==SDL_KEYDOWN, event.key.keysym.sym, event.key.keysym.unicode&0x7F); } else { current_workspace()->keyboard_event(event.key); editor->keyboard_event(event.key); for(t_dyninputhandler_list::iterator i= dyninputhandlers.begin(); i!=dyninputhandlers.end(); i++) (*i)->keyboard_event(event.key); } keystate[event.key.keysym.sym]= (event.key.state==SDL_PRESSED? 1: 0); break; } case SDL_MOUSEMOTION: flux_mouse_move_event(event.motion.xrel, event.motion.yrel); if( find_prim_pos(event.motion.x, event.motion.y, true) || find_mouse_handler(event.motion.x, event.motion.y) ) guimouse= true; else { guimouse= false; mouse.x= event.motion.x; mouse.y= event.motion.y; mouse.buttons= event.motion.state; current_workspace()->mouse_motion_event(event.motion); editor->mouse_motion_event(event.motion); for(t_dyninputhandler_list::iterator i= dyninputhandlers.begin(); i!=dyninputhandlers.end(); i++) (*i)->mouse_motion_event(event.motion); } break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: { int b= event.button.button; int fluxbutton= (b==SDL_BUTTON_RIGHT? 2: b==SDL_BUTTON_MIDDLE? 3: b)-1; flux_mouse_button_event(fluxbutton, event.type==SDL_MOUSEBUTTONDOWN); if( find_prim_pos(event.button.x, event.button.y, true) || find_mouse_handler(event.button.x, event.button.y) ) { guimouse= true; } else { guimouse= false; wnd_setkbdfocus(NOWND); if(event.type==SDL_MOUSEBUTTONUP) mouse.buttons&= ~(SDL_BUTTON(event.button.button)); else mouse.buttons|= SDL_BUTTON(event.button.button); mouse.x= event.button.x; mouse.y= event.button.y; current_workspace()->mouse_button_event(event.button); editor->mouse_button_event(event.button); for(t_dyninputhandler_list::iterator i= dyninputhandlers.begin(); i!=dyninputhandlers.end(); i++) (*i)->mouse_button_event(event.button); } break; } case SDL_QUIT: quit= true; break; case SDL_VIDEORESIZE: { SDL_Surface *surf= SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL|SDL_RESIZABLE); if(!surf) break; screen.sdl_surface= surf; screen.gl_init(event.resize.w, event.resize.h); current_workspace()->centerimage(); break; } case SDL_ACTIVEEVENT: { if(event.active.state&SDL_APPINPUTFOCUS) { hasinputfocus= event.active.gain; SDL_ShowCursor(!hasinputfocus); } if(event.active.state&SDL_APPMOUSEFOCUS) hasmousefocus= event.active.gain; break; } case SDL_VIDEOEXPOSE: { if(!hasinputfocus) { glClear(GL_DEPTH_BUFFER_BIT); current_workspace()->render(); SDL_GL_SwapBuffers(); checkglerror(); } break; } } } int x, y; SDL_GetMouseState(&x, &y); mousepos.x= x; mousepos.y= y; SDL_GetRelativeMouseState(&x, &y); mousevel.x= x; mousevel.y= y; mousevel.mul( 1000.0/(curmillis-lastmillis) ); current_workspace()->image->frame_tick((curmillis-lastmillis)*0.001); runphysics(); if(hasinputfocus) { glClear(GL_DEPTH_BUFFER_BIT); //~ screen.setperspective(); current_workspace()->render(); if(hasmousefocus && !guimouse) editor->render(); #if 1 next_event(); //~ aq_exec(); run_timers(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, screen.width,screen.height, 0, -1000, 1000); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //~ glEnable(GL_POINT_SMOOTH); //~ glPointSize(1.0); //~ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); //~ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glColor3f(1,1,1); glDisable(GL_TEXTURE_2D); redraw_rect(&viewport); //~ cliptext(0,0,0,0); update_rect(&viewport); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); #endif gui->tick( (curmillis-lastmillis)*0.001 ); if(guimouse) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glDisable(GL_DEPTH_TEST); redraw_cursor(); } SDL_GL_SwapBuffers(); checkglerror(); } int delay= 10 - (curmillis-lastmillis); if(!hasinputfocus) SDL_Delay(100); if(delay>0) SDL_Delay(delay); } SDL_WM_GrabInput(SDL_GRAB_OFF); delete gui; gui= 0; }
int do_eventsel_loop(HANDLE other_event) { int n, nhandles, nallhandles, netindex, otherindex; long next, ticks; HANDLE *handles; SOCKET *sklist; int skcount; long now = GETTICKCOUNT(); static int timeoutCount = 0; if (sk_isClosed()) { return -1; } if (run_timers(now, &next)) { ticks = next - GETTICKCOUNT(); if (ticks < 0) ticks = 0; /* just in case */ } else { ticks = INFINITE; } if (ticks < 0 || ticks > 100) ticks = 100; handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+2, HANDLE); nallhandles = nhandles; if (netevent != INVALID_HANDLE_VALUE) handles[netindex = nallhandles++] = netevent; else netindex = -1; if (other_event != INVALID_HANDLE_VALUE) handles[otherindex = nallhandles++] = other_event; else otherindex = -1; n = WaitForMultipleObjects(nallhandles, handles, FALSE, ticks); if (STATUS_TIMEOUT == n) { sfree(handles); ++timeoutCount; return timeoutCount > 50 ? -1 : 0; } timeoutCount = 0; if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (netindex >= 0 && n == WAIT_OBJECT_0 + netindex) { WSANETWORKEVENTS things; SOCKET socket; extern SOCKET first_socket(int *), next_socket(int *); extern int select_result(WPARAM, LPARAM); int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the * tree. This is because select_result() may close * the socket and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sklist = snewn(i, SOCKET); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(socket); noise_ultralight(things.lNetworkEvents); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } sfree(sklist); } sfree(handles); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } if (otherindex >= 0 && n == WAIT_OBJECT_0 + otherindex) return 1; return 0; }
int main(int argc, char **argv) { bool sending; SOCKET *sklist; size_t skcount, sksize; int exitcode; bool errors; bool use_subsystem = false; bool just_test_share_exists = false; enum TriState sanitise_stdout = AUTO, sanitise_stderr = AUTO; unsigned long now, next, then; const struct BackendVtable *vt; dll_hijacking_protection(); sklist = NULL; skcount = sksize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; flags = 0; cmdline_tooltype |= (TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG_CAN_BE_SESSION | TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX | TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD); /* * Process the command line. */ conf = conf_new(); do_defaults(NULL, conf); loaded_session = false; default_protocol = conf_get_int(conf, CONF_protocol); default_port = conf_get_int(conf, CONF_port); errors = false; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); if (p) { const struct BackendVtable *vt = backend_vt_from_name(p); if (vt) { default_protocol = vt->protocol; default_port = vt->default_port; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); } } } while (--argc) { char *p = *++argv; int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, conf); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = true; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = true; } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = true; } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); } else if (!strcmp(p, "--help")) { usage(); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (!strcmp(p, "-shareexists")) { just_test_share_exists = true; } else if (!strcmp(p, "-sanitise-stdout") || !strcmp(p, "-sanitize-stdout")) { sanitise_stdout = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stdout") || !strcmp(p, "-no-sanitize-stdout")) { sanitise_stdout = FORCE_OFF; } else if (!strcmp(p, "-sanitise-stderr") || !strcmp(p, "-sanitize-stderr")) { sanitise_stderr = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stderr") || !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (!strcmp(p, "-no-antispoof")) { console_antispoof_prompt = false; } else if (*p != '-') { strbuf *cmdbuf = strbuf_new(); while (argc > 0) { if (cmdbuf->len > 0) put_byte(cmdbuf, ' '); /* add space separator */ put_datapl(cmdbuf, ptrlen_from_asciz(p)); if (--argc > 0) p = *++argv; } conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = true; } } if (errors) return 1; if (!cmdline_host_ok(conf)) { usage(); } prepare_session(conf); /* * Perform command-line overrides on session configuration. */ cmdline_run_saved(conf); /* * Apply subsystem status. */ if (use_subsystem) conf_set_bool(conf, CONF_ssh_subsys, true); if (!*conf_get_str(conf, CONF_remote_cmd) && !*conf_get_str(conf, CONF_remote_cmd2) && !*conf_get_str(conf, CONF_ssh_nc_host)) flags |= FLAG_INTERACTIVE; /* * Select protocol. This is farmed out into a table in a * separate file to enable an ssh-free variant. */ vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol)); if (vt == NULL) { fprintf(stderr, "Internal fault: Unsupported protocol found\n"); return 1; } sk_init(); if (p_WSAEventSelect == NULL) { fprintf(stderr, "Plink requires WinSock 2\n"); return 1; } /* * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ if (conf_get_int(conf, CONF_protocol) == PROT_SSH && !conf_get_bool(conf, CONF_x11_forward) && !conf_get_bool(conf, CONF_agentfwd) && !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_bool(conf, CONF_ssh_simple, true); logctx = log_init(default_logpolicy, conf); if (just_test_share_exists) { if (!vt->test_for_upstream) { fprintf(stderr, "Connection sharing not supported for connection " "type '%s'\n", vt->name); return 1; } if (vt->test_for_upstream(conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), conf)) return 0; else return 1; } if (restricted_acl) { lp_eventlog(default_logpolicy, "Running with restricted process ACL"); } /* * Start up the connection. */ netevent = CreateEvent(NULL, false, false, NULL); { const char *error; char *realhost; /* nodelay is only useful if stdin is a character device (console) */ bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); error = backend_init(vt, plink_seat, &backend, logctx, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), &realhost, nodelay, conf_get_bool(conf, CONF_tcp_keepalives)); if (error) { fprintf(stderr, "Unable to open connection:\n%s", error); return 1; } sfree(realhost); } inhandle = GetStdHandle(STD_INPUT_HANDLE); outhandle = GetStdHandle(STD_OUTPUT_HANDLE); errhandle = GetStdHandle(STD_ERROR_HANDLE); /* * Turn off ECHO and LINE input modes. We don't care if this * call fails, because we know we aren't necessarily running in * a console. */ GetConsoleMode(inhandle, &orig_console_mode); SetConsoleMode(inhandle, ENABLE_PROCESSED_INPUT); /* * Pass the output handles to the handle-handling subsystem. * (The input one we leave until we're through the * authentication process.) */ stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0); stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0); handle_sink_init(&stdout_hs, stdout_handle); handle_sink_init(&stderr_hs, stderr_handle); stdout_bs = BinarySink_UPCAST(&stdout_hs); stderr_bs = BinarySink_UPCAST(&stderr_hs); /* * Decide whether to sanitise control sequences out of standard * output and standard error. * * If we weren't given a command-line override, we do this if (a) * the fd in question is pointing at a console, and (b) we aren't * trying to allocate a terminal as part of the session. * * (Rationale: the risk of control sequences is that they cause * confusion when sent to a local console, so if there isn't one, * no problem. Also, if we allocate a remote terminal, then we * sent a terminal type, i.e. we told it what kind of escape * sequences we _like_, i.e. we were expecting to receive some.) */ if (sanitise_stdout == FORCE_ON || (sanitise_stdout == AUTO && is_console_handle(outhandle) && conf_get_bool(conf, CONF_nopty))) { stdout_scc = stripctrl_new(stdout_bs, true, L'\0'); stdout_bs = BinarySink_UPCAST(stdout_scc); } if (sanitise_stderr == FORCE_ON || (sanitise_stderr == AUTO && is_console_handle(errhandle) && conf_get_bool(conf, CONF_nopty))) { stderr_scc = stripctrl_new(stderr_bs, true, L'\0'); stderr_bs = BinarySink_UPCAST(stderr_scc); } main_thread_id = GetCurrentThreadId(); sending = false; now = GETTICKCOUNT(); while (1) { int nhandles; HANDLE *handles; int n; DWORD ticks; if (!sending && backend_sendok(backend)) { stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL, 0); sending = true; } if (toplevel_callback_pending()) { ticks = 0; next = now; } else if (run_timers(now, &next)) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; } else { ticks = INFINITE; /* no need to initialise next here because we can never * get WAIT_TIMEOUT */ } handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+1, HANDLE); handles[nhandles] = netevent; n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks, QS_POSTMESSAGE); if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (n == WAIT_OBJECT_0 + nhandles) { WSANETWORKEVENTS things; SOCKET socket; int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the tree. * This is because select_result() may close the socket * and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sgrowarray(sklist, sksize, i); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(NOISE_SOURCE_IOID, socket); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } } else if (n == WAIT_OBJECT_0 + nhandles + 1) { MSG msg; while (PeekMessage(&msg, INVALID_HANDLE_VALUE, WM_AGENT_CALLBACK, WM_AGENT_CALLBACK, PM_REMOVE)) { struct agent_callback *c = (struct agent_callback *)msg.lParam; c->callback(c->callback_ctx, c->data, c->len); sfree(c); } } run_toplevel_callbacks(); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } sfree(handles); if (sending) handle_unthrottle(stdin_handle, backend_sendbuffer(backend)); if (!backend_connected(backend) && handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0) break; /* we closed the connection */ } exitcode = backend_exitcode(backend); if (exitcode < 0) { fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } cleanup_exit(exitcode); return 0; /* placate compiler warning */ }
void nh_timeout() { register struct prop *upp; int sleeptime; int m_idx; int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0; if (flags.friday13) baseluck -= 1; if (u.uluck != baseluck && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th */ register int time_luck = stone_luck(FALSE); boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE); if(u.uluck > baseluck && (nostone || time_luck < 0)) u.uluck--; else if(u.uluck < baseluck && (nostone || time_luck > 0)) u.uluck++; } if(u.uinvulnerable) return; /* things past this point could kill you */ if(Stoned) stoned_dialogue(); if(Slimed) slime_dialogue(); if(Vomiting) vomiting_dialogue(); if(Strangled) choke_dialogue(); if(u.mtimedone && !--u.mtimedone) { if (Unchanging) u.mtimedone = rnd(100*youmonst.data->mlevel + 1); else rehumanize(); } if(u.ucreamed) u.ucreamed--; /* Dissipate spell-based protection. */ if (u.usptime) { if (--u.usptime == 0 && u.uspellprot) { u.usptime = u.uspmtime; u.uspellprot--; find_ac(); if (!Blind) Norep("The %s haze around you %s.", hcolor(NH_GOLDEN), u.uspellprot ? "becomes less dense" : "disappears"); } } #ifdef STEED if (u.ugallop) { if (--u.ugallop == 0L && u.usteed) pline("%s stops galloping.", Monnam(u.usteed)); } #endif for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++) if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) { switch(upp - u.uprops){ case STONED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { /* leaving killer_format would make it "petrified by petrification" */ killer_format = NO_KILLER_PREFIX; killer = "killed by petrification"; } done(STONING); break; case SLIMED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { killer_format = NO_KILLER_PREFIX; killer = "turned into green slime"; } done(TURNED_SLIME); break; case VOMITING: make_vomiting(0L, TRUE); break; case SICK: You("die from your illness."); killer_format = KILLED_BY_AN; killer = u.usick_cause; if ((m_idx = name_to_mon(killer)) >= LOW_PM) { if (type_is_pname(&mons[m_idx])) { killer_format = KILLED_BY; } else if (mons[m_idx].geno & G_UNIQ) { killer = the(killer); Strcpy(u.usick_cause, killer); killer_format = KILLED_BY; } } u.usick_type = 0; done(POISONING); break; case FAST: if (!Very_fast) You_feel("yourself slowing down%s.", Fast ? " a bit" : ""); break; case CONFUSION: HConfusion = 1; /* So make_confused works properly */ make_confused(0L, TRUE); stop_occupation(); break; case STUNNED: HStun = 1; make_stunned(0L, TRUE); stop_occupation(); break; case BLINDED: Blinded = 1; make_blinded(0L, TRUE); stop_occupation(); break; case INVIS: newsym(u.ux,u.uy); if (!Invis && !BInvis && !Blind) { You(!See_invisible ? "are no longer invisible." : "can no longer see through yourself."); stop_occupation(); } break; case SEE_INVIS: set_mimic_blocking(); /* do special mimic handling */ see_monsters(); /* make invis mons appear */ newsym(u.ux,u.uy); /* make self appear */ stop_occupation(); break; case WOUNDED_LEGS: heal_legs(); stop_occupation(); break; case HALLUC: HHallucination = 1; (void) make_hallucinated(0L, TRUE, 0L); stop_occupation(); break; case SLEEPING: if (unconscious() || Sleep_resistance) HSleeping += rnd(100); else if (Sleeping) { You("fall asleep."); sleeptime = rnd(20); fall_asleep(-sleeptime, TRUE); HSleeping += sleeptime + rnd(100); } break; case LEVITATION: (void) float_down(I_SPECIAL|TIMEOUT, 0L); break; case STRANGLED: killer_format = KILLED_BY; killer = (u.uburied) ? "suffocation" : "strangulation"; done(DIED); break; case FUMBLING: /* call this only when a move took place. */ /* otherwise handle fumbling msgs locally. */ if (u.umoved && !Levitation) { slip_or_trip(); nomul(-2, "fumbling"); nomovemsg = ""; /* The more you are carrying the more likely you * are to make noise when you fumble. Adjustments * to this number must be thoroughly play tested. */ if ((inv_weight() > -500)) { You("make a lot of noise!"); wake_nearby(); } } /* from outside means slippery ice; don't reset counter if that's the only fumble reason */ HFumbling &= ~FROMOUTSIDE; if (Fumbling) HFumbling += rnd(20); break; case DETECT_MONSTERS: see_monsters(); break; case PREGNANT: { char buf[BUFSZ]; if (!flags.female) { strcpy(buf, body_part(STOMACH)); if (!strcmp(buf, "stomach")) strcpy(buf, "belly"); pline("Something bursts out of your %s!"); killer_format = KILLED_BY; killer = "male childbirth"; done(DIED); } mksobj_at(PLACENTA, u.ux, u.uy, FALSE, FALSE); pline("BABIES!"); /* TODO */ stop_occupation(); break; } } } run_timers(); }
/* Monitor thread main loop. Monitor reads events from the realtime MTP thread, and processes them at non-realtime priority. It also handles timers for ISUP etc. */ static void *monitor_main(void *data) { int res = 0, nres; struct pollfd fds[(MAX_LINKS+1)]; int i, n_fds = 0; int rebuild_fds = 1; struct lffifo *receive_fifo = mtp_get_receive_fifo(); time_t lastcheck = 0, now; ast_verbose(VERBOSE_PREFIX_3 "Starting monitor thread, pid=%d.\n", getpid()); fds[0].fd = get_receive_pipe(); fds[0].events = POLLIN; while(monitor_running) { time(&now); if (lastcheck + 10 < now) { rebuild_fds = 1; lastcheck = now; } if (rebuild_fds) { if (rebuild_fds > 1) poll(fds, 0, 200); /* sleep */ rebuild_fds = 0; n_fds = 1; for (i = 0; i < n_linksets; i++) { struct linkset* linkset = &linksets[i]; int j; for (j = 0; j < linkset->n_links; j++) { int k, l, f = 0; struct link* link = linkset->links[j]; for (k = 0; (k < this_host->n_spans) && !f; k++) { for (l = 0; l < (this_host->spans[k].n_links) && !f; l++) { if ((this_host->spans[k].links[l] == link) || (this_host->spans[k].links[l]->linkset == link->linkset) || (is_combined_linkset(this_host->spans[k].links[l]->linkset, link->linkset))) { if (link->remote) { if (link->mtp3fd == -1) { link->mtp3fd = mtp3_connect_socket(link->mtp3server_host, *link->mtp3server_port ? link->mtp3server_port : "11999"); if (link->mtp3fd != -1) res = mtp3_register_isup(link->mtp3fd, link->linkix); else poll(NULL, 0, 5000); if ((link->mtp3fd == -1) || (res == -1)) rebuild_fds += 2; } fds[n_fds].fd = link->mtp3fd; fds[n_fds++].events = POLLIN|POLLERR|POLLNVAL|POLLHUP; f = 1; } } } } } } } int timeout = timers_wait(); nres = poll(fds, n_fds, timeout); if(nres < 0) { if(errno == EINTR) { /* Just try again. */ } else { ast_log(LOG_ERROR, "poll() failure, errno=%d: %s\n", errno, strerror(errno)); } } else if(nres > 0) { for (i = 0; (i < n_fds) && (nres > 0); i++) { unsigned char eventbuf[MTP_EVENT_MAX_SIZE]; struct mtp_event *event = (struct mtp_event*) eventbuf; struct link* link = NULL; if(fds[i].revents) { int j; for (j = 0; j < n_links; j++) { if (links[j].remote && (links[j].mtp3fd == fds[i].fd)) { link = &links[j]; break; } } } else continue; if(fds[i].revents & (POLLERR|POLLNVAL|POLLHUP)) { if (i == 0) { /* receivepipe */ ast_log(LOG_ERROR, "poll() return bad revents for receivepipe, 0x%04x\n", fds[i].revents); } close(fds[i].fd); if (link) link->mtp3fd = -1; rebuild_fds++; rebuild_fds++; /* when > 1, use short sleep */ nres--; continue; } if(!(fds[i].revents & POLLIN)) continue; if (i == 0) { /* Events waiting in the receive buffer. */ unsigned char dummy[512]; /* Empty the pipe before pulling from fifo. This way the race condition between mtp and monitor threads may cause spurious wakeups, but not loss/delay of messages. */ res = read(fds[i].fd, dummy, sizeof(dummy)); /* Process all available events. */ while((res = lffifo_get(receive_fifo, eventbuf, sizeof(eventbuf))) != 0) { if(res < 0) { ast_log(LOG_ERROR, "Yuck! oversized frame in receive fifo, bailing out.\n"); return NULL; } process_event(event); } } else { if (mtp3_ipproto == IPPROTO_TCP) { res = read(fds[i].fd, eventbuf, sizeof(struct mtp_event)); if ((res > 0) && (event->len > 0)) { int p = res; int len = event->len; if (sizeof(struct mtp_event) + event->len > MTP_EVENT_MAX_SIZE) { ast_log(LOG_NOTICE, "Got too large packet: len %zu, max %zu, closing connection", sizeof(struct mtp_event) + event->len, MTP_EVENT_MAX_SIZE); len = 0; res = 0; shutdown(fds[i].fd, SHUT_RD); } do { res = read(fds[i].fd, &eventbuf[p], len); if (res > 0) { p += res; len -= res; } else if ((res < 0) && (errno != EINTR)) { len = 0; } else { len = 0; } } while (len > 0); } } else res = read(fds[i].fd, eventbuf, sizeof(eventbuf)+MTP_MAX_PCK_SIZE); if (res > 0) { if (event->typ == MTP_EVENT_ISUP) { event->isup.link = NULL; event->isup.slink = &links[event->isup.slinkix]; } process_event(event); } else if (res == 0) { int j; for (j = 0; j < n_links; j++) { struct link* link = &links[j]; if (link->remote && (link->mtp3fd == fds[i].fd)) { close(fds[i].fd); link->mtp3fd = -1; rebuild_fds++; } } } } nres--; } } /* We need to lock the global glock mutex around ast_sched_runq() so that we avoid a race with ss7_hangup. With the lock, invalidating the channel in ss7_hangup() and removing associated monitor_sched entries is an atomic operation, so that we avoid calling timer handlers with references to invalidated channels. */ run_timers(); } for (i = 0; i < n_links; i++) { struct link* link = &links[i]; if (link->remote && (link->mtp3fd != -1)) close(link->mtp3fd); } return NULL; }
int main(int argc, char **argv) { bool sending; int *fdlist; int fd; int i, fdstate; size_t fdsize; int exitcode; bool errors; enum TriState sanitise_stdout = AUTO, sanitise_stderr = AUTO; bool use_subsystem = false; bool just_test_share_exists = false; unsigned long now; struct winsize size; const struct BackendVtable *backvt; fdlist = NULL; fdsize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; bufchain_init(&stdout_data); bufchain_init(&stderr_data); bufchain_sink_init(&stdout_bcs, &stdout_data); bufchain_sink_init(&stderr_bcs, &stderr_data); stdout_bs = BinarySink_UPCAST(&stdout_bcs); stderr_bs = BinarySink_UPCAST(&stderr_bcs); outgoingeof = EOF_NO; flags = FLAG_STDERR_TTY; cmdline_tooltype |= (TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG_CAN_BE_SESSION | TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX | TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD); stderr_tty_init(); /* * Process the command line. */ conf = conf_new(); do_defaults(NULL, conf); loaded_session = false; default_protocol = conf_get_int(conf, CONF_protocol); default_port = conf_get_int(conf, CONF_port); errors = false; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); if (p) { const struct BackendVtable *vt = backend_vt_from_name(p); if (vt) { default_protocol = vt->protocol; default_port = vt->default_port; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); } } } while (--argc) { char *p = *++argv; int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, conf); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = true; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = true; } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = true; } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); } else if (!strcmp(p, "--help")) { usage(); exit(0); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (!strcmp(p, "-o")) { if (argc <= 1) { fprintf(stderr, "plink: option \"-o\" requires an argument\n"); errors = true; } else { --argc; /* Explicitly pass "plink" in place of appname for * error reporting purposes. appname will have been * set by be_foo.c to something more generic, probably * "PuTTY". */ provide_xrm_string(*++argv, "plink"); } } else if (!strcmp(p, "-shareexists")) { just_test_share_exists = true; } else if (!strcmp(p, "-fuzznet")) { conf_set_int(conf, CONF_proxy_type, PROXY_FUZZ); conf_set_str(conf, CONF_proxy_telnet_command, "%host"); } else if (!strcmp(p, "-sanitise-stdout") || !strcmp(p, "-sanitize-stdout")) { sanitise_stdout = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stdout") || !strcmp(p, "-no-sanitize-stdout")) { sanitise_stdout = FORCE_OFF; } else if (!strcmp(p, "-sanitise-stderr") || !strcmp(p, "-sanitize-stderr")) { sanitise_stderr = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stderr") || !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (!strcmp(p, "-no-antispoof")) { console_antispoof_prompt = false; } else if (*p != '-') { strbuf *cmdbuf = strbuf_new(); while (argc > 0) { if (cmdbuf->len > 0) put_byte(cmdbuf, ' '); /* add space separator */ put_datapl(cmdbuf, ptrlen_from_asciz(p)); if (--argc > 0) p = *++argv; } conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = true; } } if (errors) return 1; if (!cmdline_host_ok(conf)) { usage(); } prepare_session(conf); /* * Perform command-line overrides on session configuration. */ cmdline_run_saved(conf); /* * If we have no better ideas for the remote username, use the local * one, as 'ssh' does. */ if (conf_get_str(conf, CONF_username)[0] == '\0') { char *user = get_username(); if (user) { conf_set_str(conf, CONF_username, user); sfree(user); } } /* * Apply subsystem status. */ if (use_subsystem) conf_set_bool(conf, CONF_ssh_subsys, true); if (!*conf_get_str(conf, CONF_remote_cmd) && !*conf_get_str(conf, CONF_remote_cmd2) && !*conf_get_str(conf, CONF_ssh_nc_host)) flags |= FLAG_INTERACTIVE; /* * Select protocol. This is farmed out into a table in a * separate file to enable an ssh-free variant. */ backvt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol)); if (!backvt) { fprintf(stderr, "Internal fault: Unsupported protocol found\n"); return 1; } /* * Block SIGPIPE, so that we'll get EPIPE individually on * particular network connections that go wrong. */ putty_signal(SIGPIPE, SIG_IGN); /* * Set up the pipe we'll use to tell us about SIGWINCH. */ if (pipe(signalpipe) < 0) { perror("pipe"); exit(1); } /* We don't want the signal handler to block if the pipe's full. */ nonblock(signalpipe[0]); nonblock(signalpipe[1]); cloexec(signalpipe[0]); cloexec(signalpipe[1]); putty_signal(SIGWINCH, sigwinch); /* * Now that we've got the SIGWINCH handler installed, try to find * out the initial terminal size. */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &size) >= 0) { conf_set_int(conf, CONF_width, size.ws_col); conf_set_int(conf, CONF_height, size.ws_row); } /* * Decide whether to sanitise control sequences out of standard * output and standard error. * * If we weren't given a command-line override, we do this if (a) * the fd in question is pointing at a terminal, and (b) we aren't * trying to allocate a terminal as part of the session. * * (Rationale: the risk of control sequences is that they cause * confusion when sent to a local terminal, so if there isn't one, * no problem. Also, if we allocate a remote terminal, then we * sent a terminal type, i.e. we told it what kind of escape * sequences we _like_, i.e. we were expecting to receive some.) */ if (sanitise_stdout == FORCE_ON || (sanitise_stdout == AUTO && isatty(STDOUT_FILENO) && conf_get_bool(conf, CONF_nopty))) { stdout_scc = stripctrl_new(stdout_bs, true, L'\0'); stdout_bs = BinarySink_UPCAST(stdout_scc); } if (sanitise_stderr == FORCE_ON || (sanitise_stderr == AUTO && isatty(STDERR_FILENO) && conf_get_bool(conf, CONF_nopty))) { stderr_scc = stripctrl_new(stderr_bs, true, L'\0'); stderr_bs = BinarySink_UPCAST(stderr_scc); } sk_init(); uxsel_init(); /* * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ if (conf_get_int(conf, CONF_protocol) == PROT_SSH && !conf_get_bool(conf, CONF_x11_forward) && !conf_get_bool(conf, CONF_agentfwd) && !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_bool(conf, CONF_ssh_simple, true); if (just_test_share_exists) { if (!backvt->test_for_upstream) { fprintf(stderr, "Connection sharing not supported for connection " "type '%s'\n", backvt->name); return 1; } if (backvt->test_for_upstream(conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), conf)) return 0; else return 1; } /* * Start up the connection. */ logctx = log_init(default_logpolicy, conf); { const char *error; char *realhost; /* nodelay is only useful if stdin is a terminal device */ bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && isatty(0); /* This is a good place for a fuzzer to fork us. */ #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif error = backend_init(backvt, plink_seat, &backend, logctx, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), &realhost, nodelay, conf_get_bool(conf, CONF_tcp_keepalives)); if (error) { fprintf(stderr, "Unable to open connection:\n%s\n", error); return 1; } ldisc_create(conf, NULL, backend, plink_seat); sfree(realhost); } /* * Set up the initial console mode. We don't care if this call * fails, because we know we aren't necessarily running in a * console. */ local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0); atexit(cleanup_termios); seat_echoedit_update(plink_seat, 1, 1); sending = false; now = GETTICKCOUNT(); pollwrapper *pw = pollwrap_new(); while (1) { int rwx; int ret; unsigned long next; pollwrap_clear(pw); pollwrap_add_fd_rwx(pw, signalpipe[0], SELECT_R); if (!sending && backend_connected(backend) && backend_sendok(backend) && backend_sendbuffer(backend) < MAX_STDIN_BACKLOG) { /* If we're OK to send, then try to read from stdin. */ pollwrap_add_fd_rwx(pw, STDIN_FILENO, SELECT_R); } if (bufchain_size(&stdout_data) > 0) { /* If we have data for stdout, try to write to stdout. */ pollwrap_add_fd_rwx(pw, STDOUT_FILENO, SELECT_W); } if (bufchain_size(&stderr_data) > 0) { /* If we have data for stderr, try to write to stderr. */ pollwrap_add_fd_rwx(pw, STDERR_FILENO, SELECT_W); } /* Count the currently active fds. */ i = 0; for (fd = first_fd(&fdstate, &rwx); fd >= 0; fd = next_fd(&fdstate, &rwx)) i++; /* Expand the fdlist buffer if necessary. */ sgrowarray(fdlist, fdsize, i); /* * Add all currently open fds to pw, and store them in fdlist * as well. */ int fdcount = 0; for (fd = first_fd(&fdstate, &rwx); fd >= 0; fd = next_fd(&fdstate, &rwx)) { fdlist[fdcount++] = fd; pollwrap_add_fd_rwx(pw, fd, rwx); } if (toplevel_callback_pending()) { ret = pollwrap_poll_instant(pw); } else if (run_timers(now, &next)) { do { unsigned long then; long ticks; then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; bool overflow = false; if (ticks > INT_MAX) { ticks = INT_MAX; overflow = true; } ret = pollwrap_poll_timeout(pw, ticks); if (ret == 0 && !overflow) now = next; else now = GETTICKCOUNT(); } while (ret < 0 && errno == EINTR); } else { ret = pollwrap_poll_endless(pw); } if (ret < 0 && errno == EINTR) continue; if (ret < 0) { perror("poll"); exit(1); } for (i = 0; i < fdcount; i++) { fd = fdlist[i]; int rwx = pollwrap_get_fd_rwx(pw, fd); /* * We must process exceptional notifications before * ordinary readability ones, or we may go straight * past the urgent marker. */ if (rwx & SELECT_X) select_result(fd, SELECT_X); if (rwx & SELECT_R) select_result(fd, SELECT_R); if (rwx & SELECT_W) select_result(fd, SELECT_W); } if (pollwrap_check_fd_rwx(pw, signalpipe[0], SELECT_R)) { char c[1]; struct winsize size; if (read(signalpipe[0], c, 1) <= 0) /* ignore error */; /* ignore its value; it'll be `x' */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0) backend_size(backend, size.ws_col, size.ws_row); } if (pollwrap_check_fd_rwx(pw, STDIN_FILENO, SELECT_R)) { char buf[4096]; int ret; if (backend_connected(backend)) { ret = read(STDIN_FILENO, buf, sizeof(buf)); noise_ultralight(NOISE_SOURCE_IOLEN, ret); if (ret < 0) { perror("stdin: read"); exit(1); } else if (ret == 0) { backend_special(backend, SS_EOF, 0); sending = false; /* send nothing further after this */ } else { if (local_tty) from_tty(buf, ret); else backend_send(backend, buf, ret); } } } if (pollwrap_check_fd_rwx(pw, STDOUT_FILENO, SELECT_W)) { backend_unthrottle(backend, try_output(false)); } if (pollwrap_check_fd_rwx(pw, STDERR_FILENO, SELECT_W)) { backend_unthrottle(backend, try_output(true)); } run_toplevel_callbacks(); if (!backend_connected(backend) && bufchain_size(&stdout_data) == 0 && bufchain_size(&stderr_data) == 0) break; /* we closed the connection */ } exitcode = backend_exitcode(backend); if (exitcode < 0) { fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } cleanup_exit(exitcode); return exitcode; /* shouldn't happen, but placates gcc */ }