Import code to load configuration from file.

WARNING: This commit do not contains a fully cleaned code:
 - Only nfc-list have been tested
 - Some -commented- code is not used ATM
 - Some printf-as-debug remain in this commit
... but that a bit usable so... happy hacking ;-)
This commit is contained in:
Romuald Conty 2012-11-24 13:10:28 +01:00
parent 3ee77eb79e
commit 7963fdfc3b
9 changed files with 231 additions and 36 deletions

View file

@ -63,7 +63,7 @@ extern "C" {
# endif // __cplusplus
/* Library initialization/deinitialization */
NFC_EXPORT void nfc_init(nfc_context *context);
NFC_EXPORT void nfc_init(nfc_context **context);
NFC_EXPORT void nfc_exit(nfc_context *context);
/* NFC Device/Hardware manipulation */

8
libnfc.conf.sample Normal file
View file

@ -0,0 +1,8 @@
# Allow device auto-detection (default: true)
# Note: if this auto-detection is disable, user have to set manually a device
# configuration using file or environnement variable
#allow_autoscan = true
# Allow intrusive auto-detection (default: false)
# Warning: intrusive auto-detection can seriously disturb other devices
#allow_intrusive_autoscan = false

View file

@ -4,6 +4,7 @@ SUBDIRS = chips buses drivers .
AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS)
noinst_HEADERS = \
conf.h \
drivers.h \
iso7816.h \
log.h \
@ -13,6 +14,7 @@ noinst_HEADERS = \
lib_LTLIBRARIES = libnfc.la
libnfc_la_SOURCES = \
conf.c \
iso14443-subr.c \
mirror-subr.c \
nfc.c \

131
libnfc/conf.c Normal file
View file

@ -0,0 +1,131 @@
/*-
* Copyright (C) 2012 Romuald Conty
*
* This program 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 3 of the License, or (at your
* option) any later version.
*
* 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 Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <regex.h>
#include <sys/stat.h>
#include <nfc/nfc.h>
#include "nfc-internal.h"
#include "log.h"
#define LOG_CATEGORY "libnfc.config"
#define LIBNFC_SYSCONFDIR "/etc/nfc"
#define LIBNFC_CONFFILE LIBNFC_SYSCONFDIR"/libnfc.conf"
#define LIBNFC_DEVICECONFDIR LIBNFC_SYSCONFDIR"/devices.d"
bool conf_parse_file(const char* filename, void (*conf_keyvalue)(void* data, const char* key, const char* value), void* data)
{
FILE *f = fopen (filename, "r");
if (!f) {
perror ("fopen");
return false;
}
char line[BUFSIZ];
const char *str_regex = "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*=[[:space:]]*(\"(.+)\"|([^[:space:]]+))[[:space:]]*$";
regex_t preg;
if(regcomp (&preg, str_regex, REG_EXTENDED|REG_NOTEOL) != 0) {
printf ("regcomp error\n");
return false;
}
size_t nmatch = preg.re_nsub + 1;
regmatch_t *pmatch = malloc (sizeof (*pmatch) * nmatch);
if(!pmatch) {
perror ("malloc");
return false;
}
int lineno = 0;
while (fgets(line, BUFSIZ, f) != NULL) {
lineno++;
switch(line[0]) {
case '#':
case '\n':
break;
default: {
int match;
if ((match = regexec (&preg, line, nmatch, pmatch, 0)) == 0) {
const size_t key_size = pmatch[1].rm_eo - pmatch[1].rm_so;
const off_t value_pmatch = pmatch[3].rm_eo!=-1?3:4;
const size_t value_size = pmatch[value_pmatch].rm_eo - pmatch[value_pmatch].rm_so;
char key[key_size+1];
char value[value_size+1];
strncpy(key, line+(pmatch[1].rm_so), key_size); key[key_size]='\0';
strncpy(value, line+(pmatch[value_pmatch].rm_so), value_size); value[value_size]='\0';
conf_keyvalue(data, key, value);
} else {
log_put( LOG_CATEGORY, NFC_PRIORITY_TRACE, "parse error on line #%d: %s", lineno, line);
}
}
break;
}
}
return false;
}
void
conf_keyvalue_context(void *data, const char* key, const char* value)
{
nfc_context *context = (nfc_context*)data;
printf ("key: [%s], value: [%s]\n", key, value);
if (strcmp(key, "allow_autoscan") == 0) {
string_as_boolean(value, &(context->allow_autoscan));
} else if (strcmp(key, "allow_intrusive_scan") == 0) {
string_as_boolean(value, &(context->allow_intrusive_scan));
} else {
log_put( LOG_CATEGORY, NFC_PRIORITY_INFO, "unknown key in config line: %s = %s", key, value);
}
}
void
conf_load(nfc_context *context)
{
conf_parse_file(LIBNFC_CONFFILE, conf_keyvalue_context, context);
}
/*
int
main(int argc, char *argv[])
{
DIR *d = opendir(LIBNFC_DEVICECONFDIR);
if (!d) {
perror ("opendir");
} else {
struct dirent* de;
while (de = readdir(d)) {
if (de->d_name[0]!='.') {
printf ("\t%s\n", de->d_name);
char filename[BUFSIZ] = LIBNFC_DEVICECONFDIR"/";
strcat (filename, de->d_name);
struct stat s;
if (stat(filename, &s) == -1) {
perror("stat");
continue;
}
if(S_ISREG(s.st_mode)) {
nfc_open_from_file (filename);
}
}
}
}
}
*/

19
libnfc/conf.h Normal file
View file

@ -0,0 +1,19 @@
/*-
* Copyright (C) 2012 Romuald Conty
*
* This program 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 3 of the License, or (at your
* option) any later version.
*
* 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 Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
void conf_load(nfc_context *context);

View file

@ -24,20 +24,31 @@
#include <nfc/nfc.h>
#include "nfc-internal.h"
#include "conf.h"
#include <stdlib.h>
#include <string.h>
static bool
string_as_boolean(const char* s)
void
string_as_boolean(const char* s, bool *value)
{
if ((s) && (
(strcmp(s, "yes") == 0) ||
if (s) {
if (!(*value)) {
if ( (strcmp(s, "yes") == 0) ||
(strcmp(s, "true") == 0) ||
(strcmp(s, "1") == 0))) {
return true;
(strcmp(s, "1") == 0) ) {
*value = true;
return;
}
} else {
if ( (strcmp(s, "no") == 0) ||
(strcmp(s, "false") == 0) ||
(strcmp(s, "0") == 0) ) {
*value = false;
return;
}
}
}
return false;
}
nfc_context *
@ -49,10 +60,20 @@ nfc_context_new(void)
err(EXIT_FAILURE, "nfc_context_new: malloc");
}
// Set default context values
res->allow_autoscan = true;
res->allow_intrusive_scan = false;
// Load options from configuration file (ie. /etc/nfc/libnfc.conf)
conf_load(res);
// Environment variables
// Load "intrusive scan" option
// XXX: Load this option from configuration file too ?
char *envvar = getenv("LIBNFC_INTRUSIVE_SCAN");
res->allow_intrusive_scan = string_as_boolean(envvar);
string_as_boolean(envvar, &(res->allow_intrusive_scan));
// Debug context state
log_put ("libnfc", NFC_PRIORITY_DEBUG, "allow_autoscan is set to %s", (res->allow_autoscan)?"true":"false");
log_put ("libnfc", NFC_PRIORITY_DEBUG, "allow_intrusive_scan is set to %s", (res->allow_intrusive_scan)?"true":"false");
return res;
}

View file

@ -158,6 +158,7 @@ struct nfc_driver {
* Struct which contains internal options, references, pointers, etc. used by library
*/
struct nfc_context {
bool allow_autoscan;
bool allow_intrusive_scan;
};
@ -195,6 +196,8 @@ struct nfc_device {
nfc_device *nfc_device_new(const nfc_connstring connstring);
void nfc_device_free(nfc_device *dev);
void string_as_boolean(const char* s, bool *value);
void iso14443_cascade_uid(const uint8_t abtUID[], const size_t szUID, uint8_t *pbtCascadedUID, size_t *pszCascadedUID);
void prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t *pszInitiatorData);

