1 /* $Id: macstore.c,v 1.7 2003/01/08 22:46:12 ben Exp $ */
4 * macstore.c: Macintosh-specific impementation of the interface
11 #include <Resources.h>
12 #include <TextUtils.h>
20 #define PUTTY_CREATOR FOUR_CHAR_CODE('pTTY')
21 #define SESS_TYPE FOUR_CHAR_CODE('Sess')
22 #define SEED_TYPE FOUR_CHAR_CODE('Seed')
25 OSErr
FSpGetDirID(FSSpec
*f
, long *idp
, Boolean makeit
);
28 * We store each session as a file in the "PuTTY" sub-directory of the
29 * preferences folder. Each (key,value) pair is stored as a resource.
32 OSErr
get_putty_dir(Boolean makeit
, short *pVRefNum
, long *pDirID
)
37 long prefDirID
, puttyDirID
;
39 error
= FindFolder(kOnSystemDisk
, kPreferencesFolderType
, makeit
,
40 &prefVRefNum
, &prefDirID
);
41 if (error
!= noErr
) goto out
;
43 error
= FSMakeFSSpec(prefVRefNum
, prefDirID
, "\pPuTTY", &puttydir
);
44 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
45 error
= FSpGetDirID(&puttydir
, &puttyDirID
, makeit
);
46 if (error
!= noErr
) goto out
;
48 *pVRefNum
= prefVRefNum
;
55 OSErr
get_session_dir(Boolean makeit
, short *pVRefNum
, long *pDirID
) {
59 long puttyDirID
, sessDirID
;
61 error
= get_putty_dir(makeit
, &puttyVRefNum
, &puttyDirID
);
62 if (error
!= noErr
) goto out
;
63 error
= FSMakeFSSpec(puttyVRefNum
, puttyDirID
, "\pSaved Sessions",
65 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
66 error
= FSpGetDirID(&sessdir
, &sessDirID
, makeit
);
67 if (error
!= noErr
) goto out
;
69 *pVRefNum
= puttyVRefNum
;
76 OSErr
FSpGetDirID(FSSpec
*f
, long *idp
, Boolean makeit
) {
80 pb
.dirInfo
.ioNamePtr
= f
->name
;
81 pb
.dirInfo
.ioVRefNum
= f
->vRefNum
;
82 pb
.dirInfo
.ioDrDirID
= f
->parID
;
83 pb
.dirInfo
.ioFDirIndex
= 0;
84 error
= PBGetCatInfoSync(&pb
);
85 if (error
== fnfErr
&& makeit
)
86 return FSpDirCreate(f
, smSystemScript
, idp
);
87 if (error
!= noErr
) goto out
;
88 if ((pb
.dirInfo
.ioFlAttrib
& ioDirMask
) == 0) {
92 *idp
= pb
.dirInfo
.ioDrDirID
;
98 struct write_settings
{
104 void *open_settings_w(char *sessionname
) {
105 short sessVRefNum
, tmpVRefNum
;
106 long sessDirID
, tmpDirID
;
109 struct write_settings
*ws
;
111 ws
= safemalloc(sizeof *ws
);
112 error
= get_session_dir(kCreateFolder
, &sessVRefNum
, &sessDirID
);
113 if (error
!= noErr
) goto out
;
115 c2pstrcpy(psessionname
, sessionname
);
116 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &ws
->dstfile
);
117 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
118 if (error
== fnfErr
) {
119 FSpCreateResFile(&ws
->dstfile
, PUTTY_CREATOR
, SESS_TYPE
,
121 if ((error
= ResError()) != noErr
) goto out
;
124 /* Create a temporary file to save to first. */
125 error
= FindFolder(sessVRefNum
, kTemporaryFolderType
, kCreateFolder
,
126 &tmpVRefNum
, &tmpDirID
);
127 if (error
!= noErr
) goto out
;
128 error
= FSMakeFSSpec(tmpVRefNum
, tmpDirID
, psessionname
, &ws
->tmpfile
);
129 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
130 if (error
== noErr
) {
131 error
= FSpDelete(&ws
->tmpfile
);
132 if (error
!= noErr
) goto out
;
134 FSpCreateResFile(&ws
->tmpfile
, PUTTY_CREATOR
, SESS_TYPE
, smSystemScript
);
135 if ((error
= ResError()) != noErr
) goto out
;
137 ws
->fd
= FSpOpenResFile(&ws
->tmpfile
, fsWrPerm
);
138 if (ws
->fd
== -1) {error
= ResError(); goto out
;}
144 fatalbox("Failed to open session for write (%d)", error
);
147 void write_setting_s(void *handle
, char *key
, char *value
) {
148 int fd
= *(int *)handle
;
154 if (ResError() != noErr
)
155 fatalbox("Failed to open saved session (%d)", ResError());
157 error
= PtrToHand(value
, &h
, strlen(value
));
159 fatalbox("Failed to allocate memory");
160 /* Put the data in a resource. */
161 id
= Unique1ID(FOUR_CHAR_CODE('TEXT'));
162 if (ResError() != noErr
)
163 fatalbox("Failed to get ID for resource %s (%d)", key
, ResError());
164 addresource(h
, FOUR_CHAR_CODE('TEXT'), id
, key
);
165 if (ResError() != noErr
)
166 fatalbox("Failed to add resource %s (%d)", key
, ResError());
169 void write_setting_i(void *handle
, char *key
, int value
) {
170 int fd
= *(int *)handle
;
176 if (ResError() != noErr
)
177 fatalbox("Failed to open saved session (%d)", ResError());
179 /* XXX assume all systems have the same "int" format */
180 error
= PtrToHand(&value
, &h
, sizeof(int));
182 fatalbox("Failed to allocate memory (%d)", error
);
184 /* Put the data in a resource. */
185 id
= Unique1ID(FOUR_CHAR_CODE('Int '));
186 if (ResError() != noErr
)
187 fatalbox("Failed to get ID for resource %s (%d)", key
, ResError());
188 addresource(h
, FOUR_CHAR_CODE('Int '), id
, key
);
189 if (ResError() != noErr
)
190 fatalbox("Failed to add resource %s (%d)", key
, ResError());
193 void close_settings_w(void *handle
) {
194 struct write_settings
*ws
= handle
;
197 CloseResFile(ws
->fd
);
198 if ((error
= ResError()) != noErr
)
200 error
= FSpExchangeFiles(&ws
->tmpfile
, &ws
->dstfile
);
201 if (error
!= noErr
) goto out
;
202 error
= FSpDelete(&ws
->tmpfile
);
203 if (error
!= noErr
) goto out
;
207 fatalbox("Close of saved session failed (%d)", error
);
211 void *open_settings_r(char *sessionname
)
219 error
= get_session_dir(kDontCreateFolder
, &sessVRefNum
, &sessDirID
);
221 c2pstrcpy(psessionname
, sessionname
);
222 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &sessfile
);
223 if (error
!= noErr
) goto out
;
224 return open_settings_r_fsp(&sessfile
);
230 void *open_settings_r_fsp(FSSpec
*sessfile
)
236 fd
= FSpOpenResFile(sessfile
, fsRdPerm
);
237 if (fd
== 0) {error
= ResError(); goto out
;}
239 handle
= safemalloc(sizeof *handle
);
247 char *read_setting_s(void *handle
, char *key
, char *buffer
, int buflen
) {
252 if (handle
== NULL
) goto out
;
255 if (ResError() != noErr
) goto out
;
256 h
= get1namedresource(FOUR_CHAR_CODE('TEXT'), key
);
257 if (h
== NULL
) goto out
;
259 len
= GetHandleSize(h
);
260 if (len
+ 1 > buflen
) goto out
;
261 memcpy(buffer
, *h
, len
);
265 if (ResError() != noErr
) goto out
;
272 int read_setting_i(void *handle
, char *key
, int defvalue
) {
277 if (handle
== NULL
) goto out
;
280 if (ResError() != noErr
) goto out
;
281 h
= get1namedresource(FOUR_CHAR_CODE('Int '), key
);
282 if (h
== NULL
) goto out
;
285 if (ResError() != noErr
) goto out
;
292 void close_settings_r(void *handle
) {
295 if (handle
== NULL
) return;
298 if (ResError() != noErr
)
299 fatalbox("Close of saved session failed (%d)", ResError());
303 void del_settings(char *sessionname
) {
310 error
= get_session_dir(kDontCreateFolder
, &sessVRefNum
, &sessDirID
);
312 c2pstrcpy(psessionname
, sessionname
);
313 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &sessfile
);
314 if (error
!= noErr
) goto out
;
316 error
= FSpDelete(&sessfile
);
319 fatalbox("Delete session failed (%d)", error
);
322 struct enum_settings_state
{
328 void *enum_settings_start(void) {
330 struct enum_settings_state
*state
;
332 state
= safemalloc(sizeof(*state
));
333 error
= get_session_dir(kDontCreateFolder
, &state
->vRefNum
, &state
->dirID
);
334 if (error
!= noErr
) {
342 char *enum_settings_next(void *handle
, char *buffer
, int buflen
) {
343 struct enum_settings_state
*e
= handle
;
348 if (e
== NULL
) return NULL
;
350 pb
.hFileInfo
.ioNamePtr
= name
;
351 pb
.hFileInfo
.ioVRefNum
= e
->vRefNum
;
352 pb
.hFileInfo
.ioDirID
= e
->dirID
;
353 pb
.hFileInfo
.ioFDirIndex
= e
->index
++;
354 error
= PBGetCatInfoSync(&pb
);
355 if (error
!= noErr
) return NULL
;
356 } while (!((pb
.hFileInfo
.ioFlAttrib
& ioDirMask
) == 0 &&
357 pb
.hFileInfo
.ioFlFndrInfo
.fdCreator
== PUTTY_CREATOR
&&
358 pb
.hFileInfo
.ioFlFndrInfo
.fdType
== SESS_TYPE
&&
361 p2cstrcpy(buffer
, name
);
365 void enum_settings_finish(void *handle
) {
370 #define SEED_SIZE 512
372 void read_random_seed(noise_consumer_t consumer
)
379 long count
= SEED_SIZE
;
381 if (get_putty_dir(kDontCreateFolder
, &puttyVRefNum
, &puttyDirID
) != noErr
)
383 if (HOpenDF(puttyVRefNum
, puttyDirID
, "\pPuTTY Random Seed", fsRdPerm
,
386 error
= FSRead(refnum
, &count
, buf
);
387 if (error
!= noErr
&& error
!= eofErr
)
389 (*consumer
)(buf
, count
);
393 void write_random_seed(void *data
, int len
)
395 short puttyVRefNum
, tmpVRefNum
;
396 long puttyDirID
, tmpDirID
;
398 FSSpec dstfile
, tmpfile
;
402 if (get_putty_dir(kCreateFolder
, &puttyVRefNum
, &puttyDirID
) != noErr
)
405 error
= FSMakeFSSpec(puttyVRefNum
, puttyDirID
, "\pPuTTY Random Seed",
407 if (error
!= noErr
&& error
!= fnfErr
) return;
409 /* Create a temporary file to save to first. */
410 error
= FindFolder(puttyVRefNum
, kTemporaryFolderType
, kCreateFolder
,
411 &tmpVRefNum
, &tmpDirID
);
412 if (error
!= noErr
) return;
413 error
= FSMakeFSSpec(tmpVRefNum
, tmpDirID
, "\pPuTTY Random Seed",
415 if (error
!= noErr
&& error
!= fnfErr
) return;
416 if (error
== noErr
) {
417 error
= FSpDelete(&tmpfile
);
418 if (error
!= noErr
) return;
420 error
= FSpCreate(&tmpfile
, PUTTY_CREATOR
, SEED_TYPE
, smRoman
);
421 if (error
!= noErr
) return;
423 if (FSpOpenDF(&tmpfile
, fsWrPerm
, &refnum
) != noErr
) goto fail
;
425 if (FSWrite(refnum
, &count
, data
) != noErr
) goto fail2
;
426 if (FSClose(refnum
) != noErr
) goto fail
;
428 if (FSpExchangeFiles(&tmpfile
, &dstfile
) != noErr
) goto fail
;
429 if (FSpDelete(&tmpfile
) != noErr
) return;
442 * c-file-style: "simon"