home *** CD-ROM | disk | FTP | other *** search
- /* macos.c -- operating system dependant mpack code for the Macintosh
- *
- * (C) Copyright 1993 by Christopher J. Newman
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Christopher J. Newman not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Christopher J. Newman makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
- * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <errno.h>
- #include "common.h"
- #include "macnapp.h"
- #include "macmpack.h"
-
- extern char *malloc(), *realloc();
-
- char *xmalloc(unsigned size)
- {
- char *ret;
-
- if (ret = malloc((unsigned) size))
- return ret;
-
- yell("Virtual memory exhausted");
- exit(1);
- }
-
- char *xrealloc (char *ptr, unsigned size)
- {
- char *ret;
-
- /* xrealloc (NULL, size) behaves like xmalloc (size), as in ANSI C */
- if (ret = !ptr ? malloc ((unsigned) size) : realloc (ptr, (unsigned) size))
- return ret;
-
- yell("Virtual memory exhausted");
- exit(1);
- }
-
- char *strsave(char *str)
- {
- char *p = xmalloc(strlen(str)+1);
- strcpy(p, str);
- return p;
- }
-
- /* save output filename buffer */
- static char *output_fname = NULL;
-
- /* TMPL resource for IDna -- ID to name mappings
- */
- char TMPL[] = {
- 16 , 'D', 'i', 'r', 'e', 'c', 't', 'o',
- 'r', 'y', ' ', 'N', 'u', 'm', 'b', 'e',
- 'r', 'D', 'W', 'R', 'D'
- };
-
- /* Generate a message-id */
- char *os_genid()
- {
- char *result;
- long tick;
- unsigned long time;
-
- tick = TickCount();
- result = malloc(64);
- GetDateTime(&time);
- HLock((Handle) mpack_prefs);
- sprintf(result, "%lu.%lu@%s", tick, time, (*mpack_prefs)->internet_host);
- HUnlock((Handle) mpack_prefs);
-
- /* make sure tick count is bumped before we return... */
- while (tick == TickCount());
-
- return (result);
- }
-
- /* Create and return directory for a message-id
- */
- char *os_idtodir(id)
- char *id;
- {
- static PCstr buf[257];
- static unsigned char mpackdir[] = "\pmpack-tmp";
- PCstr idbuf[257];
- char *fname;
- short wrefnum, vrefnum, resfile, uqid, createflag = 0;
- long dirid, procid;
- OSErr err;
- Handle h;
- ResType type = 'IDna';
- FInfo finfo;
-
- /* get name of default volume */
- if (GetVol(P(buf), &wrefnum) != noErr) return (NULL);
- procid = 0;
- if (GetWDInfo(wrefnum, &vrefnum, &dirid, &procid) != noErr) return (NULL);
-
- /* try creating tmp dir */
- err = DirCreate(vrefnum, 0, mpackdir, &dirid);
- if (err != noErr && err != dupFNErr) return (NULL);
- CtoPCstrcat(buf, ":");
- PtoPCstrcat(buf, (char *) mpackdir);
- CtoPCstrcat(buf, ":");
- fname = C(buf) + PCstrlen(buf);
-
- /* open the map file */
- strcpy(fname, "map");
- SetPlen(buf);
- CreateResFile(P(buf));
- if ((err = ResError()) == noErr && GetFInfo(P(buf), vrefnum, &finfo) == noErr) {
- finfo.fdType = 'rsrc';
- finfo.fdCreator = 'RSED';
- SetFInfo(P(buf), vrefnum, &finfo);
- }
- if ((resfile = OpenResFile(P(buf))) < 0) return (NULL);
- if (err == noErr && PtrToHand((Ptr) TMPL, &h, sizeof (TMPL)) == noErr) {
- AddResource(h, 'TMPL', 1000, "\pIDna");
- }
-
- /* is there a mapping for the id? */
- CtoPCstrcpy(idbuf, id);
- h = GetNamedResource(type, P(idbuf));
-
- /* no mapping -- create one */
- if (!h) {
- createflag = 1;
- while ((uqid = UniqueID(type)) < 128);
- h = NewHandle(sizeof (short));
- if (h) (**(short **)h) = uqid;
- AddResource(h, type, uqid, P(idbuf));
- if ((err = ResError()) != noErr) {
- CloseResFile(resfile);
- return (NULL);
- }
- } else {
- uqid = ** (short **) h;
- }
-
- /* set directory name & create it */
- sprintf(fname, "%d:", uqid);
- SetPlen(buf);
- err = DirCreate(vrefnum, 0, P(buf), &dirid);
- if (err != noErr && err != dupFNErr) {
- RmveResource(h);
- DisposHandle(h);
- h = NULL;
- }
-
- /* done with map file */
- CloseResFile(resfile);
-
- return (h ? C(buf) : NULL);
- }
-
- /*
- * We are done with the directory returned by os_idtodir()
- * Remove it
- */
- os_donewithdir(dir)
- char *dir;
- {
- PCstr buf[257];
- short uqid, resfile;
- char *fname;
- Handle h;
-
- CtoPCstrcpy(buf, dir);
- HDelete(0, 0, P(buf));
- fname = strchr(C(buf), ':');
- if (fname && (fname = strchr(fname + 1, ':'))) {
- uqid = atoi(fname + 1);
- strcpy(fname, ":map");
- SetPlen(buf);
- if ((resfile = OpenResFile(P(buf))) >= 0) {
- h = GetResource('IDna', uqid);
- if (h) {
- RmveResource(h);
- DisposHandle(h);
- }
- CloseResFile(resfile);
- }
- }
- }
-
- /*
- * Create a new file, with suggested filename "fname".
- * "fname" may have come from an insecure source, so clean it up first.
- * It may also be null.
- * "contentType" is passed in for use by systems that have typed filesystems.
- * "binary" is nonzero if the new file should be opened in binary mode.
- */
- FILE *os_newtypedfile(fname, contentType, binary)
- char *fname;
- char *contentType;
- int binary;
- {
- char *p;
- static int filesuffix=0;
- char buf[128], *descfname=0;
- FILE *outfile = 0;
- extern long _ftype, _fcreator;
- extern Cursor watch;
- Handle h;
- PCstr tstr[257];
-
- if (!fname) fname = "";
-
- /* Translate ':' to underscore */
- for (p=fname; *p; p++) {
- if (*p == ':' || !isprint(*p)) *p = '_';
- }
-
- /* chop filename to length */
- if (strlen(fname) > 31) {
- fname += strlen(fname) - 31;
- }
-
- if (!fname[0]) {
- do {
- if (outfile) fclose(outfile);
- sprintf(buf, "part%d", ++filesuffix);
- } while (outfile = fopen(buf, "r"));
- fname = buf;
- }
- else if (outfile = fopen(fname, "r")) {
- CtoPCstrcpy(tstr, fname);
- ParamText(P(tstr), NULL, NULL, NULL);
- SetCursor(&arrow);
- if (NAalert(replaceALRT) != iReplace) {
- do {
- fclose(outfile);
- sprintf(buf, "%s.%d", fname, ++filesuffix);
-
- } while (outfile = fopen(buf, "r"));
- fname = buf;
- } else {
- fclose(outfile);
- }
- SetCursor(&watch);
- }
-
- /* set the type */
- CtoPCstrcpy(tstr, contentType);
- h = GetNamedResource('TyCr', P(tstr));
- if (h) {
- _ftype = (*(OSType **)h)[0];
- _fcreator = (*(OSType **)h)[1];
- } else {
- _ftype = '????';
- }
-
- /* save file */
- outfile = fopen(fname, "wb");
- if (!outfile) {
- sprintf(buf, "Couldn't open file %s", fname);
- warn(buf);
- return (0);
- }
-
- if (output_fname) free(output_fname);
- output_fname = strsave(fname);
-
- if (strlen(fname) > sizeof(buf)-6) {
- descfname = xmalloc(strlen(fname)+6);
- }
- else {
- descfname = buf;
- }
- strcpy(descfname, fname);
-
- if (p = strrchr(descfname, '.')) *p = '\0';
-
- strcat(descfname, ".desc");
- (void) rename(TEMPFILENAME, descfname);
- if (descfname != buf) free(descfname);
- CtoPstr(descfname);
- _ftype = 'TEXT';
- _fcreator = 'mPAK';
-
- return outfile;
- }
-
- /*
- * Warn user that the MD5 digest of the last file created by os_newtypedfile()
- * did not match that supplied in the Content-MD5: header.
- */
- os_warnMD5mismatch()
- {
- char *warning;
-
- warning = xmalloc(strlen(output_fname) + 100);
- sprintf(warning, "%s was corrupted in transit",
- output_fname);
- warn(warning);
- free(warning);
- }
-
- /* bring up an error dialog for a file error
- */
- void os_perror(char *str)
- {
- extern int errno;
- char *err = strerror(errno), *scan;
- char msg[256];
- short maxflen;
-
- maxflen = 255 - (strlen(err) + 2);
- if (strlen(str) > maxflen) {
- str += strlen(str) - maxflen;
- for (scan = str; *scan && *scan++ != ':';);
- if (*scan) str = scan;
- }
- sprintf(msg, "%s: %s", str, err);
- yell(msg);
- }
-