X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Futils.c;h=cd1e645d42e7968ec4eb5d8dfdf5d9400b818e5a;hb=f3d3a50a5697957befaf94cb44797234a68068c3;hp=69f0bdc0090b20e832c5cca9ebf3cc55854314e8;hpb=75699d62131af1f72895bfa7c8858ccaf1cb100c;p=wget diff --git a/src/utils.c b/src/utils.c index 69f0bdc0..cd1e645d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -59,6 +59,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # include #endif +/* Needed for run_with_timeout. */ +#undef USE_SIGNAL_TIMEOUT +#ifdef HAVE_SIGNAL_H +# include +#endif +#ifdef HAVE_SETJMP_H +# include +#endif +/* If sigsetjmp is a macro, configure won't pick it up. */ +#ifdef sigsetjmp +# define HAVE_SIGSETJMP +#endif +#ifdef HAVE_SIGNAL +# ifdef HAVE_SIGSETJMP +# define USE_SIGNAL_TIMEOUT +# endif +# ifdef HAVE_SIGBLOCK +# define USE_SIGNAL_TIMEOUT +# endif +#endif + #include "wget.h" #include "utils.h" #include "fnmatch.h" @@ -579,6 +600,7 @@ make_directory (const char *directory) { int quit = 0; int i; + int ret = 0; char *dir; /* Make a copy of dir, to be able to write to it. Otherwise, the @@ -594,18 +616,19 @@ make_directory (const char *directory) if (!dir[i]) quit = 1; dir[i] = '\0'; - /* Check whether the directory already exists. */ + /* Check whether the directory already exists. Allow creation of + of intermediate directories to fail, as the initial path components + are not necessarily directories! */ if (!file_exists_p (dir)) - { - if (mkdir (dir, 0777) < 0) - return -1; - } + ret = mkdir (dir, 0777); + else + ret = 0; if (quit) break; else dir[i] = '/'; } - return 0; + return ret; } /* Merge BASE with FILE. BASE can be a directory or a file name, FILE @@ -790,6 +813,31 @@ suffix (const char *str) return NULL; } +/* Return non-zero if FNAME ends with a typical HTML suffix. The + following (case-insensitive) suffixes are presumed to be HTML files: + + html + htm + ?html (`?' matches one character) + + #### CAVEAT. This is not necessarily a good indication that FNAME + refers to a file that contains HTML! */ +int +has_html_suffix_p (const char *fname) +{ + char *suf; + + if ((suf = suffix (fname)) == NULL) + return 0; + if (!strcasecmp (suf, "html")) + return 1; + if (!strcasecmp (suf, "htm")) + return 1; + if (suf[0] && !strcasecmp (suf + 1, "html")) + return 1; + return 0; +} + /* Read a line from FP and return the pointer to freshly allocated storage. The stoarage space is obtained through malloc() and should be freed with free() when it is no longer needed. @@ -1730,3 +1778,73 @@ debug_test_md5 (char *buf) return res; } #endif + +/* Implementation of run_with_timeout, a generic timeout handler for + systems with Unix-like signal handling. */ +#ifdef HAVE_SIGSETJMP +#define SETJMP(env) sigsetjmp (env, 1) + +static sigjmp_buf run_with_timeout_env; + +static RETSIGTYPE +abort_run_with_timeout (int sig) +{ + assert (sig == SIGALRM); + siglongjmp (run_with_timeout_env, -1); +} +#else /* not HAVE_SIGSETJMP */ +#define SETJMP(env) setjmp (env) + +static jmp_buf run_with_timeout_env; + +static RETSIGTYPE +abort_run_with_timeout (int sig) +{ + assert (sig == SIGALRM); + /* We don't have siglongjmp to preserve the set of blocked signals; + if we longjumped out of the handler at this point, SIGALRM would + remain blocked. We must unblock it manually. */ + int mask = siggetmask (); + mask &= ~sigmask(SIGALRM); + sigsetmask (mask); + + /* Now it's safe to longjump. */ + longjmp (run_with_timeout_env, -1); +} +#endif /* not HAVE_SIGSETJMP */ + +int +run_with_timeout (long timeout, void (*fun) (void *), void *arg) +{ +#ifndef USE_SIGNAL_TIMEOUT + fun (arg); + return 0; +#else + int saved_errno; + + if (timeout == 0) + { + fun (arg); + return 0; + } + + signal (SIGALRM, abort_run_with_timeout); + if (SETJMP (run_with_timeout_env) != 0) + { + /* Longjumped out of FUN with a timeout. */ + signal (SIGALRM, SIG_DFL); + return 1; + } + alarm (timeout); + fun (arg); + + /* Preserve errno in case alarm() or signal() modifies it. */ + saved_errno = errno; + alarm (0); + signal (SIGALRM, SIG_DFL); + errno = saved_errno; + + return 0; +#endif +} +