1/* Copyright (c) 1999,2003-2004,2008 Apple Inc.
2 *
3 * attachLeak.c - analyze memory leaks from CSSM_Init/ModuleAttach.
4 *
5 */
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <time.h>
10#include <Security/cssm.h>
11#include "cspwrap.h"
12#include "common.h"
13
14static CSSM_API_MEMORY_FUNCS memFuncs = {
15	appMalloc,
16	appFree,
17	appRealloc,
18 	appCalloc,
19 	NULL
20 };
21
22static CSSM_VERSION vers = {2, 0};
23
24static void usage(char **argv)
25{
26	printf("usage: %s [options]\n", argv[0]);
27	printf("   Options: \n");
28	printf("   l (do ModuleLoad on each loop)\n");
29	printf("   u (do Module{Load,Unload} on each loop)\n");
30	printf("   d (CSP/DL; default = bare CSP)\n");
31	printf("   t (TP)\n");
32	printf("   c (CL)\n");
33	exit(1);
34}
35
36static int doPause(const char *state)
37{
38	char resp;
39
40	fpurge(stdin);
41	printf("%s\n", state);
42	printf("q to abort, anything else to continue: ");
43	resp = getchar();
44	return(resp == 'q');
45}
46
47int main(int argc, char **argv)
48{
49	int					arg;
50	char				*argp;
51	CSSM_HANDLE 		modHand = 0;
52	void 				*foo;
53	CSSM_SERVICE_TYPE	svcType = CSSM_SERVICE_CSP;
54	const CSSM_GUID		*guid = &gGuidAppleCSP;
55	const char			*modName = "AppleCSP";
56	CSSM_RETURN			crtn;
57	CSSM_BOOL			doLoad = CSSM_FALSE;
58	CSSM_BOOL			doUnload = CSSM_FALSE;
59
60	/* force link against malloc */
61	foo = malloc(1);
62	for(arg=1; arg<argc; arg++) {
63		argp = argv[arg];
64		switch(argp[0]) {
65			case 'l':
66				doLoad = CSSM_TRUE;
67				break;
68			case 'u':
69				doLoad = doUnload = CSSM_TRUE;
70				break;
71			case 'd':
72				guid = &gGuidAppleCSPDL;
73				modName = "AppleCSPDL";
74				break;
75			case 'c':
76				guid = &gGuidAppleX509CL;
77				svcType = CSSM_SERVICE_CL;
78				modName = "AppleX509CL";
79				break;
80			case 't':
81				guid = &gGuidAppleX509TP;
82				svcType = CSSM_SERVICE_TP;
83				modName = "AppleX509TP";
84				break;
85		    case 'h':
86		    default:
87				usage(argv);
88		}
89	}
90
91	if(doPause("Top of test")) {
92		goto done;
93	}
94
95	/* CSSM init, just once */
96	if(!cssmStartup()) {
97		printf("Oops, error starting up CSSM\n");
98		exit(1);
99	}
100	if(doPause("CSSM initialized")) {
101		goto done;
102	}
103
104
105	if(!doLoad) {
106		/* load, just once */
107		crtn = CSSM_ModuleLoad(guid,
108			CSSM_KEY_HIERARCHY_NONE,
109			NULL,			// eventHandler
110			NULL);			// AppNotifyCallbackCtx
111		if(crtn) {
112			printf("Error loading %s\n", modName);
113			printError("CSSM_ModuleLoad", crtn);
114			return 0;
115		}
116		if(doPause("CSSM_ModuleLoad() complete")) {
117			goto done;
118		}
119	}
120	while(1) {
121		if(doLoad) {
122			/* load, each time */
123			crtn = CSSM_ModuleLoad(guid,
124				CSSM_KEY_HIERARCHY_NONE,
125				NULL,			// eventHandler
126				NULL);			// AppNotifyCallbackCtx
127			if(crtn) {
128				printf("Error loading %s\n", modName);
129				printError("CSSM_ModuleLoad", crtn);
130				return 0;
131			}
132			if(doPause("CSSM_ModuleLoad() complete")) {
133				break;
134			}
135		}
136		crtn = CSSM_ModuleAttach (guid,
137			&vers,
138			&memFuncs,				// memFuncs
139			0,						// SubserviceID
140			svcType,
141			0,						// AttachFlags
142			CSSM_KEY_HIERARCHY_NONE,
143			NULL,					// FunctionTable
144			0,						// NumFuncTable
145			NULL,					// reserved
146			&modHand);
147		if(crtn) {
148			printf("Error attaching to %s\n", modName);
149			printError("CSSM_ModuleAttach", crtn);
150			return 0;
151		}
152		if(doPause("ModuleAttach() complete")) {
153			break;
154		}
155		CSSM_ModuleDetach(modHand);
156		modHand = 0;
157		if(doPause("ModuleDetach() complete")) {
158			break;
159		}
160		if(doUnload) {
161			/* unload, each time */
162			crtn = CSSM_ModuleUnload(guid, NULL, NULL);
163			if(crtn) {
164				printf("Error unloading %s\n", modName);
165				printError("CSSM_ModuleUnload", crtn);
166				return 0;
167			}
168			if(doPause("ModuleUnload() complete")) {
169				break;
170			}
171		}	/* unloading */
172	}		/* main loop */
173
174done:
175	fpurge(stdin);
176	if(modHand) {
177		CSSM_ModuleDetach(modHand);
178		printf("Final detach complete; cr to exit: ");
179	}
180	else {
181		printf("Test complete; cr to exit: ");
182	}
183	getchar();
184	return 0;
185}
186