Hello again. Sorry, was short on time, and it tooked me time to learn flex and bison.
So, this is beta version of patch, that reimplement netrc parsing and cleanup some utility functions. All kind of constructive critic are welcome. I am not finished with tests and integration, but to give community idea. I would like to acent attention on `auth_free` function. Why gl_list operates on const pointers? I already asked on gnulib list. I did my best to make code clean and simple, no-more, then 20 lines function, but probably I missed portability issues. -- Best regards, illusionoflife. This mail is for mailing lists. For private, responce-warrantied mail use [email protected].
>From b1a788a5ad423e4db960d15d604b8909d2e7155a Mon Sep 17 00:00:00 2001 From: illusionoflife <[email protected]> Date: Mon, 24 Sep 2012 16:25:56 +0400 Subject: [PATCH] Rewrite netrc code. Implement libwget. Implement netrc parsing via flex/bison. Moved `home_dir` function to libwget, cleaned up code. Not integrated in yet. --- Makefile.am | 2 +- bootstrap | 8 ++-- check/Makefile.am | 3 ++ check/check_netrc.c | 4 ++ check/netrc-1.sh | 2 + check/netrc-2.sh | 2 + configure.ac | 14 +++--- libwget/Makefile.am | 8 ++++ libwget/netrc.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++ libwget/netrc.h | 12 +++++ libwget/netrc_grammar.y | 67 +++++++++++++++++++++++++++ libwget/netrc_tokenize.l | 43 ++++++++++++++++++ libwget/utility.c | 64 ++++++++++++++++++++++++++ libwget/utility.h | 6 +++ 14 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 check/Makefile.am create mode 100644 check/check_netrc.c create mode 100755 check/netrc-1.sh create mode 100755 check/netrc-2.sh create mode 100644 libwget/Makefile.am create mode 100644 libwget/netrc.c create mode 100644 libwget/netrc.h create mode 100644 libwget/netrc_grammar.y create mode 100644 libwget/netrc_tokenize.l create mode 100644 libwget/utility.c create mode 100644 libwget/utility.h mode change 100644 => 100755 tests/Test-auth-retcode.px diff --git a/Makefile.am b/Makefile.am index 7a500ba..f21edaf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,7 +41,7 @@ distuninstallcheck_listfiles = find . -type f | \ ACLOCAL_AMFLAGS = -I m4 # subdirectories in the distribution -SUBDIRS = lib src doc po tests util +SUBDIRS = lib libwget src doc po tests check util EXTRA_DIST = ChangeLog.README MAILING-LIST \ msdos/ChangeLog msdos/config.h msdos/Makefile.DJ \ diff --git a/bootstrap b/bootstrap index e3e270b..0d409dc 100755 --- a/bootstrap +++ b/bootstrap @@ -109,9 +109,6 @@ die() { warn_ "$@"; exit 1; } # Name of the Makefile.am gnulib_mk=gnulib.mk -# List of gnulib modules needed. -gnulib_modules= - # Any gnulib files needed that are not in modules. gnulib_files= @@ -845,7 +842,8 @@ if test $with_gettext = yes || test $use_libtool = 1; then rm -f $tempbase.0 $tempbase.1 trap - 1 2 13 15 fi - +# List of gnulib modules needed. +gnulib_modules+="list xlist array-list" # Import from gnulib. gnulib_tool_options="\ @@ -866,7 +864,7 @@ if test $use_libtool = 1; then *) gnulib_tool_options="$gnulib_tool_options --libtool" ;; esac fi -echo "$0: $gnulib_tool $gnulib_tool_options --import ..." +echo "$0: $gnulib_tool $gnulib_tool_options --import ... $gnulib_modules" $gnulib_tool $gnulib_tool_options --import $gnulib_modules && for file in $gnulib_files; do diff --git a/check/Makefile.am b/check/Makefile.am new file mode 100644 index 0000000..faa6eef --- /dev/null +++ b/check/Makefile.am @@ -0,0 +1,3 @@ +check_PROGRAMS = check_netrc +TESTS= +TESTS += netrc-1.sh netrc-2.sh diff --git a/check/check_netrc.c b/check/check_netrc.c new file mode 100644 index 0000000..ed4563e --- /dev/null +++ b/check/check_netrc.c @@ -0,0 +1,4 @@ +int main(int argc, char **argv) +{ + return 0; +} diff --git a/check/netrc-1.sh b/check/netrc-1.sh new file mode 100755 index 0000000..20d602b --- /dev/null +++ b/check/netrc-1.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash + diff --git a/check/netrc-2.sh b/check/netrc-2.sh new file mode 100755 index 0000000..20d602b --- /dev/null +++ b/check/netrc-2.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash + diff --git a/configure.ac b/configure.ac index 873c3c9..c227e34 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,6 @@ dnl dnl Automake setup dnl AM_INIT_AUTOMAKE([1.9]) - dnl dnl Get cannonical host dnl @@ -102,6 +101,8 @@ AC_PROG_CC AM_PROG_CC_C_O AC_AIX +AM_PROG_LEX +AC_PROG_YACC gl_EARLY dnl @@ -192,7 +193,8 @@ AC_CHECK_TYPES(sig_atomic_t, [], [], [ # gnulib gl_INIT - +gl_XALLOC +dnl gl_LIST dnl dnl Checks for library functions. dnl @@ -257,7 +259,7 @@ AS_IF([test x"$with_ssl" = xopenssl], [ case $host_os in *mingw32* ) dnl prefer link to openssl dlls if possible. if not then fallback on static libs. if not then error - + AC_CHECK_LIB(eay32, EVP_MD_CTX_init) if test x"$ac_cv_lib_eay32_EVP_MD_CTX_init" != xno then @@ -269,7 +271,7 @@ AS_IF([test x"$with_ssl" = xopenssl], [ AC_DEFINE([HAVE_LIBSSL32], [1], [Define to 1 if you have the `ssl32' library (-lssl32).]) ], AC_MSG_ERROR([openssl not found: shared lib eay32 found but ssl32 not found])) - + else LIBS+=' -lgdi32' dnl fallback and test static libs @@ -544,7 +546,7 @@ AC_CHECK_HEADER(pcre.h, ]) ) - + dnl Needed by src/Makefile.am AM_CONDITIONAL([IRI_IS_ENABLED], [test "X$iri" != "Xno"]) @@ -554,6 +556,6 @@ dnl Create output dnl AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile util/Makefile po/Makefile.in tests/Makefile tests/WgetTest.pm - lib/Makefile]) + lib/Makefile libwget/Makefile check/Makefile]) AC_CONFIG_HEADERS([src/config.h]) AC_OUTPUT diff --git a/libwget/Makefile.am b/libwget/Makefile.am new file mode 100644 index 0000000..a9a5202 --- /dev/null +++ b/libwget/Makefile.am @@ -0,0 +1,8 @@ +AM_YFLAGS = -d -pnetrc_yy +AM_LFLAGS = -o lex.yy.c -Pnetrc_yy +AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) + + +lib_LIBRARIES = libwget.a +libwget_a_SOURCES = netrc_grammar.y netrc_tokenize.l netrc.c utility.h utility.c +libwget_a_LIBADD= $(top_builddir)/lib/libgnu.a diff --git a/libwget/netrc.c b/libwget/netrc.c new file mode 100644 index 0000000..7f68a3e --- /dev/null +++ b/libwget/netrc.c @@ -0,0 +1,115 @@ +#include <config.h> +#include "netrc.h" +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <gl_xlist.h> +#include <gl_array_list.h> +#include <libwget/utility.h> +#include "netrc_grammar.h" + +#define NETRC_DEFAULT_FILENAME ".netrc" +extern FILE *netrc_yyin; +typedef struct netrc_info { +} netrc_info; + +static inline void +auth_strassign (const struct auth *src, const char **login, const char **pwd) +{ + *login = src->login; + *pwd = src->pwd; +} + +static inline void +auth_free(const void *ptr) +{ + struct auth *ath = (struct auth *) ptr; + + free(ath->login); + free(ath->pwd); + free(ath->host); + free(ath); +} +#if defined __VMS +/* Simplicity over perfomance */ +static char * +netrc_default_filepath(void) +{ + return xstrdup("SYS$LOGIN:.netrc" NETRC_DEFAULT_FILENAME); +} +#else +static char * +netrc_default_filepath(void) +{ + char *home = home_dir(); + char *path = xzalloc(strlen(home)+1+strlen(NETRC_DEFAULT_FILENAME)+1); + sprintf(path, "%s/%s", home, NETRC_DEFAULT_FILENAME); + free(home); +} +#endif + +netrc_info* +netrc_parse_default() +{ + char *path = netrc_default_filepath(); + netrc_info *info = netrc_parse(path); + free(path); + return info; +} + +netrc_info * +netrc_parse(const char *path) +{ + gl_list_t list = gl_list_create_empty(GL_ARRAY_LIST, + NULL, NULL, auth_free, true); + + if (path) { + netrc_yyin = fopen(path, "r"); + if (netrc_yyin) + { + netrc_yyparse(list); + fclose(netrc_yyin); + } + } + /* gl_list_t is actually pointer, so I can do this */ + return (netrc_info *) list; +} + +void +netrc_search(const netrc_info *info, const char *host, + const char **login, const char **pwd, bool use_default) +{ + gl_list_t list = (gl_list_t) info; + gl_list_iterator_t it = gl_list_iterator(list); + const void *current_voidptr; + + *login = *pwd = NULL; + while (gl_list_iterator_next (&it, ¤t_voidptr, NULL)) + { + const struct auth *current = current_voidptr; + if (current->host) { + if (!strcmp(current->host, host)) { + auth_strassign(current, login, pwd); + break; + } + } else { /* current->host == NULL */ + if (use_default) /* No break, because default is only one and last */ + auth_strassign(current, login, pwd); + } + } + gl_list_iterator_free(&it); +} + +void +netrc_free(netrc_info *info) +{ + gl_list_t list = (gl_list_t) info; + + gl_list_free(list); +} + +int main() +{ + return 0; +} diff --git a/libwget/netrc.h b/libwget/netrc.h new file mode 100644 index 0000000..49a7ae8 --- /dev/null +++ b/libwget/netrc.h @@ -0,0 +1,12 @@ +#ifndef NETRC_H +#define NETRC_H +#include <stdbool.h> +typedef struct netrc_info netrc_info; +netrc_info* netrc_parse(const char *path); +netrc_info* netrc_parse_default(); +void netrc_search(const netrc_info *info, const char *host, const char **login, + const char **pwd, bool use_default); +void netrc_free(netrc_info *); + + +#endif diff --git a/libwget/netrc_grammar.y b/libwget/netrc_grammar.y new file mode 100644 index 0000000..7abe5eb --- /dev/null +++ b/libwget/netrc_grammar.y @@ -0,0 +1,67 @@ + /* Into generated header */ +%code requires { +#include <config.h> +#define YYSTYPE char * +#include "gl_xlist.h" +#include "xalloc.h" + +/* Last `auth' in list with host=NULL is + * default account */ +struct auth { + char *host; + char *login; + char *pwd; +}; +} + /* To the top of C file */ +%code top { +#include <stdio.h> +#include <string.h> +#include "netrc_grammar.h" +} + +%code { +static void +netrc_yyerror(gl_list_t parsearg, char const *s) +{ + puts("Warning: incorrect netrc file. Made best efford"); +} +static struct auth* +auth_xalloc(char *host, char *login, char *pwd) +{ + struct auth *ath = xmalloc(sizeof(struct auth)); + + ath->host = host; + ath->login = login; + ath->pwd = pwd; + + return ath; +} +int +netrc_yywrap() +{ + return 1; +} +} + +%parse-param{gl_list_t list} +%token TOKMACHINE TOKLOGIN TOKPASSWORD TOKVALUE TOKDEFAULT TOKMACDEF +%% +input: auths macdefs +auths: /* empty */ | auth auths | authdefault +macdefs: /* empty */| macdef macdefs +values: TOKVALUE| TOKVALUE values +macdef: TOKMACDEF values + +authdefault: TOKDEFAULT TOKLOGIN TOKVALUE + TOKPASSWORD TOKVALUE +{ + gl_list_add_last(list, auth_xalloc(NULL, $3, $5)); +} + +auth: TOKMACHINE TOKVALUE + TOKLOGIN TOKVALUE + TOKPASSWORD TOKVALUE +{ + gl_list_add_last(list, auth_xalloc($2, $4, $6)); +}; diff --git a/libwget/netrc_tokenize.l b/libwget/netrc_tokenize.l new file mode 100644 index 0000000..796feb3 --- /dev/null +++ b/libwget/netrc_tokenize.l @@ -0,0 +1,43 @@ +%{ +#include <config.h> +#include "netrc_grammar.h" +#include "xalloc.h" +#include "assert.h" +/* @str have at least opening and closing quote */ +static char * +strdup_unescaped (const char *str) +{ + unsigned int len = strlen (str); + unsigned int index; + unsigned int res_index = 0; + char *res = xmalloc (len - 1); /* Little memory overhead from simplity */ + char q = str[0]; + assert(len >= 2); + /* Exclude quotes -- last and first symbol */ + for (index = 1; index < len - 1; ++index) + { + /* Skip backslash, that escapes quote or another backslash */ + if (str[index] == '\\' && + (str[index + 1] == q || str[index + 1] == '\\')) + index++; + res[res_index++] = str[index]; + } + res[res_index] = '\0'; + return res; +} + +%} +qstring \"(\\.|[^\\"])*\" +astring \'(\\.|[^\\'])*\' +bstring [[:alpha:][:punct:][:digit:]]+ +string {qstring}|{astring} +%% +machine return TOKMACHINE; +login return TOKLOGIN; +password return TOKPASSWORD; +default return TOKDEFAULT; +macdef return TOKMACDEF; +{string} {netrc_yylval = xstrdup_unescaped(netrc_yytext); return TOKVALUE;} +{bstring} {netrc_yylval = xstrdup(netrc_yytext); return TOKVALUE;} +. +%% diff --git a/libwget/utility.c b/libwget/utility.c new file mode 100644 index 0000000..aaab272 --- /dev/null +++ b/libwget/utility.c @@ -0,0 +1,64 @@ +#include "utility.h" +#include <config.h> +#include <assert.h> +#include <xalloc.h> +#include <stdlib.h> +#include <pwd.h> +static char get_separator(const char *path) +{ + const char *p = path; + + while (p) { + if (*p == '/') /* djgpp */ + return '/'; + else if (*p == '\\') /* others */ + return '\\'; + p++; + } + assert(0 && "No separator found"); +} + +#if defined (MSDOS) +extern const char *_w32_get_argv0 (void); /* in libwatt.a/pcconfig.c */ +/* Under MSDOS, if $HOME isn't defined, use the directory where + `wget.exe' resides. */ +static char * +noenv_homedir(void) +{ + const char *argv0 = _w32_get_argv0 (); + const char *last_sep; + char *home; + + last_sep = strrchr(argv0, get_separator(argv0)); + home = strndup(last_sep - argv0); + + return home; +} +#elseif defined(WINDOWS) +extern char* ws_mypath(void); +static char * +noenv_homedir(void) +{ + return xstrdup(ws_mypath()); +} +#else /* POSIX-like */ +static char* +noenv_homedir(void) +{ + const struct passwd *pwd = getpwuid (getuid ()); + if (pwd && pwd->pw_dir) + return xstrdup(pwd->pw_dir); + else + return NULL; +} +#endif /*noenv_homedir */ + +char * +home_dir (void) +{ + char *home; + if (home = getenv ("HOME")) + return xstrdup(home); + else + return noenv_homedir(); +} diff --git a/libwget/utility.h b/libwget/utility.h new file mode 100644 index 0000000..cdd71f9 --- /dev/null +++ b/libwget/utility.h @@ -0,0 +1,6 @@ +#ifndef UTILITY_H +#define UTILITY_H + +char *home_dir(void); + +#endif diff --git a/tests/Test-auth-retcode.px b/tests/Test-auth-retcode.px old mode 100644 new mode 100755 -- 1.7.12
signature.asc
Description: This is a digitally signed message part.
