X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/0c5c7f5c1841d6e3d1897e77ea9ee07943f401bf..1e00c92b81273392a7db4796dc163b0729891e44:/mac/mac.c diff --git a/mac/mac.c b/mac/mac.c index d8b9b2fa..25362061 100644 --- a/mac/mac.c +++ b/mac/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.51 2003/02/23 11:58:59 ben Exp $ */ +/* $Id$ */ /* * Copyright (c) 1999, 2003 Ben Harris * All rights reserved. @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include "macresid.h" #include "putty.h" #include "ssh.h" +#include "terminal.h" #include "mac.h" Session *sesslist; @@ -68,6 +70,8 @@ Session *sesslist; static int cold = 1; static int borednow = FALSE; struct mac_gestalts mac_gestalts; +UInt32 sleeptime; +static long timing_next_time; static void mac_startup(void); static void mac_eventloop(void); @@ -157,6 +161,9 @@ static void mac_startup(void) { if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr || &SetWindowContentColor == kUnresolvedCFragSymbolAddress) mac_gestalts.windattr = 0; + /* Mac OS 8.5 Menu Manager? */ + if (Gestalt(gestaltMenuMgrAttr, &mac_gestalts.menuattr) != noErr) + mac_gestalts.menuattr = 0; #endif /* Text Encoding Conversion Manager? */ if ( @@ -189,6 +196,11 @@ static void mac_startup(void) { fatalbox("Unable to create menu bar."); SetMenuBar(menuBar); AppendResMenu(GetMenuHandle(mApple), 'DRVR'); + if (mac_gestalts.menuattr & gestaltMenuMgrAquaLayoutMask) { + DeleteMenuItem(GetMenuHandle(mFile), iQuit); + /* Also delete the separator above the Quit item. */ + DeleteMenuItem(GetMenuHandle(mFile), iQuit - 1); + } mac_adjustmenus(); DrawMenuBar(); InitCursor(); @@ -198,13 +210,10 @@ static void mac_startup(void) { default_protocol = be_default_protocol; /* Find the appropriate default port. */ { - int i; + Backend *b = backend_from_proto(default_protocol); default_port = 0; /* illegal */ - for (i = 0; backends[i].backend != NULL; i++) - if (backends[i].protocol == default_protocol) { - default_port = backends[i].backend->default_port; - break; - } + if (b) + default_port = b->default_port; } flags = FLAG_INTERACTIVE; @@ -233,22 +242,48 @@ static void mac_startup(void) { NewAEEventHandlerUPP(&mac_aevt_quit), 0, FALSE); } +void timer_change_notify(long next) +{ + timing_next_time = next; +} + static void mac_eventloop(void) { Boolean gotevent; EventRecord event; RgnHandle cursrgn; + long next; + long ticksleft; cursrgn = NewRgn(); + sleeptime = 0; for (;;) { - mac_adjustcursor(cursrgn); - gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn); + ticksleft=timing_next_time-GETTICKCOUNT(); + if (sleeptime > ticksleft && ticksleft >=0) + sleeptime=ticksleft; + gotevent = WaitNextEvent(everyEvent, &event, sleeptime, cursrgn); + if (timing_next_time <= GETTICKCOUNT()) { + if (run_timers(timing_next_time, &next)) { + timer_change_notify(next); + } + } + + /* + * XXX For now, limit sleep time to 1/10 s to work around + * wake-before-sleep race in MacTCP code. + */ + sleeptime = 6; mac_adjustcursor(cursrgn); - if (gotevent) + if (gotevent) { + /* Ensure we get a null event when the real ones run out. */ + sleeptime = 0; mac_event(&event); - if (borednow) - cleanup_exit(0); - sk_poll(); - mac_pollterm(); + if (borednow) + cleanup_exit(0); + } + if (!gotevent) + sk_poll(); + if (mac_gestalts.apprvers >= 0x100 && mac_frontwindow() != NULL) + IdleControls(mac_frontwindow()); } DisposeRgn(cursrgn); } @@ -434,6 +469,9 @@ static void mac_menucommand(long result) { case iOpen: mac_opensession(); goto done; + case iChange: + mac_reconfig(); + goto done; case iClose: mac_closewindow(window); goto done; @@ -529,6 +567,7 @@ static void mac_adjustmenus(void) { if (window != NULL && mac_wininfo(window)->adjustmenus != NULL) (*mac_wininfo(window)->adjustmenus)(window); else { + DisableItem(menu, iChange); DisableItem(menu, iSave); DisableItem(menu, iSaveAs); DisableItem(menu, iDuplicate); @@ -617,9 +656,10 @@ void cleanup_exit(int status) } /* This should only kill the current session, not the whole application. */ -void connection_fatal(void *fontend, char *fmt, ...) { +void connection_fatal(void *frontend, char *fmt, ...) { va_list ap; Str255 stuff; + Session *s = frontend; va_start(ap, fmt); /* We'd like stuff to be a Pascal string */ @@ -627,7 +667,11 @@ void connection_fatal(void *fontend, char *fmt, ...) { va_end(ap); ParamText(stuff, NULL, NULL, NULL); StopAlert(128, NULL); - cleanup_exit(1); + + s->session_closed = TRUE; + + if (s->cfg.close_on_exit == FORCE_ON) + mac_closewindow(s->window); } /* Null SSH agent client -- never finds an agent. */ @@ -638,24 +682,81 @@ int agent_exists(void) return FALSE; } -void agent_query(void *in, int inlen, void **out, int *outlen) +int agent_query(void *in, int inlen, void **out, int *outlen, + void (*callback)(void *, void *, int), void *callback_ctx) { *out = NULL; *outlen = 0; + return 1; } /* Temporary null routines for testing. */ -void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, - char *keystr, char *fingerprint) +int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, + char *keystr, char *fingerprint, + void (*callback)(void *ctx, int result), void *ctx) { + Str255 pappname; + Str255 pfingerprint; + Str255 pkeytype; + Session *s = frontend; + int ret, alertret; + + c2pstrcpy(pappname, appname); + c2pstrcpy(pkeytype, keytype); + c2pstrcpy(pfingerprint, fingerprint); + + /* + * The alert shouldn't be modal, it should be movable modal, or + * a sheet in Aqua. Also, PuTTY might be in the background, in + * which case we should use the Notification Manager to wake up + * the user. In any case, we shouldn't hold up processing of + * other connections' data just because this one's waiting for + * the user. + */ + + /* Verify the key against the cache */ + ret = verify_host_key(host, port, keytype, keystr); + + if (ret == 0) { /* success - key matched OK */ + return 1; + } else if (ret == 2) { /* key was different */ + ParamText(pappname, pkeytype, pfingerprint, NULL); + alertret=CautionAlert(wWrong, NULL); + if (alertret == 8) { + /* Cancel */ + return 0; + } else if (alertret == 9) { + /* Connect Just Once */ + return 1; + } else { + /* Update Key */ + store_host_key(host, port, keytype, keystr); + return 1; + } + } else /* ret == 1 */ { /* key was absent */ + ParamText(pkeytype, pfingerprint, pappname, NULL); + alertret=CautionAlert(wAbsent, NULL); + if (alertret == 7) { + /* Cancel */ + return 0; + } else if (alertret == 8) { + /* Connect Just Once */ + return 1; + } else { + /* Update Key */ + store_host_key(host, port, keytype, keystr); + return 1; + } + } } -void askcipher(void *frontend, char *ciphername, int cs) +int askalg(void *frontend, const char *algtype, const char *algname, + void (*callback)(void *ctx, int result), void *ctx) { - + return 0; } void old_keyfile_warning(void) @@ -723,6 +824,52 @@ void platform_get_x11_auth(char *display, int *proto, /* SGT: I have no idea whether Mac X servers need anything here. */ } +void update_specials_menu(void *frontend) +{ + Session *s = frontend; + WindowPtr front; + + front = mac_frontwindow(); + if (front != NULL && mac_windowsession(front) == s) + mac_adjustmenus(); +} + +void notify_remote_exit(void *frontend) +{ + Session *s = frontend; + int exitcode; + + if (!s->session_closed && + (exitcode = s->back->exitcode(s->backhandle)) >=0) { + s->session_closed = TRUE; + if (s->cfg.close_on_exit == FORCE_ON || + (s->cfg.close_on_exit == AUTO && exitcode == 0)) { + mac_closewindow(s->window); + return; + } + + /* The session's dead */ + + if (s->ldisc) { + ldisc_free(s->ldisc); + s->ldisc = NULL; + } + + if (s->back) { + s->back->free(s->backhandle); + s->backhandle = NULL; + s->back = NULL; + update_specials_menu(s); + } + + { + char title[100]; + sprintf(title, "%.70s (inactive)", appname); + set_title(s, title); + } + } +} + /* * Local Variables: * c-file-style: "simon"