1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Retire the old Mac Classic port directory! It's been unused for

ages, is increasingly irrelevant now that 'Mac' pretty much
universally means something running OS X, is probably bit-rotted
past usefulness already, and certainly will be after the next time
some major reengineering takes place.

[originally from svn r9004]
This commit is contained in:
Simon Tatham 2010-09-25 07:30:08 +00:00
parent 406e62f77b
commit 7ac1f17aab
27 changed files with 0 additions and 12709 deletions

View File

@ -1,104 +0,0 @@
$Id$
Information about PuTTY for the Mac OS
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
This is a port of PuTTY to the Classic Mac OS. It is a work in
progress and should be considered unfinished and insecure. It is
not considered to be of release quality, even if you found it (and
you're reading this) in a PuTTY release source archive. Unless you
know what you're doing, don't use it.
Compiling it:
See ../README for generic information.
To compile PuTTY for Mac OS you will need:
MPW
<ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./
MPW-GM_Images/MPW-GM.img.bin>
Install this in the usual way.
Universal Headers
<ftp://ftp.apple.com/developer/Development_Kits/
UniversalHeaders3.4.2.img.bin>
Install using the script in "Documentation:MPW Users - ReadMe".
Text Encoding Converter SDK
<ftp://ftp.apple.com/developer/Development_Kits/TEC_1.5.sit.hqx>
Copy contents of "68K Static Libraries" to
"Interfaces&Libraries:Libraries:Libraries".
Copy contents of "Stub Libraries" to
"Interfaces&Libraries:Libraries:SharedLibraries".
CarbonStdCLib.o
<ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/
MPW_Website_Downloads/CarbonStdCLib.o-3.8d3.hqx>
Copy contents of "CIncludes" to
"Interfaces&Libraries:Interfaces:CIncludes".
Copy contents of "PPCLibraries" to
"Interfaces&Libraries:Libraries:PPCLibraries".
The "mkputty.mpw" script does all the work, and currently producess a
Classic 68K build of PuTTY called "PuTTY.68k", a non-Carbon PowerPC
build called "PuTTY.ppc", and similar builds of PuTTYtel called
"PuTTYtel.68k" and "PuTTYtel.ppc". The CFM-68K build is currently
disabled because it overflows the global data space and I can't work
out how to stop this happening. The Carbon build doesn't work yet.
Runtime requirements:
The Classic 68K build of PuTTY should work on any Macintosh running
System 7.0 or later. It runs in the Classic environment in Mac OS X.
The CFM-68K build of PuTTY should work on any Macintosh with a 68020,
68030 or 68040 processor and with either the CFM-68K Runtime Enabler
or Mac OS 7.6.1 or later installed.
The PowerPC build of PuTTY should work on any Power Macintosh. It
runs in the Classic environment in Mac OS X.
The Carbon build of PuTTY (when it works) should work on any Power
Macintosh with CarbonLib (and Mac OS 8.1 or later), Mac OS 9 or
Mac OS X installed.
Known bugs:
* Display is far too slow.
* Real bold doesn't compensate for changing character widths without Color
QuickDraw. [MAYBE FIXED]
* When the last terminal window closes, the Edit menu doesn't get disabled
immediately, which it should.
* When using the "VT100" font, text copied to the clipboard doesn't
get newlines in it, because that font has a graphic character at
position 0x0d. Even if we did insert 0x0d manually, TextEdit
insists on displaying the graphic version, so I think we need a
font switch at this point. This can be seen as a special case of
the need to switch fonts to get odd characters.
* Pasting large blocks of text doesn't work.
* The host key database is currently limited by its implementation to
2727 host keys.
Unimplemented features (should be done before release):
* TCP urgent data.
* Listening sockets.
* Changing font size in reponse to resize requests.
* Full screen mode.
* Session configuration.
* Entropy collection.
* Private key files.
* Pageant and PuTTYgen.
* Do something with Open Application Apple Events.
* Close-on-exit.
* Warn-on-quit.
* Non-block cursors.
Wishlist (after release):
* SFTP client (GUI?)
* Carbon compatibility (requires Open Transport and Navigation Services).
* 'styl' paste, for script codes.
* Handle 'gurl' Apple Events.
Local Variables:
mode: text
End:

877
mac/mac.c
View File

@ -1,877 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 1999, 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* mac.c -- miscellaneous Mac-specific routines
*/
#include <MacTypes.h>
#include <AEDataModel.h>
#include <AppleEvents.h>
#include <Controls.h>
#include <Quickdraw.h>
#include <Fonts.h>
#include <MacWindows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Appearance.h>
#include <CodeFragments.h>
#include <Dialogs.h>
#include <Devices.h>
#include <DiskInit.h>
#include <Gestalt.h>
#include <LowMem.h>
#include <Navigation.h>
#include <Resources.h>
#include <Script.h>
#include <TextCommon.h>
#include <ToolUtils.h>
#include <UnicodeConverter.h>
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h> /* putty.h needs size_t */
#include <stdio.h> /* for vsprintf */
#define PUTTY_DO_GLOBALS
#include "macresid.h"
#include "putty.h"
#include "ssh.h"
#include "terminal.h"
#include "mac.h"
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);
#pragma noreturn (mac_eventloop)
static void mac_event(EventRecord *);
static void mac_contentclick(WindowPtr, EventRecord *);
static void mac_growwindow(WindowPtr, EventRecord *);
static void mac_activatewindow(WindowPtr, EventRecord *);
static void mac_suspendresume(EventRecord *);
static void mac_activateabout(WindowPtr, EventRecord *);
static void mac_updatewindow(WindowPtr);
static void mac_updatelicence(WindowPtr);
static void mac_keypress(EventRecord *);
static int mac_windowtype(WindowPtr);
static void mac_menucommand(long);
static void mac_openlicence(void);
static void mac_adjustcursor(RgnHandle);
static void mac_adjustmenus(void);
static void mac_closewindow(WindowPtr);
static void mac_zoomwindow(WindowPtr, short);
#pragma noreturn (cleanup_exit)
struct mac_windows {
WindowPtr about;
WindowPtr licence;
};
struct mac_windows windows;
int main (int argc, char **argv) {
mac_startup();
mac_eventloop();
}
#pragma noreturn (main)
static void mac_startup(void) {
Handle menuBar;
TECInfoHandle ti;
#if !TARGET_API_MAC_CARBON
/* Init Memory Manager */
MaxApplZone();
/* Init QuickDraw */
InitGraf(&qd.thePort);
/* Init Font Manager */
InitFonts();
/* Init Window Manager */
InitWindows();
/* Init Menu Manager */
InitMenus();
/* Init TextEdit */
TEInit();
/* Init Dialog Manager */
InitDialogs(NULL);
#endif
cold = 0;
/* Get base system version (only used if there's no better selector) */
if (Gestalt(gestaltSystemVersion, &mac_gestalts.sysvers) != noErr ||
(mac_gestalts.sysvers &= 0xffff) < 0x700)
fatalbox("PuTTY requires System 7 or newer");
/* Find out if we've got Color Quickdraw */
if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
mac_gestalts.qdvers = gestaltOriginalQD;
/* ... and the Appearance Manager? */
if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
mac_gestalts.apprvers = 0x0100;
else
mac_gestalts.apprvers = 0;
#if TARGET_RT_MAC_CFM
/* Paranoia: Did we manage to pull in AppearanceLib? */
if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
mac_gestalts.apprvers = 0;
#endif
#if TARGET_CPU_68K
mac_gestalts.cntlattr = 0;
mac_gestalts.windattr = 0;
#else
/* Mac OS 8.5 Control Manager (proportional scrollbars)? */
if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr ||
&SetControlViewSize == kUnresolvedCFragSymbolAddress)
mac_gestalts.cntlattr = 0;
/* Mac OS 8.5 Window Manager? */
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 (
#if TARGET_RT_MAC_CFM
&TECGetInfo == kUnresolvedCFragSymbolAddress ||
#else
InitializeUnicodeConverter(NULL) != noErr ||
#endif
TECGetInfo(&ti) != noErr)
mac_gestalts.encvvers = 0;
else {
mac_gestalts.encvvers = (*ti)->tecVersion;
mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures;
DisposeHandle((Handle)ti);
}
/* Navigation Services? */
if (NavServicesAvailable())
mac_gestalts.navsvers = NavLibraryVersion();
else
mac_gestalts.navsvers = 0;
sk_init();
/* We've been tested with the Appearance Manager */
if (mac_gestalts.apprvers != 0)
RegisterAppearanceClient();
menuBar = GetNewMBar(128);
if (menuBar == NULL)
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();
windows.about = NULL;
windows.licence = NULL;
default_protocol = be_default_protocol;
/* Find the appropriate default port. */
{
Backend *b = backend_from_proto(default_protocol);
default_port = 0; /* illegal */
if (b)
default_port = b->default_port;
}
flags = FLAG_INTERACTIVE;
#if !TARGET_API_MAC_CARBON
{
short vol;
long dirid;
/* Set the default directory for loading and saving settings. */
/* XXX Should we create it? */
if (get_session_dir(FALSE, &vol, &dirid) == noErr) {
LMSetSFSaveDisk(-vol);
LMSetCurDirStore(dirid);
}
}
#endif
/* Install Apple Event handlers. */
AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
NewAEEventHandlerUPP(&mac_aevt_oapp), 0, FALSE);
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
NewAEEventHandlerUPP(&mac_aevt_odoc), 0, FALSE);
AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
NewAEEventHandlerUPP(&mac_aevt_pdoc), 0, FALSE);
AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
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 (;;) {
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) {
/* Ensure we get a null event when the real ones run out. */
sleeptime = 0;
mac_event(&event);
if (borednow)
cleanup_exit(0);
}
if (!gotevent)
sk_poll();
if (mac_gestalts.apprvers >= 0x100 && mac_frontwindow() != NULL)
IdleControls(mac_frontwindow());
}
DisposeRgn(cursrgn);
}
static void mac_event(EventRecord *event) {
short part;
WindowPtr window;
switch (event->what) {
case mouseDown:
part = FindWindow(event->where, &window);
switch (part) {
case inMenuBar:
mac_adjustmenus();
mac_menucommand(MenuSelect(event->where));
break;
#if !TARGET_API_MAC_CARBON
case inSysWindow:
SystemClick(event, window);
break;
#endif
case inContent:
if (window != FrontWindow())
/* XXX: check for movable modal dboxes? */
SelectWindow(window);
else
mac_contentclick(window, event);
break;
case inGoAway:
if (TrackGoAway(window, event->where))
mac_closewindow(window);
break;
case inDrag:
/* XXX: moveable modal check? */
#if TARGET_API_MAC_CARBON
{
BitMap screenBits;
GetQDGlobalsScreenBits(&screenBits);
DragWindow(window, event->where, &screenBits.bounds);
}
#else
DragWindow(window, event->where, &qd.screenBits.bounds);
#endif
break;
case inGrow:
mac_growwindow(window, event);
break;
case inZoomIn:
case inZoomOut:
if (TrackBox(window, event->where, part))
mac_zoomwindow(window, part);
break;
}
break;
case keyDown:
case autoKey:
mac_keypress(event);
break;
case activateEvt:
mac_activatewindow((WindowPtr)event->message, event);
break;
case updateEvt:
mac_updatewindow((WindowPtr)event->message);
break;
#if !TARGET_API_MAC_CARBON
case diskEvt:
if (HiWord(event->message) != noErr) {
Point pt;
SetPt(&pt, 120, 120);
DIBadMount(pt, event->message);
}
break;
#endif
case osEvt:
switch ((event->message & osEvtMessageMask) >> 24) {
case suspendResumeMessage:
mac_suspendresume(event);
break;
}
break;
case kHighLevelEvent:
AEProcessAppleEvent(event); /* errors? */
break;
}
}
static void mac_contentclick(WindowPtr window, EventRecord *event)
{
if (mac_wininfo(window)->click != NULL)
(*mac_wininfo(window)->click)(window, event);
}
static void mac_growwindow(WindowPtr window, EventRecord *event)
{
if (mac_wininfo(window)->grow != NULL)
(*mac_wininfo(window)->grow)(window, event);
}
static void mac_activatewindow(WindowPtr window, EventRecord *event)
{
mac_adjustmenus();
if (mac_wininfo(window)->activate != NULL)
(*mac_wininfo(window)->activate)(window, event);
}
static void mac_updatewindow(WindowPtr window)
{
if (mac_wininfo(window)->update != NULL)
(*mac_wininfo(window)->update)(window);
}
/*
* Work out what kind of window we're dealing with.
*/
static int mac_windowtype(WindowPtr window)
{
#if !TARGET_API_MAC_CARBON
if (GetWindowKind(window) < 0)
return wDA;
#endif
return ((WinInfo *)GetWRefCon(window))->wtype;
}
/*
* Handle a key press
*/
static void mac_keypress(EventRecord *event) {
WindowPtr window;
window = mac_frontwindow();
/*
* Check for a command-key combination, but ignore it if it counts
* as a meta-key combination and we're in a terminal window.
*/
if (event->what == keyDown && (event->modifiers & cmdKey) /*&&
!((event->modifiers & cfg.meta_modifiers) == cfg.meta_modifiers &&
mac_windowtype(window) == wTerminal)*/) {
mac_adjustmenus();
mac_menucommand(MenuKey(event->message & charCodeMask));
} else {
if (window != NULL && mac_wininfo(window)->key != NULL)
(*mac_wininfo(window)->key)(window, event);
}
}
static void mac_menucommand(long result) {
short menu, item;
WindowPtr window;
#if !TARGET_API_MAC_CARBON
Str255 da;
#endif
menu = HiWord(result);
item = LoWord(result);
window = mac_frontwindow();
/* Things which do the same whatever window we're in. */
switch (menu) {
case mApple:
switch (item) {
case iAbout:
mac_openabout();
goto done;
#if !TARGET_API_MAC_CARBON
default:
GetMenuItemText(GetMenuHandle(mApple), item, da);
OpenDeskAcc(da);
goto done;
#endif
}
break;
case mFile:
switch (item) {
case iNew:
mac_newsession();
goto done;
case iOpen:
mac_opensession();
goto done;
case iChange:
mac_reconfig();
goto done;
case iClose:
mac_closewindow(window);
goto done;
case iSave:
mac_savesession();
goto done;
case iSaveAs:
mac_savesessionas();
goto done;
case iDuplicate:
mac_dupsession();
goto done;
case iQuit:
cleanup_exit(0);
goto done;
}
break;
}
/* If we get here, handling is up to window-specific code. */
if (window != NULL && mac_wininfo(window)->menu != NULL)
(*mac_wininfo(window)->menu)(window, menu, item);
done:
HiliteMenu(0);
}
static void mac_closewindow(WindowPtr window) {
switch (mac_windowtype(window)) {
#if !TARGET_API_MAC_CARBON
case wDA:
CloseDeskAcc(GetWindowKind(window));
break;
#endif
default:
if (mac_wininfo(window)->close != NULL)
(*mac_wininfo(window)->close)(window);
break;
}
}
static void mac_suspendresume(EventRecord *event)
{
WindowPtr front;
EventRecord fakeevent;
/*
* We're called either before we're suspended or after we're
* resumed, so we're the front application at this point.
*/
front = FrontWindow();
if (front != NULL) {
fakeevent.what = activateEvt;
fakeevent.message = (UInt32)front;
fakeevent.when = event->when;
fakeevent.where = event->where;
fakeevent.modifiers =
(event->message & resumeFlag) ? activeFlag : 0;
mac_activatewindow(front, &fakeevent);
}
}
static void mac_zoomwindow(WindowPtr window, short part) {
/* FIXME: do something */
}
/*
* Make the menus look right before the user gets to see them.
*/
#if TARGET_API_MAC_CARBON
#define EnableItem EnableMenuItem
#define DisableItem DisableMenuItem
#endif
static void mac_adjustmenus(void) {
WindowPtr window;
MenuHandle menu;
window = mac_frontwindow();
menu = GetMenuHandle(mApple);
EnableItem(menu, 0);
EnableItem(menu, iAbout);
menu = GetMenuHandle(mFile);
EnableItem(menu, 0);
EnableItem(menu, iNew);
if (window != NULL)
EnableItem(menu, iClose);
else
DisableItem(menu, iClose);
EnableItem(menu, iQuit);
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);
menu = GetMenuHandle(mEdit);
DisableItem(menu, 0);
menu = GetMenuHandle(mWindow);
DisableItem(menu, 0); /* Until we get more than 1 item on it. */
}
DrawMenuBar();
}
/*
* Make sure the right cursor's being displayed.
*/
static void mac_adjustcursor(RgnHandle cursrgn) {
Point mouse;
WindowPtr window, front;
short part;
#if TARGET_API_MAC_CARBON
Cursor arrow;
RgnHandle visrgn;
#endif
GetMouse(&mouse);
LocalToGlobal(&mouse);
part = FindWindow(mouse, &window);
front = FrontWindow();
if (part != inContent || window == NULL || window != front) {
/* Cursor isn't in the front window, so switch to arrow */
#if TARGET_API_MAC_CARBON
GetQDGlobalsArrow(&arrow);
SetCursor(&arrow);
#else
SetCursor(&qd.arrow);
#endif
SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
if (front != NULL) {
#if TARGET_API_MAC_CARBON
visrgn = NewRgn();
GetPortVisibleRegion(GetWindowPort(front), visrgn);
DiffRgn(cursrgn, visrgn, cursrgn);
DisposeRgn(visrgn);
#else
DiffRgn(cursrgn, front->visRgn, cursrgn);
#endif
}
} else {
if (mac_wininfo(window)->adjustcursor != NULL)
(*mac_wininfo(window)->adjustcursor)(window, mouse, cursrgn);
else {
#if TARGET_API_MAC_CARBON
GetQDGlobalsArrow(&arrow);
SetCursor(&arrow);
GetPortVisibleRegion(GetWindowPort(window), cursrgn);
#else
SetCursor(&qd.arrow);
CopyRgn(window->visRgn, cursrgn);
#endif
}
}
}
pascal OSErr mac_aevt_quit(const AppleEvent *req, AppleEvent *reply,
long refcon)
{
DescType type;
Size size;
if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
&type, NULL, 0, &size) == noErr)
return errAEParamMissed;
borednow = 1;
return noErr;
}
void cleanup_exit(int status)
{
#if !TARGET_RT_MAC_CFM
if (mac_gestalts.encvvers != 0)
TerminateUnicodeConverter();
#endif
sk_cleanup();
exit(status);
}
/* This should only kill the current session, not the whole application. */
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 */
stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
va_end(ap);
ParamText(stuff, NULL, NULL, NULL);
StopAlert(128, NULL);
s->session_closed = TRUE;
if (s->cfg.close_on_exit == FORCE_ON)
mac_closewindow(s->window);
}
/* Null SSH agent client -- never finds an agent. */
int agent_exists(void)
{
return FALSE;
}
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. */
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;
}
}
}
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)
{
}
FontSpec platform_default_fontspec(char const *name)
{
FontSpec ret;
long smfs;
if (!strcmp(name, "Font")) {
smfs = GetScriptVariable(smSystemScript, smScriptMonoFondSize);
if (smfs == 0)
smfs = GetScriptVariable(smRoman, smScriptMonoFondSize);
if (smfs != 0) {
GetFontName(HiWord(smfs), ret.name);
if (ret.name[0] == 0)
memcpy(ret.name, "\pMonaco", 7);
ret.size = LoWord(smfs);
} else {
memcpy(ret.name, "\pMonaco", 7);
ret.size = 9;
}
ret.face = 0;
} else {
ret.name[0] = 0;
}
return ret;
}
Filename platform_default_filename(const char *name)
{
Filename ret;
if (!strcmp(name, "LogFileName"))
FSMakeFSSpec(0, 0, "\pputty.log", &ret.fss);
else
memset(&ret, 0, sizeof(ret));
return ret;
}
char *platform_default_s(char const *name)
{
return NULL;
}
int platform_default_i(char const *name, int def)
{
/* Non-raw cut and paste of line-drawing chars works badly on the
* current Unix stub implementation of the Unicode functions.
* So I'm going to temporarily set the default to raw mode so
* that the failure mode isn't quite so drastically horrid.
* When Unicode comes in, this can all be put right. */
if (!strcmp(name, "RawCNP"))
return 1;
return def;
}
void platform_get_x11_auth(char *display, int *proto,
unsigned char *data, int *datalen)
{
/* 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"
* End:
*/

238
mac/mac.h
View File

@ -1,238 +0,0 @@
/*
* mac.h -- macintosh-specific declarations
*/
#ifndef PUTTY_MAC_H
#define PUTTY_MAC_H
#include <MacTypes.h>
#include <Controls.h>
#include <Events.h>
#include <Gestalt.h>
#include <Lists.h>
#include <MacWindows.h>
#include <Palettes.h>
#include <UnicodeConverter.h>
#include "charset.h"
#include "tree234.h"
#define PUTTY_CREATOR FOUR_CHAR_CODE('pTTY')
#define INTERNAL_CREATOR FOUR_CHAR_CODE('pTTI')
#define SESS_TYPE FOUR_CHAR_CODE('Sess')
#define SEED_TYPE FOUR_CHAR_CODE('Seed')
#define HKYS_TYPE FOUR_CHAR_CODE('Hkys')
struct mac_gestalts {
long sysvers;
long qdvers;
long apprvers;
long cntlattr;
long windattr;
long menuattr;
long encvvers; /* TEC version (from TECGetInfo()) */
long uncvattr; /* Unicode Converter attributes (frem TECGetInfo()) */
long navsvers; /* Navigation Services version */
};
extern struct mac_gestalts mac_gestalts;
extern UInt32 sleeptime;
#if TARGET_RT_MAC_CFM
/* All systems that can use CFM have Color QuickDraw */
#define HAVE_COLOR_QD() 1
#else
#define HAVE_COLOR_QD() (mac_gestalts.qdvers > gestaltOriginalQD)
#endif
/* Every window used by PuTTY has a refCon field pointing to one of these. */
typedef struct {
struct Session *s; /* Only used in PuTTY */
struct KeyState *ks; /* Only used in PuTTYgen */
struct macctrls *mcs;
void (*activate) (WindowPtr, EventRecord *);
void (*adjustcursor)(WindowPtr, Point, RgnHandle);
void (*adjustmenus) (WindowPtr);
void (*update) (WindowPtr);
void (*click) (WindowPtr, EventRecord *);
void (*grow) (WindowPtr, EventRecord *);
void (*key) (WindowPtr, EventRecord *);
void (*menu) (WindowPtr, short, short);
void (*close) (WindowPtr);
int wtype;
} WinInfo;
#define mac_wininfo(w) ((WinInfo *)GetWRefCon(w))
#define mac_windowsession(w) (((WinInfo *)GetWRefCon(w))->s)
#define mac_winctrls(w) (((WinInfo *)GetWRefCon(w))->mcs)
union macctrl;
struct macctrls {
WindowPtr window;
void (*end)(WindowPtr, int);
tree234 *byctrl;
void *data; /* private data for config box */
unsigned int npanels;
unsigned int curpanel;
union macctrl **panels; /* lists of controls by panel */
union macctrl *focus; /* Input focus for System 7 */
union macctrl *defbutton; /* Default button */
union macctrl *canbutton; /* Cancel button */
Boolean gotcolour;
RGBColor thecolour;
};
typedef struct Session {
struct Session *next;
struct Session **prev;
/* Config that created this session */
Config cfg;
/* Temporary config for passing to Change Settings */
Config temp_cfg;
/* Terminal emulator internal state */
Terminal *term;
/* Display state */
int font_width, font_height;
/* Line discipline */
void *ldisc;
/* Backend */
Backend *back;
void *backhandle;
char *realhost;
/* Logging */
void *logctx;
/* Unicode stuff */
struct unicode_data ucsdata;
/* Session closed flag */
int session_closed;
/* Mac-specific elements */
short fontnum;
int font_ascent;
int font_leading;
int font_boldadjust;
Point font_stdnumer;
Point font_stddenom;
Point font_widenumer;
Point font_widedenom;
Point font_bignumer;
Point font_bigdenom;
WindowPtr window;
WindowPtr eventlog_window;
ListHandle eventlog;
PaletteHandle palette;
ControlHandle scrollbar;
WCTabHandle wctab;
int raw_mouse;
UnicodeToTextInfo uni_to_font; /* Only one of uni_to_font and */
charset_t font_charset; /* font_charset is used at a time. */
int hasfile;
FSSpec savefile;
/* Config dialogue bits */
WindowPtr settings_window;
struct controlbox *ctrlbox;
struct macctrls settings_ctrls;
} Session;
extern Session *sesslist;
/* PuTTYgen per-window state */
typedef struct KeyState {
DialogPtr box;
int collecting_entropy;
int entropy_got, entropy_required, entropy_size;
unsigned *entropy;
ControlHandle progress;
} KeyState;
#define mac_windowkey(w) (((WinInfo *)GetWRefCon(w))->ks)
/* from macmisc.c */
extern WindowPtr mac_frontwindow(void);
/* from macdlg.c */
extern void mac_newsession(void);
extern void mac_reconfig(void);
extern void mac_dupsession(void);
extern void mac_savesession(void);
extern void mac_savesessionas(void);
/* from maceventlog.c */
extern void mac_freeeventlog(Session *);
extern void mac_showeventlog(Session *);
/* from macterm.c */
extern void mac_opensession(void);
extern void mac_startsession(Session *);
/* from macstore.c */
extern OSErr get_putty_dir(Boolean makeit, short *pVRefNum, long *pDirID);
extern OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID);
extern void *open_settings_r_fsp(FSSpec *);
extern void *open_settings_w_fsp(FSSpec *);
extern int verify_host_key(const char *, int, const char *, const char*);
extern void store_host_key(const char *, int, const char *, const char*);
/* from macucs.c */
extern void init_ucs(Session *);
/* from macnet.c */
extern void sk_poll(void);
/* from mtcpnet.c */
extern OSErr mactcp_init(void);
extern void mactcp_cleanup(void);
extern void mactcp_poll(void);
extern SockAddr mactcp_namelookup(char const *, char **);
extern SockAddr mactcp_nonamelookup(char const *);
extern void mactcp_getaddr(SockAddr, char *, int);
extern int mactcp_hostname_is_local(char *);
extern int mactcp_address_is_local(SockAddr);
extern int mactcp_addrtype(SockAddr);
extern void mactcp_addrcopy(SockAddr, char *);
extern void mactcp_addr_free(SockAddr);
extern Socket mactcp_register(void *, Plug);
extern Socket mactcp_new(SockAddr addr, int, int, int, int, int, Plug);
extern Socket mactcp_newlistener(char *, int, Plug, int, int);
extern char *mactcp_addr_error(SockAddr);
/* from otnet.c */
extern OSErr ot_init(void);
extern void ot_cleanup(void);
extern void ot_poll(void);
extern SockAddr ot_namelookup(char const *, char **);
extern SockAddr ot_nonamelookup(char const *);
extern void ot_getaddr(SockAddr, char *, int);
extern int ot_hostname_is_local(char *);
extern int ot_address_is_local(SockAddr);
extern int ot_addrtype(SockAddr);
extern void ot_addrcopy(SockAddr, char *);
extern void ot_addr_free(SockAddr);
extern Socket ot_register(void *, Plug);
extern Socket ot_new(SockAddr addr, int, int, int, int, int, Plug);
extern Socket ot_newlistener(char *, int, Plug, int, int);
extern char *ot_addr_error(SockAddr);
/* from macabout.c */
extern void mac_openabout(void);
/* from macctrls.c */
extern void macctrl_layoutbox(struct controlbox *, WindowPtr,
struct macctrls *);
extern void macctrl_activate(WindowPtr, EventRecord *);
extern void macctrl_click(WindowPtr, EventRecord *);
extern void macctrl_key(WindowPtr, EventRecord *);
extern void macctrl_update(WindowPtr);
extern void macctrl_adjustmenus(WindowPtr);
extern void macctrl_close(WindowPtr);
/* from macpgkey.c */
extern void mac_newkey(void);
/* Apple Event Handlers (in various files) */
extern pascal OSErr mac_aevt_oapp(const AppleEvent *, AppleEvent *, long);
extern pascal OSErr mac_aevt_odoc(const AppleEvent *, AppleEvent *, long);
extern pascal OSErr mac_aevt_pdoc(const AppleEvent *, AppleEvent *, long);
extern pascal OSErr mac_aevt_quit(const AppleEvent *, AppleEvent *, long);
#endif
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 1999, 2002, 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <MacTypes.h>
#include <Dialogs.h>
#include <MacWindows.h>
#include <Resources.h>
#include <Script.h>
#include <ToolUtils.h>
#include <assert.h>
#include <stdlib.h>
#include "putty.h"
#include "mac.h"
#include "macresid.h"
static struct mac_windows {
WindowPtr about;
WindowPtr licence;
} windows;
static void mac_openlicence(void);
static void mac_clickabout(WindowPtr window, EventRecord *event)
{
short item;
DialogRef dialog;
dialog = GetDialogFromWindow(window);
if (DialogSelect(event, &dialog, &item))
switch (item) {
case wiAboutLicence:
mac_openlicence();
break;
}
}
static void mac_activateabout(WindowPtr window, EventRecord *event)
{
DialogRef dialog;
DialogItemType itemtype;
Handle itemhandle;
short item;
Rect itemrect;
int active;
dialog = GetDialogFromWindow(window);
active = (event->modifiers & activeFlag) != 0;
GetDialogItem(dialog, wiAboutLicence, &itemtype, &itemhandle, &itemrect);
HiliteControl((ControlHandle)itemhandle, active ? 0 : 255);
DialogSelect(event, &dialog, &item);
}
static void mac_updateabout(WindowPtr window)
{
#if TARGET_API_MAC_CARBON
RgnHandle rgn;
#endif
BeginUpdate(window);
#if TARGET_API_MAC_CARBON
rgn = NewRgn();
GetPortVisibleRegion(GetWindowPort(window), rgn);
UpdateDialog(GetDialogFromWindow(window), rgn);
DisposeRgn(rgn);
#else
UpdateDialog(window, window->visRgn);
#endif
EndUpdate(window);
}
static void mac_closeabout(WindowPtr window)
{
windows.about = NULL;
DisposeDialog(GetDialogFromWindow(window));
}
static void mac_updatelicence(WindowPtr window)
{
Handle h;
int len;
long fondsize;
Rect textrect;
SetPort((GrafPtr)GetWindowPort(window));
BeginUpdate(window);
fondsize = GetScriptVariable(smRoman, smScriptSmallFondSize);
TextFont(HiWord(fondsize));
TextSize(LoWord(fondsize));
h = Get1Resource('TEXT', wLicence);
len = GetResourceSizeOnDisk(h);
#if TARGET_API_MAC_CARBON
GetPortBounds(GetWindowPort(window), &textrect);
#else
textrect = window->portRect;
#endif
if (h != NULL) {
HLock(h);
TETextBox(*h, len, &textrect, teFlushDefault);
HUnlock(h);
}
EndUpdate(window);
}
static void mac_closelicence(WindowPtr window)
{
windows.licence = NULL;
DisposeWindow(window);
}
void mac_openabout(void)
{
DialogItemType itemtype;
Handle item;
VersRecHndl vers;
Rect box;
StringPtr longvers;
WinInfo *wi;
if (windows.about)
SelectWindow(windows.about);
else {
windows.about =
GetDialogWindow(GetNewDialog(wAbout, NULL, (WindowPtr)-1));
wi = snew(WinInfo);
memset(wi, 0, sizeof(*wi));
wi->wtype = wAbout;
wi->update = &mac_updateabout;
wi->click = &mac_clickabout;
wi->activate = &mac_activateabout;
wi->close = &mac_closeabout;
SetWRefCon(windows.about, (long)wi);
vers = (VersRecHndl)Get1Resource('vers', 1);
if (vers != NULL && *vers != NULL) {
longvers = (*vers)->shortVersion + (*vers)->shortVersion[0] + 1;
GetDialogItem(GetDialogFromWindow(windows.about), wiAboutVersion,
&itemtype, &item, &box);
assert(itemtype & kStaticTextDialogItem);
SetDialogItemText(item, longvers);
}
ShowWindow(windows.about);
}
}
static void mac_openlicence(void)
{
WinInfo *wi;
if (windows.licence)
SelectWindow(windows.licence);
else {
windows.licence = GetNewWindow(wLicence, NULL, (WindowPtr)-1);
wi = snew(WinInfo);
memset(wi, 0, sizeof(*wi));
wi->wtype = wLicence;
wi->update = &mac_updatelicence;
wi->close = &mac_closelicence;
SetWRefCon(windows.licence, (long)wi);
ShowWindow(windows.licence);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,408 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2002 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* macdlg.c - settings dialogue box for Mac OS.
*/
#include <MacTypes.h>
#include <AEDataModel.h>
#include <AppleEvents.h>
#include <Navigation.h>
#include <Resources.h>
#include <StandardFile.h>
#include <TextUtils.h>
#include <Windows.h>
#include <assert.h>
#include <string.h>
#include "putty.h"
#include "dialog.h"
#include "mac.h"
#include "macresid.h"
#include "storage.h"
static void mac_config(int);
static void mac_closedlg(WindowPtr);
static void mac_enddlg_config(WindowPtr, int);
static void mac_enddlg_reconfig(WindowPtr, int);
void mac_newsession(void)
{
mac_config(FALSE);
}
void mac_reconfig(void)
{
mac_config(TRUE);
}
static void mac_config(int midsession)
{
Session *s;
WinInfo *wi;
Str255 mactitle;
char *str;
if (midsession) {
s = mac_windowsession(FrontWindow());
} else {
s = snew(Session);
memset(s, 0, sizeof(*s));
do_defaults(NULL, &s->cfg);
s->hasfile = FALSE;
s->session_closed = FALSE;
}
/* Copy the configuration somewhere else in case this is a *
* reconfiguration and the user cancels the operation */
s->temp_cfg = s->cfg;
if (HAVE_COLOR_QD())
s->settings_window = GetNewCWindow(wSettings, NULL, (WindowPtr)-1);
else
s->settings_window = GetNewWindow(wSettings, NULL, (WindowPtr)-1);
s->ctrlbox = ctrl_new_box();
setup_config_box(s->ctrlbox, midsession, 0, 0);
s->settings_ctrls.data = &s->temp_cfg;
if (midsession)
s->settings_ctrls.end = &mac_enddlg_reconfig;
else
s->settings_ctrls.end = &mac_enddlg_config;
macctrl_layoutbox(s->ctrlbox, s->settings_window, &s->settings_ctrls);
wi = snew(WinInfo);
memset(wi, 0, sizeof(*wi));
wi->s = s;
wi->mcs = &s->settings_ctrls;
wi->wtype = wSettings;
wi->update = &macctrl_update;
wi->click = &macctrl_click;
wi->key = &macctrl_key;
wi->activate = &macctrl_activate;
wi->adjustmenus = &macctrl_adjustmenus;
wi->close = &mac_closedlg;
SetWRefCon(s->settings_window, (long)wi);
if (midsession)
str = dupprintf("%s Reconfiguration", appname);
else
str = dupprintf("%s Configuration", appname);
c2pstrcpy(mactitle, str);
sfree(str);
SetWTitle(s->settings_window, mactitle);
ShowWindow(s->settings_window);
}
static void mac_closedlg(WindowPtr window)
{
Session *s = mac_windowsession(window);
macctrl_close(window);
DisposeWindow(window);
if (s->window == NULL)
sfree(s);
}
static void mac_enddlg_config(WindowPtr window, int value)
{
Session *s = mac_windowsession(window);
if (value == 0)
mac_closedlg(window);
else {
s->cfg = s->temp_cfg;
mac_startsession(s);
mac_closedlg(window);
}
}
static void mac_enddlg_reconfig(WindowPtr window, int value)
{
Session *s = mac_windowsession(window);
if (value == 0)
mac_closedlg(window);
else {
Config prev_cfg = s->cfg;
s->cfg = s->temp_cfg;
mac_closedlg(window);
/* Pass new config data to the logging module */
log_reconfig(s->logctx, &s->cfg);
/*
* Flush the line discipline's edit buffer in the
* case where local editing has just been disabled.
*/
if (s->ldisc)
ldisc_send(s->ldisc, NULL, 0, 0);
/* Change the palette */
palette_reset(s);
/* Reinitialise line codepage */
init_ucs(s);
/* Pass new config data to the terminal */
term_reconfig(s->term, &s->cfg);
/* Pass new config data to the back end */
if (s->back)
s->back->reconfig(s->backhandle, &s->cfg);
/* Screen size changed ? */
if (s->cfg.height != prev_cfg.height ||
s->cfg.width != prev_cfg.width ||
s->cfg.savelines != prev_cfg.savelines) {
request_resize(s, s->cfg.width, s->cfg.height);
}
/* Set the window title */
if (s->cfg.wintitle[0])
set_title(s, s->cfg.wintitle);
/* Scroll bar */
if (s->cfg.scrollbar != prev_cfg.scrollbar)
request_resize(s, s->cfg.width, s->cfg.height);
/* TODO: zoom, font */
}
}
void mac_dupsession(void)
{
Session *s1 = mac_windowsession(FrontWindow());
Session *s2;
s2 = snew(Session);
memset(s2, 0, sizeof(*s2));
s2->cfg = s1->cfg;
s2->hasfile = s1->hasfile;
s2->savefile = s1->savefile;
mac_startsession(s2);
}
static OSErr mac_opensessionfrom(FSSpec *fss)
{
FInfo fi;
Session *s;
void *sesshandle;
OSErr err;
s = snew(Session);
memset(s, 0, sizeof(*s));
err = FSpGetFInfo(fss, &fi);
if (err != noErr) return err;
if (fi.fdFlags & kIsStationery)
s->hasfile = FALSE;
else {
s->hasfile = TRUE;
s->savefile = *fss;
}
sesshandle = open_settings_r_fsp(fss);
if (sesshandle == NULL) {
/* XXX need a way to pass up an error number */
err = -9999;
goto fail;
}
load_open_settings(sesshandle, &s->cfg);
close_settings_r(sesshandle);
mac_startsession(s);
return noErr;
fail:
sfree(s);
return err;
}
static OSErr mac_openlist(AEDesc docs)
{
OSErr err;
long ndocs, i;
FSSpec fss;
AEKeyword keywd;
DescType type;
Size size;
err = AECountItems(&docs, &ndocs);
if (err != noErr) return err;
for (i = 0; i < ndocs; i++) {
err = AEGetNthPtr(&docs, i + 1, typeFSS,
&keywd, &type, &fss, sizeof(fss), &size);
if (err != noErr) return err;;
err = mac_opensessionfrom(&fss);
if (err != noErr) return err;
}
return noErr;
}
void mac_opensession(void)
{
if (mac_gestalts.navsvers > 0) {
NavReplyRecord navr;
NavDialogOptions navopts;
NavTypeListHandle navtypes;
AEDesc defaultloc = { 'null', NULL };
AEDesc *navdefault = NULL;
short vol;
long dirid;
FSSpec fss;
if (NavGetDefaultDialogOptions(&navopts) != noErr) return;
/* XXX should we create sessions dir? */
if (get_session_dir(FALSE, &vol, &dirid) == noErr &&
FSMakeFSSpec(vol, dirid, NULL, &fss) == noErr &&
AECreateDesc(typeFSS, &fss, sizeof(fss), &defaultloc) == noErr)
navdefault = &defaultloc;
/* Can't meaningfully preview a saved session yet */
navopts.dialogOptionFlags &= ~kNavAllowPreviews;
navtypes = (NavTypeListHandle)GetResource('open', open_pTTY);
if (NavGetFile(navdefault, &navr, &navopts, NULL, NULL, NULL, navtypes,
NULL) == noErr && navr.validRecord)
mac_openlist(navr.selection);
NavDisposeReply(&navr);
if (navtypes != NULL)
ReleaseResource((Handle)navtypes);
}
#if !TARGET_API_MAC_CARBON /* XXX Navigation Services */
else {
StandardFileReply sfr;
static const OSType sftypes[] = { 'Sess', 0, 0, 0 };
StandardGetFile(NULL, 1, sftypes, &sfr);
if (!sfr.sfGood) return;
mac_opensessionfrom(&sfr.sfFile);
/* XXX handle error */
}
#endif
}
void mac_savesession(void)
{
Session *s = mac_windowsession(FrontWindow());
void *sesshandle;
assert(s->hasfile);
sesshandle = open_settings_w_fsp(&s->savefile);
if (sesshandle == NULL) return; /* XXX report error */
save_open_settings(sesshandle, &s->cfg);
close_settings_w(sesshandle);
}
void mac_savesessionas(void)
{
#if !TARGET_API_MAC_CARBON /* XXX Navigation Services */
Session *s = mac_windowsession(FrontWindow());
StandardFileReply sfr;
void *sesshandle;
StandardPutFile("\pSave session as:",
s->hasfile ? s->savefile.name : "\puntitled", &sfr);
if (!sfr.sfGood) return;
if (!sfr.sfReplacing) {
FSpCreateResFile(&sfr.sfFile, PUTTY_CREATOR, SESS_TYPE, sfr.sfScript);
if (ResError() != noErr) return; /* XXX report error */
}
sesshandle = open_settings_w_fsp(&sfr.sfFile);
if (sesshandle == NULL) return; /* XXX report error */
save_open_settings(sesshandle, &s->cfg);
close_settings_w(sesshandle);
s->hasfile = TRUE;
s->savefile = sfr.sfFile;
#endif
}
pascal OSErr mac_aevt_oapp(const AppleEvent *req, AppleEvent *reply,
long refcon)
{
DescType type;
Size size;
if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
&type, NULL, 0, &size) == noErr)
return errAEParamMissed;
/* XXX we should do something here. */
return noErr;
}
pascal OSErr mac_aevt_odoc(const AppleEvent *req, AppleEvent *reply,
long refcon)
{
DescType type;
Size size;
AEDescList docs = { typeNull, NULL };
OSErr err;
err = AEGetParamDesc(req, keyDirectObject, typeAEList, &docs);
if (err != noErr) goto out;
if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
&type, NULL, 0, &size) == noErr) {
err = errAEParamMissed;
goto out;
}
err = mac_openlist(docs);
out:
AEDisposeDesc(&docs);
return err;
}
pascal OSErr mac_aevt_pdoc(const AppleEvent *req, AppleEvent *reply,
long refcon)
{
DescType type;
Size size;
if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
&type, NULL, 0, &size) == noErr)
return errAEParamMissed;
/* We can't meaningfully do anything here. */
return errAEEventNotHandled;
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,277 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <MacTypes.h>
#include <Lists.h>
#include <MacWindows.h>
#include <Quickdraw.h>
#include <Script.h>
#include <ToolUtils.h>
#include <limits.h>
#include <string.h>
#include "putty.h"
#include "mac.h"
#include "macresid.h"
#include "terminal.h"
static void mac_draweventloggrowicon(Session *s);
static void mac_adjusteventlogscrollbar(Session *s);
static void mac_clickeventlog(WindowPtr, EventRecord *);
static void mac_activateeventlog(WindowPtr, EventRecord *);
static void mac_groweventlog(WindowPtr, EventRecord *);
static void mac_updateeventlog(WindowPtr);
static void mac_closeeventlog(WindowPtr);
static void mac_createeventlog(Session *s)
{
Rect view;
ListBounds bounds = { 0, 0, 0, 1 }; /* 1 column, 0 rows */
Point csize = { 0, 0 };
GrafPtr saveport;
long fondsize;
WinInfo *wi;
s->eventlog_window = GetNewWindow(wEventLog, NULL, (WindowPtr)-1);
wi = snew(WinInfo);
memset(wi, 0, sizeof(*wi));
wi->s = s;
wi->wtype = wEventLog;
wi->click = &mac_clickeventlog;
wi->activate = &mac_activateeventlog;
wi->grow = &mac_groweventlog;
wi->update = &mac_updateeventlog;
wi->close = &mac_closeeventlog;
SetWRefCon(s->eventlog_window, (long)wi);
GetPort(&saveport);
SetPort((GrafPtr)GetWindowPort(s->eventlog_window));
fondsize = GetScriptVariable(smRoman, smScriptSmallFondSize);
TextFont(HiWord(fondsize));
TextSize(LoWord(fondsize));
SetPort(saveport);
#if TARGET_API_MAC_CARBON
GetPortBounds(GetWindowPort(s->eventlog_window), &view);
#else
view = s->eventlog_window->portRect;
#endif
view.right -= 15; /* Scrollbar */
s->eventlog = LNew(&view, &bounds, csize, 0, s->eventlog_window,
TRUE, TRUE, FALSE, TRUE);
mac_adjusteventlogscrollbar(s);
#if TARGET_API_MAC_CARBON
SetListSelectionFlags(s->eventlog, lExtendDrag | lNoDisjoint | lNoExtend);
#else
(*s->eventlog)->selFlags = lExtendDrag | lNoDisjoint | lNoExtend;
#endif
}
void mac_freeeventlog(Session *s)
{
if (s->eventlog != NULL)
LDispose(s->eventlog);
if (s->eventlog_window != NULL) {
sfree((WinInfo *)GetWRefCon(s->eventlog_window));
DisposeWindow(s->eventlog_window);
}
}
void logevent(void *frontend, const char *str)
{
Session *s = frontend;
ListBounds bounds, visible;
Cell cell = { 0, 0 };
char timebuf[40];
struct tm tm;
char *string;
tm=ltime();
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t", &tm);
string=snewn(strlen(timebuf) + strlen(str) +1, char);
strcpy(string, timebuf);
strcat(string, str);
if (s->eventlog == NULL)
mac_createeventlog(s);
if (s->eventlog == NULL)
return;
#if TARGET_API_MAC_CARBON
GetListDataBounds(s->eventlog, &bounds);
GetListVisibleCells(s->eventlog, &visible);
#else
bounds = (*s->eventlog)->dataBounds;
visible = (*s->eventlog)->visible;
#endif
cell.v = bounds.bottom;
LAddRow(1, cell.v, s->eventlog);
LSetCell(string, strlen(string), cell, s->eventlog);
/* ">=" and "2" because there can be a blank cell below the last one. */
if (visible.bottom >= bounds.bottom)
LScroll(0, 2, s->eventlog);
sfree(string);
}
static void mac_draweventloggrowicon(Session *s)
{
Rect clip;
RgnHandle savergn;
SetPort((GrafPtr)GetWindowPort(s->eventlog_window));
/*
* Stop DrawGrowIcon giving us space for a horizontal scrollbar
* See Tech Note TB575 for details.
*/
#if TARGET_API_MAC_CARBON
GetPortBounds(GetWindowPort(s->eventlog_window), &clip);
#else
clip = s->eventlog_window->portRect;
#endif
clip.left = clip.right - 15;
savergn = NewRgn();
GetClip(savergn);
ClipRect(&clip);
DrawGrowIcon(s->eventlog_window);
SetClip(savergn);
DisposeRgn(savergn);
}
/*
* For some reason, LNew doesn't seem to respect the hasGrow
* parameter, so we hammer the scrollbar into shape ourselves.
*/
static void mac_adjusteventlogscrollbar(Session *s)
{
#if TARGET_API_MAC_CARBON
Rect winrect;
GetPortBounds(GetWindowPort(s->eventlog_window), &winrect);
SizeControl(GetListVerticalScrollBar(s->eventlog),
16, winrect.bottom - 13);
#else
SizeControl((*s->eventlog)->vScroll,
16, s->eventlog_window->portRect.bottom - 13);
#endif
}
void mac_clickeventlog(WindowPtr window, EventRecord *event)
{
Session *s = mac_windowsession(window);
Point mouse;
GrafPtr saveport;
GetPort(&saveport);
SetPort((GrafPtr)GetWindowPort(window));
mouse = event->where;
GlobalToLocal(&mouse);
LClick(mouse, event->modifiers, s->eventlog);
SetPort(saveport);
}
static void mac_groweventlog(WindowPtr window, EventRecord *event)
{
Session *s = mac_windowsession(window);
Rect limits;
long grow_result;
#if TARGET_API_MAC_CARBON
Rect rect;
Point cellsize;
#else
GrafPtr saveport;
#endif
SetRect(&limits, 15, 0, SHRT_MAX, SHRT_MAX);
grow_result = GrowWindow(window, event->where, &limits);
if (grow_result == 0) return;
SizeWindow(window, LoWord(grow_result), HiWord(grow_result), TRUE);
LSize(LoWord(grow_result) - 15, HiWord(grow_result), s->eventlog);
mac_adjusteventlogscrollbar(s);
/* We would use SetListCellSize in Carbon, but it's missing. */
(*s->eventlog)->cellSize.h = LoWord(grow_result) - 15;
#if TARGET_API_MAC_CARBON
cellsize.h = LoWord(grow_result) - 15;
GetListViewBounds(s->eventlog, &rect);
InvalWindowRect(window, &rect);
#else
GetPort(&saveport);
SetPort(window);
InvalRect(&(*s->eventlog)->rView);
SetPort(saveport);
#endif
}
static void mac_activateeventlog(WindowPtr window, EventRecord *event)
{
Session *s = mac_windowsession(window);
int active = (event->modifiers & activeFlag) != 0;
LActivate(active, s->eventlog);
mac_draweventloggrowicon(s);
}
static void mac_updateeventlog(WindowPtr window)
{
Session *s = mac_windowsession(window);
#if TARGET_API_MAC_CARBON
RgnHandle visrgn;
#endif
SetPort((GrafPtr)GetWindowPort(window));
BeginUpdate(window);
#if TARGET_API_MAC_CARBON
visrgn = NewRgn();
GetPortVisibleRegion(GetWindowPort(window), visrgn);
LUpdate(visrgn, s->eventlog);
DisposeRgn(visrgn);
#else
LUpdate(window->visRgn, s->eventlog);
#endif
mac_draweventloggrowicon(s);
EndUpdate(window);
}
static void mac_closeeventlog(WindowPtr window)
{
HideWindow(window);
}
void mac_showeventlog(Session *s)
{
SelectWindow(s->eventlog_window);
ShowWindow(s->eventlog_window);
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,207 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 1999, 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <MacTypes.h>
#include <Dialogs.h>
#include <Files.h>
#include <MacWindows.h>
#include <Processes.h>
#include <Quickdraw.h>
#include <TextUtils.h>
#include <stdarg.h>
#include <stdio.h>
#include "putty.h"
#include "mac.h"
#include "ssh.h"
#if TARGET_API_MAC_CARBON
/*
* This is used by (I think) CarbonStdCLib, but only exists in
* CarbonLib 1.1 and later. Muppets. Happily, it's documented to be
* a synonym for NULL.
*/
#include <CFBase.h>
const CFAllocatorRef kCFAllocatorDefault = NULL;
#else
QDGlobals qd;
#endif
/*
* Like FrontWindow(), but return NULL if we aren't the front process
* (i.e. the front window isn't one of ours).
*/
WindowPtr mac_frontwindow(void)
{
ProcessSerialNumber frontpsn;
ProcessSerialNumber curpsn = { 0, kCurrentProcess };
Boolean result;
GetFrontProcess(&frontpsn);
if (SameProcess(&frontpsn, &curpsn, &result) == noErr && result)
return FrontWindow();
return NULL;
}
void fatalbox(char *fmt, ...) {
va_list ap;
Str255 stuff;
va_start(ap, fmt);
/* We'd like stuff to be a Pascal string */
stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
va_end(ap);
ParamText(stuff, NULL, NULL, NULL);
StopAlert(128, NULL);
cleanup_exit(1);
}
void modalfatalbox(char *fmt, ...) {
va_list ap;
Str255 stuff;
va_start(ap, fmt);
/* We'd like stuff to be a Pascal string */
stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
va_end(ap);
ParamText(stuff, NULL, NULL, NULL);
StopAlert(128, NULL);
cleanup_exit(1);
}
Filename filename_from_str(const char *str)
{
Filename ret;
Str255 tmp;
/* XXX This fails for filenames over 255 characters long. */
c2pstrcpy(tmp, str);
FSMakeFSSpec(0, 0, tmp, &ret.fss);
return ret;
}
/*
* Convert a filename to a string for display purposes.
* See pp 2-44--2-46 of IM:Files
*
* XXX static storage considered harmful
*/
const char *filename_to_str(const Filename *fn)
{
CInfoPBRec pb;
Str255 dirname;
OSErr err;
static char *path = NULL;
char *newpath;
if (path != NULL) sfree(path);
path = snewn(fn->fss.name[0], char);
p2cstrcpy(path, fn->fss.name);
pb.dirInfo.ioNamePtr = dirname;
pb.dirInfo.ioVRefNum = fn->fss.vRefNum;
pb.dirInfo.ioDrParID = fn->fss.parID;
pb.dirInfo.ioFDirIndex = -1;
do {
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
err = PBGetCatInfoSync(&pb);
/* XXX Assume not A/UX */
newpath = snewn(strlen(path) + dirname[0] + 2, char);
p2cstrcpy(newpath, dirname);
strcat(newpath, ":");
strcat(newpath, path);
sfree(path);
path = newpath;
} while (pb.dirInfo.ioDrDirID != fsRtDirID);
return path;
}
int filename_equal(Filename f1, Filename f2)
{
return f1.fss.vRefNum == f2.fss.vRefNum &&
f1.fss.parID == f2.fss.parID &&
f1.fss.name[0] == f2.fss.name[0] &&
memcmp(f1.fss.name + 1, f2.fss.name + 1, f1.fss.name[0]) == 0;
}
int filename_is_null(Filename fn)
{
return fn.fss.vRefNum == 0 && fn.fss.parID == 0 && fn.fss.name[0] == 0;
}
FILE *f_open(Filename fn, char const *mode, int is_private)
{
short savevol;
long savedir;
char tmp[256];
FILE *ret;
HGetVol(NULL, &savevol, &savedir);
if (HSetVol(NULL, fn.fss.vRefNum, fn.fss.parID) == noErr) {
p2cstrcpy(tmp, fn.fss.name);
ret = fopen(tmp, mode);
} else
ret = NULL;
HSetVol(NULL, savevol, savedir);
return ret;
}
struct tm ltime(void)
{
struct tm tm;
DateTimeRec d;
GetTime(&d);
tm.tm_sec=d.second;
tm.tm_min=d.minute;
tm.tm_hour=d.hour;
tm.tm_mday=d.day;
tm.tm_mon=d.month-1;
tm.tm_year=d.year-1900;
tm.tm_wday=d.dayOfWeek;
tm.tm_yday=1; /* GetTime doesn't tell us */
tm.tm_isdst=0; /* Have to do DST ourselves */
/* XXX find out DST adjustment and add it */
return tm;
}
const int platform_uses_x11_unix_by_default = FALSE;
char *platform_get_x_display(void) {
return NULL;
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,189 +0,0 @@
#include "putty.h"
#include "network.h"
#include "mac.h"
#include "ssh.h"
struct macnet_stack {
SockAddr (*namelookup)(char const *, char **);
SockAddr (*nonamelookup)(char const *);
void (*getaddr)(SockAddr, char *, int);
int (*hostname_is_local)(char *);
int (*address_is_local)(SockAddr);
int (*addrtype)(SockAddr);
void (*addrcopy)(SockAddr, char *);
void (*addr_free)(SockAddr);
Socket (*skregister)(void *, Plug); /* "register" is a reserved word */
Socket (*new)(SockAddr, int, int, int, int, int, Plug);
Socket (*newlistener)(char *, int, Plug, int, int);
char *(*addr_error)(SockAddr);
void (*poll)(void);
void (*cleanup)(void);
};
static struct macnet_stack *stack;
static struct macnet_stack ot = {
ot_namelookup, ot_nonamelookup, ot_getaddr, ot_hostname_is_local,
ot_address_is_local, ot_addrtype, ot_addrcopy, ot_addr_free,
ot_register, ot_new, ot_newlistener, ot_addr_error, ot_poll, ot_cleanup
};
#if !TARGET_API_MAC_CARBON
static struct macnet_stack mactcp = {
mactcp_namelookup, mactcp_nonamelookup, mactcp_getaddr,
mactcp_hostname_is_local, mactcp_address_is_local, mactcp_addrtype,
mactcp_addrcopy, mactcp_addr_free, mactcp_register, mactcp_new,
mactcp_newlistener, mactcp_addr_error, mactcp_poll, mactcp_cleanup
};
#endif
void sk_init(void)
{
#ifndef NO_OT
if (ot_init() == noErr)
stack = &ot;
else
#endif
#if !TARGET_API_MAC_CARBON
if (mactcp_init() == noErr)
stack = &mactcp;
else
#endif
stack = NULL;
}
/*
* Network functions exported to the world. These choose whether to call
* MacTCP or OpenTransport and behave accordingly.
*/
SockAddr sk_namelookup(char const *host, char **canonicalname, int address_family)
{
if (stack != NULL)
return stack->namelookup(host, canonicalname);
return NULL;
}
SockAddr sk_nonamelookup(char const *host)
{
if (stack != NULL)
return stack->nonamelookup(host);
return NULL;
}
void sk_getaddr(SockAddr addr, char *buf, int buflen)
{
if (stack != NULL)
stack->getaddr(addr, buf, buflen);
else
*buf = '\0';
}
int sk_hostname_is_local(char *name)
{
if (stack != NULL)
return stack->hostname_is_local(name);
return 0;
}
int sk_address_is_local(SockAddr addr)
{
if (stack != NULL)
return stack->address_is_local(addr);
return 0;
}
int sk_addrtype(SockAddr addr)
{
if (stack != NULL)
return stack->addrtype(addr);
return 0;
}
void sk_addrcopy(SockAddr addr, char *buf)
{
if (stack != NULL)
stack->addrcopy(addr, buf);
}
void sk_addr_free(SockAddr addr)
{
if (stack != NULL)
stack->addr_free(addr);
}
Socket sk_register(void *sock, Plug plug)
{
if (stack != NULL)
return stack->skregister(sock, plug);
return NULL;
}
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
if (stack != NULL)
return stack->new(addr, port, privport, oobinline, nodelay, keepalive,
plug);
return NULL;
}
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family)
{
if (stack != NULL)
return stack->newlistener(srcaddr, port, plug, local_host_only, address_family);
return NULL;
}
const char *sk_addr_error(SockAddr addr)
{
if (stack != NULL)
return stack->addr_error(addr);
return "No TCP/IP stack installed";
}
void sk_poll(void)
{
if (stack != NULL)
stack->poll();
}
void sk_cleanup(void)
{
if (stack != NULL)
stack->cleanup();
}
/* We should use Internet Config here. */
int net_service_lookup(char *service)
{
return 0;
}
SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
char **canonicalname)
{
return NULL;
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,97 +0,0 @@
/*
* Noise generation for PuTTY's cryptographic random number
* generator.
*/
#include <Processes.h>
#include <Types.h>
#include <Timer.h>
#include "putty.h"
#include "ssh.h"
#include "storage.h"
/*
* This function is called once, at PuTTY startup, and will do some
* seriously silly things like listing directories and getting disk
* free space and a process snapshot.
*/
static void noise_get_processes(void (*func) (void *, int))
{
ProcessSerialNumber psn = {0, kNoProcess};
ProcessInfoRec info;
for (;;) {
GetNextProcess(&psn);
if (psn.highLongOfPSN == 0 && psn.lowLongOfPSN == kNoProcess) return;
info.processInfoLength = sizeof(info);
info.processName = NULL;
info.processAppSpec = NULL;
GetProcessInformation(&psn, &info);
func(&info, sizeof(info));
}
}
void noise_get_heavy(void (*func) (void *, int))
{
noise_get_light(func);
noise_get_processes(func);
read_random_seed(func);
/* Update the seed immediately, in case another instance uses it. */
random_save_seed();
}
void random_save_seed(void)
{
int len;
void *data;
if (random_active) {
random_get_savedata(&data, &len);
write_random_seed(data, len);
sfree(data);
}
}
/*
* This function is called every time the random pool needs
* stirring, and will acquire the system time.
*/
void noise_get_light(void (*func) (void *, int))
{
UnsignedWide utc;
Microseconds(&utc);
func(&utc, sizeof(utc));
}
/*
* This function is called on a timer, and grabs as much changeable
* system data as it can quickly get its hands on.
*/
void noise_regular(void)
{
/* XXX */
}
/*
* This function is called on every keypress or mouse move, and
* will add the current time to the noise pool. It gets the scan
* code or mouse position passed in, and adds that too.
*/
void noise_ultralight(unsigned long data)
{
UnsignedWide utc;
Microseconds(&utc);
random_add_noise(&utc, sizeof(utc));
random_add_noise(&data, sizeof(data));
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,593 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 1999, 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* macpgen.c - PuTTYgen for Mac OS
*/
#include <MacTypes.h>
#include <AEDataModel.h>
#include <AppleEvents.h>
#include <Quickdraw.h>
#include <Fonts.h>
#include <MacWindows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Appearance.h>
#include <CodeFragments.h>
#include <Dialogs.h>
#include <Devices.h>
#include <DiskInit.h>
#include <Gestalt.h>
#include <LowMem.h>
#include <Navigation.h>
#include <Resources.h>
#include <Script.h>
#include <TextCommon.h>
#include <ToolUtils.h>
#include <UnicodeConverter.h>
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h> /* putty.h needs size_t */
#include <stdio.h> /* for vsprintf */
#define PUTTY_DO_GLOBALS
#include "macpgrid.h"
#include "putty.h"
#include "ssh.h"
#include "mac.h"
static void mac_startup(void);
static void mac_eventloop(void);
#pragma noreturn (mac_eventloop)
static void mac_event(EventRecord *);
static void mac_contentclick(WindowPtr, EventRecord *);
static void mac_growwindow(WindowPtr, EventRecord *);
static void mac_activatewindow(WindowPtr, EventRecord *);
static void mac_suspendresume(EventRecord *);
static void mac_updatewindow(WindowPtr);
static void mac_keypress(EventRecord *);
static int mac_windowtype(WindowPtr);
static void mac_menucommand(long);
static void mac_adjustcursor(RgnHandle);
static void mac_adjustmenus(void);
static void mac_closewindow(WindowPtr);
static void mac_zoomwindow(WindowPtr, short);
#pragma noreturn (cleanup_exit)
struct mac_windows {
WindowPtr about;
WindowPtr licence;
};
struct mac_windows windows;
int borednow;
struct mac_gestalts mac_gestalts;
int main (int argc, char **argv) {
mac_startup();
mac_eventloop();
}
#pragma noreturn (main)
static void mac_startup(void) {
Handle menuBar;
TECInfoHandle ti;
#if !TARGET_API_MAC_CARBON
/* Init Memory Manager */
MaxApplZone();
/* Init QuickDraw */
InitGraf(&qd.thePort);
/* Init Font Manager */
InitFonts();
/* Init Window Manager */
InitWindows();
/* Init Menu Manager */
InitMenus();
/* Init TextEdit */
TEInit();
/* Init Dialog Manager */
InitDialogs(NULL);
#endif
/* Get base system version (only used if there's no better selector) */
if (Gestalt(gestaltSystemVersion, &mac_gestalts.sysvers) != noErr ||
(mac_gestalts.sysvers &= 0xffff) < 0x700)
fatalbox("PuTTYgen requires System 7 or newer");
/* Find out if we've got Color Quickdraw */
if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
mac_gestalts.qdvers = gestaltOriginalQD;
/* ... and the Appearance Manager? */
if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
mac_gestalts.apprvers = 0x0100;
else
mac_gestalts.apprvers = 0;
#if TARGET_RT_MAC_CFM
/* Paranoia: Did we manage to pull in AppearanceLib? */
if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
mac_gestalts.apprvers = 0;
#endif
#if TARGET_CPU_68K
mac_gestalts.cntlattr = 0;
mac_gestalts.windattr = 0;
#else
/* Mac OS 8.5 Control Manager (proportional scrollbars)? */
if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr ||
&SetControlViewSize == kUnresolvedCFragSymbolAddress)
mac_gestalts.cntlattr = 0;
/* Mac OS 8.5 Window Manager? */
if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr ||
&SetWindowContentColor == kUnresolvedCFragSymbolAddress)
mac_gestalts.windattr = 0;
#endif
/* Text Encoding Conversion Manager? */
if (
#if TARGET_RT_MAC_CFM
&TECGetInfo == kUnresolvedCFragSymbolAddress ||
#else
InitializeUnicodeConverter(NULL) != noErr ||
#endif
TECGetInfo(&ti) != noErr)
mac_gestalts.encvvers = 0;
else {
mac_gestalts.encvvers = (*ti)->tecVersion;
mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures;
DisposeHandle((Handle)ti);
}
/* Navigation Services? */
if (NavServicesAvailable())
mac_gestalts.navsvers = NavLibraryVersion();
else
mac_gestalts.navsvers = 0;
/* We've been tested with the Appearance Manager */
if (mac_gestalts.apprvers != 0)
RegisterAppearanceClient();
menuBar = GetNewMBar(128);
if (menuBar == NULL)
fatalbox("Unable to create menu bar.");
SetMenuBar(menuBar);
AppendResMenu(GetMenuHandle(mApple), 'DRVR');
mac_adjustmenus();
DrawMenuBar();
InitCursor();
windows.about = NULL;
windows.licence = NULL;
flags = FLAG_INTERACTIVE;
/* Install Apple Event handlers. */
#if 0
AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
NewAEEventHandlerUPP(&mac_aevt_oapp), 0, FALSE);
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
NewAEEventHandlerUPP(&mac_aevt_odoc), 0, FALSE);
AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
NewAEEventHandlerUPP(&mac_aevt_pdoc), 0, FALSE);
#endif
AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
NewAEEventHandlerUPP(&mac_aevt_quit), 0, FALSE);
}
static void mac_eventloop(void) {
Boolean gotevent;
EventRecord event;
RgnHandle cursrgn;
Point mousenow, mousethen;
KeyState *ks;
WindowPtr front;
cursrgn = NewRgn();
GetMouse(&mousethen);
for (;;) {
mac_adjustcursor(cursrgn);
gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn);
mac_adjustcursor(cursrgn);
front = mac_frontwindow();
if (front != NULL) {
ks = mac_windowkey(front);
if (ks->collecting_entropy) {
GetMouse(&mousenow);
if (mousenow.h != mousethen.h || mousenow.v != mousethen.v) {
ks->entropy[ks->entropy_got++] = *(unsigned *)&mousenow;
ks->entropy[ks->entropy_got++] = TickCount();
if (ks->entropy_got >= ks->entropy_required)
ks->collecting_entropy = 0;
SetControlValue(ks->progress, ks->entropy_got);
mousethen = mousenow;
}
SetEmptyRgn(cursrgn);
}
}
if (gotevent)
mac_event(&event);
if (borednow)
cleanup_exit(0);
}
DisposeRgn(cursrgn);
}
static void mac_event(EventRecord *event) {
short part;
WindowPtr window;
switch (event->what) {
case mouseDown:
part = FindWindow(event->where, &window);
switch (part) {
case inMenuBar:
mac_adjustmenus();
mac_menucommand(MenuSelect(event->where));
break;
#if !TARGET_API_MAC_CARBON
case inSysWindow:
SystemClick(event, window);
break;
#endif
case inContent:
if (window != FrontWindow())
/* XXX: check for movable modal dboxes? */
SelectWindow(window);
else
mac_contentclick(window, event);
break;
case inGoAway:
if (TrackGoAway(window, event->where))
mac_closewindow(window);
break;
case inDrag:
/* XXX: moveable modal check? */
#if TARGET_API_MAC_CARBON
{
BitMap screenBits;
GetQDGlobalsScreenBits(&screenBits);
DragWindow(window, event->where, &screenBits.bounds);
}
#else
DragWindow(window, event->where, &qd.screenBits.bounds);
#endif
break;
case inGrow:
mac_growwindow(window, event);
break;
case inZoomIn:
case inZoomOut:
if (TrackBox(window, event->where, part))
mac_zoomwindow(window, part);
break;
}
break;
case keyDown:
case autoKey:
mac_keypress(event);
break;
case activateEvt:
mac_activatewindow((WindowPtr)event->message, event);
break;
case updateEvt:
mac_updatewindow((WindowPtr)event->message);
break;
#if !TARGET_API_MAC_CARBON
case diskEvt:
if (HiWord(event->message) != noErr) {
Point pt;
SetPt(&pt, 120, 120);
DIBadMount(pt, event->message);
}
break;
#endif
case osEvt:
switch ((event->message & osEvtMessageMask) >> 24) {
case suspendResumeMessage:
mac_suspendresume(event);
break;
}
break;
case kHighLevelEvent:
AEProcessAppleEvent(event); /* errors? */
break;
}
}
static void mac_contentclick(WindowPtr window, EventRecord *event)
{
if (mac_wininfo(window)->click != NULL)
(*mac_wininfo(window)->click)(window, event);
}
static void mac_growwindow(WindowPtr window, EventRecord *event)
{
if (mac_wininfo(window)->grow != NULL)
(*mac_wininfo(window)->grow)(window, event);
}
static void mac_activatewindow(WindowPtr window, EventRecord *event)
{
mac_adjustmenus();
if (mac_wininfo(window)->activate != NULL)
(*mac_wininfo(window)->activate)(window, event);
}
static void mac_updatewindow(WindowPtr window)
{
if (mac_wininfo(window)->update != NULL)
(*mac_wininfo(window)->update)(window);
}
/*
* Work out what kind of window we're dealing with.
*/
static int mac_windowtype(WindowPtr window)
{
#if !TARGET_API_MAC_CARBON
if (GetWindowKind(window) < 0)
return wDA;
#endif
return ((WinInfo *)GetWRefCon(window))->wtype;
}
/*
* Handle a key press
*/
static void mac_keypress(EventRecord *event)
{
WindowPtr window;
window = FrontWindow();
if (event->what == keyDown && (event->modifiers & cmdKey)) {
mac_adjustmenus();
mac_menucommand(MenuKey(event->message & charCodeMask));
} else {
if (mac_wininfo(window)->key != NULL)
(*mac_wininfo(window)->key)(window, event);
}
}
static void mac_menucommand(long result)
{
short menu, item;
WindowPtr window;
#if !TARGET_API_MAC_CARBON
Str255 da;
#endif
menu = HiWord(result);
item = LoWord(result);
window = FrontWindow();
/* Things which do the same whatever window we're in. */
switch (menu) {
case mApple:
switch (item) {
case iAbout:
mac_openabout();
goto done;
#if !TARGET_API_MAC_CARBON
default:
GetMenuItemText(GetMenuHandle(mApple), item, da);
OpenDeskAcc(da);
goto done;
#endif
}
break;
case mFile:
switch (item) {
case iNew:
mac_newkey();
goto done;
case iClose:
mac_closewindow(window);
goto done;
case iQuit:
cleanup_exit(0);
goto done;
}
break;
}
/* If we get here, handling is up to window-specific code. */
if (mac_wininfo(window)->menu != NULL)
(*mac_wininfo(window)->menu)(window, menu, item);
done:
HiliteMenu(0);
}
static void mac_closewindow(WindowPtr window)
{
switch (mac_windowtype(window)) {
#if !TARGET_API_MAC_CARBON
case wDA:
CloseDeskAcc(GetWindowKind(window));
break;
#endif
default:
if (mac_wininfo(window)->close != NULL)
(*mac_wininfo(window)->close)(window);
}
}
static void mac_suspendresume(EventRecord *event)
{
WindowPtr front;
EventRecord fakeevent;
/*
* We're called either before we're suspended or after we're
* resumed, so we're the front application at this point.
*/
front = FrontWindow();
if (front != NULL) {
fakeevent.what = activateEvt;
fakeevent.message = (UInt32)front;
fakeevent.when = event->when;
fakeevent.where = event->where;
fakeevent.modifiers =
(event->message & resumeFlag) ? activeFlag : 0;
mac_activatewindow(front, &fakeevent);
}
}
static void mac_zoomwindow(WindowPtr window, short part) {
/* FIXME: do something */
}
/*
* Make the menus look right before the user gets to see them.
*/
#if TARGET_API_MAC_CARBON
#define EnableItem EnableMenuItem
#define DisableItem DisableMenuItem
#endif
static void mac_adjustmenus(void) {
WindowPtr window;
MenuHandle menu;
window = FrontWindow();
menu = GetMenuHandle(mApple);
EnableItem(menu, 0);
EnableItem(menu, iAbout);
menu = GetMenuHandle(mFile);
EnableItem(menu, 0);
EnableItem(menu, iNew);
if (window != NULL)
EnableItem(menu, iClose);
else
DisableItem(menu, iClose);
EnableItem(menu, iQuit);
if (mac_wininfo(window)->adjustmenus != NULL)
(*mac_wininfo(window)->adjustmenus)(window);
else {
DisableItem(menu, iSave);
DisableItem(menu, iSaveAs);
menu = GetMenuHandle(mEdit);
DisableItem(menu, 0);
menu = GetMenuHandle(mWindow);
DisableItem(menu, 0); /* Until we get more than 1 item on it. */
}
DrawMenuBar();
}
/*
* Make sure the right cursor's being displayed.
*/
static void mac_adjustcursor(RgnHandle cursrgn)
{
Point mouse;
WindowPtr window, front;
short part;
#if TARGET_API_MAC_CARBON
Cursor arrow;
RgnHandle visrgn;
#endif
GetMouse(&mouse);
LocalToGlobal(&mouse);
part = FindWindow(mouse, &window);
front = FrontWindow();
if (part != inContent || window == NULL || window != front) {
/* Cursor isn't in the front window, so switch to arrow */
#if TARGET_API_MAC_CARBON
GetQDGlobalsArrow(&arrow);
SetCursor(&arrow);
#else
SetCursor(&qd.arrow);
#endif
SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
if (front != NULL) {
#if TARGET_API_MAC_CARBON
visrgn = NewRgn();
GetPortVisibleRegion(GetWindowPort(front), visrgn);
DiffRgn(cursrgn, visrgn, cursrgn);
DisposeRgn(visrgn);
#else
DiffRgn(cursrgn, front->visRgn, cursrgn);
#endif
}
} else {
if (mac_wininfo(window)->adjustcursor != NULL)
(*mac_wininfo(window)->adjustcursor)(window, mouse, cursrgn);
else {
#if TARGET_API_MAC_CARBON
GetQDGlobalsArrow(&arrow);
SetCursor(&arrow);
GetPortVisibleRegion(GetWindowPort(window), cursrgn);
#else
SetCursor(&qd.arrow);
CopyRgn(window->visRgn, cursrgn);
#endif
}
}
}
pascal OSErr mac_aevt_quit(const AppleEvent *req, AppleEvent *reply,
long refcon)
{
DescType type;
Size size;
if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
&type, NULL, 0, &size) == noErr)
return errAEParamMissed;
borednow = 1;
return noErr;
}
void cleanup_exit(int status)
{
#if !TARGET_RT_MAC_CFM
if (mac_gestalts.encvvers != 0)
TerminateUnicodeConverter();
#endif
exit(status);
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,509 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 1999, 2002, 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* PuTTYgen resources */
/*
* The space after the # for system includes is to stop mkfiles.pl
* trying to chase them (Rez doesn't support the angle-bracket
* syntax).
*/
# include "Types.r"
# include "Dialogs.r"
# include "Palettes.r"
# include "Script.r"
/* Get resource IDs we share with C code */
#include "macpgrid.h"
#include "version.r"
/*
* Finder-related resources
*/
/* 'pGen' is now registered with Apple as PuTTYgen's signature */
type 'pGen' as 'STR ';
resource 'pGen' (0, purgeable) {
"PuTTYgen experimental Mac port"
};
resource 'SIZE' (-1) {
reserved,
acceptSuspendResumeEvents,
reserved,
canBackground,
doesActivateOnFGSwitch,
backgroundAndForeground,
dontGetFrontClicks,
ignoreAppDiedEvents,
is32BitCompatible,
isHighLevelEventAware,
localandRemoteHLEvents,
isStationeryAware,
dontUseTextEditServices,
reserved,
reserved,
reserved,
1024 * 1024, /* Minimum size */
1024 * 1024, /* Preferred size */
};
#define FREF_APPL 128
#define FREF_Seed 132
resource 'FREF' (FREF_APPL, purgeable) {
/* The application itself */
'APPL', FREF_APPL, ""
};
resource 'FREF' (FREF_Seed, purgeable) {
/* Random seed */
'Seed', FREF_Seed, ""
};
/* "Internal" file types, which can't be opened */
resource 'BNDL' (129, purgeable) {
'pTTI', 0,
{
'ICN#', {
FREF_Seed, FREF_Seed,
},
'FREF', {
FREF_Seed, FREF_Seed,
};
};
};
resource 'kind' (129) {
'pTTI',
verBritain,
{
'Seed', "PuTTY random number seed",
}
};
#if TARGET_API_MAC_CARBON
/*
* Mac OS X Info.plist.
* See Tech Note TN2013 for details.
* We don't bother with things that Mac OS X seems to be able to get from
* other resources.
*/
type 'plst' as 'TEXT';
resource 'plst' (0) {
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<!DOCTYPE plist PUBLIC '-//Apple Computer//DTD PLIST 1.0//EN'\n"
" 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>\n"
"<plist version='1.0'>\n"
" <dict>\n"
" <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string>\n"
" <key>CFBundleIdentifier</key>\n"
" <string>org.tartarus.projects.putty.puttygen</string>\n"
" <key>CFBundleName</key> <string>PuTTYgen</string>\n"
" <key>CFBundlePackageType</key> <string>APPL</string>\n"
" <key>CFBundleSignature</key> <string>pGen</string>\n"
" </dict>\n"
"</plist>\n"
};
/* Mac OS X doesn't use this, but Mac OS 9 does. */
type 'carb' as 'TEXT';
resource 'carb' (0) { "" };
#endif
/* Icons, courtesy of DeRez */
/* Random seed icon */
resource 'ICN#' (FREF_Seed, purgeable) {
{ /* array: 2 elements */
/* [1] */
$"1FFFFC00 18F36600 161EF500 1CC92C80"
$"1CF2EC40 10662C20 108E07F0 151F0490"
$"1E00C4F0 1803BBD0 1FC5BE10 108B5A90"
$"1B3C4F50 1267AC90 14B60470 1BB791B0"
$"17F4D2B0 1DC1F830 1B029450 1B753DD0"
$"145A8170 11390DD0 1E15A8B0 1CC4CD90"
$"154ECED0 15C9CF30 172CDB50 12617970"
$"15E45C90 1D4B9890 15CE4430 1FFFFFF0",
/* [2] */
$"1FFFFC00 1FFFFE00 1FFFFF00 1FFFFF80"
$"1FFFFFC0 1FFFFFE0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
$"1FFFFFF0 1FFFFFF0 1FFFFFF0 1FFFFFF0"
}
};
resource 'icl4' (FREF_Seed) {
$"000FFFFFFFFFFFFFFFFFFF0000000000"
$"000FFC0CFFFF0CFF1FFC0FF000000000"
$"000F0FF0C0CFFFF1FFFFCFCF00000000"
$"000FFF0CFF0CF11F0CFCFFCCF0000000"
$"000FFFC0FFFF11F0FFF0FFCCCF000000"
$"000F0C0C0FF11FFC0CFCFFCCCCF00000"
$"000FC0C0F111FFF0C0C0CFFFFFFF0000"
$"000F0F0F111FFFFF0C0C0F0CFC0F0000"
$"000FFFF111111111FFC0CFC0FFFF0000"
$"000FF111111111FFFCFFF0FFFF0F0000"
$"000FFFFFFF111FCFF0FFFFF0C0CF0000"
$"000F0C0CF111FCFF0F0FFCFCFC0F0000"
$"000FF0FF11FFFFC0CFC0FFFFCFCF0000"
$"000F0CF11FFC0FFFFCFCFF0CFC0F0000"
$"000FCF11F0FFCFF0C0C0CFC0CFFF0000"
$"000FF1FFFCFF0FFFFC0F0C0FFCFF0000"
$"000F1FFFFFFFCFC0FFCFC0F0F0FF0000"
$"000FFF0FFF0C0C0FFFFFFC0C0CFF0000"
$"000FF0FFC0C0C0F0F0CF0FC0CFCF0000"
$"000FFCFF0FFF0F0F0CFFFF0FFF0F0000"
$"000FCFC0CF0FF0F0F0C0C0CFCFFF0000"
$"000F0C0F0CFFFC0F0C0CFF0FFF0F0000"
$"000FFFF0C0CFCFCFF0F0F0C0F0FF0000"
$"000FFF0CFF0C0F0CFF0CFF0FFC0F0000"
$"000FCFCF0FC0FFF0FFC0FFF0FFCF0000"
$"000F0F0FFF0CFC0FFF0CFFFF0CFF0000"
$"000FCFFFC0F0FFC0FFCFF0FFCFCF0000"
$"000F0CFC0FFC0C0F0FFFFC0F0FFF0000"
$"000FCFCFFFF0CFC0CFCFFFC0F0CF0000"
$"000FFF0F0F0CF0FFFC0FFC0CFC0F0000"
$"000FCFCFFFC0FFF0CFC0CFC0C0FF0000"
$"000FFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource 'icl8' (FREF_Seed) {
$"000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000"
$"000000FFFFF5F5F5FFFFFFFFF5F5FFFF05FFFFF5F5FFFF000000000000000000"
$"000000FFF5FFFFF5F5F5F5FFFFFFFF05FFFFFFFFF5FF2BFF0000000000000000"
$"000000FFFFFFF5F5FFFFF5F5FF0505FF0000FFF5FFFF2B2BFF00000000000000"
$"000000FFFFFFF5F5FFFFFFFF0505FFF5FFFFFFF5FFFF2B2B2BFF000000000000"
$"000000FFF5F5F5F5F5FFFF0505FFFFF5F5F5FFF5FFFF2B2B2B2BFF0000000000"
$"000000FFF5F5F5F5FF050505FFFFFFF5F5F5F5F5F5FFFFFFFFFFFFFF00000000"
$"000000FFF5FFF5FF050505FFFFFFFFFFF5F5F5F5F5FFF5F5FFF5F5FF00000000"
$"000000FFFFFFFF050505050505050505FFFFF5F5F5FFF5F5FFFFFFFF00000000"
$"000000FFFF050505050505050505FFFFFFF5FFFFFFF5FFFFFFFFF5FF00000000"
$"000000FFFFFFFFFFFFFF050505FFF5FFFFF5FFFFFFFFFFF5F5F5F5FF00000000"
$"000000FFF5F5F5F5FF050505FFF5FFFFF5FFF5FFFFF5FFF5FFF5F5FF00000000"
$"000000FFFFF5FFFF0505FFFFFFFFF5F5F5FFF5F5FFFFFFFFF5FFF5FF00000000"
$"000000FFF5F5FF0505FFFFF5F5FFFFFFFFF5FFF5FFFFF5F5FFF5F5FF00000000"
$"000000FFF5FF0505FFF5FFFFF5FFFFF5F5F5F5F5F5FFF5F5F5FFFFFF00000000"
$"000000FFFF05FFFFFFF5FFFFF5FFFFFFFFF5F5FFF5F5F5FFFFF5FFFF00000000"
$"000000FF05FFFFFFFFFFFFFFF5FFF5F5FFFFF5FFF5F5FFF5FFF5FFFF00000000"
$"000000FFFFFFF5FFFFFFF5F5F5F5F5FFFFFFFFFFFFF5F5F5F5F5FFFF00000000"
$"000000FFFFF5FFFFF5F5F5F5F5F5FF00FFF5F5FFF5FFF5F5F5FFF5FF00000000"
$"000000FFFFF5FFFFF5FFFFFFF5FF00FFF5F5FFFFFFFFF5FFFFFFF5FF00000000"
$"000000FFF5FFF5F5F5FFF5FFFF00FF00FFF5F5F5F5F5F5FFF5FFFFFF00000000"
$"000000FFF5F5F5FFF5F5FFFFFF0000FFF5F5F5F5FFFFF5FFFFFF00FF00000000"
$"000000FFFFFFFFF5F5F5F5FFF5FF00FFFFF5FFF5FFF5F5F5FF00FFFF00000000"
$"000000FFFFFFF5F5FFFFF5F5F5FF0000FFFFF5F5FFFFF5FFFF0000FF00000000"
$"000000FFF5FFF5FFF5FFF5F5FFFFFF00FFFFF5F5FFFFFFF5FFFF00FF00000000"
$"000000FFF5FFF5FFFFFFF5F5FFF5F5FFFFFFF5F5FFFFFFFFF5F5FFFF00000000"
$"000000FFF5FFFFFFF5F5FFF5FFFFF5F5FFFFF5FFFFF5FFFFF5FFF5FF00000000"
$"000000FFF5F5FFF5F5FFFFF5F5F5F5FFF5FFFFFFFFF5F5FFF5FFFFFF00000000"
$"000000FFF5FFF5FFFFFFFFF5F5FFF5F5F5FFF5FFFFFFF5F5FFF5F5FF00000000"
$"000000FFFFFFF5FFF5FFF5F5FFF5FFFFFFF5F5FFFFF5F5F5FFF5F5FF00000000"
$"000000FFF5FFF5FFFFFFF5F5FFFFFFF5F5FFF5F5F5FFF5F5F5F5FFFF00000000"
$"000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource 'ics#' (FREF_Seed) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 56B0 59A8 637C 51DC 6794 59AC 76EC"
$"7224 7C6C 743C 71AC 505C 459C 4424 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics4' (FREF_Seed) {
$"0FFFFFFFFFF00000"
$"0F0F0FF1FCFF0000"
$"0FCFF11FF0FCF000"
$"0FF111FF0FFFFF00"
$"0FCF111FFFCFFF00"
$"0FF11FFFFC0F0F00"
$"0F1FF0CFF0F0FF00"
$"0FFF0FFCFFFCFF00"
$"0FFFC0F0C0F0CF00"
$"0FFFFF0C0FFCFF00"
$"0FFFCFC0C0FFFF00"
$"0FFF0C0FFCFCFF00"
$"0FCFC0C0CFCFFF00"
$"0F0C0F0FFC0FFF00"
$"0FC0CFC0C0F0CF00"
$"0FFFFFFFFFFFFF"
};
resource 'ics8' (FREF_Seed) {
$"00FFFFFFFFFFFFFFFFFFFF0000000000"
$"00FFF5FFF5FFFF05FFF5FFFF00000000"
$"00FFF5FFFF0505FFFFF5FF2BFF000000"
$"00FFFF050505FFFFF5FFFFFFFFFF0000"
$"00FFF5FF050505FFFFFFF5FFFFFF0000"
$"00FFFF0505FFFFFFFFF5F5FFF5FF0000"
$"00FF05FFFFF5F5FFFFF5FFF5FFFF0000"
$"00FFFFFFF5FFFFF5FFFFFFF5FFFF0000"
$"00FFFFFFF5F5FFF5F5F5FFF5F5FF0000"
$"00FFFFFFFFFFF5F5F5FFFFF5FFFF0000"
$"00FFFFFFF5FFF5F5F5F5FFFFFFFF0000"
$"00FFFFFFF5F5F5FFFFF5FFF5FFFF0000"
$"00FFF5FFF5F5F5F5F5FFF5FFFFFF0000"
$"00FFF5F5F5FFF5FFFFF5F5FFFFFF0000"
$"00FFF5F5F5FFF5F5F5F5FFF5F5FF0000"
$"00FFFFFFFFFFFFFFFFFFFFFFFFFF"
};
/*
* Application-missing message string, for random seed and host key database
* files.
*/
resource 'STR ' (-16397, purgeable) {
"This file is used internally by PuTTY. It cannot be opened."
};
/* Missing-application name string, for private keys. */
/* XXX Private keys should eventually be owned by Pageant */
resource 'STR ' (-16396, purgeable) {
"PuTTYgen"
};
/*
* Internal resources
*/
/* Menu bar */
resource 'MBAR' (MBAR_Main, preload) {
{ mApple, mFile, mEdit, mWindow }
};
resource 'MENU' (mApple, preload) {
mApple,
textMenuProc,
0b11111111111111111111111111111101,
enabled,
apple,
{
"About PuTTYgen\0xc9", noicon, nokey, nomark, plain,
"-", noicon, nokey, nomark, plain,
}
};
resource 'MENU' (mFile, preload) {
mFile,
textMenuProc,
0b11111111111111111111111101111011,
enabled,
"File",
{
"New", noicon, "N", nomark, plain,
"Open\0xc9", noicon, "O", nomark, plain,
"-", noicon, nokey, nomark, plain,
"Close", noicon, "W", nomark, plain,
"Save", noicon, "S", nomark, plain,
"Save As\0xc9", noicon, nokey, nomark, plain,
"-", noicon, nokey, nomark, plain,
"Quit", noicon, "Q", nomark, plain,
}
};
resource 'MENU' (mEdit, preload) {
mEdit,
textMenuProc,
0b11111111111111111111111111111101,
enabled,
"Edit",
{
"Undo", noicon, "Z", nomark, plain,
"-", noicon, nokey, nomark, plain,
"Cut", noicon, "X", nomark, plain,
"Copy", noicon, "C", nomark, plain,
"Paste", noicon, "V", nomark, plain,
"Clear", noicon, nokey, nomark, plain,
"Select All", noicon, "A", nomark, plain,
}
};
resource 'MENU' (mWindow, preload) {
mWindow,
textMenuProc,
0b11111111111111111111111111111111,
enabled,
"Window",
{
}
};
/* Fatal error box. Stolen from the Finder. */
resource 'ALRT' (wFatal, "fatalbox", purgeable) {
{54, 67, 152, 435},
wFatal,
beepStages,
alertPositionMainScreen
};
resource 'DITL' (wFatal, "fatalbox", purgeable) {
{ /* array DITLarray: 3 elements */
/* [1] */
{68, 299, 88, 358},
Button {
enabled,
"OK"
},
/* [2] */
{68, 227, 88, 286},
StaticText {
disabled,
""
},
/* [3] */
{7, 74, 55, 358},
StaticText {
disabled,
"^0"
}
}
};
/* "About" box */
resource 'DLOG' (wAbout, "about", purgeable) {
{ 0, 0, 120, 240 },
noGrowDocProc,
invisible,
goAway,
wAbout, /* RefCon -- identifies the window to PuTTY */
wAbout, /* DITL ID */
"About PuTTYgen",
alertPositionMainScreen
};
resource 'dlgx' (wAbout, "about", purgeable) {
versionZero {
kDialogFlagsUseThemeBackground | kDialogFlagsUseThemeControls
}
};
resource 'DITL' (wAbout, "about", purgeable) {
{
{ 87, 13, 107, 227 },
Button { enabled, "View Licence" },
{ 13, 13, 29, 227 },
StaticText { disabled, "PuTTYgen"},
{ 42, 13, 74, 227 },
StaticText { disabled, "Some version or other\n"
"Copyright © 1997-2010 Simon Tatham"},
}
};
/* Licence box */
resource 'WIND' (wLicence, "licence", purgeable) {
{ 0, 0, 250, 400 },
noGrowDocProc,
visible,
goAway,
wLicence,
"PuTTYgen Licence",
alertPositionParentWindowScreen
};
type 'TEXT' {
string;
};
resource 'TEXT' (wLicence, "licence", purgeable) {
"Copyright 1997-2010 Simon Tatham.\n"
"\n"
"Portions copyright Robert de Bath, Joris van Rantwijk, Delian "
"Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, "
"Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus "
"Kuhn, Colin Watson, and CORE SDI S.A.\n"
"\n"
"Permission is hereby granted, free of charge, to any person "
"obtaining a copy of this software and associated documentation "
"files (the \"Software\"), to deal in the Software without "
"restriction, including without limitation the rights to use, "
"copy, modify, merge, publish, distribute, sublicense, and/or "
"sell copies of the Software, and to permit persons to whom the "
"Software is furnished to do so, subject to the following "
"conditions:\n\n"
"The above copyright notice and this permission notice shall be "
"included in all copies or substantial portions of the Software.\n\n"
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND "
"NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR "
"ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF "
"CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN "
"CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE "
"SOFTWARE."
};
/* Key box */
resource 'DLOG' (wKey, "key", purgeable) {
{ 0, 0, 120, 240 },
noGrowDocProc,
invisible,
goAway,
wKey, /* RefCon -- identifies the window to PuTTY */
wKey, /* DITL ID */
"untitled",
staggerParentWindowScreen
};
resource 'dlgx' (wKey, "key", purgeable) {
versionZero {
kDialogFlagsUseThemeBackground | kDialogFlagsUseThemeControls
}
};
#define cProgress 129
resource 'DITL' (wKey, "key", purgeable) {
{
{ 13, 13, 33, 227 },
Button { enabled, "Generate" },
{ 46, 13, 12, 227 },
Control { enabled, cProgress },
}
};
resource 'CNTL' (cProgress) {
{ 46, 13, 12, 227 },
0, visible, 0, 0,
kControlProgressBarProc, 0, ""
};

View File

@ -1,196 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2003 Ben Harris
* Copyright (c) 1997-2003 Simon Tatham
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* Stuff to handle the key window in PuTTYgen */
#include <MacTypes.h>
#include <Controls.h>
#include <Dialogs.h>
#include <MacWindows.h>
#include "putty.h"
#include "mac.h"
#include "macpgrid.h"
#include "ssh.h"
/* ----------------------------------------------------------------------
* Progress report code. This is really horrible :-)
*/
#define PROGRESSRANGE 65535
#define MAXPHASE 5
struct progress {
int nphases;
struct {
int exponential;
unsigned startpoint, total;
unsigned param, current, n; /* if exponential */
unsigned mult; /* if linear */
} phases[MAXPHASE];
unsigned total, divisor, range;
ControlHandle progbar;
};
static void progress_update(void *param, int action, int phase, int iprogress)
{
struct progress *p = (struct progress *) param;
unsigned progress = iprogress;
int position;
if (action < PROGFN_READY && p->nphases < phase)
p->nphases = phase;
switch (action) {
case PROGFN_INITIALISE:
p->nphases = 0;
break;
case PROGFN_LIN_PHASE:
p->phases[phase-1].exponential = 0;
p->phases[phase-1].mult = p->phases[phase].total / progress;
break;
case PROGFN_EXP_PHASE:
p->phases[phase-1].exponential = 1;
p->phases[phase-1].param = 0x10000 + progress;
p->phases[phase-1].current = p->phases[phase-1].total;
p->phases[phase-1].n = 0;
break;
case PROGFN_PHASE_EXTENT:
p->phases[phase-1].total = progress;
break;
case PROGFN_READY:
{
unsigned total = 0;
int i;
for (i = 0; i < p->nphases; i++) {
p->phases[i].startpoint = total;
total += p->phases[i].total;
}
p->total = total;
p->divisor = ((p->total + PROGRESSRANGE - 1) / PROGRESSRANGE);
p->range = p->total / p->divisor;
SetControlMaximum(p->progbar, p->range);
}
break;
case PROGFN_PROGRESS:
if (p->phases[phase-1].exponential) {
while (p->phases[phase-1].n < progress) {
p->phases[phase-1].n++;
p->phases[phase-1].current *= p->phases[phase-1].param;
p->phases[phase-1].current /= 0x10000;
}
position = (p->phases[phase-1].startpoint +
p->phases[phase-1].total - p->phases[phase-1].current);
} else {
position = (p->phases[phase-1].startpoint +
progress * p->phases[phase-1].mult);
}
SetControlValue(p->progbar, position / p->divisor);
break;
}
}
static void mac_clickkey(WindowPtr window, EventRecord *event)
{
short item;
DialogRef dialog;
KeyState *ks = mac_windowkey(window);
dialog = GetDialogFromWindow(window);
if (DialogSelect(event, &dialog, &item))
switch (item) {
case wiKeyGenerate:
SetControlMaximum(ks->progress, 1024);
ks->entropy = snewn(1024, unsigned int);
ks->entropy_required = 1024;
ks->entropy_got = 0;
ks->collecting_entropy = TRUE;
/* Do something */
break;
}
}
static void mac_activatekey(WindowPtr window, EventRecord *event)
{
DialogRef dialog;
DialogItemType itemtype;
Handle itemhandle;
short item;
Rect itemrect;
int active;
dialog = GetDialogFromWindow(window);
active = (event->modifiers & activeFlag) != 0;
GetDialogItem(dialog, wiKeyGenerate, &itemtype, &itemhandle, &itemrect);
HiliteControl((ControlHandle)itemhandle, active ? 0 : 255);
DialogSelect(event, &dialog, &item);
}
static void mac_updatekey(WindowPtr window)
{
#if TARGET_API_MAC_CARBON
RgnHandle rgn;
#endif
BeginUpdate(window);
#if TARGET_API_MAC_CARBON
rgn = NewRgn();
GetPortVisibleRegion(GetWindowPort(window), rgn);
UpdateDialog(GetDialogFromWindow(window), rgn);
DisposeRgn(rgn);
#else
UpdateDialog(window, window->visRgn);
#endif
EndUpdate(window);
}
void mac_newkey(void)
{
KeyState *ks;
WinInfo *wi;
Handle h;
short type;
Rect rect;
ks = snew(KeyState);
ks->box = GetNewDialog(wKey, NULL, (WindowPtr)-1);
GetDialogItem(ks->box, wiKeyProgress, &type, &h, &rect);
ks->progress = (ControlHandle)h;
wi = snew(WinInfo);
memset(wi, 0, sizeof(*wi));
wi->ks = ks;
wi->wtype = wKey;
wi->update = &mac_updatekey;
wi->click = &mac_clickkey;
wi->activate = &mac_activatekey;
SetWRefCon(GetDialogWindow(ks->box), (long)wi);
ShowWindow(GetDialogWindow(ks->box));
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,48 +0,0 @@
/* $Id$ */
/*
* macpgrid.h -- Mac resource IDs for PuTTYgen
*
* This file is shared by C and Rez source files
*/
/* Menu bar IDs */
#define MBAR_Main 128
/* Menu IDs */
#define mApple 128
#define mFile 129
#define mEdit 130
#define mWindow 131
/* Menu Items */
/* Apple menu */
#define iAbout 1
/* File menu */
#define iNew 1
#define iOpen 2
#define iClose 4
#define iSave 5
#define iSaveAs 6
#define iQuit 8
/* Edit menu */
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
#define iSelectAll 7
/* Window menu */
/* Window types (and resource IDs) */
#define wNone 0 /* Dummy value for no window */
#define wDA 1 /* Dummy value for desk accessory */
#define wFatal 128
#define wAbout 129
#define wiAboutLicence 1
#define wiAboutVersion 3
#define wLicence 131
#define wKey 134
#define wiKeyGenerate 1
#define wiKeyProgress 2

View File

@ -1,79 +0,0 @@
/* $Id$ */
/*
* macresid.h -- Mac resource IDs
*
* This file is shared by C and Rez source files
*/
/* TMPL for saved sessions */
#define TMPL_Int 128
/* Menu bar IDs */
#define MBAR_Main 128
/* Open IDs */
#define open_pTTY 128
/* Menu IDs */
#define mApple 128
#define mFile 129
#define mEdit 130
#define mWindow 131
/* Menu Items */
/* Apple menu */
#define iAbout 1
/* File menu */
#define iNew 1
#define iOpen 2
#define iChange 4
#define iClose 6
#define iSave 7
#define iSaveAs 8
#define iDuplicate 9
#define iQuit 11
/* Edit menu */
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
#define iSelectAll 7
/* Window menu */
#define iShowEventLog 1
/* Window types (and resource IDs) */
#define wNone 0 /* Dummy value for no window */
#define wDA 1 /* Dummy value for desk accessory */
#define wFatal 128
#define wAbout 129
#define wiAboutLicence 1
#define wiAboutVersion 3
#define wTerminal 130
#define wLicence 131
#define wSettings 132
#define wiSettingsOpen 1
#define wEventLog 133
#define wQuestion 134
#define wAbsent 135
#define wWrong 136
/* Controls */
#define cVScroll 128
/* ldes for list box controls */
#define ldes_Default 128
/* xDEFs */
#define CDEF_EditBox 129
#define SYS7_EDITBOX_VARIANT 0
#define SYS7_TEXT_VARIANT 1
#define SYS7_EDITBOX_PROC ((CDEF_EditBox << 4) + SYS7_EDITBOX_VARIANT)
#define SYS7_TEXT_PROC ((CDEF_EditBox << 4) + SYS7_TEXT_VARIANT)
#define CDEF_Default 130
#define SYS7_DEFAULT_PROC (CDEF_Default << 4)
#define CDEF_ListBox 131
#define SYS7_LISTBOX_PROC (CDEF_ListBox << 4)
#define CDEF_GroupBox 132
#define SYS7_GROUPBOX_PROC (CDEF_GroupBox << 4)

View File

@ -1,739 +0,0 @@
/* $Id$ */
/*
* macstore.c: Macintosh-specific impementation of the interface
* defined in storage.h
*/
#include <MacTypes.h>
#include <Folders.h>
#include <Memory.h>
#include <Resources.h>
#include <TextUtils.h>
#include <stdio.h>
#include <string.h>
#include "putty.h"
#include "storage.h"
#include "mac.h"
#include "macresid.h"
OSErr FSpGetDirID(FSSpec *f, long *idp, Boolean makeit);
/*
* We store each session as a file in the "PuTTY" sub-directory of the
* preferences folder. Each (key,value) pair is stored as a resource.
*/
OSErr get_putty_dir(Boolean makeit, short *pVRefNum, long *pDirID)
{
OSErr error = noErr;
short prefVRefNum;
FSSpec puttydir;
long prefDirID, puttyDirID;
error = FindFolder(kOnSystemDisk, kPreferencesFolderType, makeit,
&prefVRefNum, &prefDirID);
if (error != noErr) goto out;
error = FSMakeFSSpec(prefVRefNum, prefDirID, "\pPuTTY", &puttydir);
if (error != noErr && error != fnfErr) goto out;
error = FSpGetDirID(&puttydir, &puttyDirID, makeit);
if (error != noErr) goto out;
*pVRefNum = prefVRefNum;
*pDirID = puttyDirID;
out:
return error;
}
OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID) {
OSErr error = noErr;
short puttyVRefNum;
FSSpec sessdir;
long puttyDirID, sessDirID;
error = get_putty_dir(makeit, &puttyVRefNum, &puttyDirID);
if (error != noErr) goto out;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pSaved Sessions",
&sessdir);
if (error != noErr && error != fnfErr) goto out;
error = FSpGetDirID(&sessdir, &sessDirID, makeit);
if (error != noErr) goto out;
*pVRefNum = puttyVRefNum;
*pDirID = sessDirID;
out:
return error;
}
OSErr FSpGetDirID(FSSpec *f, long *idp, Boolean makeit) {
CInfoPBRec pb;
OSErr error = noErr;
pb.dirInfo.ioNamePtr = f->name;
pb.dirInfo.ioVRefNum = f->vRefNum;
pb.dirInfo.ioDrDirID = f->parID;
pb.dirInfo.ioFDirIndex = 0;
error = PBGetCatInfoSync(&pb);
if (error == fnfErr && makeit)
return FSpDirCreate(f, smSystemScript, idp);
if (error != noErr) goto out;
if ((pb.dirInfo.ioFlAttrib & ioDirMask) == 0) {
error = dirNFErr;
goto out;
}
*idp = pb.dirInfo.ioDrDirID;
out:
return error;
}
/* Copy a resource into the current resource file */
static OSErr copy_resource(ResType restype, short resid)
{
Handle h;
Str255 resname;
h = GetResource(restype, resid);
if (h != NULL) {
GetResInfo(h, &resid, &restype, resname);
DetachResource(h);
AddResource(h, restype, resid, resname);
if (ResError() == noErr)
WriteResource(h);
}
return ResError();
}
struct write_settings {
int fd;
FSSpec tmpfile;
FSSpec dstfile;
};
void *open_settings_w(char const *sessionname, char **errmsg) {
short sessVRefNum;
long sessDirID;
OSErr error;
Str255 psessionname;
FSSpec dstfile;
*errmsg = NULL;
error = get_session_dir(kCreateFolder, &sessVRefNum, &sessDirID);
if (error != noErr) return NULL;
if (!sessionname || !*sessionname)
sessionname = "Default Settings";
c2pstrcpy(psessionname, sessionname);
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &dstfile);
if (error == fnfErr) {
FSpCreateResFile(&dstfile, PUTTY_CREATOR, SESS_TYPE, smSystemScript);
if ((error = ResError()) != noErr) return NULL;
} else if (error != noErr) return NULL;
return open_settings_w_fsp(&dstfile);
}
/*
* NB: Destination file must exist.
*/
void *open_settings_w_fsp(FSSpec *dstfile)
{
short tmpVRefNum;
long tmpDirID;
struct write_settings *ws;
OSErr error;
Str255 tmpname;
ws = snew(struct write_settings);
ws->dstfile = *dstfile;
/* Create a temporary file to save to first. */
error = FindFolder(ws->dstfile.vRefNum, kTemporaryFolderType,
kCreateFolder, &tmpVRefNum, &tmpDirID);
if (error != noErr) goto out;
c2pstrcpy(tmpname, tmpnam(NULL));
error = FSMakeFSSpec(tmpVRefNum, tmpDirID, tmpname, &ws->tmpfile);
if (error != noErr && error != fnfErr) goto out;
if (error == noErr) {
error = FSpDelete(&ws->tmpfile);
if (error != noErr) goto out;
}
FSpCreateResFile(&ws->tmpfile, PUTTY_CREATOR, SESS_TYPE, smSystemScript);
if ((error = ResError()) != noErr) goto out;
ws->fd = FSpOpenResFile(&ws->tmpfile, fsWrPerm);
if (ws->fd == -1) {error = ResError(); goto out;}
/* Set up standard resources. Doesn't matter if these fail. */
copy_resource('STR ', -16396);
copy_resource('TMPL', TMPL_Int);
return ws;
out:
safefree(ws);
fatalbox("Failed to open session for write (%d)", error);
}
void write_setting_s(void *handle, char const *key, char const *value) {
int fd = *(int *)handle;
Handle h;
int id;
OSErr error;
Str255 pkey;
UseResFile(fd);
if (ResError() != noErr)
fatalbox("Failed to open saved session (%d)", ResError());
error = PtrToHand(value, &h, strlen(value));
if (error != noErr)
fatalbox("Failed to allocate memory");
/* Put the data in a resource. */
id = Unique1ID(FOUR_CHAR_CODE('TEXT'));
if (ResError() != noErr)
fatalbox("Failed to get ID for resource %s (%d)", key, ResError());
c2pstrcpy(pkey, key);
AddResource(h, FOUR_CHAR_CODE('TEXT'), id, pkey);
if (ResError() != noErr)
fatalbox("Failed to add resource %s (%d)", key, ResError());
}
void write_setting_i(void *handle, char const *key, int value) {
int fd = *(int *)handle;
Handle h;
int id;
OSErr error;
Str255 pkey;
UseResFile(fd);
if (ResError() != noErr)
fatalbox("Failed to open saved session (%d)", ResError());
/* XXX assume all systems have the same "int" format */
error = PtrToHand(&value, &h, sizeof(int));
if (error != noErr)
fatalbox("Failed to allocate memory (%d)", error);
/* Put the data in a resource. */
id = Unique1ID(FOUR_CHAR_CODE('Int '));
if (ResError() != noErr)
fatalbox("Failed to get ID for resource %s (%d)", key, ResError());
c2pstrcpy(pkey, key);
AddResource(h, FOUR_CHAR_CODE('Int '), id, pkey);
if (ResError() != noErr)
fatalbox("Failed to add resource %s (%d)", key, ResError());
}
void close_settings_w(void *handle) {
struct write_settings *ws = handle;
OSErr error;
CloseResFile(ws->fd);
if ((error = ResError()) != noErr)
goto out;
error = FSpExchangeFiles(&ws->tmpfile, &ws->dstfile);
if (error != noErr) goto out;
error = FSpDelete(&ws->tmpfile);
if (error != noErr) goto out;
return;
out:
fatalbox("Close of saved session failed (%d)", error);
safefree(handle);
}
void *open_settings_r(char const *sessionname)
{
short sessVRefNum;
long sessDirID;
FSSpec sessfile;
OSErr error;
Str255 psessionname;
error = get_session_dir(kDontCreateFolder, &sessVRefNum, &sessDirID);
if (!sessionname || !*sessionname)
sessionname = "Default Settings";
c2pstrcpy(psessionname, sessionname);
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &sessfile);
if (error != noErr) goto out;
return open_settings_r_fsp(&sessfile);
out:
return NULL;
}
void *open_settings_r_fsp(FSSpec *sessfile)
{
OSErr error;
int fd;
int *handle;
fd = FSpOpenResFile(sessfile, fsRdPerm);
if (fd == 0) {error = ResError(); goto out;}
handle = snew(int);
*handle = fd;
return handle;
out:
return NULL;
}
char *read_setting_s(void *handle, char const *key, char *buffer, int buflen) {
int fd;
Handle h;
size_t len;
Str255 pkey;
if (handle == NULL) goto out;
fd = *(int *)handle;
UseResFile(fd);
if (ResError() != noErr) goto out;
c2pstrcpy(pkey, key);
h = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), pkey);
if (h == NULL) goto out;
len = GetHandleSize(h);
if (len + 1 > buflen) goto out;
memcpy(buffer, *h, len);
buffer[len] = '\0';
ReleaseResource(h);
if (ResError() != noErr) goto out;
return buffer;
out:
return NULL;
}
int read_setting_i(void *handle, char const *key, int defvalue) {
int fd;
Handle h;
int value;
Str255 pkey;
if (handle == NULL) goto out;
fd = *(int *)handle;
UseResFile(fd);
if (ResError() != noErr) goto out;
c2pstrcpy(pkey, key);
h = Get1NamedResource(FOUR_CHAR_CODE('Int '), pkey);
if (h == NULL) goto out;
value = *(int *)*h;
ReleaseResource(h);
if (ResError() != noErr) goto out;
return value;
out:
return defvalue;
}
int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
{
char *settingname;
FontSpec ret;
char tmp[256];
if (!read_setting_s(handle, name, tmp, sizeof(tmp)))
return 0;
c2pstrcpy(ret.name, tmp);
settingname = dupcat(name, "Face", NULL);
ret.face = read_setting_i(handle, settingname, 0);
sfree(settingname);
settingname = dupcat(name, "Height", NULL);
ret.size = read_setting_i(handle, settingname, 0);
sfree(settingname);
if (ret.size == 0) return 0;
*result = ret;
return 1;
}
void write_setting_fontspec(void *handle, const char *name, FontSpec font)
{
char *settingname;
char tmp[256];
p2cstrcpy(tmp, font.name);
write_setting_s(handle, name, tmp);
settingname = dupcat(name, "Face", NULL);
write_setting_i(handle, settingname, font.face);
sfree(settingname);
settingname = dupcat(name, "Size", NULL);
write_setting_i(handle, settingname, font.size);
sfree(settingname);
}
int read_setting_filename(void *handle, const char *key, Filename *result)
{
int fd;
AliasHandle h;
Boolean changed;
OSErr err;
Str255 pkey;
if (handle == NULL) goto out;
fd = *(int *)handle;
UseResFile(fd);
if (ResError() != noErr) goto out;
c2pstrcpy(pkey, key);
h = (AliasHandle)Get1NamedResource(rAliasType, pkey);
if (h == NULL) goto out;
if ((*h)->userType == 'pTTY' && (*h)->aliasSize == sizeof(**h))
memset(result, 0, sizeof(*result));
else {
err = ResolveAlias(NULL, h, &result->fss, &changed);
if (err != noErr && err != fnfErr) goto out;
if ((*h)->userType == 'pTTY') {
long dirid;
StrFileName fname;
/* Tail of record is pascal string contaning leafname */
if (FSpGetDirID(&result->fss, &dirid, FALSE) != noErr) goto out;
memcpy(fname, (char *)*h + (*h)->aliasSize,
GetHandleSize((Handle)h) - (*h)->aliasSize);
err = FSMakeFSSpec(result->fss.vRefNum, dirid, fname,
&result->fss);
if (err != noErr && err != fnfErr) goto out;
}
}
ReleaseResource((Handle)h);
if (ResError() != noErr) goto out;
return 1;
out:
return 0;
}
void write_setting_filename(void *handle, const char *key, Filename fn)
{
int fd = *(int *)handle;
AliasHandle h;
int id;
OSErr error;
Str255 pkey;
UseResFile(fd);
if (ResError() != noErr)
fatalbox("Failed to open saved session (%d)", ResError());
if (filename_is_null(fn)) {
/* Generate a special "null" alias */
h = (AliasHandle)NewHandle(sizeof(**h));
if (h == NULL)
fatalbox("Failed to create fake alias");
(*h)->userType = 'pTTY';
(*h)->aliasSize = sizeof(**h);
} else {
error = NewAlias(NULL, &fn.fss, &h);
if (error == fnfErr) {
/*
* NewAlias can't create an alias for a nonexistent file.
* Create an alias for the directory, and record the
* filename as well.
*/
FSSpec tmpfss;
FSMakeFSSpec(fn.fss.vRefNum, fn.fss.parID, NULL, &tmpfss);
error = NewAlias(NULL, &tmpfss, &h);
if (error != noErr)
fatalbox("Failed to create alias");
(*h)->userType = 'pTTY';
SetHandleSize((Handle)h, (*h)->aliasSize + fn.fss.name[0] + 1);
if (MemError() != noErr)
fatalbox("Failed to create alias");
memcpy((char *)*h + (*h)->aliasSize, fn.fss.name,
fn.fss.name[0] + 1);
}
if (error != noErr)
fatalbox("Failed to create alias");
}
/* Put the data in a resource. */
id = Unique1ID(rAliasType);
if (ResError() != noErr)
fatalbox("Failed to get ID for resource %s (%d)", key, ResError());
c2pstrcpy(pkey, key);
AddResource((Handle)h, rAliasType, id, pkey);
if (ResError() != noErr)
fatalbox("Failed to add resource %s (%d)", key, ResError());
}
void close_settings_r(void *handle) {
int fd;
if (handle == NULL) return;
fd = *(int *)handle;
CloseResFile(fd);
if (ResError() != noErr)
fatalbox("Close of saved session failed (%d)", ResError());
sfree(handle);
}
void del_settings(char const *sessionname) {
OSErr error;
FSSpec sessfile;
short sessVRefNum;
long sessDirID;
Str255 psessionname;
error = get_session_dir(kDontCreateFolder, &sessVRefNum, &sessDirID);
c2pstrcpy(psessionname, sessionname);
error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &sessfile);
if (error != noErr) goto out;
error = FSpDelete(&sessfile);
return;
out:
fatalbox("Delete session failed (%d)", error);
}
struct enum_settings_state {
short vRefNum;
long dirID;
int index;
};
void *enum_settings_start(void) {
OSErr error;
struct enum_settings_state *state;
state = snew(struct enum_settings_state);
error = get_session_dir(kDontCreateFolder, &state->vRefNum, &state->dirID);
if (error != noErr) {
sfree(state);
return NULL;
}
state->index = 1;
return state;
}
char *enum_settings_next(void *handle, char *buffer, int buflen) {
struct enum_settings_state *e = handle;
CInfoPBRec pb;
OSErr error = noErr;
Str255 name;
if (e == NULL) return NULL;
do {
pb.hFileInfo.ioNamePtr = name;
pb.hFileInfo.ioVRefNum = e->vRefNum;
pb.hFileInfo.ioDirID = e->dirID;
pb.hFileInfo.ioFDirIndex = e->index++;
error = PBGetCatInfoSync(&pb);
if (error != noErr) return NULL;
} while (!((pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 &&
pb.hFileInfo.ioFlFndrInfo.fdCreator == PUTTY_CREATOR &&
pb.hFileInfo.ioFlFndrInfo.fdType == SESS_TYPE &&
name[0] < buflen));
p2cstrcpy(buffer, name);
return buffer;
}
void enum_settings_finish(void *handle) {
safefree(handle);
}
#define SEED_SIZE 512
void read_random_seed(noise_consumer_t consumer)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
char buf[SEED_SIZE];
short refnum;
long count = SEED_SIZE;
if (get_putty_dir(kDontCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
return;
if (HOpenDF(puttyVRefNum, puttyDirID, "\pPuTTY Random Seed", fsRdPerm,
&refnum) != noErr)
return;
error = FSRead(refnum, &count, buf);
if (error != noErr && error != eofErr)
return;
(*consumer)(buf, count);
FSClose(refnum);
}
/*
* We don't bother with the usual FSpExchangeFiles dance here because
* it doesn't really matter if the old random seed gets lost.
*/
void write_random_seed(void *data, int len)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
FSSpec dstfile;
short refnum;
long count = len;
if (get_putty_dir(kCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
return;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pPuTTY Random Seed",
&dstfile);
if (error == fnfErr) {
/* Set up standard resources */
FSpCreateResFile(&dstfile, INTERNAL_CREATOR, SEED_TYPE, smRoman);
refnum = FSpOpenResFile(&dstfile, fsWrPerm);
if (ResError() == noErr) {
copy_resource('STR ', -16397);
CloseResFile(refnum);
}
} else if (error != noErr) return;
if (FSpOpenDF(&dstfile, fsWrPerm, &refnum) != noErr) return;
FSWrite(refnum, &count, data);
FSClose(refnum);
return;
}
/*
* This host key cache uses a file in the PuTTY Preferences folder and
* stores keys as individual TEXT resources in the resource fork of
* that file. This has two problems. Firstly, a resource fork can
* contain no more than 2727 resources. Secondly, the Resource
* Manager uses a linear search to find a particular resource, which
* could make having lots of host keys quite slow.
*/
int verify_host_key(const char *hostname, int port,
const char *keytype, const char *key)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
FSSpec keyfile;
short refnum;
char *resname;
Str255 presname;
char *resvalue;
Handle reshandle;
int len, compare;
if (get_putty_dir(kCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
return 1;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pSSH Host Keys",
&keyfile);
if (error == fnfErr) {
/* Keys file doesn't exist yet, so we can't match the key */
return 1;
}
refnum = FSpOpenResFile(&keyfile, fsRdPerm);
if (refnum == -1) {
/* We couldn't open the resource fork, so we can't match the key */
return 1;
}
UseResFile(refnum);
resname = dupprintf("%s@%d:%s", keytype, port, hostname);
c2pstrcpy(presname, resname);
reshandle = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), presname);
if (ResError() != noErr) {
/* Couldn't open the specific resource */
return 1;
}
len = GetHandleSize(reshandle);
resvalue = snewn(len+1, char);
memcpy(resvalue, *reshandle, len);
resvalue[len]='\0';
ReleaseResource(reshandle);
CloseResFile(refnum);
compare = strncmp(resvalue, key, strlen(resvalue));
sfree(resname);
sfree(resvalue);
if (compare) {
/* Key different */
return 2;
} else {
/* Key matched */
return 0;
}
}
void store_host_key(const char *hostname, int port,
const char *keytype, const char *key)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
FSSpec keyfile;
short keyrefnum;
char *resname;
Str255 presname;
Handle resvalue;
Handle reshandle;
int id;
/* Open the host key file */
if (get_putty_dir(~kCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
goto out;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pSSH Host Keys",
&keyfile);
if (error == fnfErr) {
/* It doesn't exist, so create it */
FSpCreateResFile(&keyfile, INTERNAL_CREATOR, HKYS_TYPE, smRoman);
keyrefnum = FSpOpenResFile(&keyfile, fsWrPerm);
if (ResError() == noErr) {
copy_resource('STR', -16397); /* XXX: wtf is this? */
CloseResFile(keyrefnum);
}
} else if (error != noErr) goto out;
keyrefnum = FSpOpenResFile(&keyfile, fsWrPerm);
if (keyrefnum == -1) goto out;
UseResFile(keyrefnum);
resname = dupprintf("%s@%d:%s", keytype, port, hostname);
c2pstrcpy(presname, resname);
reshandle = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), presname);
if (reshandle != NULL) {
/* The resource exists, we're replacing a host key */
RemoveResource(reshandle);
}
error = PtrToHand(key, &resvalue, strlen(key));
if (error != noErr) goto out;
id = Unique1ID(FOUR_CHAR_CODE('TEXT'));
if (ResError() != noErr) goto out;
AddResource(resvalue, FOUR_CHAR_CODE('TEXT'), id, presname);
if (ResError() != noErr) goto out;
CloseResFile(keyrefnum);
return;
out:
fatalbox("Writing host key failed (%d)", error);
sfree(resname);
}
/*
* Emacs magic:
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,72 +0,0 @@
/*
* macstuff.h -- Mac-specific definitions visible to the rest of PuTTY.
*/
typedef void *Context; /* FIXME */
#include <MacTypes.h>
#include <Files.h>
#include <stdio.h>
#include "charset.h"
struct Filename {
FSSpec fss;
};
extern FILE * f_open(struct Filename, char const *, int);
/* Suspiciously similar to an ICFontRecord */
struct FontSpec {
short size;
Style face;
char pad;
Str255 name;
};
/*
* On the Mac, Unicode text copied to the clipboard has U+2028 line separators.
* Non-Unicode text will have these converted to CR along with the rest of the
* content.
*/
#define SEL_NL { 0x2028 }
#include <MacTypes.h>
#include <Events.h> /* Timing related goo */
#define GETTICKCOUNT TickCount
#define CURSORBLINK GetCaretTime()
#define TICKSPERSEC 60
#define DEFAULT_CODEPAGE 0 /* FIXME: no idea how to do this */
#define WCHAR wchar_t
#define BYTE UInt8
#define DWORD UInt32
typedef UInt32 uint32;
#define PUTTY_UINT32_DEFINED
#define OPTIMISE_SCROLL
/*
* sk_getxdmdata() does not exist under the Mac (SGT: I have no
* idea whatsoever how to write it, and furthermore I'm unconvinced
* it's necessary), so it's a macro which always returns NULL.
*/
#define sk_getxdmdata(socket, lenp) (NULL)
/* To make it compile */
#include <stdarg.h>
extern int vsnprintf(char *, size_t, char const *, va_list);
extern int stricmp(char const *, char const *);
extern int strnicmp(char const *, char const *, size_t);
#define HELPCTX(foo) I(0)
#define FILTER_KEY_FILES "pAgt.PPK"
#define CP_UTF8 CS_UTF8 /* from libcharset */

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +0,0 @@
/* $Id$ */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "putty.h"
#include "charset.h"
#include "terminal.h"
#include "misc.h"
#include "mac.h"
/*
* Mac Unicode-handling routines.
*
* BJH:
* What we _should_ do is to use the Text Encoding Conversion Manager
* when it's available, and have our own routines for converting to
* standard Mac OS scripts when it's not. Support for ATSUI might be
* nice, too.
*
* I (OSD) am unsure any of the above is necessary if we just use
* libcharset */
/*
* Determine whether a byte is the first byte of a double-byte
* character in a system character set. Only MI use is by clipme()
* when copying direct-to-font text to the clipboard.
*/
int is_dbcs_leadbyte(int codepage, char byte)
{
return 0; /* we don't do DBCS */
}
/*
* Convert from Unicode to a system character set. MI uses are:
* (1) by lpage_send(), whose only MI use is to convert the answerback
* string to Unicode, and
* (2) by clipme() when copying direct-to-font text to the clipboard.
*/
int mb_to_wc(int codepage, int flags, char *mbstr, int mblen,
wchar_t *wcstr, int wclen)
{
int ret = 0;
while (mblen > 0 && wclen > 0) {
*wcstr++ = (unsigned char) *mbstr++;
mblen--, wclen--, ret++;
}
return ret; /* FIXME: check error codes! */
}
/*
* Convert from a system character set to Unicode. Used by luni_send
* to convert Unicode into the line character set.
*/
int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
char *mbstr, int mblen, char *defchr, int *defused,
struct unicode_data *ucsdata)
{
int ret = 0;
if (defused)
*defused = 0;
while (mblen > 0 && wclen > 0) {
if (*wcstr >= 0x100) {
if (defchr)
*mbstr++ = *defchr;
else
*mbstr++ = '.';
if (defused)
*defused = 1;
} else
*mbstr++ = (unsigned char) *wcstr;
wcstr++;
mblen--, wclen--, ret++;
}
return ret; /* FIXME: check error codes! */
}
/* Character conversion array,
* the xterm one has the four scanlines that have no unicode 2.0
* equivalents mapped to their unicode 3.0 locations.
*/
static const wchar_t unitab_xterm_std[32] = {
0x2666, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
};
void init_ucs(Session *s)
{
int i;
s->ucsdata.line_codepage = decode_codepage(s->cfg.line_codepage);
/* Find the line control characters. FIXME: this is not right. */
for (i = 0; i < 256; i++)
if (i < ' ' || (i >= 0x7F && i < 0xA0))
s->ucsdata.unitab_ctrl[i] = i;
else
s->ucsdata.unitab_ctrl[i] = 0xFF;
for (i = 0; i < 256; i++)
s->ucsdata.unitab_line[i] = s->ucsdata.unitab_scoacs[i] = i;
/* VT100 graphics - NB: Broken for non-ascii CP's */
memcpy(s->ucsdata.unitab_xterm, s->ucsdata.unitab_line,
sizeof(s->ucsdata.unitab_xterm));
memcpy(s->ucsdata.unitab_xterm + '`', unitab_xterm_std,
sizeof(unitab_xterm_std));
s->ucsdata.unitab_xterm['_'] = ' ';
}
int decode_codepage(char *cp_name)
{
if (!*cp_name)
return CS_NONE; /* use font encoding */
return charset_from_localenc(cp_name);
}
char const *cp_enumerate (int index)
{
int charset;
if (index == 0)
return "Use font encoding";
charset = charset_localenc_nth(index-1);
if (charset == CS_NONE)
return NULL;
return charset_to_localenc(charset);
}
char const *cp_name(int codepage)
{
if (codepage == CS_NONE)
return "Use font encoding";
return charset_to_localenc(codepage);
}

View File

@ -1,15 +0,0 @@
# $Id$
Set makefile Makefile.mpw
# Run Make, then execute its output.
Echo "# `Date -t` ----- Analyzing dependencies."
Begin
Echo "Set Echo 1"
Make {"Parameters"} -f "{makefile}"
End > make.out
Echo "# `Date -t` ----- Executing build commands."
make.out
Delete make.out
Echo "# `Date -t` ----- Done."

View File

@ -1,842 +0,0 @@
/*
* Copyright (c) 2003 Ben Harris
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* mtcpnet.c - MacTCP interface
*/
#if !TARGET_API_MAC_CARBON
#include <MacTypes.h>
#include <Devices.h>
#include <Endian.h>
#include <Folders.h>
#include <MacTCP.h>
#include <MixedMode.h>
#include <Resources.h>
#include <assert.h>
#define DEFINE_PLUG_METHOD_MACROS
#include "putty.h"
#include "network.h"
#include "mac.h"
/*
* The following structures are documented as being in
* <AddressXlation.h>, but that isn't shipped with Universal
* Interfaces, and it's easier to define them here than to require
* people to download yet another SDK.
*/
static OSErr OpenResolver(char *);
static OSErr CloseResolver(void);
enum {
OPENRESOLVER = 1,
CLOSERESOLVER,
STRTOADDR,
ADDRTOSTR,
ENUMCACHE,
ADDRTONAME,
HXINFO,
MXINFO
};
#define NUM_ALT_ADDRS 4
typedef struct hostInfo {
int rtnCode;
char cname[255];
unsigned long addr[NUM_ALT_ADDRS];
};
typedef CALLBACK_API(void, ResultProcPtr)(struct hostInfo *, char *);
typedef STACK_UPP_TYPE(ResultProcPtr) ResultUPP;
enum { uppResultProcInfo = kPascalStackBased
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct hostInfo*)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
};
#define NewResultUPP(userRoutine) \
(ResultUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
uppResultProcInfo, \
GetCurrentArchitecture())
#define DisposeResultUPP(userUPP) DisposeRoutineDescriptor(userUPP)
static OSErr StrToAddr(char *, struct hostInfo *, ResultUPP *, char *);
typedef CALLBACK_API_C(OSErr, OpenResolverProcPtr)(UInt32, char *);
typedef STACK_UPP_TYPE(OpenResolverProcPtr) OpenResolverUPP;
enum { uppOpenResolverProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*)))
};
#define InvokeOpenResolverUPP(selector, fileName, userUPP) \
CALL_TWO_PARAMETER_UPP((userUPP), uppOpenResolverProcInfo, \
(selector), (fileName))
typedef CALLBACK_API_C(OSErr, CloseResolverProcPtr)(UInt32);
typedef STACK_UPP_TYPE(CloseResolverProcPtr) CloseResolverUPP;
enum { uppCloseResolverProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32)))
};
#define InvokeCloseResolverUPP(selector, userUPP) \
CALL_ONE_PARAMETER_UPP((userUPP), uppCloseResolverProcInfo, (selector))
typedef CALLBACK_API_C(OSErr, StrToAddrProcPtr)(UInt32, char *,
struct hostInfo *, ResultUPP,
char *);
typedef STACK_UPP_TYPE(StrToAddrProcPtr) StrToAddrUPP;
enum { uppStrToAddrProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
| STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
| STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ResultUPP)))
| STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
};
#define InvokeStrToAddrUPP(selector, hostName, hostInfoPtr, ResultProc, \
userDataPtr, userUPP) \
CALL_FIVE_PARAMETER_UPP((userUPP), uppStrToAddrProcInfo, (selector),\
(hostName), (hostInfoPtr), (ResultProc), \
(userDataPtr))
#define StrToAddr(hostName, hostInfoPtr, ResultProc, userDataPtr) \
InvokeStrToAddrUPP(STRTOADDR, hostName, hostInfoPtr, ResultProc, \
userDataPtr, (StrToAddrUPP)*mactcp.dnr_handle)
typedef CALLBACK_API_C(OSErr, AddrToStrProcPtr)(UInt32, unsigned long, char *);
typedef STACK_UPP_TYPE(AddrToStrProcPtr) AddrToStrUPP;
enum { uppAddrToStrProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
| STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
};
#define InvokeAddrToStrUPP(selector, addr, addrStr, userUPP) \
CALL_THREE_PARAMETER_UPP((userUPP), uppAddrToStrProcInfo, (selector),\
(addr), (addrStr))
#define AddrToStr(addr, addrStr) \
InvokeAddrToStrUPP(ADDRTOSTR, addr, addrStr, \
(AddrToStrUPP)*mactcp.dnr_handle)
/* End of AddressXlation.h bits */
/* TCP connection states, mysteriously missing from <MacTCP.h> */
#define TCPS_CLOSED 0
#define TCPS_LISTEN 2
#define TCPS_SYN_RECEIVED 4
#define TCPS_SYN_SENT 6
#define TCPS_ESTABLISHED 8
#define TCPS_FIN_WAIT_1 10
#define TCPS_FIN_WAIT_2 12
#define TCPS_CLOSE_WAIT 14
#define TCPS_CLOSING 16
#define TCPS_LAST_ACK 18
#define TCPS_TIME_WAIT 20
struct Socket_tag {
struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
StreamPtr s;
OSErr err;
Plug plug;
void *private_ptr;
bufchain output_data;
int connected;
int writable;
int frozen; /* this causes readability notifications to be ignored */
int frozen_readable; /* this means we missed at least one readability
* notification while we were frozen */
int localhost_only; /* for listening sockets */
char oobdata[1];
int sending_oob;
int oobpending; /* is there OOB data available to read? */
int oobinline;
int pending_error; /* in case send() returns error */
int listener;
struct Socket_tag *next;
struct Socket_tag **prev;
};
/*
* We used to typedef struct Socket_tag *Socket.
*
* Since we have made the networking abstraction slightly more
* abstract, Socket no longer means a tcp socket (it could mean
* an ssl socket). So now we must use Actual_Socket when we know
* we are talking about a tcp socket.
*/
typedef struct Socket_tag *Actual_Socket;
struct SockAddr_tag {
int resolved;
struct hostInfo hostinfo;
char hostname[512];
};
/* Global variables */
static struct {
Handle dnr_handle;
int initialised;
short refnum;
ProcessSerialNumber self;
Actual_Socket socklist;
} mactcp;
static pascal void mactcp_lookupdone(struct hostInfo *hi, char *cookie);
static pascal void mactcp_asr(StreamPtr, unsigned short, Ptr, unsigned short,
struct ICMPReport *);
static Plug mactcp_plug(Socket, Plug);
static void mactcp_flush(Socket);
static void mactcp_close(Socket);
static int mactcp_write(Socket, char const *, int);
static int mactcp_write_oob(Socket, char const*, int);
static void mactcp_set_private_ptr(Socket, void *);
static void *mactcp_get_private_ptr(Socket);
static const char *mactcp_socket_error(Socket);
static void mactcp_set_frozen(Socket, int);
static void mactcp_recv(Actual_Socket s, size_t len);
/*
* Initialise MacTCP.
* This should be called once before any TCP connection is opened.
*/
OSErr mactcp_init(void)
{
OSErr err;
/*
* IM:Devices describes a convoluted way of finding a spare unit
* number to open a driver on before calling OpenDriver. Happily,
* the MacTCP INIT ensures that .IPP is already open (and hence
* has a valid unit number already) so we don't need to go through
* all that. (MacTCP Programmer's Guide p6)
*/
err = OpenDriver("\p.IPP", &mactcp.refnum);
if (err != noErr) return err;
err = OpenResolver(NULL);
if (err != noErr) return err;
mactcp.initialised = TRUE;
return noErr;
}
void mactcp_cleanup(void)
{
Actual_Socket s, next;
/*
* Eventually, PuTTY should close down each session as it exits,
* so there should be no sockets left when we get here. Still,
* better safe than sorry.
*
* XXX What about in-flight aync I/O (when we support that)?
*/
for (s = mactcp.socklist; s != NULL; s = next) {
next = s->next; /* s is about to vanish */
mactcp_close(&s->fn);
}
/*
* When we get async DNS, we have to wait for any outstanding
* requests to complete here before exiting.
*/
CloseResolver();
mactcp.initialised = FALSE;
}
static ResultUPP mactcp_lookupdone_upp;
SockAddr mactcp_namelookup(char const *host, char **canonicalname)
{
SockAddr ret = snew(struct SockAddr_tag);
OSErr err;
volatile int done = FALSE;
char *realhost;
int realhostlen;
/* Clear the structure. */
memset(ret, 0, sizeof(struct SockAddr_tag));
if (mactcp_lookupdone_upp == NULL)
mactcp_lookupdone_upp = NewResultUPP(&mactcp_lookupdone);
/* Casting away const -- hope StrToAddr is sensible */
err = StrToAddr((char *)host, &ret->hostinfo, mactcp_lookupdone_upp,
(char *)&done);
/*
* PuTTY expects DNS lookups to be synchronous (see bug
* "async-dns"), so we pretend they are.
*/
if (err == cacheFault)
while (!done)
continue;
ret->resolved = TRUE;
if (ret->hostinfo.rtnCode == noErr) {
realhost = ret->hostinfo.cname;
/* MacTCP puts trailing dots on canonical names. */
realhostlen = strlen(realhost);
if (realhost[realhostlen - 1] == '.')
realhost[realhostlen - 1] = '\0';
} else
realhost = "";
*canonicalname = snewn(1 + strlen(realhost), char);
strcpy(*canonicalname, realhost);
return ret;
}
static pascal void mactcp_lookupdone(struct hostInfo *hi, char *cookie)
{
volatile int *donep = (int *)cookie;
*donep = TRUE;
}
SockAddr mactcp_nonamelookup(char const *host)
{
SockAddr ret = snew(struct SockAddr_tag);
ret->resolved = FALSE;
ret->hostinfo.rtnCode = noErr;
ret->hostname[0] = '\0';
strncat(ret->hostname, host, lenof(ret->hostname) - 1);
return ret;
}
void mactcp_getaddr(SockAddr addr, char *buf, int buflen)
{
char mybuf[16];
OSErr err;
if (addr->resolved) {
/* XXX only return first address */
err = AddrToStr(addr->hostinfo.addr[0], mybuf);
buf[0] = '\0';
if (err != noErr)
strncat(buf, mybuf, buflen - 1);
} else {
buf[0] = '\0';
strncat(buf, addr->hostname, buflen - 1);
}
}
/* I think "local" here really means "loopback" */
int mactcp_hostname_is_local(char *name)
{
return !strcmp(name, "localhost");
}
int mactcp_address_is_local(SockAddr addr)
{
int i;
if (addr->resolved)
for (i = 0; i < NUM_ALT_ADDRS; i++)
if (addr->hostinfo.addr[i] & 0xff000000 == 0x7f000000)
return TRUE;
return FALSE;
}
int mactcp_addrtype(SockAddr addr)
{
if (addr->resolved)
return ADDRTYPE_IPV4;
return ADDRTYPE_NAME;
}
void mactcp_addrcopy(SockAddr addr, char *buf)
{
/* XXX only return first address */
memcpy(buf, &addr->hostinfo.addr[0], 4);
}
void mactcp_addr_free(SockAddr addr)
{
sfree(addr);
}
static Plug mactcp_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock;
Plug ret = s->plug;
if (p)
s->plug = p;
return ret;
}
static void mactcp_flush(Socket s)
{
fatalbox("mactcp_flush");
}
Socket mactcp_register(void *sock, Plug plug)
{
fatalbox("mactcp_register");
}
static TCPNotifyUPP mactcp_asr_upp;
Socket mactcp_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
static struct socket_function_table fn_table = {
mactcp_plug,
mactcp_close,
mactcp_write,
mactcp_write_oob,
mactcp_flush,
mactcp_set_private_ptr,
mactcp_get_private_ptr,
mactcp_set_frozen,
mactcp_socket_error
};
TCPiopb pb;
UDPiopb upb;
Actual_Socket ret;
ip_addr dstaddr;
size_t buflen;
/*
* Create Socket structure.
*/
ret = snew(struct Socket_tag);
ret->s = 0;
ret->fn = &fn_table;
ret->err = noErr;
ret->plug = plug;
bufchain_init(&ret->output_data);
ret->connected = 0; /* to start with */
ret->writable = 0; /* to start with */
ret->sending_oob = 0;
ret->frozen = 0;
ret->frozen_readable = 0;
ret->localhost_only = 0; /* unused, but best init anyway */
ret->pending_error = 0;
ret->oobinline = oobinline;
ret->oobpending = FALSE;
ret->listener = 0;
dstaddr = addr->hostinfo.addr[0]; /* XXX should try all of them */
/*
* Create a TCP stream.
*
* MacTCP requires us to provide it with some buffer memory. Page
* 31 of the Programmer's Guide says it should be a minimum of
* 4*MTU+1024. Page 36 says a minimum of 4096 bytes. Assume
* they're both correct.
*/
assert(addr->resolved);
upb.ioCRefNum = mactcp.refnum;
upb.csCode = UDPMaxMTUSize;
upb.csParam.mtu.remoteHost = dstaddr;
upb.csParam.mtu.userDataPtr = NULL;
ret->err = PBControlSync((ParmBlkPtr)&upb);
if (ret->err != noErr) return (Socket)ret;
buflen = upb.csParam.mtu.mtuSize * 4 + 1024;
if (buflen < 4096) buflen = 4096;
if (mactcp_asr_upp == NULL)
mactcp_asr_upp = NewTCPNotifyUPP(&mactcp_asr);
GetCurrentProcess(&mactcp.self);
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPCreate;
pb.csParam.create.rcvBuff = snewn(buflen, char);
pb.csParam.create.rcvBuffLen = buflen;
pb.csParam.create.notifyProc = mactcp_asr_upp;
pb.csParam.create.userDataPtr = (Ptr)ret;
ret->err = PBControlSync((ParmBlkPtr)&pb);
if (ret->err != noErr) return (Socket)ret;
ret->s = pb.tcpStream;
/*
* Open the connection.
*/
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPActiveOpen;
pb.tcpStream = ret->s;
pb.csParam.open.validityFlags = 0;
pb.csParam.open.remoteHost = dstaddr;
pb.csParam.open.remotePort = port;
pb.csParam.open.localPort = privport ? 1023 : 0;
pb.csParam.open.dontFrag = FALSE;
pb.csParam.open.timeToLive = 0;
pb.csParam.open.security = 0;
pb.csParam.open.optionCnt = 0;
pb.csParam.open.userDataPtr = (Ptr)ret;
while (1) {
ret->err = PBControlSync((ParmBlkPtr)&pb);
if (!privport || ret->err != duplicateSocket)
break;
pb.csParam.open.localPort--;
if (pb.csParam.open.localPort == 0)
break;
}
if (ret->err != noErr) return (Socket)ret;
ret->connected = TRUE;
ret->writable = TRUE;
/* Add this to the list of all sockets */
ret->next = mactcp.socklist;
ret->prev = &mactcp.socklist;
if (ret->next != NULL)
ret->next->prev = &ret->next;
mactcp.socklist = ret;
sk_addr_free(addr); /* don't need this anymore */
return (Socket)ret;
}
Socket mactcp_newlistener(char *srcaddr, int port, Plug plug,
int local_host_only, int address_family)
{
fatalbox("mactcp_newlistener");
}
static void mactcp_close(Socket sock)
{
Actual_Socket s = (Actual_Socket)sock;
TCPiopb pb;
/*
* TCPClose is equivalent to shutdown(fd, SHUT_WR), and hence
* leaves the Rx side open, while TCPAbort seems rather vicious,
* throwing away Tx data that haven't been ACKed yet. We do both
* in succession.
*/
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPClose;
pb.tcpStream = s->s;
pb.csParam.close.validityFlags = 0;
pb.csParam.close.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
/* Not much we can do about an error anyway. */
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPAbort;
pb.tcpStream = s->s;
pb.csParam.abort.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
/* Even less we can do about an error here. */
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPRelease;
pb.tcpStream = s->s;
pb.csParam.create.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
if (s->err == noErr)
sfree(pb.csParam.create.rcvBuff);
/* Unhitch from list of sockets */
*s->prev = s->next;
if (s->next != NULL)
s->next->prev = s->prev;
sfree(s);
}
static int mactcp_write(Socket sock, char const *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
wdsEntry wds[2];
TCPiopb pb;
/*
* Casting away const from buf should be safe -- MacTCP won't
* write to it.
*/
wds[0].length = len;
wds[0].ptr = (char *)buf;
wds[1].length = 0;
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPSend;
pb.tcpStream = s->s;
pb.csParam.send.validityFlags = 0;
pb.csParam.send.pushFlag = TRUE; /* XXX we want it to return. */
pb.csParam.send.urgentFlag = 0;
pb.csParam.send.wdsPtr = (Ptr)wds;
pb.csParam.send.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
return 0;
}
static int mactcp_write_oob(Socket sock, char const *buf, int len)
{
fatalbox("mactcp_write_oob");
}
static pascal void mactcp_asr(StreamPtr str, unsigned short event, Ptr cookie,
unsigned short termin_reason,
struct ICMPReport *icmp)
{
WakeUpProcess(&mactcp.self);
}
/*
* Called from our event loop if there's work to do.
*/
void mactcp_poll(void)
{
Actual_Socket s, next;
TCPiopb pb;
for (s = mactcp.socklist; s != NULL; s = next) {
next = s->next;
do {
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPStatus;
pb.tcpStream = s->s;
pb.csParam.status.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
if (s->err != noErr)
goto next_socket;
if (pb.csParam.status.amtUnreadData == 0)
break;
mactcp_recv(s, pb.csParam.status.amtUnreadData);
} while (TRUE);
switch (pb.csParam.status.connectionState) {
case TCPS_CLOSE_WAIT:
/* Remote end has sent us a FIN */
plug_closing(s->plug, NULL, 0, 0);
}
next_socket:
;
}
}
static void mactcp_recv(Actual_Socket s, size_t len)
{
rdsEntry rds[2];
TCPiopb pb;
if (s->frozen) return;
while (len > 0) {
pb.ioCRefNum = mactcp.refnum;
pb.csCode = TCPNoCopyRcv;
pb.tcpStream = s->s;
pb.csParam.receive.commandTimeoutValue = 0;
pb.csParam.receive.rdsPtr = (Ptr)rds;
pb.csParam.receive.rdsLength = lenof(rds) - 1;
pb.csParam.receive.userDataPtr = (Ptr)s;
s->err = PBControlSync((ParmBlkPtr)&pb);
if (s->err != noErr)
return;
plug_receive(s->plug, 0, rds[0].ptr, rds[0].length);
len -= rds[0].length;
pb.csCode = TCPRcvBfrReturn;
s->err = PBControlSync((ParmBlkPtr)&pb);
if (s->err != noErr)
return;
}
}
/*
* Each socket abstraction contains a `void *' private field in
* which the client can keep state.
*/
static void mactcp_set_private_ptr(Socket sock, void *ptr)
{
Actual_Socket s = (Actual_Socket) sock;
s->private_ptr = ptr;
}
static void *mactcp_get_private_ptr(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
return s->private_ptr;
}
/*
* Special error values are returned from mactcp_namelookup and
* mactcp_new if there's a problem. These functions extract an error
* message, or return NULL if there's no problem.
*/
char *mactcp_addr_error(SockAddr addr)
{
static char buf[64];
switch (addr->hostinfo.rtnCode) {
case noErr:
return NULL;
case nameSyntaxErr:
return "Name syntax error";
case noNameServer:
return "No name server found";
case authNameErr:
return "Domain name does not exist";
case noAnsErr:
return "No answer from domain name server";
case dnrErr:
return "Domain name server returned an error";
case outOfMemory:
return "Out of memory";
default:
sprintf(buf, "Unknown DNR error %d", addr->hostinfo.rtnCode);
return buf;
}
}
static const char *mactcp_socket_error(Socket sock)
{
static char buf[64];
Actual_Socket s = (Actual_Socket) sock;
switch (s->err) {
case noErr:
return NULL;
case insufficientResources:
return "Insufficient resources to open TCP stream";
case duplicateSocket:
return "Duplicate socket";
case openFailed:
return "Connection failed while opening";
default:
sprintf(buf, "Unknown MacTCP error %d", s->err);
return buf;
}
}
static void mactcp_set_frozen(Socket sock, int is_frozen)
{
Actual_Socket s = (Actual_Socket) sock;
if (s->frozen == is_frozen)
return;
s->frozen = is_frozen;
}
/*
* Bits below here would usually be in dnr.c, shipped with the MacTCP
* SDK, but its convenient not to require that, and since we assume
* System 7 we can actually simplify things a lot.
*/
static OSErr OpenResolver(char *hosts_file)
{
short vrefnum;
long dirid;
HParamBlockRec pb;
Str255 filename;
OSErr err;
int fd;
Handle dnr_handle;
if (mactcp.dnr_handle != NULL)
return noErr;
err = FindFolder(kOnSystemDisk, kControlPanelFolderType, FALSE, &vrefnum,
&dirid);
if (err != noErr) return err;
/*
* Might be better to use PBCatSearch here, but it's not always
* available.
*/
pb.fileParam.ioCompletion = NULL;
pb.fileParam.ioNamePtr = filename;
pb.fileParam.ioVRefNum = vrefnum;
pb.fileParam.ioFDirIndex = 1;
pb.fileParam.ioDirID = dirid;
fd = -1;
while (PBHGetFInfoSync(&pb) == noErr) {
if (pb.fileParam.ioFlFndrInfo.fdType == 'cdev' &&
pb.fileParam.ioFlFndrInfo.fdCreator == 'ztcp') {
fd = HOpenResFile(vrefnum, dirid, filename, fsRdPerm);
if (fd == -1) continue;
dnr_handle = Get1IndResource('dnrp', 1);
if (dnr_handle != NULL)
break;
CloseResFile(fd);
fd = -1;
}
pb.fileParam.ioDirID = dirid;
pb.fileParam.ioFDirIndex++;
}
if (fd == -1)
return fnfErr;
DetachResource(dnr_handle);
CloseResFile(fd);
MoveHHi(dnr_handle);
HLock(dnr_handle);
err = InvokeOpenResolverUPP(OPENRESOLVER, hosts_file,
(OpenResolverUPP)*dnr_handle);
if (err != noErr) {
HUnlock(dnr_handle);
DisposeHandle(dnr_handle);
return err;
}
mactcp.dnr_handle = dnr_handle;
return noErr;
}
OSErr CloseResolver(void)
{
Handle dnr_handle = mactcp.dnr_handle;
OSErr err;
if (mactcp.dnr_handle == NULL)
return notOpenErr;
err = InvokeCloseResolverUPP(CLOSERESOLVER,
(CloseResolverUPP)*mactcp.dnr_handle);
if (err != noErr)
return err;
mactcp.dnr_handle = NULL;
HUnlock(dnr_handle);
DisposeHandle(dnr_handle);
return noErr;
}
#endif
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,638 +0,0 @@
/*
* Macintosh OpenTransport networking abstraction
*/
#if TARGET_API_MAC_CARBON
#define OTCARBONAPPLICATION 1
#endif
#include <Files.h> /* Needed by OpenTransportInternet.h */
#include <OpenTransport.h>
#include <OpenTptInternet.h>
#include <string.h>
#define DEFINE_PLUG_METHOD_MACROS
#include "putty.h"
#include "network.h"
#include "mac.h"
struct Socket_tag {
struct socket_function_table *fn;
/* other stuff... */
OSStatus error;
EndpointRef ep;
Plug plug;
void *private_ptr;
bufchain output_data;
int connected;
int writable;
int frozen; /* this causes readability notifications to be ignored */
int frozen_readable; /* this means we missed at least one readability
* notification while we were frozen */
int localhost_only; /* for listening sockets */
char oobdata[1];
int sending_oob;
int oobpending; /* is there OOB data available to read?*/
int oobinline;
int pending_error; /* in case send() returns error */
int listener;
int nodelay, keepalive;
int privport, port;
struct Socket_tag *next;
struct Socket_tag **prev;
};
typedef struct Socket_tag *Actual_Socket;
struct SockAddr_tag {
int resolved;
OSStatus error;
InetHostInfo hostinfo;
char hostname[512];
};
/* Globals */
static struct {
Actual_Socket socklist;
InetSvcRef inetsvc;
} ot;
OSErr ot_init(void)
{
OSStatus err;
err = InitOpenTransport();
if (err != kOTNoError) return err;
ot.inetsvc = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err);
return err;
}
void ot_cleanup(void)
{
Actual_Socket s;
for (s = ot.socklist; s !=NULL; s = s->next) {
OTUnbind(s->ep);
OTCloseProvider(s->ep);
}
CloseOpenTransport();
}
SockAddr ot_namelookup(char const *host, char **canonicalname)
{
SockAddr ret = snew(struct SockAddr_tag);
char *realhost;
/* Casting away const -- hope OTInetStringToAddress is sensible */
ret->error = OTInetStringToAddress(ot.inetsvc, (char *)host,
&ret->hostinfo);
ret->resolved = TRUE;
if (ret->error == kOTNoError)
realhost = ret->hostinfo.name;
else
realhost = "";
*canonicalname = snewn(1+strlen(realhost), char);
strcpy(*canonicalname, realhost);
return ret;
}
SockAddr ot_nonamelookup(char const *host)
{
SockAddr ret = snew(struct SockAddr_tag);
ret->resolved = FALSE;
ret->error = kOTNoError;
ret->hostname[0] = '\0';
strncat(ret->hostname, host, lenof(ret->hostname) - 1);
return ret;
}
void ot_getaddr(SockAddr addr, char *buf, int buflen)
{
char mybuf[16];
buf[0] = '\0';
if (addr->resolved) {
/* XXX only return first address */
OTInetHostToString(addr->hostinfo.addrs[0], mybuf);
strncat(buf, mybuf, buflen - 1);
} else
strncat(buf, addr->hostname, buflen - 1);
}
/* I think "local" here really means "loopback" */
int ot_hostname_is_local(char *name)
{
return !strcmp(name, "localhost");
}
int ot_address_is_local(SockAddr addr)
{
int i;
if (addr->resolved)
for (i = 0; i < kMaxHostAddrs; i++)
if (addr->hostinfo.addrs[i] & 0xff000000 == 0x7f000000)
return TRUE;
return FALSE;
}
int ot_addrtype(SockAddr addr)
{
if (addr->resolved)
return ADDRTYPE_IPV4;
return ADDRTYPE_NAME;
}
void ot_addrcopy(SockAddr addr, char *buf)
{
/* XXX only return first address */
memcpy(buf, &addr->hostinfo.addrs[0], 4);
}
void ot_addr_free(SockAddr addr)
{
sfree(addr);
}
static Plug ot_tcp_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock;
Plug ret = s->plug;
if (p)
s->plug = p;
return ret;
}
static void ot_tcp_flush(Socket s)
{
/*
* We send data to the socket as soon as we can anyway,
* so we don't need to do anything here. :-)
*/
}
static void ot_tcp_close(Socket s);
static int ot_tcp_write(Socket s, char const *data, int len);
static int ot_tcp_write_oob(Socket s, char const *data, int len);
static void ot_tcp_set_private_ptr(Socket s, void *ptr);
static void *ot_tcp_get_private_ptr(Socket s);
static void ot_tcp_set_frozen(Socket s, int is_frozen);
static const char *ot_tcp_socket_error(Socket s);
static void ot_recv(Actual_Socket s);
static void ot_listenaccept(Actual_Socket s);
static void ot_setoption(EndpointRef, OTXTILevel, OTXTIName, UInt32);
void ot_poll(void);
Socket ot_register(void *sock, Plug plug)
{
static struct socket_function_table fn_table = {
ot_tcp_plug,
ot_tcp_close,
ot_tcp_write,
ot_tcp_write_oob,
ot_tcp_flush,
ot_tcp_set_private_ptr,
ot_tcp_get_private_ptr,
ot_tcp_set_frozen,
ot_tcp_socket_error
};
Actual_Socket ret;
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret->error = kOTNoError;
ret->plug = plug;
bufchain_init(&ret->output_data);
ret->writable = 1; /* to start with */
ret->sending_oob = 0;
ret->frozen = 1;
ret->frozen_readable = 0;
ret->localhost_only = 0; /* unused, but best init anyway */
ret->pending_error = 0;
ret->oobpending = FALSE;
ret->listener = 0;
ret->ep = (EndpointRef)sock;
/* some sort of error checking */
ret->oobinline = 0;
/* Add this to the list of all sockets */
ret->next = ot.socklist;
ret->prev = &ot.socklist;
ot.socklist = ret;
return (Socket) ret;
}
Socket ot_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
static struct socket_function_table fn_table = {
ot_tcp_plug,
ot_tcp_close,
ot_tcp_write,
ot_tcp_write_oob,
ot_tcp_flush,
ot_tcp_set_private_ptr,
ot_tcp_get_private_ptr,
ot_tcp_set_frozen,
ot_tcp_socket_error
};
Actual_Socket ret;
EndpointRef ep;
OSStatus err;
InetAddress dest;
TCall connectCall;
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret->error = kOTNoError;
ret->plug = plug;
bufchain_init(&ret->output_data);
ret->connected = 0; /* to start with */
ret->writable = 0; /* to start with */
ret->sending_oob = 0;
ret->frozen = 0;
ret->frozen_readable = 0;
ret->localhost_only = 0; /* unused, but best init anyway */
ret->pending_error = 0;
ret->oobinline = oobinline;
ret->nodelay = nodelay;
ret->keepalive = keepalive;
ret->oobpending = FALSE;
ret->listener = 0;
/* Open Endpoint, configure it for TCP over anything */
ep = OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL, &err);
ret->ep = ep;
if (err) {
ret->error = err;
return (Socket) ret;
}
if (ret->oobinline)
ot_setoption(ep, INET_TCP, TCP_OOBINLINE, T_YES);
if (ret->nodelay)
ot_setoption(ep, INET_TCP, TCP_NODELAY, T_YES);
if (ret->keepalive) {
ot_setoption(ep, INET_TCP, TCP_KEEPALIVE, T_YES);
}
/*
* Bind to local address.
*/
/* FIXME: pay attention to privport */
err = OTBind(ep, NULL, NULL); /* OpenTransport always picks our address */
if (err) {
ret->error = err;
return (Socket) ret;
}
/*
* Connect to remote address.
*/
/* XXX Try non-primary addresses */
OTInitInetAddress(&dest, port, addr->hostinfo.addrs[0]);
memset(&connectCall, 0, sizeof(TCall));
connectCall.addr.buf = (UInt8 *) &dest;
connectCall.addr.len = sizeof(dest);
err = OTConnect(ep, &connectCall, nil);
if (err) {
ret->error = err;
return (Socket) ret;
} else {
ret->connected = 1;
ret->writable = 1;
}
/* Add this to the list of all sockets */
ret->next = ot.socklist;
ret->prev = &ot.socklist;
if (ret->next != NULL)
ret->next->prev = &ret->next;
ot.socklist = ret;
/* XXX: don't know whether we can sk_addr_free(addr); */
return (Socket) ret;
}
Socket ot_newlistener(char *srcaddr, int port, Plug plug, int local_host_only,
int address_family)
{
static struct socket_function_table fn_table = {
ot_tcp_plug,
ot_tcp_close,
ot_tcp_write,
ot_tcp_write_oob,
ot_tcp_flush,
ot_tcp_set_private_ptr,
ot_tcp_get_private_ptr,
ot_tcp_set_frozen,
ot_tcp_socket_error
};
Actual_Socket ret;
EndpointRef ep;
OSStatus err;
InetAddress addr;
TBind tbind;
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret->error = kOTNoError;
ret->plug = plug;
bufchain_init(&ret->output_data);
ret->writable = 0; /* to start with */
ret->sending_oob = 0;
ret->frozen = 0;
ret->frozen_readable = 0;
ret->localhost_only = local_host_only;
ret->pending_error = 0;
ret->oobinline = 0;
ret->oobpending = FALSE;
ret->listener = 1;
/* Open Endpoint, configure it for TCP over anything, and load the
* tilisten module to serialize multiple simultaneous
* connections. */
ep = OTOpenEndpoint(OTCreateConfiguration("tilisten,tcp"), 0, NULL, &err);
ret->ep = ep;
if (err) {
ret->error = err;
return (Socket) ret;
}
ot_setoption(ep, INET_IP, IP_REUSEADDR, T_YES);
OTInitInetAddress(&addr, port, kOTAnyInetAddress);
/* XXX: pay attention to local_host_only */
tbind.addr.buf = (UInt8 *) &addr;
tbind.addr.len = sizeof(addr);
tbind.qlen = 10;
err = OTBind(ep, &tbind, NULL); /* XXX: check qlen we got */
if (err) {
ret->error = err;
return (Socket) ret;
}
/* Add this to the list of all sockets */
ret->next = ot.socklist;
ret->prev = &ot.socklist;
if (ret->next != NULL)
ret->next->prev = &ret->next;
ot.socklist = ret;
return (Socket) ret;
}
static void ot_tcp_close(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
OTCloseProvider(s->ep);
/* Unhitch from list of sockets */
*s->prev = s->next;
if (s->next != NULL)
s->next->prev = s->prev;
sfree(s);
}
static void try_send(Actual_Socket s)
{
while (bufchain_size(&s->output_data) > 0) {
int nsent;
void *data;
int len;
/* Don't care about oob right now */
bufchain_prefix(&s->output_data, &data, &len);
nsent = OTSnd(s->ep, data, len, 0);
noise_ultralight(nsent);
if (nsent <= 0) {
/* something bad happened, hey ho */
} else {
/* still don't care about oob */
bufchain_consume(&s->output_data, nsent);
}
}
}
static int ot_tcp_write(Socket sock, char const *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
bufchain_add(&s->output_data, buf, len);
if (s->writable)
try_send(s);
return bufchain_size(&s->output_data);
}
static int ot_tcp_write_oob(Socket sock, char const *buf, int len)
{
/* Don't care about oob */
return 0;
}
/*
* Each socket abstraction contains a `void *' private field in
* which the client can keep state.
*/
static void ot_tcp_set_private_ptr(Socket sock, void *ptr)
{
Actual_Socket s = (Actual_Socket) sock;
s->private_ptr = ptr;
}
static void *ot_tcp_get_private_ptr(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
return s->private_ptr;
}
/*
* Special error values are returned from ot_namelookup and ot_new
* if there's a problem. These functions extract an error message,
* or return NULL if there's no problem.
*/
char *ot_addr_error(SockAddr addr)
{
static char buf[128];
if (addr->error == kOTNoError)
return NULL;
sprintf(buf, "error %d", addr->error);
return buf;
}
static const char *ot_tcp_socket_error(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
static char buf[128];
if (s->error == kOTNoError)
return NULL;
sprintf(buf, "error %d", s->error);
return buf;
}
static void ot_tcp_set_frozen(Socket sock, int is_frozen)
{
Actual_Socket s = (Actual_Socket) sock;
if (s->frozen == is_frozen)
return;
s->frozen = is_frozen;
}
/*
* Poll all our sockets from an event loop
*/
void ot_poll(void)
{
Actual_Socket s;
OTResult o;
for (s = ot.socklist; s != NULL; s = s->next) {
o = OTLook(s->ep);
switch(o) {
case T_DATA: /* Normal Data */
ot_recv(s);
break;
case T_EXDATA: /* Expedited Data (urgent?) */
ot_recv(s);
break;
case T_LISTEN: /* Connection attempt */
ot_listenaccept(s);
break;
case T_ORDREL: /* Orderly disconnect */
plug_closing(s->plug, NULL, 0, 0);
break;
case T_DISCONNECT: /* Abortive disconnect*/
plug_closing(s->plug, NULL, 0, 0);
break;
}
}
}
void ot_recv(Actual_Socket s)
{
OTResult o;
char buf[2048];
OTFlags flags;
if (s->frozen) return;
o = OTRcv(s->ep, buf, sizeof(buf), &flags);
if (o > 0)
plug_receive(s->plug, 0, buf, o);
if (o < 0 && o != kOTNoDataErr)
plug_closing(s->plug, NULL, 0, 0); /* XXX Error msg */
}
void ot_listenaccept(Actual_Socket s)
{
OTResult o;
OSStatus err;
InetAddress remoteaddr;
TCall tcall;
EndpointRef ep;
tcall.addr.maxlen = sizeof(InetAddress);
tcall.addr.buf = (unsigned char *)&remoteaddr;
tcall.opt.maxlen = 0;
tcall.opt.buf = NULL;
tcall.udata.maxlen = 0;
tcall.udata.buf = NULL;
o = OTListen(s->ep, &tcall);
if (o != kOTNoError)
return;
/* We've found an incoming connection, accept it */
ep = OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL, &err);
o = OTAccept(s->ep, ep, &tcall);
if (plug_accepting(s->plug, ep)) {
OTUnbind(ep);
OTCloseProvider(ep);
}
}
static void ot_setoption(EndpointRef ep,
OTXTILevel level,
OTXTIName name,
UInt32 value)
{
TOption option;
TOptMgmt request;
TOptMgmt result;
if (name == TCP_KEEPALIVE) {
option.len = sizeof(struct t_kpalive);
option.value[1] = T_UNSPEC;
} else
option.len = kOTFourByteOptionSize;
option.level = level;
option.name = name;
option.status = 0;
option.value[0] = value;
request.opt.buf = (unsigned char *) &option;
request.opt.len = sizeof(option);
request.flags = T_NEGOTIATE;
result.opt.buf = (unsigned char *) &option;
result.opt.maxlen = sizeof(option);
OTOptionManagement(ep, &request, &result);
}
/*
* Local Variables:
* c-file-style: "simon"
* End:
*/

