Skip to content

Instantly share code, notes, and snippets.

@h2oota
Created January 3, 2013 12:43
Show Gist options
  • Save h2oota/4443189 to your computer and use it in GitHub Desktop.
Save h2oota/4443189 to your computer and use it in GitHub Desktop.
s_client(OpenSSL)をWindows版Emacsの非同期プロセスから利用するためのパッチ。 s_clientは標準入出力がコンソールでないと動作しませんが、このパッチを適用する事で標準入出力がパイプの場合にも動作するようになります。
--- ./apps/app_rand.c.orig 2001-02-20 17:13:19.000000000 +0900
+++ ./apps/app_rand.c 2013-01-03 12:55:09.000000000 +0900
@@ -129,6 +129,7 @@ int app_RAND_load_file(const char *file,
BIO_flush(bio_e);
RAND_screen();
BIO_printf(bio_e," done\n");
+ BIO_flush(bio_e);
#endif
if (file == NULL)
--- ./apps/s_client.c.orig 2012-03-19 03:14:46.000000000 +0900
+++ ./apps/s_client.c 2013-01-03 17:11:46.000000000 +0900
@@ -378,6 +378,204 @@ enum
PROTO_XMPP
};
+#ifdef OPENSSL_SYS_WINNT
+#include <process.h>
+#define OPENSSL_WINNT_THREAD_IO
+#if !defined(_WIN32) || !defined(STD_INPUT_HANDLE)
+#error invalid comile environment
+#endif
+#define openssl_fdclr(a,b) FD_CLR((unsigned int)a, b)
+
+#define STATIC_ASSERT(expr) typedef char __static_assert_t[ (expr) ? 1 : -1 ]
+#define compare_and_set(dst, new_val, old_val) _InterlockedCompareExchange64((dst), (new_val), (old_val))
+
+#define MAX_QLEN (sizeof(intptr_t) * 2 - 1)
+#define DATA_BUFFER_SIZE BUFSIZZ
+
+struct buffer {
+#define QUSED(Q) (((Q)->q) >> (sizeof(intptr_t) * 8 - 4))
+#define QLEN(i) (((uintptr_t)(i)) << (sizeof(intptr_t) * 8 - 4))
+#define QMASK QLEN(0xf)
+#define QRESET(Q, n) do {(Q)->q = 0;} while(0)
+ /*
+ * struct queue {
+ * int used:4;
+ * int q:4[MAX_DATA_BUFFERS];
+ * };
+ */
+ struct queue {
+ volatile uintptr_t q;
+ } free_q, filled_q;
+ HANDLE sem;
+ uintptr_t thrd;
+ struct {
+ int c;
+ char b[DATA_BUFFER_SIZE];
+ } data[];
+} *read_buffer, *write_buffer;
+
+/*
+ * lock-free queue
+ */
+static int dequeue(struct queue *q)
+{
+ uintptr_t qstatus = q->q;
+ int w = 2;
+ for (qstatus = q->q;
+ compare_and_set(
+ &q->q,
+ (qstatus - QLEN(1) & QMASK)
+ + ((qstatus & ~QMASK) >> 4),
+ qstatus) != qstatus;
+ qstatus = q->q) {
+ Sleep(w);
+ if ((w = (int)(1.5 * w)) > 1000)
+ w = 1000;
+ }
+ return qstatus & 0xf;
+}
+
+static void enqueue(struct queue *q, int n)
+{
+ uintptr_t qstatus;
+ int w = 2;
+ for (qstatus = q->q;
+ compare_and_set(
+ &q->q,
+ qstatus + QLEN(1) + ((uintptr_t)n << (QUSED(q) * 4)),
+ qstatus) != qstatus;
+ qstatus = q->q) {
+ Sleep(w);
+ if ((w = (int)(1.5 * w)) > 1000)
+ w = 1000;
+ }
+}
+
+unsigned int reader_thread(void *vp)
+{
+ struct buffer *b = (struct buffer *)vp;
+ for (;;) {
+ int n, cc;
+ n = dequeue(&b->free_q);
+ cc = b->data[n].c = raw_read_stdin(b->data[n].b, DATA_BUFFER_SIZE);
+ enqueue(&b->filled_q, n);
+ ReleaseSemaphore(b->sem, 1, NULL);
+ if (cc <= 0)
+ return 0;
+ }
+}
+
+unsigned int writer_thread(void *vp)
+{
+ struct buffer *b = (struct buffer *)vp;
+ for (;;) {
+ int n, cc;
+ DWORD v = WaitForSingleObject(b->sem, INFINITE);
+ assert(v == WAIT_OBJECT_0);
+ n = dequeue(&b->filled_q);
+ if (b->data[n].c <= 0)
+ return 0;
+
+ for (;b->data[n].c > 0; b->data[n].c -= cc)
+ cc = raw_write_stdout(b->data[n].b, b->data[n].c);
+ enqueue(&b->free_q, n);
+ }
+}
+
+static void start_tty(int s)
+{
+ enum {
+ rq_leng = 3,
+ wq_leng = 10,
+ };
+ STATIC_ASSERT(rq_leng < MAX_QLEN && wq_leng < MAX_QLEN);
+ static char r[sizeof(struct buffer)
+ + DATA_BUFFER_SIZE * rq_leng] = {0};
+ static char w[sizeof(struct buffer)
+ + DATA_BUFFER_SIZE * wq_leng] = {0};
+ int i;
+#define INIT_BUFFER(b, n) do { \
+ static char d[ \
+ sizeof(struct buffer) \
+ + DATA_BUFFER_SIZE * (n)]; \
+ b = (struct buffer *)(d); \
+ b->sem = CreateSemaphore(NULL, 0, (n), NULL); \
+ QRESET(&b->free_q, (n)); \
+ QRESET(&b->filled_q, (n)); \
+ } while(0)
+
+ INIT_BUFFER(read_buffer, rq_leng);
+ INIT_BUFFER(write_buffer, wq_leng);
+#undef INIT_BUFFER
+
+ for (i = 0; i < rq_leng; i++)
+ enqueue(&read_buffer->free_q, i);
+ read_buffer->thrd
+ = _beginthreadex(
+ NULL, 0, reader_thread, read_buffer, 0, 0);
+
+ for (i = 0; i < wq_leng; i++)
+ enqueue(&write_buffer->free_q, i);
+ write_buffer->thrd
+ = _beginthreadex(
+ NULL, 0, writer_thread, write_buffer, 0, 0);
+}
+
+static int winnt_raw_write_stdout(const void *buf,int siz);
+static void stop_tty()
+{
+ if (read_buffer && write_buffer) {
+ HANDLE h[] = {
+ (HANDLE)read_buffer->thrd,
+ (HANDLE)write_buffer->thrd,
+ };
+ /* stop reader_thread */
+ CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
+ /* stop writer_thread */
+ winnt_raw_write_stdout(write_buffer, -1);
+
+ if (WaitForMultipleObjects(
+ sizeof(h) / sizeof(h[0]), h, TRUE, 3000) == 0)
+ BIO_printf(bio_err,"reader, writer thread could not terminate\n");
+
+ CloseHandle((HANDLE)read_buffer->thrd);
+ CloseHandle((HANDLE)write_buffer->thrd);
+ }
+}
+
+static int winnt_raw_write_stdout(const void *buf,int siz)
+{
+ int n = dequeue(&write_buffer->free_q); /* dequeue always success */
+
+ if (siz > 0)
+ memcpy(write_buffer->data[n].b, buf, siz);
+ write_buffer->data[n].c = siz;
+ enqueue(&write_buffer->filled_q, n);
+ ReleaseSemaphore(write_buffer->sem, 1, NULL);
+ return siz;
+}
+
+static int winnt_raw_read_stdin(void *buf,int siz)
+{
+ int c, n = dequeue(&read_buffer->filled_q);
+
+ if (read_buffer->data[n].c > 0)
+ memcpy(buf, read_buffer->data[n].b,
+ read_buffer->data[n].c);
+ c = read_buffer->data[n].c;
+ enqueue(&read_buffer->free_q, n);
+ return c;
+}
+int winnt_kbhit(void)
+{
+ return (read_buffer->filled_q.q & QMASK) != 0;
+}
+
+#define _kbhit() winnt_kbhit()
+#define raw_write_stdout(b, l) winnt_raw_write_stdout((b), (l))
+#define raw_read_stdin(b, s) winnt_raw_read_stdin((b), (s))
+#endif
+
int MAIN(int, char **);
int MAIN(int argc, char **argv)
@@ -1194,6 +1392,9 @@ SSL_set_tlsext_status_ids(con, ids);
mbuf[0] = 0;
}
+#if defined(OPENSSL_WINNT_THREAD_IO)
+ start_tty(SSL_get_fd(con));
+#endif
for (;;)
{
FD_ZERO(&readfds);
@@ -1583,6 +1784,9 @@ shut:
SSL_shutdown(con);
SHUTDOWN(SSL_get_fd(con));
end:
+#ifdef OPENSSL_WINNT_THREAD_IO
+ stop_tty();
+#endif
if (con != NULL)
{
if (prexit != 0)
--- ./Configure.orig 2012-03-03 22:48:21.000000000 +0900
+++ ./Configure 2013-01-03 13:22:16.000000000 +0900
@@ -491,7 +491,7 @@ my %table=(
#
# Win64 targets, WIN64I denotes IA-64 and WIN64A - AMD64
"VC-WIN64I","cl:-W3 -Gs0 -Gy -nologo -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_DEPRECATE:::WIN64I::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:ia64cpuid.o:ia64.o::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o:::::::ias:win32",
-"VC-WIN64A","cl:-W3 -Gs0 -Gy -nologo -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_DEPRECATE:::WIN64A::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:x86_64cpuid.o:bn_asm.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:auto:win32",
+"VC-WIN64A","cl:-W3 -Gs0 -Gy -nologo -DOPENSSL_SYSNAME_WINNT -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_DEPRECATE:::WIN64A::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:x86_64cpuid.o:bn_asm.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:auto:win32",
"debug-VC-WIN64I","cl:-W3 -Gs0 -Gy -Zi -nologo -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_DEPRECATE:::WIN64I::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:ia64cpuid.o:ia64.o::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o:::::::ias:win32",
"debug-VC-WIN64A","cl:-W3 -Gs0 -Gy -Zi -nologo -DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_DEPRECATE:::WIN64A::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:x86_64cpuid.o:bn_asm.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:auto:win32",
# x86 Win32 target defaults to ANSI API, if you want UNICODE, complement
--- ./crypto/aes/asm/aes-x86_64.pl.orig 2008-12-27 22:32:21.000000000 +0900
+++ ./crypto/aes/asm/aes-x86_64.pl 2013-01-03 12:41:03.000000000 +0900
@@ -36,7 +36,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
$verticalspin=1; # unlike 32-bit version $verticalspin performs
# ~15% better on both AMD and Intel cores
--- ./crypto/bn/asm/x86_64-mont.pl.orig 2008-12-19 20:17:27.000000000 +0900
+++ ./crypto/bn/asm/x86_64-mont.pl 2013-01-03 12:43:36.000000000 +0900
@@ -26,7 +26,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
# int bn_mul_mont(
$rp="%rdi"; # BN_ULONG *rp,
--- ./crypto/camellia/asm/cmll-x86_64.pl.orig 2009-09-18 04:35:49.000000000 +0900
+++ ./crypto/camellia/asm/cmll-x86_64.pl 2013-01-03 12:41:31.000000000 +0900
@@ -40,7 +40,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; }
sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/;
--- ./crypto/md5/asm/md5-x86_64.pl.orig 2008-12-19 20:17:27.000000000 +0900
+++ ./crypto/md5/asm/md5-x86_64.pl 2013-01-03 12:39:00.000000000 +0900
@@ -120,7 +120,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1
die "can't locate x86_64-xlate.pl";
no warnings qw(uninitialized);
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
$code .= <<EOF;
.text
--- ./crypto/rc4/asm/rc4-x86_64.pl.orig 2009-04-28 04:31:04.000000000 +0900
+++ ./crypto/rc4/asm/rc4-x86_64.pl 2013-01-03 12:40:28.000000000 +0900
@@ -69,7 +69,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
$dat="%rdi"; # arg1
$len="%rsi"; # arg2
--- ./crypto/sha/asm/sha1-x86_64.pl.orig 2010-01-18 01:58:56.000000000 +0900
+++ ./crypto/sha/asm/sha1-x86_64.pl 2013-01-03 12:39:35.000000000 +0900
@@ -40,7 +40,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
$ctx="%rdi"; # 1st arg
$inp="%rsi"; # 2nd arg
--- ./crypto/sha/asm/sha512-x86_64.pl.orig 2008-12-19 20:17:28.000000000 +0900
+++ ./crypto/sha/asm/sha512-x86_64.pl 2013-01-03 12:39:46.000000000 +0900
@@ -51,7 +51,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
if ($output =~ /512/) {
$func="sha512_block_data_order";
--- ./crypto/whrlpool/asm/wp-x86_64.pl.orig 2008-12-19 20:17:28.000000000 +0900
+++ ./crypto/whrlpool/asm/wp-x86_64.pl 2013-01-03 12:46:55.000000000 +0900
@@ -41,7 +41,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output";
+open STDOUT,qq!| "$^X" $xlate $flavour $output!;
sub L() { $code.=".byte ".join(',',@_)."\n"; }
sub LL(){ $code.=".byte ".join(',',@_).",".join(',',@_)."\n"; }
--- ./crypto/x86_64cpuid.pl.orig 2010-04-15 04:25:09.000000000 +0900
+++ ./crypto/x86_64cpuid.pl 2013-01-03 12:38:26.000000000 +0900
@@ -7,7 +7,7 @@ if ($flavour =~ /\./) { $output = $flavo
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-open STDOUT,"| $^X ${dir}perlasm/x86_64-xlate.pl $flavour $output";
+open STDOUT,qq!| "$^X" ${dir}perlasm/x86_64-xlate.pl $flavour $output!;
if ($win64) { $arg1="%rcx"; $arg2="%rdx"; }
else { $arg1="%rdi"; $arg2="%rsi"; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment