1 /*
2  * Copyright (c) 2005 William Pitcock, et al.
3  * The rights to this code are as documented in doc/LICENSE.
4  *
5  * This file contains data structures concerning modules.
6  *
7  */
8 
9 #ifndef MODULE_H
10 #define MODULE_H
11 
12 #include "privs.h"
13 #include "abirev.h"
14 
15 typedef enum {
16 	MODULE_UNLOAD_INTENT_PERM,
17 	MODULE_UNLOAD_INTENT_RELOAD,
18 } module_unload_intent_t;
19 
20 typedef enum {
21 	MODULE_UNLOAD_CAPABILITY_OK,
22 	MODULE_UNLOAD_CAPABILITY_NEVER,
23 	MODULE_UNLOAD_CAPABILITY_RELOAD_ONLY,
24 } module_unload_capability_t;
25 
26 typedef struct module_ module_t;
27 typedef struct v4_moduleheader_ v4_moduleheader_t;
28 
29 typedef void (*module_unload_handler_t)(module_t *, module_unload_intent_t);
30 
31 /* Module structure. Might be a loaded .so module, or something else that
32  * behaves as a module for dependency purposes (perl script, etc).
33  */
34 struct module_ {
35 	char name[BUFSIZE];
36 	char modpath[BUFSIZE];
37 	module_unload_capability_t can_unload;
38 
39 	unsigned int mflags;
40 
41 	/* These three are real-module-specific. Either all will be set, or all
42 	 * will be null.
43 	 */
44 	v4_moduleheader_t *header;
45 	void *address;
46 	mowgli_module_t *handle;
47 
48 	/* If this module is not a loaded .so (the above three are null), and
49 	 * can_unload is not never, then * this must be set to a working unload
50 	 * function.
51 	 */
52 	module_unload_handler_t unload_handler;
53 
54 	mowgli_list_t dephost;
55 	mowgli_list_t deplist;
56 
57 	mowgli_list_t symlist;		/* MAPIv2 symbol dependencies. */
58 };
59 
60 #define MODTYPE_STANDARD	0
61 #define MODTYPE_CORE		1 /* Can't be unloaded. */
62 #define MODTYPE_FAIL		0x8000 /* modinit failed */
63 
64 #define MAPI_ATHEME_MAGIC	0xdeadbeef
65 #define MAPI_ATHEME_V4		4
66 
67 #define MAX_CMD_PARC		20
68 
69 struct v4_moduleheader_ {
70 	unsigned int atheme_mod;
71 	unsigned int abi_ver;
72 	unsigned int abi_rev;
73 	const char *serial;
74 	const char *name;
75 	module_unload_capability_t can_unload;
76 	void (*modinit)(module_t *m);
77 	void (*deinit)(module_unload_intent_t intent);
78 	const char *vendor;
79 	const char *version;
80 };
81 
82 /* name is the module name we're searching for.
83  * path is the likely full path name, which may be ignored.
84  * If it is found, set module to the loaded module_t pointer
85  */
86 typedef struct {
87 	const char *name;
88 	const char *path;
89 	module_t *module;
90 	int handled;
91 } hook_module_load_t;
92 
93 #define DECLARE_MODULE_V1(name, norestart, modinit, deinit, ver, ven) \
94 	v4_moduleheader_t _header = { \
95 		MAPI_ATHEME_MAGIC, MAPI_ATHEME_V4, \
96 		CURRENT_ABI_REVISION, "unknown", \
97 		name, norestart, modinit, deinit, ven, ver \
98 	}
99 
100 E void _modinit(module_t *m);
101 E void _moddeinit(module_unload_intent_t intent);
102 
103 E void modules_init(void);
104 E module_t *module_load(const char *filespec);
105 E void module_load_dir(const char *dirspec);
106 E void module_load_dir_match(const char *dirspec, const char *pattern);
107 E void *module_locate_symbol(const char *modname, const char *sym);
108 E void module_unload(module_t *m, module_unload_intent_t intent);
109 E module_t *module_find(const char *name);
110 E module_t *module_find_published(const char *name);
111 E bool module_request(const char *name);
112 
113 #define MODULE_TRY_REQUEST_DEPENDENCY(self, modname) \
114 	if (module_request(modname) == false)				\
115 	{								\
116 		(self)->mflags = MODTYPE_FAIL;				\
117 		return;							\
118 	}
119 
120 #define MODULE_TRY_REQUEST_SYMBOL(self, dest, modname, sym) \
121 	if ((dest = module_locate_symbol(modname, sym)) == NULL)		\
122 	{									\
123 		MODULE_TRY_REQUEST_DEPENDENCY(self, modname);			\
124 		if ((dest = module_locate_symbol(modname, sym)) == NULL)	\
125 		{								\
126 			(self)->mflags = MODTYPE_FAIL;				\
127 			return;							\
128 		}								\
129 	}
130 
131 #define MODULE_CONFLICT(self, modname) \
132 	if (module_find_published(modname))					\
133 	{									\
134 		slog(LG_ERROR, "module %s conflicts with %s, unloading",	\
135 		     self->name, modname);					\
136 		(self)->mflags = MODTYPE_FAIL;					\
137 		return;								\
138 	}
139 
140 typedef struct module_dependency_ {
141 	char *name;
142 	module_unload_capability_t can_unload;
143 } module_dependency_t;
144 
145 #endif
146 
147 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
148  * vim:ts=8
149  * vim:sw=8
150  * vim:noexpandtab
151  */
152