1 /**
2  * Glue between OpenSSL BIO and Win32 compiler run-time
3  *
4  * Duplicate the content of the `applink.c` source file
5  * to avoid linking it in user code without adding a dependency
6  * to a C build system/compiler.
7  *
8  * See_Also: https://www.openssl.org/docs/manmaster/man3/OPENSSL_Applink.html
9  */
10 module deimos.openssl.applink;
11 
12 import core.stdc.stdio;
13 import std.stdio : _fileno, _setmode, _O_BINARY;
14 import core.sys.posix.fcntl;
15 import core.sys.posix.unistd;
16 import core.stdc.stdio;
17 
18 enum APPLINK_STDIN	=1;
19 enum APPLINK_STDOUT	=2;
20 enum APPLINK_STDERR	=3;
21 enum APPLINK_FPRINTF	=4;
22 enum APPLINK_FGETS	=5;
23 enum APPLINK_FREAD	=6;
24 enum APPLINK_FWRITE	=7;
25 enum APPLINK_FSETMOD	=8;
26 enum APPLINK_FEOF	=9;
27 enum APPLINK_FCLOSE 	=10;	/* should not be used */
28 
29 enum APPLINK_FOPEN	=11;	/* solely for completeness */
30 enum APPLINK_FSEEK	=12;
31 enum APPLINK_FTELL	=13;
32 enum APPLINK_FFLUSH	=14;
33 enum APPLINK_FERROR	=15;
34 enum APPLINK_CLEARERR =16;
35 enum APPLINK_FILENO	=17;	/* to be used with below */
36 
37 enum APPLINK_OPEN	=18;	/* formally can't be used, as flags can vary */
38 enum APPLINK_READ	=19;
39 enum APPLINK_WRITE	=20;
40 enum APPLINK_LSEEK	=21;
41 enum APPLINK_CLOSE	=22;
42 enum APPLINK_MAX	=22;	/* always same as last macro */
43 
44 enum _O_TEXT = 0x4000;
45 
46 extern(C)
47 {
48 	void *app_stdin()
49 	{
50 		return cast(void*)stdin;
51 	}
52 
53 	void *app_stdout()
54 	{
55 		return cast(void*)stdout;
56 	}
57 
58 	void *app_stderr()
59 	{
60 		return cast(void*)stderr;
61 	}
62 
63 	int app_feof(FILE *fp)
64 	{
65 		return feof(fp);
66 	}
67 
68 	int app_ferror(FILE *fp)
69 	{
70 		return ferror(fp);
71 	}
72 
73 	void app_clearerr(FILE *fp)
74 	{
75 		clearerr(fp);
76 	}
77 
78 	int app_fileno(FILE *fp)
79 	{
80 		return _fileno(fp);
81 	}
82 
83 	int app_fsetmod(FILE *fp, char mod)
84 	{
85 		return _setmode (_fileno(fp),mod=='b'?_O_BINARY:_O_TEXT);
86 	}
87 
88 	__gshared bool once = true;
89 	__gshared void*[APPLINK_MAX+1] OPENSSL_ApplinkTable = cast(void*)APPLINK_MAX;
90 
91 	export void** OPENSSL_Applink()
92 	{
93 		if (once)
94 		{
95 			OPENSSL_ApplinkTable[APPLINK_STDIN]		= &app_stdin;
96 			OPENSSL_ApplinkTable[APPLINK_STDOUT]	= &app_stdout;
97 			OPENSSL_ApplinkTable[APPLINK_STDERR]	= &app_stderr;
98 			OPENSSL_ApplinkTable[APPLINK_FPRINTF]	= &fprintf;
99 			OPENSSL_ApplinkTable[APPLINK_FGETS]		= &fgets;
100 			OPENSSL_ApplinkTable[APPLINK_FREAD]		= &fread;
101 			OPENSSL_ApplinkTable[APPLINK_FWRITE]	= &fwrite;
102 			OPENSSL_ApplinkTable[APPLINK_FSETMOD]	= &app_fsetmod;
103 			OPENSSL_ApplinkTable[APPLINK_FEOF]		= &app_feof;
104 			OPENSSL_ApplinkTable[APPLINK_FCLOSE]	= &fclose;
105 
106 			OPENSSL_ApplinkTable[APPLINK_FOPEN]		= &fopen;
107 			OPENSSL_ApplinkTable[APPLINK_FSEEK]		= &fseek;
108 			OPENSSL_ApplinkTable[APPLINK_FTELL]		= &ftell;
109 			OPENSSL_ApplinkTable[APPLINK_FFLUSH]	= &fflush;
110 			OPENSSL_ApplinkTable[APPLINK_FERROR]	= &app_ferror;
111 			OPENSSL_ApplinkTable[APPLINK_CLEARERR]	= &app_clearerr;
112 			OPENSSL_ApplinkTable[APPLINK_FILENO]	= &app_fileno;
113 
114 			OPENSSL_ApplinkTable[APPLINK_OPEN]		= &fopen;
115 			OPENSSL_ApplinkTable[APPLINK_READ]		= &fread;
116 			OPENSSL_ApplinkTable[APPLINK_WRITE]		= &fwrite;
117 			OPENSSL_ApplinkTable[APPLINK_LSEEK]		= &fseek;
118 			OPENSSL_ApplinkTable[APPLINK_CLOSE]		= &fclose;
119 
120 			once = false;
121 		}
122 
123 		return OPENSSL_ApplinkTable.ptr;
124 	}
125 }