1133359Sobrien/*
2133359Sobrien * Adapted from: apptype.c, Written by Eberhard Mattes and put into the
3133359Sobrien * public domain
4133359Sobrien *
5133359Sobrien * Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous
6133359Sobrien * searches.
7133359Sobrien *
8133359Sobrien * 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com"
9133359Sobrien * (other than an OS/2 exe or Win exe with this name). Eberhard Mattes
10133359Sobrien * remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very
11133359Sobrien * bug ridden) Win Emacs as "OS/2 executable".
12133359Sobrien *
13133359Sobrien * 3. apptype() uses the filename if given, otherwise a tmp file is created with
14133359Sobrien * the contents of buf. If buf is not the complete file, apptype can
15133359Sobrien * incorrectly identify the exe type. The "-z" option of "file" is the reason
16133359Sobrien * for this ugly code.
17133359Sobrien */
18133359Sobrien
19133359Sobrien/*
20133359Sobrien * amai: Darrel Hankerson did the changes described here.
21133359Sobrien *
22133359Sobrien * It remains to check the validity of comments (2.) since it's referred to an
23133359Sobrien * "old" OS/2 version.
24133359Sobrien *
25133359Sobrien */
26133359Sobrien
27133359Sobrien#include "file.h"
28133359Sobrien
29191736Sobrien#ifndef	lint
30226048SobrienFILE_RCSID("@(#)$File: apptype.c,v 1.13 2011/09/07 21:57:15 christos Exp $")
31191736Sobrien#endif /* lint */
32191736Sobrien
33133359Sobrien#include <stdlib.h>
34133359Sobrien#include <string.h>
35133359Sobrien
36133359Sobrien#ifdef __EMX__
37133359Sobrien#include <io.h>
38133359Sobrien#define INCL_DOSSESMGR
39133359Sobrien#define INCL_DOSERRORS
40133359Sobrien#define INCL_DOSFILEMGR
41133359Sobrien#include <os2.h>
42133359Sobrientypedef ULONG   APPTYPE;
43133359Sobrien
44133359Sobrienprotected int
45133359Sobrienfile_os2_apptype(struct magic_set *ms, const char *fn, const void *buf,
46133359Sobrien    size_t nb)
47133359Sobrien{
48133359Sobrien	APPTYPE         rc, type;
49133359Sobrien	char            path[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_DIR],
50133359Sobrien			fname[_MAX_FNAME], ext[_MAX_EXT];
51133359Sobrien	char           *filename;
52133359Sobrien	FILE           *fp;
53133359Sobrien
54133359Sobrien	if (fn)
55133359Sobrien		filename = strdup(fn);
56133359Sobrien	else if ((filename = tempnam("./", "tmp")) == NULL) {
57133359Sobrien		file_error(ms, errno, "cannot create tempnam");
58133359Sobrien		return -1;
59133359Sobrien	}
60133359Sobrien	/* qualify the filename to prevent extraneous searches */
61133359Sobrien	_splitpath(filename, drive, dir, fname, ext);
62133359Sobrien	(void)sprintf(path, "%s%s%s%s", drive,
63133359Sobrien		(*dir == '\0') ? "./" : dir,
64133359Sobrien		fname,
65133359Sobrien		(*ext == '\0') ? "." : ext);
66133359Sobrien
67133359Sobrien	if (fn == NULL) {
68133359Sobrien		if ((fp = fopen(path, "wb")) == NULL) {
69133359Sobrien			file_error(ms, errno, "cannot open tmp file `%s'", path);
70133359Sobrien			return -1;
71133359Sobrien		}
72133359Sobrien		if (fwrite(buf, 1, nb, fp) != nb) {
73133359Sobrien			file_error(ms, errno, "cannot write tmp file `%s'",
74133359Sobrien			    path);
75226048Sobrien			(void)fclose(fp);
76133359Sobrien			return -1;
77133359Sobrien		}
78133359Sobrien		(void)fclose(fp);
79133359Sobrien	}
80192348Sdelphij	rc = DosQueryAppType((unsigned char *)path, &type);
81133359Sobrien
82133359Sobrien	if (fn == NULL) {
83133359Sobrien		unlink(path);
84133359Sobrien		free(filename);
85133359Sobrien	}
86133359Sobrien#if 0
87133359Sobrien	if (rc == ERROR_INVALID_EXE_SIGNATURE)
88133359Sobrien		printf("%s: not an executable file\n", fname);
89133359Sobrien	else if (rc == ERROR_FILE_NOT_FOUND)
90133359Sobrien		printf("%s: not found\n", fname);
91133359Sobrien	else if (rc == ERROR_ACCESS_DENIED)
92133359Sobrien		printf("%s: access denied\n", fname);
93133359Sobrien	else if (rc != 0)
94133359Sobrien		printf("%s: error code = %lu\n", fname, rc);
95133359Sobrien	else
96133359Sobrien#else
97133359Sobrien
98133359Sobrien	/*
99133359Sobrien	 * for our purpose here it's sufficient to just ignore the error and
100133359Sobrien	 * return w/o success (=0)
101133359Sobrien	 */
102133359Sobrien
103133359Sobrien	if (rc)
104133359Sobrien		return (0);
105133359Sobrien
106133359Sobrien#endif
107133359Sobrien
108133359Sobrien	if (type & FAPPTYP_32BIT)
109133359Sobrien		if (file_printf(ms, "32-bit ") == -1)
110133359Sobrien			return -1;
111133359Sobrien	if (type & FAPPTYP_PHYSDRV) {
112133359Sobrien		if (file_printf(ms, "physical device driver") == -1)
113133359Sobrien			return -1;
114133359Sobrien	} else if (type & FAPPTYP_VIRTDRV) {
115133359Sobrien		if (file_printf(ms, "virtual device driver") == -1)
116133359Sobrien			return -1;
117133359Sobrien	} else if (type & FAPPTYP_DLL) {
118133359Sobrien		if (type & FAPPTYP_PROTDLL)
119133359Sobrien			if (file_printf(ms, "protected ") == -1)
120133359Sobrien				return -1;
121133359Sobrien		if (file_printf(ms, "DLL") == -1)
122133359Sobrien			return -1;
123133359Sobrien	} else if (type & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT)) {
124133359Sobrien		if (file_printf(ms, "Windows executable") == -1)
125133359Sobrien			return -1;
126133359Sobrien	} else if (type & FAPPTYP_DOS) {
127133359Sobrien		/*
128133359Sobrien		 * The API routine is partially broken on filenames ending
129133359Sobrien		 * ".com".
130133359Sobrien		 */
131133359Sobrien		if (stricmp(ext, ".com") == 0)
132133359Sobrien			if (strncmp((const char *)buf, "MZ", 2))
133133359Sobrien				return (0);
134133359Sobrien		if (file_printf(ms, "DOS executable") == -1)
135133359Sobrien			return -1;
136133359Sobrien		/* ---------------------------------------- */
137133359Sobrien		/* Might learn more from the magic(4) entry */
138133359Sobrien		if (file_printf(ms, ", magic(4)-> ") == -1)
139133359Sobrien			return -1;
140133359Sobrien		return (0);
141133359Sobrien		/* ---------------------------------------- */
142133359Sobrien	} else if (type & FAPPTYP_BOUND) {
143133359Sobrien		if (file_printf(ms, "bound executable") == -1)
144133359Sobrien			return -1;
145133359Sobrien	} else if ((type & 7) == FAPPTYP_WINDOWAPI) {
146133359Sobrien		if (file_printf(ms, "PM executable") == -1)
147133359Sobrien			return -1;
148133359Sobrien	} else if (file_printf(ms, "OS/2 executable") == -1)
149133359Sobrien		return -1;
150133359Sobrien
151133359Sobrien	switch (type & (FAPPTYP_NOTWINDOWCOMPAT |
152133359Sobrien			FAPPTYP_WINDOWCOMPAT |
153133359Sobrien			FAPPTYP_WINDOWAPI)) {
154133359Sobrien	case FAPPTYP_NOTWINDOWCOMPAT:
155133359Sobrien		if (file_printf(ms, " [NOTWINDOWCOMPAT]") == -1)
156133359Sobrien			return -1;
157133359Sobrien		break;
158133359Sobrien	case FAPPTYP_WINDOWCOMPAT:
159133359Sobrien		if (file_printf(ms, " [WINDOWCOMPAT]") == -1)
160133359Sobrien			return -1;
161133359Sobrien		break;
162133359Sobrien	case FAPPTYP_WINDOWAPI:
163133359Sobrien		if (file_printf(ms, " [WINDOWAPI]") == -1)
164133359Sobrien			return -1;
165133359Sobrien		break;
166133359Sobrien	}
167133359Sobrien	return 1;
168133359Sobrien}
169133359Sobrien#endif
170