View File

@ -1,25 +0,0 @@
#!/bin/sh
# Shell script to be run on Mac OS X, which uses `SetFile' to set
# up the appropriate file metadata so that you can run MPW and have
# it build classic-Mac PuTTY.
SETFILE=/Developer/Tools/SetFile
# I want to be able to run this either from the `mac' subdirectory
# or from the main `putty' source directory.
if test -f mac_res.r -a -f ../putty.h; then
cd ..
fi
if test ! -f putty.h; then
echo 'putty.h not found.' >&2
echo 'This script should be run in the PuTTY source directory.' >&2
exit 1
fi
# Now we can assume we're in the main PuTTY source dir.
find . -name .svn -prune -o -name '*.[chr]' -exec $SETFILE -t TEXT {} \;
# CR-ise mkputty.mpw and set the new version to TEXT.
tr '\n' '\r' < mac/mkputty.mpw > mac/mk.mpw
$SETFILE -t TEXT mac/mk.mpw

View File

@ -1,82 +0,0 @@
#include "putty.h"
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define _DIAGASSERT(e) /* nothing */
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From NetBSD: strcasecmp.c,v 1.12 2000/01/22 22:19:20 mycroft Exp
*/
#include <ctype.h>
typedef unsigned char u_char;
int
strcasecmp(s1, s2)
const char *s1, *s2;
{
const u_char *us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
_DIAGASSERT(s1 != NULL);
_DIAGASSERT(s2 != NULL);
while (tolower(*us1) == tolower(*us2++))
if (*us1++ == '\0')
return (0);
return (tolower(*us1) - tolower(*--us2));
}
int
strncasecmp(s1, s2, n)
const char *s1, *s2;
size_t n;
{
_DIAGASSERT(s1 != NULL);
_DIAGASSERT(s2 != NULL);
if (s1 == NULL || s2 == NULL)
return (0);
if (n != 0) {
const u_char *us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
do {
if (tolower(*us1) != tolower(*us2++))
return (tolower(*us1) - tolower(*--us2));
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return (0);
}

View File

@ -1,54 +0,0 @@
/*
* Current PuTTY version number. Minor is in BCD
*/
#define VERSION_MAJOR 0x00
#define VERSION_MINOR 0x60
resource 'vers' (1, purgeable) {
#ifdef RELEASE
VERSION_MAJOR, VERSION_MINOR,
beta,
#else
VERSION_MAJOR, VERSION_MINOR + 1,
development,
#endif
0, /* No prerelease version */
verBritain,
#ifdef RELEASESTR
RELEASESTR,
"Release " RELEASESTR,
#else
#ifdef SNAPSHOTSTR
SNAPSHOTSTR,
"Development snapshot " SNAPSHOTSTR,
#else
"unknown",
"Unidentified build, " $$Date " " $$Time,
#endif
#endif
};
resource 'vers' (2, purgeable) {
#ifdef RELEASE
VERSION_MAJOR, VERSION_MINOR,
beta,
#else
VERSION_MAJOR, VERSION_MINOR + 1,
development,
#endif
0, /* No prerelease version */
verBritain,
#ifdef RELEASESTR
RELEASESTR,
"PuTTY " RELEASESTR,
#else
#ifdef SNAPSHOTSTR
SNAPSHOTSTR,
"PuTTY snapshot " SNAPSHOTSTR,
#else
"unknown",
"PuTTY",
#endif
#endif
};

View File

@ -1,539 +0,0 @@
#include <limits.h>
#include <stdarg.h>
#include "putty.h"
#define __P(decl) decl
/* XXX */
typedef unsigned long u_quad_t;
typedef long quad_t;
typedef unsigned long u_long;
typedef unsigned int u_int;
typedef unsigned short u_short;
typedef long intmax_t;
typedef unsigned long uintmax_t;
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef int ssize_t;
#define NBBY CHAR_BIT
/*-
* Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From NetBSD: subr_prf.c,v 1.86 2002/11/02 07:25:22 perry Exp
* @(#)subr_prf.c 8.4 (Berkeley) 5/4/95
*/
/* flags for kprintf */
#define TOCONS 0x01 /* to the console */
#define TOTTY 0x02 /* to the process' tty */
#define TOLOG 0x04 /* to the kernel message buffer */
#define TOBUFONLY 0x08 /* to the buffer (only) [for snprintf] */
#define TODDB 0x10 /* to ddb console */
/* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */
#define KPRINTF_BUFSIZE (sizeof(quad_t) * NBBY / 3 + 2)
/*
* local prototypes
*/
static int kprintf __P((const char *, int, void *,
char *, va_list));
/*
* vsnprintf: print a message to a buffer [already have va_alist]
*/
int
vsnprintf(buf, size, fmt, ap)
char *buf;
size_t size;
const char *fmt;
va_list ap;
{
int retval;
char *p;
if (size < 1)
return (-1);
p = buf + size - 1;
retval = kprintf(fmt, TOBUFONLY, &p, buf, ap);
*(p) = 0; /* null terminate */
return(retval);
}
/*
* kprintf: scaled down version of printf(3).
*
* this version based on vfprintf() from libc which was derived from
* software contributed to Berkeley by Chris Torek.
*
* NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS!
*/
/*
* macros for converting digits to letters and vice versa
*/
#define to_digit(c) ((c) - '0')
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
#define to_char(n) ((n) + '0')
/*
* flags used during conversion.
*/
#define ALT 0x001 /* alternate form */
#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
#define LADJUST 0x004 /* left adjustment */
#define LONGDBL 0x008 /* long double; unimplemented */
#define LONGINT 0x010 /* long integer */
#define QUADINT 0x020 /* quad integer */
#define SHORTINT 0x040 /* short integer */
#define MAXINT 0x080 /* intmax_t */
#define PTRINT 0x100 /* intptr_t */
#define SIZEINT 0x200 /* size_t */
#define ZEROPAD 0x400 /* zero (as opposed to blank) pad */
#define FPT 0x800 /* Floating point number */
/*
* To extend shorts properly, we need both signed and unsigned
* argument extraction methods.
*/
#define SARG() \
(flags&MAXINT ? va_arg(ap, intmax_t) : \
flags&PTRINT ? va_arg(ap, intptr_t) : \
flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \
flags&QUADINT ? va_arg(ap, quad_t) : \
flags&LONGINT ? va_arg(ap, long) : \
flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
(long)va_arg(ap, int))
#define UARG() \
(flags&MAXINT ? va_arg(ap, uintmax_t) : \
flags&PTRINT ? va_arg(ap, uintptr_t) : \
flags&SIZEINT ? va_arg(ap, size_t) : \
flags&QUADINT ? va_arg(ap, u_quad_t) : \
flags&LONGINT ? va_arg(ap, u_long) : \
flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
(u_long)va_arg(ap, u_int))
#define KPRINTF_PUTCHAR(C) { \
if (oflags == TOBUFONLY) { \
if ((vp != NULL) && (sbuf == tailp)) { \
ret += 1; /* indicate error */ \
goto overflow; \
} \
*sbuf++ = (C); \
} \
}
/*
* Guts of kernel printf. Note, we already expect to be in a mutex!
*/
static int
kprintf(fmt0, oflags, vp, sbuf, ap)
const char *fmt0;
int oflags;
void *vp;
char *sbuf;
va_list ap;
{
char *fmt; /* format string */
int ch; /* character from fmt */
int n; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format (%.3d), or -1 */
char sign; /* sign prefix (' ', '+', '-', or \0) */
u_quad_t _uquad; /* integer arguments %[diouxX] */
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
int realsz; /* field size expanded by dprec */
int size; /* size of converted field or string */
char *xdigs; /* digits for [xX] conversion */
char buf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
char *tailp; /* tail pointer for snprintf */
tailp = NULL; /* XXX: shutup gcc */
if (oflags == TOBUFONLY && (vp != NULL))
tailp = *(char **)vp;
cp = NULL; /* XXX: shutup gcc */
size = 0; /* XXX: shutup gcc */
fmt = (char *)fmt0;
ret = 0;
xdigs = NULL; /* XXX: shut up gcc warning */
/*
* Scan the format for conversions (`%' character).
*/
for (;;) {
while (*fmt != '%' && *fmt) {
ret++;
KPRINTF_PUTCHAR(*fmt++);
}
if (*fmt == 0)
goto done;
fmt++; /* skip over '%' */
flags = 0;
dprec = 0;
width = 0;
prec = -1;
sign = '\0';
rflag: ch = *fmt++;
reswitch: switch (ch) {
case ' ':
/*
* ``If the space and + flags both appear, the space
* flag will be ignored.''
* -- ANSI X3J11
*/
if (!sign)
sign = ' ';
goto rflag;
case '#':
flags |= ALT;
goto rflag;
case '*':
/*
* ``A negative field width argument is taken as a
* - flag followed by a positive field width.''
* -- ANSI X3J11
* They don't exclude field widths read from args.
*/
if ((width = va_arg(ap, int)) >= 0)
goto rflag;
width = -width;
/* FALLTHROUGH */
case '-':
flags |= LADJUST;
goto rflag;
case '+':
sign = '+';
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
n = va_arg(ap, int);
prec = n < 0 ? -1 : n;
goto rflag;
}
n = 0;
while (is_digit(ch)) {
n = 10 * n + to_digit(ch);
ch = *fmt++;
}
prec = n < 0 ? -1 : n;
goto reswitch;
case '0':
/*
* ``Note that 0 is taken as a flag, not as the
* beginning of a field width.''
* -- ANSI X3J11
*/
flags |= ZEROPAD;
goto rflag;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = 0;
do {
n = 10 * n + to_digit(ch);
ch = *fmt++;
} while (is_digit(ch));
width = n;
goto reswitch;
case 'h':
flags |= SHORTINT;
goto rflag;
case 'j':
flags |= MAXINT;
goto rflag;
case 'l':
if (*fmt == 'l') {
fmt++;
flags |= QUADINT;
} else {
flags |= LONGINT;
}
goto rflag;
case 'q':
flags |= QUADINT;
goto rflag;
case 't':
flags |= PTRINT;
goto rflag;
case 'z':
flags |= SIZEINT;
goto rflag;
case 'c':
*(cp = buf) = va_arg(ap, int);
size = 1;
sign = '\0';
break;
case 'D':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'd':
case 'i':
_uquad = SARG();
if ((quad_t)_uquad < 0) {
_uquad = -_uquad;
sign = '-';
}
base = DEC;
goto number;
case 'n':
if (flags & MAXINT)
*va_arg(ap, intmax_t *) = ret;
else if (flags & PTRINT)
*va_arg(ap, intptr_t *) = ret;
else if (flags & SIZEINT)
*va_arg(ap, ssize_t *) = ret;
else if (flags & QUADINT)
*va_arg(ap, quad_t *) = ret;
else if (flags & LONGINT)
*va_arg(ap, long *) = ret;
else if (flags & SHORTINT)
*va_arg(ap, short *) = ret;
else
*va_arg(ap, int *) = ret;
continue; /* no output */
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
_uquad = UARG();
base = OCT;
goto nosign;
case 'p':
/*
* ``The argument shall be a pointer to void. The
* value of the pointer is converted to a sequence
* of printable characters, in an implementation-
* defined manner.''
* -- ANSI X3J11
*/
/* NOSTRICT */
_uquad = (u_long)va_arg(ap, void *);
base = HEX;
xdigs = "0123456789abcdef";
flags |= HEXPREFIX;
ch = 'x';
goto nosign;
case 's':
if ((cp = va_arg(ap, char *)) == NULL)
cp = "(null)";
if (prec >= 0) {
/*
* can't use strlen; can only look for the
* NUL in the first `prec' characters, and
* strlen() will go further.
*/
char *p = memchr(cp, 0, prec);
if (p != NULL) {
size = p - cp;
if (size > prec)
size = prec;
} else
size = prec;
} else
size = strlen(cp);
sign = '\0';
break;
case 'U':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
_uquad = UARG();
base = DEC;
goto nosign;
case 'X':
xdigs = "0123456789ABCDEF";
goto hex;
case 'x':
xdigs = "0123456789abcdef";
hex: _uquad = UARG();
base = HEX;
/* leading 0x/X only if non-zero */
if (flags & ALT && _uquad != 0)
flags |= HEXPREFIX;
/* unsigned conversions */
nosign: sign = '\0';
/*
* ``... diouXx conversions ... if a precision is
* specified, the 0 flag will be ignored.''
* -- ANSI X3J11
*/
number: if ((dprec = prec) >= 0)
flags &= ~ZEROPAD;
/*
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
*/
cp = buf + KPRINTF_BUFSIZE;
if (_uquad != 0 || prec != 0) {
/*
* Unsigned mod is hard, and unsigned mod
* by a constant is easier than that by
* a variable; hence this switch.
*/
switch (base) {
case OCT:
do {
*--cp = to_char(_uquad & 7);
_uquad >>= 3;
} while (_uquad);
/* handle octal leading 0 */
if (flags & ALT && *cp != '0')
*--cp = '0';
break;
case DEC:
/* many numbers are 1 digit */
while (_uquad >= 10) {
*--cp = to_char(_uquad % 10);
_uquad /= 10;
}
*--cp = to_char(_uquad);
break;
case HEX:
do {
*--cp = xdigs[_uquad & 15];
_uquad >>= 4;
} while (_uquad);
break;
default:
cp = "bug in kprintf: bad base";
size = strlen(cp);
goto skipsize;
}
}
size = buf + KPRINTF_BUFSIZE - cp;
skipsize:
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
/* pretend it was %c with argument ch */
cp = buf;
*cp = ch;
size = 1;
sign = '\0';
break;
}
/*
* All reasonable formats wind up here. At this point, `cp'
* points to a string which (if not flags&LADJUST) should be
* padded out to `width' places. If flags&ZEROPAD, it should
* first be prefixed by any sign or other prefix; otherwise,
* it should be blank padded before the prefix is emitted.
* After any left-hand padding and prefixing, emit zeroes
* required by a decimal [diouxX] precision, then print the
* string proper, then emit zeroes required by any leftover
* floating precision; finally, if LADJUST, pad with blanks.
*
* Compute actual size, so we know how much to pad.
* size excludes decimal prec; realsz includes it.
*/
realsz = dprec > size ? dprec : size;
if (sign)
realsz++;
else if (flags & HEXPREFIX)
realsz+= 2;
/* adjust ret */
ret += width > realsz ? width : realsz;
/* right-adjusting blank padding */
if ((flags & (LADJUST|ZEROPAD)) == 0) {
n = width - realsz;
while (n-- > 0)
KPRINTF_PUTCHAR(' ');
}
/* prefix */
if (sign) {
KPRINTF_PUTCHAR(sign);
} else if (flags & HEXPREFIX) {
KPRINTF_PUTCHAR('0');
KPRINTF_PUTCHAR(ch);
}
/* right-adjusting zero padding */
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
n = width - realsz;
while (n-- > 0)
KPRINTF_PUTCHAR('0');
}
/* leading zeroes from decimal precision */
n = dprec - size;
while (n-- > 0)
KPRINTF_PUTCHAR('0');
/* the string or number proper */
while (size--)
KPRINTF_PUTCHAR(*cp++);
/* left-adjusting padding (always blank) */
if (flags & LADJUST) {
n = width - realsz;
while (n-- > 0)
KPRINTF_PUTCHAR(' ');
}
}
done:
if ((oflags == TOBUFONLY) && (vp != NULL))
*(char **)vp = sbuf;
overflow:
return (ret);
/* NOTREACHED */
}