View file

@ -108,12 +108,16 @@ const struct nfc_driver *nfc_drivers[] = {
/** @ingroup lib
* @brief Initialize libnfc.
* This function must be called before calling any other libnfc function
* @param context Optional output location for context pointer
* @param context Output location for nfc_context
*/
void
nfc_init(nfc_context *context)
nfc_init(nfc_context **context)
{
(void) context;
if (!context) {
printf("Error: NULL context is not supported anymore, please fix your code.\n");
exit(EXIT_FAILURE);
}
*context = nfc_context_new();
log_init();
}
@ -265,9 +269,14 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_
const struct nfc_driver *ndr;
const struct nfc_driver **pndr = nfc_drivers;
if (!context) context = nfc_context_new(); // Should we support NULL context ?
// FIXME: Load device(s) from configuration file(s)
if (!context) {
printf ("NULL context is not supported anymore! Please fix your code.");
}
// TODO Load manually configured devices (from config file and env variables)
// Device auto-detection
if (context->allow_autoscan) {
while ((ndr = *pndr)) {
size_t _device_found = 0;
if((ndr->scan_type == NOT_INTRUSIVE) || ((context->allow_intrusive_scan) && (ndr->scan_type == INTRUSIVE))) {
@ -281,7 +290,8 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_
} // scan_type is INTRUSIVE but not allowed or NOT_AVAILABLE
pndr++;
}
log_fini();
}
return device_found;
}

View file

@ -75,7 +75,8 @@ main(int argc, const char *argv[])
bool verbose = false;
int res = 0;
nfc_init(NULL);
nfc_context *context;
nfc_init(&context);
// Display libnfc version
acLibnfcVersion = nfc_version();
@ -97,7 +98,7 @@ main(int argc, const char *argv[])
/* Lazy way to open an NFC device */
#if 0
pnd = nfc_open(NULL, NULL);
pnd = nfc_open(context, NULL);
#endif
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
@ -106,7 +107,7 @@ main(int argc, const char *argv[])
ndd.pcDriver = "ARYGON";
ndd.pcPort = "/dev/ttyUSB0";
ndd.uiSpeed = 115200;
pnd = nfc_open(NULL, &ndd);
pnd = nfc_open(context, &ndd);
#endif
/* If specific device is wanted, i.e. a SCL3711 on USB */
@ -114,10 +115,10 @@ main(int argc, const char *argv[])
nfc_device_desc_t ndd;
ndd.pcDriver = "PN533_USB";
strcpy(ndd.acDevice, "SCM Micro / SCL3711-NFC&RW");
pnd = nfc_open(NULL, &ndd);
pnd = nfc_open(context, &ndd);
#endif
nfc_connstring connstrings[MAX_DEVICE_COUNT];
size_t szDeviceFound = nfc_list_devices(NULL, connstrings, MAX_DEVICE_COUNT);
size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);
if (szDeviceFound == 0) {
printf("No NFC device found.\n");
@ -125,7 +126,7 @@ main(int argc, const char *argv[])
for (i = 0; i < szDeviceFound; i++) {
nfc_target ant[MAX_TARGET_COUNT];
pnd = nfc_open(NULL, connstrings[i]);
pnd = nfc_open(context, connstrings[i]);
if (pnd == NULL) {
ERR("Unable to open NFC device: %s", connstrings[i]);