rawyaml mode
This commit is contained in:
parent
30c05eb266
commit
c57f10316f
3
common.h
3
common.h
@ -7,6 +7,9 @@
|
|||||||
#define PKPREFIX_SIZE (29 + 3)
|
#define PKPREFIX_SIZE (29 + 3)
|
||||||
#define SKPREFIX_SIZE (29 + 3)
|
#define SKPREFIX_SIZE (29 + 3)
|
||||||
|
|
||||||
|
extern const char * const pkprefix;
|
||||||
|
extern const char * const skprefix;
|
||||||
|
|
||||||
#define FORMATTED_PUBLIC_LEN (PKPREFIX_SIZE + PUBLIC_LEN)
|
#define FORMATTED_PUBLIC_LEN (PKPREFIX_SIZE + PUBLIC_LEN)
|
||||||
#define FORMATTED_SECRET_LEN (SKPREFIX_SIZE + SECRET_LEN)
|
#define FORMATTED_SECRET_LEN (SKPREFIX_SIZE + SECRET_LEN)
|
||||||
|
|
||||||
|
25
main.c
25
main.c
@ -106,6 +106,7 @@ static void printhelp(FILE *out,const char *progname)
|
|||||||
"\t-T - do not reset statistics counters when printing\n"
|
"\t-T - do not reset statistics counters when printing\n"
|
||||||
"\t-y - output generated keys in YAML format instead of dumping them to filesystem\n"
|
"\t-y - output generated keys in YAML format instead of dumping them to filesystem\n"
|
||||||
"\t-Y [filename [host.onion]] - parse YAML encoded input and extract key(s) to filesystem\n"
|
"\t-Y [filename [host.onion]] - parse YAML encoded input and extract key(s) to filesystem\n"
|
||||||
|
"\t--rawyaml - raw (unprefixed) public/secret keys for -y/-Y (may be useful for tor controller API)\n"
|
||||||
#ifdef PASSPHRASE
|
#ifdef PASSPHRASE
|
||||||
"\t-p passphrase - use passphrase to initialize the random seed with\n"
|
"\t-p passphrase - use passphrase to initialize the random seed with\n"
|
||||||
"\t-P - same as -p, but takes passphrase from PASSPHRASE environment variable\n"
|
"\t-P - same as -p, but takes passphrase from PASSPHRASE environment variable\n"
|
||||||
@ -180,7 +181,7 @@ int main(int argc,char **argv)
|
|||||||
{
|
{
|
||||||
const char *outfile = 0;
|
const char *outfile = 0;
|
||||||
const char *infile = 0;
|
const char *infile = 0;
|
||||||
const char *hostname = 0;
|
const char *onehostname = 0;
|
||||||
const char *arg;
|
const char *arg;
|
||||||
int ignoreargs = 0;
|
int ignoreargs = 0;
|
||||||
int dirnameflag = 0;
|
int dirnameflag = 0;
|
||||||
@ -237,6 +238,8 @@ int main(int argc,char **argv)
|
|||||||
printhelp(stdout,progname);
|
printhelp(stdout,progname);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(arg,"rawyaml"))
|
||||||
|
yamlraw = 1;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr,"unrecognised argument: --%s\n",arg);
|
fprintf(stderr,"unrecognised argument: --%s\n",arg);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -352,10 +355,10 @@ int main(int argc,char **argv)
|
|||||||
infile = 0;
|
infile = 0;
|
||||||
if (argc) {
|
if (argc) {
|
||||||
--argc;
|
--argc;
|
||||||
hostname = *argv++;
|
onehostname = *argv++;
|
||||||
if (!*hostname)
|
if (!*onehostname)
|
||||||
hostname = 0;
|
onehostname = 0;
|
||||||
if (hostname && strlen(hostname) != ONION_LEN) {
|
if (onehostname && strlen(onehostname) != ONION_LEN) {
|
||||||
fprintf(stderr,"bad onion argument length\n");
|
fprintf(stderr,"bad onion argument length\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -392,6 +395,16 @@ int main(int argc,char **argv)
|
|||||||
filters_add(arg);
|
filters_add(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (yamlinput && yamloutput) {
|
||||||
|
fprintf(stderr,"both -y and -Y does not make sense\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yamlraw && !yamlinput && !yamloutput) {
|
||||||
|
fprintf(stderr,"--rawyaml requires either -y or -Y to do anything\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (outfile) {
|
if (outfile) {
|
||||||
fout = fopen(outfile,!outfileoverwrite ? "a" : "w");
|
fout = fopen(outfile,!outfileoverwrite ? "a" : "w");
|
||||||
if (!fout) {
|
if (!fout) {
|
||||||
@ -429,7 +442,7 @@ int main(int argc,char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tret = yamlin_parseandcreate(fin,sname,hostname);
|
tret = yamlin_parseandcreate(fin,sname,onehostname,yamlraw);
|
||||||
if (infile) {
|
if (infile) {
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
fin = 0;
|
fin = 0;
|
||||||
|
10
worker.c
10
worker.c
@ -33,8 +33,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// additional 0 terminator is added by C
|
// additional 0 terminator is added by C
|
||||||
static const char * const pkprefix = "== ed25519v1-public: type0 ==\0\0";
|
const char * const pkprefix = "== ed25519v1-public: type0 ==\0\0";
|
||||||
static const char * const skprefix = "== ed25519v1-secret: type0 ==\0\0";
|
const char * const skprefix = "== ed25519v1-secret: type0 ==\0\0";
|
||||||
|
|
||||||
static const char checksumstr[] = ".onion checksum";
|
static const char checksumstr[] = ".onion checksum";
|
||||||
#define checksumstrlen (sizeof(checksumstr) - 1) // 15
|
#define checksumstrlen (sizeof(checksumstr) - 1) // 15
|
||||||
@ -44,6 +44,7 @@ volatile size_t keysgenerated = 0;
|
|||||||
volatile int endwork = 0;
|
volatile int endwork = 0;
|
||||||
|
|
||||||
int yamloutput = 0;
|
int yamloutput = 0;
|
||||||
|
int yamlraw = 0;
|
||||||
int numwords = 1;
|
int numwords = 1;
|
||||||
size_t numneedgenerate = 0;
|
size_t numneedgenerate = 0;
|
||||||
|
|
||||||
@ -127,8 +128,9 @@ static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
|||||||
fflush(fout);
|
fflush(fout);
|
||||||
pthread_mutex_unlock(&fout_mutex);
|
pthread_mutex_unlock(&fout_mutex);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
yamlout_writekeys(&sname[direndpos],pubonion,secret);
|
else
|
||||||
|
yamlout_writekeys(&sname[direndpos],pubonion,secret,yamlraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "filters_worker.inc.h"
|
#include "filters_worker.inc.h"
|
||||||
|
1
worker.h
1
worker.h
@ -4,6 +4,7 @@ extern volatile size_t keysgenerated;
|
|||||||
extern volatile int endwork;
|
extern volatile int endwork;
|
||||||
|
|
||||||
extern int yamloutput;
|
extern int yamloutput;
|
||||||
|
extern int yamlraw;
|
||||||
extern int numwords;
|
extern int numwords;
|
||||||
extern size_t numneedgenerate;
|
extern size_t numneedgenerate;
|
||||||
|
|
||||||
|
77
yaml.c
77
yaml.c
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#define LINEFEED_LEN (sizeof(char))
|
#define LINEFEED_LEN (sizeof(char))
|
||||||
#define NULLTERM_LEN (sizeof(char))
|
#define NULLTERM_LEN (sizeof(char))
|
||||||
#define PATH_SEPARATOR_LEN (sizeof(char))
|
|
||||||
|
|
||||||
static const char keys_field_generated[] = "---";
|
static const char keys_field_generated[] = "---";
|
||||||
static const char keys_field_hostname[] = "hostname: ";
|
static const char keys_field_hostname[] = "hostname: ";
|
||||||
@ -37,15 +36,20 @@ static const char keys_field_time[] = "time: ";
|
|||||||
|
|
||||||
#define B64_PUBKEY_LEN (BASE64_TO_LEN(FORMATTED_PUBLIC_LEN))
|
#define B64_PUBKEY_LEN (BASE64_TO_LEN(FORMATTED_PUBLIC_LEN))
|
||||||
#define B64_SECKEY_LEN (BASE64_TO_LEN(FORMATTED_SECRET_LEN))
|
#define B64_SECKEY_LEN (BASE64_TO_LEN(FORMATTED_SECRET_LEN))
|
||||||
#define TIME_LEN (21 * sizeof(char)) // strlen("2018-07-04 21:31:20 Z")
|
#define B64_RAW_PUBKEY_LEN (BASE64_TO_LEN(PUBLIC_LEN))
|
||||||
|
#define B64_RAW_SECKEY_LEN (BASE64_TO_LEN(SECRET_LEN))
|
||||||
|
#define TIME_LEN 21 // strlen("2018-07-04 21:31:20 Z")
|
||||||
|
|
||||||
#define KEYS_LEN ( \
|
#define KEYS_LEN ( \
|
||||||
KEYS_FIELD_GENERATED_LEN + LINEFEED_LEN + \
|
KEYS_FIELD_GENERATED_LEN + LINEFEED_LEN + \
|
||||||
KEYS_FIELD_HOSTNAME_LEN + ONION_LEN + LINEFEED_LEN + \
|
KEYS_FIELD_HOSTNAME_LEN + ONION_LEN + LINEFEED_LEN + \
|
||||||
KEYS_FIELD_PUBLICKEY_LEN + B64_PUBKEY_LEN + LINEFEED_LEN + \
|
KEYS_FIELD_PUBLICKEY_LEN + B64_PUBKEY_LEN + LINEFEED_LEN + \
|
||||||
KEYS_FIELD_SECRETKEY_LEN + B64_SECKEY_LEN + LINEFEED_LEN + \
|
KEYS_FIELD_SECRETKEY_LEN + B64_SECKEY_LEN + LINEFEED_LEN + \
|
||||||
KEYS_FIELD_TIME_LEN + TIME_LEN + LINEFEED_LEN \
|
KEYS_FIELD_TIME_LEN + TIME_LEN + LINEFEED_LEN \
|
||||||
)
|
)
|
||||||
|
#define RAW_KEYS_LEN (KEYS_LEN \
|
||||||
|
- B64_PUBKEY_LEN + B64_RAW_PUBKEY_LEN \
|
||||||
|
- B64_SECKEY_LEN + B64_RAW_SECKEY_LEN)
|
||||||
|
|
||||||
static pthread_mutex_t tminfo_mutex;
|
static pthread_mutex_t tminfo_mutex;
|
||||||
|
|
||||||
@ -67,7 +71,8 @@ do { \
|
|||||||
#define BUF_APPEND_CSTR(buf,offset,src) BUF_APPEND(buf,offset,src,strlen(src))
|
#define BUF_APPEND_CSTR(buf,offset,src) BUF_APPEND(buf,offset,src,strlen(src))
|
||||||
#define BUF_APPEND_CHAR(buf,offset,c) buf[offset++] = (c)
|
#define BUF_APPEND_CHAR(buf,offset,c) buf[offset++] = (c)
|
||||||
|
|
||||||
void yamlout_writekeys(const char *hostname,const u8 *formated_public,const u8 *formated_secret)
|
void yamlout_writekeys(
|
||||||
|
const char *hostname,const u8 *publickey,const u8 *secretkey,int rawkeys)
|
||||||
{
|
{
|
||||||
char keysbuf[KEYS_LEN];
|
char keysbuf[KEYS_LEN];
|
||||||
char pubkeybuf[B64_PUBKEY_LEN + NULLTERM_LEN];
|
char pubkeybuf[B64_PUBKEY_LEN + NULLTERM_LEN];
|
||||||
@ -75,23 +80,38 @@ void yamlout_writekeys(const char *hostname,const u8 *formated_public,const u8 *
|
|||||||
char timebuf[TIME_LEN + NULLTERM_LEN];
|
char timebuf[TIME_LEN + NULLTERM_LEN];
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
|
|
||||||
BUF_APPEND(keysbuf,offset,keys_field_generated,KEYS_FIELD_GENERATED_LEN);
|
BUF_APPEND(keysbuf,offset,keys_field_generated,KEYS_FIELD_GENERATED_LEN);
|
||||||
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
||||||
|
|
||||||
|
|
||||||
BUF_APPEND(keysbuf,offset,keys_field_hostname,KEYS_FIELD_HOSTNAME_LEN);
|
BUF_APPEND(keysbuf,offset,keys_field_hostname,KEYS_FIELD_HOSTNAME_LEN);
|
||||||
BUF_APPEND(keysbuf,offset,hostname,ONION_LEN);
|
BUF_APPEND(keysbuf,offset,hostname,ONION_LEN);
|
||||||
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
||||||
|
|
||||||
|
|
||||||
BUF_APPEND(keysbuf,offset,keys_field_publickey,KEYS_FIELD_PUBLICKEY_LEN);
|
BUF_APPEND(keysbuf,offset,keys_field_publickey,KEYS_FIELD_PUBLICKEY_LEN);
|
||||||
base64_to(pubkeybuf,formated_public,FORMATTED_PUBLIC_LEN);
|
|
||||||
BUF_APPEND(keysbuf,offset,pubkeybuf,B64_PUBKEY_LEN);
|
if (!rawkeys)
|
||||||
|
base64_to(pubkeybuf,publickey,FORMATTED_PUBLIC_LEN);
|
||||||
|
else
|
||||||
|
base64_to(pubkeybuf,&publickey[PKPREFIX_SIZE],PUBLIC_LEN);
|
||||||
|
|
||||||
|
BUF_APPEND_CSTR(keysbuf,offset,pubkeybuf);
|
||||||
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
||||||
|
|
||||||
|
|
||||||
BUF_APPEND(keysbuf,offset,keys_field_secretkey,KEYS_FIELD_SECRETKEY_LEN);
|
BUF_APPEND(keysbuf,offset,keys_field_secretkey,KEYS_FIELD_SECRETKEY_LEN);
|
||||||
base64_to(seckeybuf,formated_secret,FORMATTED_SECRET_LEN);
|
|
||||||
BUF_APPEND(keysbuf,offset,seckeybuf,B64_SECKEY_LEN);
|
if (!rawkeys)
|
||||||
|
base64_to(seckeybuf,secretkey,FORMATTED_SECRET_LEN);
|
||||||
|
else
|
||||||
|
base64_to(seckeybuf,&secretkey[SKPREFIX_SIZE],SECRET_LEN);
|
||||||
|
|
||||||
|
BUF_APPEND_CSTR(keysbuf,offset,seckeybuf);
|
||||||
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
||||||
|
|
||||||
|
|
||||||
BUF_APPEND(keysbuf,offset,keys_field_time,KEYS_FIELD_TIME_LEN);
|
BUF_APPEND(keysbuf,offset,keys_field_time,KEYS_FIELD_TIME_LEN);
|
||||||
|
|
||||||
time_t currtime;
|
time_t currtime;
|
||||||
@ -106,10 +126,12 @@ void yamlout_writekeys(const char *hostname,const u8 *formated_public,const u8 *
|
|||||||
BUF_APPEND(keysbuf,offset,timebuf,TIME_LEN);
|
BUF_APPEND(keysbuf,offset,timebuf,TIME_LEN);
|
||||||
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
BUF_APPEND_CHAR(keysbuf,offset,'\n');
|
||||||
|
|
||||||
assert(offset == KEYS_LEN);
|
|
||||||
|
assert(offset == (!rawkeys ? KEYS_LEN : RAW_KEYS_LEN));
|
||||||
|
|
||||||
|
|
||||||
pthread_mutex_lock(&fout_mutex);
|
pthread_mutex_lock(&fout_mutex);
|
||||||
fwrite(keysbuf,sizeof(keysbuf),1,fout);
|
fwrite(keysbuf,offset,1,fout);
|
||||||
fflush(fout);
|
fflush(fout);
|
||||||
pthread_mutex_unlock(&fout_mutex);
|
pthread_mutex_unlock(&fout_mutex);
|
||||||
}
|
}
|
||||||
@ -119,7 +141,8 @@ void yamlout_writekeys(const char *hostname,const u8 *formated_public,const u8 *
|
|||||||
#undef BUF_APPEND
|
#undef BUF_APPEND
|
||||||
|
|
||||||
// pseudo YAML parser
|
// pseudo YAML parser
|
||||||
int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
int yamlin_parseandcreate(
|
||||||
|
FILE *fin,char *sname,const char *onehostname,int rawkeys)
|
||||||
{
|
{
|
||||||
char line[256];
|
char line[256];
|
||||||
size_t len,cnt;
|
size_t len,cnt;
|
||||||
@ -128,6 +151,11 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
int hashost = 0,haspub = 0,hassec = 0,skipthis = 0;
|
int hashost = 0,haspub = 0,hassec = 0,skipthis = 0;
|
||||||
enum keytype { HOST, PUB, SEC } keyt;
|
enum keytype { HOST, PUB, SEC } keyt;
|
||||||
|
|
||||||
|
if (rawkeys) {
|
||||||
|
memcpy(pubbuf,pkprefix,PKPREFIX_SIZE);
|
||||||
|
memcpy(secbuf,skprefix,SKPREFIX_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
while (!feof(fin) && !ferror(fin)) {
|
while (!feof(fin) && !ferror(fin)) {
|
||||||
if (!fgets(line,sizeof(line),fin))
|
if (!fgets(line,sizeof(line),fin))
|
||||||
break;
|
break;
|
||||||
@ -143,7 +171,7 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (len >= 3 && line[0] == '-' && line[1] == '-' && line[2] == '-') {
|
if (len >= 3 && line[0] == '-' && line[1] == '-' && line[2] == '-') {
|
||||||
// end of document indicator
|
// end of document / start of new document indicator
|
||||||
if (!skipthis && (hashost || haspub || hassec)) {
|
if (!skipthis && (hashost || haspub || hassec)) {
|
||||||
fprintf(stderr,"ERROR: incomplete record\n");
|
fprintf(stderr,"ERROR: incomplete record\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -206,15 +234,18 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
fprintf(stderr,"ERROR: invalid hostname syntax\n");
|
fprintf(stderr,"ERROR: invalid hostname syntax\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!hostname || !strcmp(hostname,p)) {
|
if (!onehostname || !strcmp(onehostname,p)) {
|
||||||
memcpy(&sname[direndpos],p,len + 1);
|
memcpy(&sname[direndpos],p,len + 1);
|
||||||
hashost = 1;
|
hashost = 1;
|
||||||
} else
|
} else
|
||||||
skipthis = 1;
|
skipthis = 1;
|
||||||
break;
|
break;
|
||||||
case PUB:
|
case PUB:
|
||||||
if (len != B64_PUBKEY_LEN || !base64_valid(p,0) ||
|
if (!rawkeys
|
||||||
base64_from(pubbuf,p,len) != FORMATTED_PUBLIC_LEN)
|
? (len != B64_PUBKEY_LEN || !base64_valid(p,0) ||
|
||||||
|
base64_from(pubbuf,p,len) != FORMATTED_PUBLIC_LEN)
|
||||||
|
: (len != B64_RAW_PUBKEY_LEN || !base64_valid(p,0) ||
|
||||||
|
base64_from(&pubbuf[PKPREFIX_SIZE],p,len) != PUBLIC_LEN))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"ERROR: invalid pubkey syntax\n");
|
fprintf(stderr,"ERROR: invalid pubkey syntax\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -222,8 +253,11 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
haspub = 1;
|
haspub = 1;
|
||||||
break;
|
break;
|
||||||
case SEC:
|
case SEC:
|
||||||
if (len != B64_SECKEY_LEN || !base64_valid(p,0) ||
|
if (!rawkeys
|
||||||
base64_from(secbuf,p,len) != FORMATTED_SECRET_LEN)
|
? (len != B64_SECKEY_LEN || !base64_valid(p,0) ||
|
||||||
|
base64_from(secbuf,p,len) != FORMATTED_SECRET_LEN)
|
||||||
|
: (len != B64_RAW_SECKEY_LEN || !base64_valid(p,0) ||
|
||||||
|
base64_from(&secbuf[SKPREFIX_SIZE],p,len) != SECRET_LEN))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"ERROR: invalid seckey syntax\n");
|
fprintf(stderr,"ERROR: invalid seckey syntax\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -264,8 +298,9 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
sigprocmask(SIG_SETMASK,&oset,0);
|
sigprocmask(SIG_SETMASK,&oset,0);
|
||||||
#endif
|
#endif
|
||||||
if (hostname)
|
if (onehostname)
|
||||||
return 0; // finished
|
return 0; // finished
|
||||||
|
// skip rest of lines until we hit start of new doc indicator
|
||||||
skipthis = 1;
|
skipthis = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +310,7 @@ int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostname) {
|
if (onehostname) {
|
||||||
fprintf(stderr,"hostname wasn't found in input\n");
|
fprintf(stderr,"hostname wasn't found in input\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
6
yaml.h
6
yaml.h
@ -1,4 +1,6 @@
|
|||||||
extern void yamlout_init(void);
|
extern void yamlout_init(void);
|
||||||
extern void yamlout_clean(void);
|
extern void yamlout_clean(void);
|
||||||
extern void yamlout_writekeys(const char *hostname,const u8 *formated_public,const u8 *formated_secret);
|
extern void yamlout_writekeys(
|
||||||
extern int yamlin_parseandcreate(FILE *fin,char *sname,const char *hostname);
|
const char *hostname,const u8 *publickey,const u8 *secretkey,int rawkeys);
|
||||||
|
extern int yamlin_parseandcreate(
|
||||||
|
FILE *fin,char *sname,const char *hostname,int rawkeys);
|
||||||
|
Loading…
Reference in New Issue
Block a user