From 4192eb887632ba4fa00d63a3a9fac014bc4a3078 Mon Sep 17 00:00:00 2001 From: Damien Stuart Date: Sun, 24 May 2009 16:46:33 +0000 Subject: [PATCH] Updates and revisions to accommodate a Windows build. git-svn-id: file:///home/mbr/svn/fwknop/trunk@88 510a4753-2344-4c79-9c09-4d669213fbeb --- fko/cipher_funcs.c | 35 +- fko/fko.h | 126 ++-- fko/fko_common.h | 22 +- fko/fko_context.h | 2 +- fko/fko_encryption.c | 5 +- fko/fko_rand_value.c | 32 +- fko/fko_timestamp.c | 10 +- fko/fko_user.c | 2 + fko/md5.c | 4 +- fko/sha.h | 4 + fko/sha1.c | 4 +- fko/sha256.c | 6 +- src/config_init.c | 27 +- src/fwknop.c | 118 ++-- src/fwknop_common.h | 7 +- src/getpasswd.c | 40 +- src/spa_comm.c | 18 +- src/spa_comm.h | 10 + src/utils.h | 8 + win32/config.h | 202 ++++++ win32/fwknop-client.vcproj | 269 ++++++++ win32/getopt.c | 1258 ++++++++++++++++++++++++++++++++++++ win32/getopt.h | 185 ++++++ win32/libfko.sln | 29 + win32/libfko.vcproj | 324 ++++++++++ 25 files changed, 2577 insertions(+), 170 deletions(-) create mode 100644 win32/config.h create mode 100644 win32/fwknop-client.vcproj create mode 100644 win32/getopt.c create mode 100644 win32/getopt.h create mode 100644 win32/libfko.sln create mode 100644 win32/libfko.vcproj diff --git a/fko/cipher_funcs.c b/fko/cipher_funcs.c index e017c36e..5ffa2916 100644 --- a/fko/cipher_funcs.c +++ b/fko/cipher_funcs.c @@ -23,13 +23,22 @@ */ #include #include -#include + +#ifdef WIN32 + #include + #include + #include +#else + #include +#endif #include "cipher_funcs.h" #include "digest.h" -#ifndef RAND_FILE - #define RAND_FILE "/dev/urandom" +#ifndef WIN32 + #ifndef RAND_FILE + #define RAND_FILE "/dev/urandom" + #endif #endif /* Get random data. @@ -37,9 +46,23 @@ void get_random_data(unsigned char *data, size_t len) { - FILE *rfd; + uint32_t i; +#ifdef WIN32 + int rnum; + struct _timeb tb; + + _ftime_s(&tb); + + srand((uint32_t)(tb.time*1000)+tb.millitm); + + for(i=0; i= 48 && c <= 57) #endif -#if HAVE_STDINT_H - #include +#ifdef WIN32 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + + #define strdup _strdup +#else + #if HAVE_STDINT_H + #include + #endif #endif /* Work out endianess (sp?) @@ -74,6 +81,17 @@ #endif #endif +#ifdef WIN32 + #include +#else + #ifdef HAVE_SYS_TIME_H + #include + #ifdef TIME_WITH_SYS_TIME + #include + #endif + #endif +#endif + /* Convenient macros for wrapping sections in 'extern "C" {' constructs. */ #ifdef __cplusplus diff --git a/fko/fko_context.h b/fko/fko_context.h index 7e27b42f..2b11e632 100644 --- a/fko/fko_context.h +++ b/fko/fko_context.h @@ -48,7 +48,7 @@ struct fko_context { /* FKO SPA user-definable message data */ char *rand_val; char *username; - unsigned int timestamp; + time_t timestamp; short message_type; char *message; char *nat_access; diff --git a/fko/fko_encryption.c b/fko/fko_encryption.c index c4e9ce3e..8d97dced 100644 --- a/fko/fko_encryption.c +++ b/fko/fko_encryption.c @@ -103,7 +103,8 @@ _rijndael_encrypt(fko_ctx_t ctx, char *enc_key) int _rijndael_decrypt(fko_ctx_t ctx, char *dec_key, int b64_len) { - char *tbuf, *ndx; + char *tbuf; + unsigned char *ndx; unsigned char *cipher; int cipher_len, pt_len, i, err = 0; @@ -384,7 +385,7 @@ int fko_decrypt_spa_data(fko_ctx_t ctx, char *dec_key) { int b64_len, res; - char *ndx; + //char *ndx; /* First, make sure we have data to work with. */ diff --git a/fko/fko_rand_value.c b/fko/fko_rand_value.c index 77242594..1879cdc7 100644 --- a/fko/fko_rand_value.c +++ b/fko/fko_rand_value.c @@ -26,24 +26,33 @@ #include "fko_common.h" #include "fko.h" -#ifdef HAVE_SYS_TIME_H - #include - #ifdef TIME_WITH_SYS_TIME - #include +#ifdef WIN32 + #include + #include +#else + #ifdef HAVE_SYS_TIME_H + #include + #ifdef TIME_WITH_SYS_TIME + #include + #endif #endif -#endif -#define RAND_FILE "/dev/urandom" + #define RAND_FILE "/dev/urandom" +#endif /* Set/Generate the SPA data random value string. */ int fko_set_rand_value(fko_ctx_t ctx, const char *new_val) { +#ifdef WIN32 + struct _timeb tb; +#else FILE *rfd; struct timeval tv; - unsigned int seed; - char *tmp_buf; +#endif + unsigned long seed; + char *tmp_buf; /* Context must be initialized. */ @@ -66,6 +75,10 @@ fko_set_rand_value(fko_ctx_t ctx, const char *new_val) return(FKO_SUCCESS); } +#ifdef WIN32 + _ftime_s(&tb); + seed = ((tb.time * 1000) + tb.millitm) & 0xFFFFFFFF; +#else /* Attempt to read seed data from /dev/urandom. If that does not * work, then fall back to a time-based method (less secure, but * probably more portable). @@ -85,6 +98,7 @@ fko_set_rand_value(fko_ctx_t ctx, const char *new_val) seed = tv.tv_usec; } +#endif srand(seed); @@ -97,7 +111,7 @@ fko_set_rand_value(fko_ctx_t ctx, const char *new_val) return(FKO_ERROR_MEMORY_ALLOCATION); sprintf(ctx->rand_val, "%u", rand()); - + while(strlen(ctx->rand_val) < FKO_RAND_VAL_SIZE) { sprintf(tmp_buf, "%u", rand()); diff --git a/fko/fko_timestamp.c b/fko/fko_timestamp.c index 431a8408..d1bb0ee8 100644 --- a/fko/fko_timestamp.c +++ b/fko/fko_timestamp.c @@ -26,19 +26,13 @@ #include "fko_common.h" #include "fko.h" -#ifdef HAVE_SYS_TIME_H - #include - #ifdef TIME_WITH_SYS_TIME - #include - #endif -#endif /* Set the timestamp. */ int fko_set_timestamp(fko_ctx_t ctx, int offset) { - unsigned int ts; + time_t ts; /* Must be initialized */ @@ -60,7 +54,7 @@ fko_set_timestamp(fko_ctx_t ctx, int offset) /* Return the current timestamp. */ int -fko_get_timestamp(fko_ctx_t ctx, unsigned int *timestamp) +fko_get_timestamp(fko_ctx_t ctx, time_t *timestamp) { /* Must be initialized */ diff --git a/fko/fko_user.c b/fko/fko_user.c index 00449c5f..e76c21ef 100644 --- a/fko/fko_user.c +++ b/fko/fko_user.c @@ -54,6 +54,8 @@ fko_set_username(fko_ctx_t ctx, const char *spoof_user) /* cuserid will return the effective user (i.e. su or setuid). */ username = cuserid(NULL); +#elif WIN32 + username = strdup("NO_USER"); #else username = getlogin(); #endif diff --git a/fko/md5.c b/fko/md5.c index caae9d22..e36912b8 100644 --- a/fko/md5.c +++ b/fko/md5.c @@ -53,7 +53,9 @@ } #else #define byteReverse(buf, len) /* Nothing */ - #warning Undetermined or unsupported Byte Order... We will try LITTLE_ENDIAN + #ifndef WIN32 + #warning Undetermined or unsupported Byte Order... We will try LITTLE_ENDIAN + #endif #endif /* diff --git a/fko/sha.h b/fko/sha.h index ab96be9b..b8c3bff6 100644 --- a/fko/sha.h +++ b/fko/sha.h @@ -30,6 +30,10 @@ #include "fko_common.h" +#ifdef WIN32 + #define BYTEORDER 1234 +#endif + /* Truncate to 32 bits -- should be a null op on 32-bit machines */ #ifndef TRUNC32 diff --git a/fko/sha1.c b/fko/sha1.c index 7c2aa68c..0554d033 100644 --- a/fko/sha1.c +++ b/fko/sha1.c @@ -123,7 +123,9 @@ sha1_transform(SHA_INFO *sha_info) dp += 4; W[i] = TRUNC32(T); } -#warning Unknown byte order -- we will try LITTLE_ENDIAN + #ifndef WIN32 + #warning Undetermined or unsupported Byte Order... We will try LITTLE_ENDIAN + #endif #endif /* SWAP_DONE */ for (i = 16; i < 80; ++i) { diff --git a/fko/sha256.c b/fko/sha256.c index bac518ea..b22f002e 100644 --- a/fko/sha256.c +++ b/fko/sha256.c @@ -127,7 +127,9 @@ sha256_transform(SHA_INFO *sha_info) dp += 4; W[i] = TRUNC32(T); } -#warning Unknown byte order -- we will try LITTLE_ENDIAN + #ifndef WIN32 + #warning Undetermined or unsupported Byte Order... We will try LITTLE_ENDIAN + #endif #endif /* SWAP_DONE */ A = sha_info->digest[0]; @@ -195,7 +197,7 @@ sha256_update(SHA_INFO *sha_info, uint8_t *buffer, int count) sha_info->count_hi++; } sha_info->count_lo = clo; - sha_info->count_hi += (uint8_t) count >> 29; + sha_info->count_hi += (uint32_t) count >> 29; if (sha_info->local) { i = SHA_BLOCKSIZE - sha_info->local; if (i > count) { diff --git a/src/config_init.c b/src/config_init.c index 0a1b7c15..fb05f18a 100644 --- a/src/config_init.c +++ b/src/config_init.c @@ -25,6 +25,9 @@ */ #include "fwknop_common.h" #include "config_init.h" +#include "getopt.h" +#include "spa_comm.h" +#include "utils.h" /* Routine to extract the configuration value from a line in the config * file. @@ -39,7 +42,7 @@ get_char_val(const char *var_name, char *dest, char *lptr) /* var_name is guaranteed to be NULL-terminated. */ - for (i=0; i < strlen(var_name); i++) + for (i=0; i < (int)strlen(var_name); i++) if (tmp_ptr[i] != var_name[i]) return 0; @@ -147,7 +150,7 @@ parse_config_file(fko_cli_options_t *options, struct opts_track* ot) static void validate_options(fko_cli_options_t *options) { - char *tmpc; + //char *tmpc; /* Gotta have a Destination unless we are just testing or getting the * the version. @@ -183,7 +186,7 @@ void config_init(fko_cli_options_t *options, int argc, char **argv) { int cmd_arg, index; - unsigned int tmpint; + //unsigned int tmpint; struct opts_track ot; @@ -198,8 +201,13 @@ config_init(fko_cli_options_t *options, int argc, char **argv) options->proto = FKO_DEFAULT_PROTO; options->port = FKO_DEFAULT_PORT; +#ifdef WIN32 + while ((cmd_arg = getopt(argc, argv, + "A:a:D:G:S:Q:m:p:P:B:bghqdTvVn")) != -1) { +#else while ((cmd_arg = getopt_long(argc, argv, "A:a:D:G:S:Q:p:P:BbghqdTvVn", cmd_opts, &index)) != -1) { +#endif switch(cmd_arg) { case 'A': strlcpy(options->access_str, optarg, MAX_LINE_LEN); @@ -273,6 +281,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv) usage(); exit(0); case FKO_DIGEST_NAME: + case 'm': if(strncasecmp(optarg, "md5", 3) == 0) options->digest_type = FKO_DIGEST_MD5; else if(strncasecmp(optarg, "sha1", 4) == 0) @@ -336,7 +345,9 @@ usage(void) " -c, --config-file - Specify an alternate configuration file.\n" " -A, --access - Provide a list of ports/protocols to open\n" " on the server.\n" - " -a, --allow-ip - Specify IP address to allow within the SPA\n" + " -B, --save-packet - Save the generated packet data to the\n" + " specified file.\n" + " -a, --allow-ip - Specify IP address to allow within the SPA\n" " packet.\n" " -D, --destination - Specify the IP address of the fwknop server.\n" " -p, --server-port - Set the destination port for outgoing SPA\n" @@ -353,7 +364,7 @@ usage(void) " -d, --debug - Set debug mode.\n" " -v, --verbose - Set verbose mode.\n" " -V, --version - Print version number.\n" - " --digest-type - Speciy the message digest algorithm to use.\n" + " -m, --digest-type - Speciy the message digest algorithm to use.\n" " (md5, sha1, or sha256 (default)).\n" " --gpg-encryption - Use GPG encyrption (default is Rijndael).\n" " --gpg-recipient-key - Specify the recipient GPG key name or ID.\n" @@ -363,6 +374,12 @@ usage(void) "\n" ); + // --DSS TEMP +#ifdef WIN32 + printf("NOTE: Long options and GPG encryption are not available\n"); + printf(" under Windows yet.\n\n"); +#endif + return; } diff --git a/src/fwknop.c b/src/fwknop.c index 717651b8..9382e3fc 100644 --- a/src/fwknop.c +++ b/src/fwknop.c @@ -40,7 +40,7 @@ main(int argc, char **argv) { fko_ctx_t ctx, ctx2; int res; - char *pw, *spa_data, *version; + char *spa_data, *version; char access_buf[MAX_LINE_LEN]; fko_cli_options_t options; @@ -69,8 +69,10 @@ main(int argc, char **argv) /* If use-gpg-agent was not specified, then remove the GPG_AGENT_INFO * ENV variable if it exists. */ +#ifndef WIN32 if(!options.use_gpg_agent) unsetenv("GPG_AGENT_INFO"); +#endif res = fko_set_spa_encryption_type(ctx, FKO_ENCRYPTION_GPG); if(res != FKO_SUCCESS) @@ -175,7 +177,7 @@ main(int argc, char **argv) fko_set_spa_client_timeout(ctx, 120); */ - /* Set a serer auth string. + /* Set a server auth string. res = fko_set_spa_server_auth(ctx, "crypt,SomePW"); if(res != FKO_SUCCESS) fprintf(stderr, "Error #%i from fko_set_spa_server_auth: %s\n", res, fko_errstr(res)); @@ -221,7 +223,6 @@ main(int argc, char **argv) /* Now we create a new context based on data from the first one. */ res = fko_get_spa_data(ctx, &spa_data); - if(res != FKO_SUCCESS) { fprintf(stderr, @@ -281,7 +282,6 @@ main(int argc, char **argv) exit(EXIT_FAILURE); } - */ if(options.use_gpg) { @@ -298,8 +298,9 @@ main(int argc, char **argv) } } } +*/ -fko_set_gpg_signature_verify(ctx2, 0); +//fko_set_gpg_signature_verify(ctx2, 0); //fko_set_gpg_ignore_verify_error(ctx2, 1); res = fko_decrypt_spa_data( @@ -319,35 +320,6 @@ fko_set_gpg_signature_verify(ctx2, 0); exit(EXIT_FAILURE); } -/* --DSS temp for test -*/ -if(options.use_gpg) -{ - int summ=-1, stat=-1; - char *fpr, *id; - - res = fko_get_gpg_signature_fpr(ctx2, &fpr); - if(res == FKO_SUCCESS) - printf("++ SIG FPR: %s\n", fpr); - else - printf("++ SIG FPR ERROR %i: %s\n", res, fko_errstr(res)); - - res = fko_get_gpg_signature_id(ctx2, &id); - if(res == FKO_SUCCESS) - printf("++ SIG ID: %s\n", id); - else - printf("++ SIG ID ERROR %i: %s\n", res, fko_errstr(res)); - - res = fko_get_gpg_signature_status(ctx2, &stat); - if(res != FKO_SUCCESS) - printf("++ SIG Status ERROR %i: %s\n", res, fko_errstr(res)); - - res = fko_get_gpg_signature_summary(ctx2, &summ); - if(res != FKO_SUCCESS) - printf("++ SIG Summary ERROR %i: %s\n", res, fko_errstr(res)); - - printf("++ Status: %i, Summary: %i\n", stat, summ); -} if (! options.quiet) { printf("\nDump of the Decoded Data\n"); @@ -392,56 +364,70 @@ display_ctx(fko_ctx_t ctx) { char *rand_val, *username, *version, *spa_message, *nat_access, *server_auth, *enc_data, *spa_digest, *spa_data; - unsigned int timestamp=0; + time_t timestamp=0; short msg_type=-1, digest_type=-1; - int client_timeout=-1, res; + int client_timeout=-1; /* Should be checking return values, but this is temp code. --DSS */ fko_get_rand_value(ctx, &rand_val); +//printf("RAND: '%s'\n", rand_val); fko_get_username(ctx, &username); +//printf("USER: '%s'\n", username); fko_get_timestamp(ctx, ×tamp); +//printf("TIME: '%lu'\n", timestamp); fko_get_version(ctx, &version); +//printf("VER: '%s'\n", version); fko_get_spa_message_type(ctx, &msg_type); +//printf("MTYP: '%i'\n", msg_type); fko_get_spa_message(ctx, &spa_message); +//printf("MSG: '%s'\n", spa_message); fko_get_spa_nat_access(ctx, &nat_access); +//printf("NAT: '%s'\n", nat_access); fko_get_spa_server_auth(ctx, &server_auth); +//printf("AUTH: '%s'\n", server_auth); fko_get_spa_client_timeout(ctx, &client_timeout); +//printf("CLTO: '%s'\n", client_timeout); fko_get_spa_digest_type(ctx, &digest_type); +//printf("DTYP: '%i'\n", digest_type); fko_get_encoded_data(ctx, &enc_data); +//printf("ENC: '%s'\n", enc_data); fko_get_spa_digest(ctx, &spa_digest); +//printf("DIG: '%s'\n", spa_digest); fko_get_spa_data(ctx, &spa_data); +//printf("SDAT: '%s'\n", spa_data); - printf( - "\nFKO Context Values:\n===================\n\n" - " Random Value: %s\n" - " Username: %s\n" - " Timestamp: %u\n" - " FKO Version: %s\n" - " Message Type: %i\n" - " Message String: %s\n" - " Nat Access: %s\n" - " Server Auth: %s\n" - " Client Timeout: %u\n" - " Digest Type: %u\n" - "\n Encoded Data: %s\n" - "\nSPA Data Digest: %s\n" - "\nFinal Packed/Encrypted/Encoded Data:\n\n%s\n\n" - , - rand_val == NULL ? "" : rand_val, - username == NULL ? "" : username, - timestamp, - version == NULL ? "" : version, - msg_type, - spa_message == NULL ? "" : spa_message, - nat_access == NULL ? "" : nat_access, - server_auth == NULL ? "" : server_auth, - client_timeout, - digest_type, - enc_data == NULL ? "" : enc_data, - spa_digest == NULL ? "" : spa_digest, - spa_data == NULL ? "" : spa_data - ); +//return; + + printf("\nFKO Context Values:\n===================\n\n"); + printf(" Random Value: %s\n", rand_val); + printf(" Username: %s\n", username); + printf(" Timestamp: %u\n", timestamp); + printf(" FKO Version: %s\n", version); + printf(" Message Type: %i\n", msg_type); + printf(" Message String: %s\n", spa_message); + printf(" Nat Access: %s\n", nat_access); + printf(" Server Auth: %s\n", server_auth); + printf(" Client Timeout: %u\n", client_timeout); + printf(" Digest Type: %u\n", digest_type); + printf("\n Encoded Data: %s\n", enc_data); + printf("\nSPA Data Digest: %s\n", spa_digest); + printf("\nFinal Packed/Encrypted/Encoded Data:\n\n%s\n\n", spa_data); + //, + //rand_val,// == NULL ? "" : rand_val, + //username,// == NULL ? "" : username, + //timestamp, + //version, // == NULL ? "" : version, + //msg_type, + //spa_message // == NULL ? "" : spa_message, + //nat_access == NULL ? "" : nat_access, + //server_auth == NULL ? "" : server_auth, + //client_timeout, + //digest_type, + //enc_data == NULL ? "" : enc_data, + //spa_digest == NULL ? "" : spa_digest, + //spa_data == NULL ? "" : spa_data + //); } diff --git a/src/fwknop_common.h b/src/fwknop_common.h index 2d4c2889..4b14f82f 100644 --- a/src/fwknop_common.h +++ b/src/fwknop_common.h @@ -50,7 +50,12 @@ #include #endif -#include +#ifdef WIN32 + #define strncasecmp _strnicmp + #define snprintf _snprintf +#else + #include +#endif #include "fko.h" diff --git a/src/getpasswd.c b/src/getpasswd.c index 090b77b2..b0b49fd6 100644 --- a/src/getpasswd.c +++ b/src/getpasswd.c @@ -25,7 +25,12 @@ */ #include #include -#include + +#ifdef WIN32 + #include +#else + #include +#endif #include "fwknop_common.h" #include "getpasswd.h" @@ -39,11 +44,13 @@ getpasswd(const char *prompt) { static char pwbuf[MAX_PASS_LEN + 1] = {0}; char *ptr; - sigset_t sig, old_sig; - struct termios ts, old_ts; - FILE *fp; int c; +#ifndef WIN32 + FILE *fp; + sigset_t sig, old_sig; + struct termios ts, old_ts; + if((fp = fopen(ctermid(NULL), "r+")) == NULL) return(NULL); @@ -66,33 +73,46 @@ getpasswd(const char *prompt) tcsetattr(fileno(fp), TCSAFLUSH, &ts); fputs(prompt, fp); +#endif /* Read in the password. */ ptr = pwbuf; - while((c = getc(fp)) != EOF && c != '\n') +#ifdef WIN32 + _cputs(prompt); + while((c = _getch()) != '\r') +#else + while((c = getc(fp)) != EOF && c != '\n') +#endif if(ptr < &pwbuf[MAX_PASS_LEN]) *ptr++ = c; - /* Null terminate the password. + /* Null terminate the password. */ *ptr = 0; +#ifndef WIN32 /* we can go ahead and echo out a newline. */ putc('\n', fp); - /* Restore our tty state and signal handlers. + /* Restore our tty state and signal handlers. */ tcsetattr(fileno(fp), TCSAFLUSH, &old_ts); sigprocmask(SIG_BLOCK, &old_sig, NULL); fclose(fp); +#else + /* In Windows, it would be a CR-LF + */ + _putch('\r'); + _putch('\n'); +#endif return(pwbuf); } -/* Function for accepting password input from users +/* Function for accepting password input from from a file */ char* getpasswd_file(const char *pw_file, const char *dst_ip_str) @@ -108,7 +128,7 @@ getpasswd_file(const char *pw_file, const char *dst_ip_str) if ((pwfile_ptr = fopen(pw_file, "r")) == NULL) { fprintf(stderr, "[*] Could not open config file: %s\n", pw_file); - exit(EXIT_FAILURE); + exit(1); } while ((fgets(conf_line_buf, MAX_LINE_LEN, pwfile_ptr)) != NULL) @@ -163,7 +183,7 @@ getpasswd_file(const char *pw_file, const char *dst_ip_str) if (pwbuf[0] == '\0') { fprintf(stderr, "[*] Could not get password for IP: %s from: %s\n", dst_ip_str, pw_file); - exit(EXIT_FAILURE); + exit(1); } return pwbuf; diff --git a/src/spa_comm.c b/src/spa_comm.c index 92f6f030..955f50f6 100644 --- a/src/spa_comm.c +++ b/src/spa_comm.c @@ -25,9 +25,6 @@ ***************************************************************************** */ #include "spa_comm.h" -#if HAVE_SYS_SOCKET_H - #include -#endif /* Send the SPA data via UDP packet. */ @@ -40,6 +37,17 @@ send_spa_packet_udp(fko_ctx_t ctx, struct sockaddr_in *saddr, int res; char *spa_data; +#ifdef WIN32 + WSADATA wsa_data; + + res = WSAStartup( MAKEWORD(1,1), &wsa_data ); + if( res != 0 ) + { + fprintf(stderr, "[*] Winsock initialization error %d\n", res ); + exit(0); + } +#endif + /* create the socket */ sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -72,7 +80,7 @@ int send_spa_packet_tcp(fko_ctx_t ctx, struct sockaddr_in *saddr, struct sockaddr_in *daddr, fko_cli_options_t *options) { - int rv; + int rv = -1; return rv; } @@ -81,7 +89,7 @@ send_spa_packet_tcp(fko_ctx_t ctx, struct sockaddr_in *saddr, int send_spa_packet_icmp(fko_ctx_t ctx, fko_cli_options_t *options) { - int rv; + int rv = -1; return rv; } diff --git a/src/spa_comm.h b/src/spa_comm.h index d9685696..64c458e0 100644 --- a/src/spa_comm.h +++ b/src/spa_comm.h @@ -28,6 +28,16 @@ #include "fwknop_common.h" +#ifdef WIN32 + #include + + #define unlink _unlink +#else + #if HAVE_SYS_SOCKET_H + #include + #endif +#endif + /* Prototypes */ int send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options); diff --git a/src/utils.h b/src/utils.h index b31fac51..a0573442 100644 --- a/src/utils.h +++ b/src/utils.h @@ -31,4 +31,12 @@ */ void hex_dump(unsigned char *data, int size); + +#ifdef WIN32 + /* Function prototypes we need for Windows + */ + size_t strlcat(char *dst, const char *src, size_t siz); + size_t strlcpy(char *dst, const char *src, size_t siz); +#endif + #endif /* UTILS_H */ diff --git a/win32/config.h b/win32/config.h new file mode 100644 index 00000000..78d05300 --- /dev/null +++ b/win32/config.h @@ -0,0 +1,202 @@ +/* $Id$ + ***************************************************************************** + * + * File: fko_common.h + * + * Author: Damien S. Stuart + * + * Purpose: Common header for libfko source files. + * + * Copyright (C) 2008 Damien Stuart (dstuart@dstuart.org) + * + * License (GNU Public License): + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + ***************************************************************************** +*/ +#ifndef CONFIG_H +#define CONFIG_H 1 + +/* Define to 1 if you have the `bzero' function. */ +#undef HAVE_BZERO + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ENDIAN_H + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have libgpgme */ +#undef HAVE_LIBGPGME + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcspn' function. */ +#define HAVE_STRCSPN 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strspn' function. */ +#define HAVE_STRSPN 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BYTEORDER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if the system has the type `uint32_t'. */ +#undef HAVE_UINT32_T + +/* Define to 1 if the system has the type `uint8_t'. */ +#undef HAVE_UINT8_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `unsigned int', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_INT + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#define VERSION "0.61" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to rpl_realloc if the replacement function should be used. */ +#undef realloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t + + +#endif /* CONFIG_H */ diff --git a/win32/fwknop-client.vcproj b/win32/fwknop-client.vcproj new file mode 100644 index 00000000..4dd52576 --- /dev/null +++ b/win32/fwknop-client.vcproj @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/getopt.c b/win32/getopt.c new file mode 100644 index 00000000..67b47673 --- /dev/null +++ b/win32/getopt.c @@ -0,0 +1,1258 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#ifdef VMS +# include +# if HAVE_STRING_H - 0 +# include +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. */ +# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC +# include +# ifndef _ +# define _(msgid) gettext (msgid) +# endif +# else +# define _(msgid) (msgid) +# endif +# if defined _LIBC && defined USE_IN_LIBIO +# include +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include +# define my_index strchr +#else + +# if HAVE_STRING_H || WIN32 /* Pete Wilson mod 7/28/02 */ +# include +# else +# include +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +# ifdef USE_NONOPTION_FLAGS +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; +# endif + +# ifdef USE_NONOPTION_FLAGS +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (posixly_correct == NULL + && argc == __libc_argc && argv == __libc_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int print_errors = opterr; + if (optstring[0] == ':') + print_errors = 0; + + if (argc < 1) + return -1; + + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT and LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); +#endif + } + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (argv[optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); +#endif + } + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (argv[optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; +#endif + + if (posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } + else + { +#if defined _LIBC && defined USE_IN_LIBIO + __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#endif + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option requires an argument -- %c\n"), + argv[0], c); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); +#endif + } + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); +#endif + } + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + __asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + free (buf); +#else + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +/* #define TEST */ /* Pete Wilson mod 7/28/02 */ +#ifdef TEST + +#ifndef exit /* Pete Wilson mod 7/28/02 */ + int exit(int); /* Pete Wilson mod 7/28/02 */ +#endif /* Pete Wilson mod 7/28/02 */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/win32/getopt.h b/win32/getopt.h new file mode 100644 index 00000000..482b80bc --- /dev/null +++ b/win32/getopt.h @@ -0,0 +1,185 @@ +/* getopt.h */ +/* Declarations for getopt. + Copyright (C) 1989-1994, 1996-1999, 2001 Free Software + Foundation, Inc. This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute + it and/or modify it under the terms of the GNU Lesser + General Public License as published by the Free Software + Foundation; either version 2.1 of the License, or + (at your option) any later version. + + The GNU C Library is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with the GNU C Library; if not, write + to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +/* If __GNU_LIBRARY__ is not already defined, either we are being used + standalone, or this is the first header included in the source file. + If we are being used with glibc, we need to include , but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include , which will pull in for us + if it's from glibc. (Why ctype.h? It's guaranteed to exist and it + doesn't flood the namespace with stuff the way some other headers do.) */ +#if !defined __GNU_LIBRARY__ +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if (defined __STDC__ && __STDC__) || defined __cplusplus + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if (defined __STDC__ && __STDC__) || defined __cplusplus +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ + diff --git a/win32/libfko.sln b/win32/libfko.sln new file mode 100644 index 00000000..8b6d60f7 --- /dev/null +++ b/win32/libfko.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfko", "libfko.vcproj", "{133BC195-4877-481D-9F56-9F1BEBAD21F0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fwknop-client", "fwknop-client.vcproj", "{D8AFA02D-14BF-42F4-97DE-EF4924D046D6}" + ProjectSection(ProjectDependencies) = postProject + {133BC195-4877-481D-9F56-9F1BEBAD21F0} = {133BC195-4877-481D-9F56-9F1BEBAD21F0} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {133BC195-4877-481D-9F56-9F1BEBAD21F0}.Debug|Win32.ActiveCfg = Debug|Win32 + {133BC195-4877-481D-9F56-9F1BEBAD21F0}.Debug|Win32.Build.0 = Debug|Win32 + {133BC195-4877-481D-9F56-9F1BEBAD21F0}.Release|Win32.ActiveCfg = Release|Win32 + {133BC195-4877-481D-9F56-9F1BEBAD21F0}.Release|Win32.Build.0 = Release|Win32 + {D8AFA02D-14BF-42F4-97DE-EF4924D046D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {D8AFA02D-14BF-42F4-97DE-EF4924D046D6}.Debug|Win32.Build.0 = Debug|Win32 + {D8AFA02D-14BF-42F4-97DE-EF4924D046D6}.Release|Win32.ActiveCfg = Release|Win32 + {D8AFA02D-14BF-42F4-97DE-EF4924D046D6}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/libfko.vcproj b/win32/libfko.vcproj new file mode 100644 index 00000000..c3f4ffaf --- /dev/null +++ b/win32/libfko.vcproj @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +