binding c++ class members as c signal handlers
#include <signal.h>
#include <functional>
std::function<void(int)> callback_wrapper;
void callback_function(int value)
{
callback_wrapper(value);
}
class Foo {
public:
void catch_signal(int) {}
};
int main(int argc, char** argv)
{
Foo foo;
// deprecated since C++-11
callback_wrapper = std::bind1st(std::mem_fun(&Foo::catch_signal),
&foo);
// or
callback_wrapper = std::bind(&Foo::catch_signal,
&foo,
std::placeholders::_1);
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = callback_function;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGTERM, &sigIntHandler, NULL);
}
c, c++ measure elapsed time
Elapsed time of function, for performance measurement
C style
#include <sys/time.h>
struct timeval begin_v, end_v;
gettimeofday(&begin_v, NULL);
// the function
gettimeofday(&end_v, NULL);
const double s = end_v.tv_sec + end_v.tv_usec / 1e6 - begin_v.tv_sec - begin_v.tv_usec / 1e6;
printf ("Elasped time: %f s\n", s );
C++ style
#include <chrono> std::chrono::time_point<std::chrono::steady_clock> start, end; start = std::chrono::steady_clock::now(); // the function end = std::chrono::steady_clock::now(); std::chrono::duration<double> elapsed_seconds = end-start; std::cout << "Elapsed time: " << elapsed_seconds.count() << " s" << std::endl;
edit: instead of user-adjustable system_clock, the monotonic steady_clock can be a better choice.
Stringizing Operator, Token concatenation
After many years, even C shows new stuff:
Stringizing Operator
#define QUOTEME(x) #x
According to wiki:
Although macro expansion does not occur within a quoted string, the text of the macro arguments can be quoted and treated as a string literal by using the "#" directive (also known as the "Stringizing Operator").
the code
printf("%s\n", QUOTEME(1+2));
will expand to
printf("%s\n", "1+2");
Token concatenation
Token concatenation, also called token pasting, is one of the most subtle — and easy to abuse — features of the C macro preprocessor. Two arguments can be 'glued' together using ## preprocessor operator; this allows two tokens to be concatenated in the preprocessed code. This can be used to construct elaborate macros which act like a crude version of C++ templates.
For instance:
#define MYCASE(item,id) \ case id: \ item##_##id = id;\ break
the code
MYCASE(widget,23);
will expand to
widget_23 = 23;
create signature (of hash) with openssl c api
This is just too long...
You can find another version where all return value is checked here
EDIT: There is another solution, with SHA256_x to create digest and RSA_sign to sign here
/* gcc ./openssl_sign.c -lssl */
#include s<tdio.h>
#include <string.h>
#include <error.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include o<penssl/evp.h>
int pass_cb( char *buf, int size, int rwflag, void *u )
{
int len;
char tmp[1024];
printf( "Enter pass phrase for '%s': ", (char*)u );
scanf( "%s", tmp );
len = strlen( tmp );
if ( len <= 0 ) return 0;
if ( len > size ) len = size;
memset( buf, '\0', size );
memcpy( buf, tmp, len );
return len;
}
RSA* getRsaFp( const char* rsaprivKeyPath )
{
FILE* fp;
fp = fopen( rsaprivKeyPath, "r" );
if ( fp == 0 ) {
fprintf( stderr, "Couldn't open RSA priv key: '%s'. %s\n",
rsaprivKeyPath, strerror(errno) );
exit(1);
}
RSA *rsa = 0;
rsa = RSA_new();
rsa = PEM_read_RSAPrivateKey(fp, 0, pass_cb, (char*)rsaprivKeyPath);
fclose( fp );
return rsa;
}
int main( int argc, char* argv[] )
{
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s <text to sign>\n", argv[0] );
exit( 1 );
}
const char *clearText = argv[1];
char rsaprivKeyPath[1024];
sprintf( rsaprivKeyPath, "%s/.ssh/id_rsa", getenv ("HOME") );
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
EVP_PKEY *evpKey = 0;
evpKey = EVP_PKEY_new();
RSA *rsa = 0;
rsa = getRsaFp( rsaprivKeyPath );
EVP_PKEY_set1_RSA( evpKey, rsa );
EVP_MD_CTX* ctx = 0;
ctx = EVP_MD_CTX_create();
EVP_SignInit_ex( ctx, EVP_sha1(), 0 );
EVP_SignUpdate( ctx, clearText, strlen( clearText ) );
const int MAX_LEN = 1024;
unsigned char sig[MAX_LEN];
unsigned int sigLen;
memset(sig, 0, MAX_LEN);
EVP_SignFinal( ctx, sig, &sigLen, evpKey );
printf( "Got signature: '%s'\n", sig );
EVP_MD_CTX_destroy( ctx );
RSA_free( rsa );
EVP_PKEY_free( evpKey );
ERR_free_strings();
return 0;
}