⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.c

📁 wget (command line browser) source code
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Various functions of utilitarian nature.   Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001   Free Software Foundation, Inc.This file is part of GNU Wget.GNU Wget is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.GNU Wget is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Wget; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.In addition, as a special exception, the Free Software Foundationgives permission to link the code of its release of Wget with theOpenSSL project's "OpenSSL" library (or with modified versions of itthat use the same license as the "OpenSSL" library), and distributethe linked executables.  You must obey the GNU General Public Licensein all respects for all of the code used other than "OpenSSL".  If youmodify this file, you may extend this exception to your version of thefile, but you are not obligated to do so.  If you do not wish to doso, delete this exception statement from your version.  */#include <config.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_STRING_H# include <string.h>#else  /* not HAVE_STRING_H */# include <strings.h>#endif /* not HAVE_STRING_H */#include <sys/types.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_MMAP# include <sys/mman.h>#endif#ifdef HAVE_PWD_H# include <pwd.h>#endif#include <limits.h>#ifdef HAVE_UTIME_H# include <utime.h>#endif#ifdef HAVE_SYS_UTIME_H# include <sys/utime.h>#endif#include <errno.h>#ifdef NeXT# include <libc.h>		/* for access() */#endif#include <fcntl.h>#include <assert.h>/* For TIOCGWINSZ and friends: */#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif#ifdef HAVE_TERMIOS_H# include <termios.h>#endif/* Needed for run_with_timeout. */#undef USE_SIGNAL_TIMEOUT#ifdef HAVE_SIGNAL_H# include <signal.h>#endif#ifdef HAVE_SETJMP_H# include <setjmp.h>#endif#ifndef HAVE_SIGSETJMP/* If sigsetjmp is a macro, configure won't pick it up. */# ifdef sigsetjmp#  define HAVE_SIGSETJMP# endif#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 "hash.h"#ifndef errnoextern int errno;#endif/* This section implements several wrappers around the basic   allocation routines.  This is done for two reasons: first, so that   the callers of these functions need not consistently check for   errors.  If there is not enough virtual memory for running Wget,   something is seriously wrong, and Wget exits with an appropriate   error message.   The second reason why these are useful is that, if DEBUG_MALLOC is   defined, they also provide a handy (if crude) malloc debugging   interface that checks memory leaks.  *//* Croak the fatal memory error and bail out with non-zero exit   status.  */static voidmemfatal (const char *what){  /* Make sure we don't try to store part of the log line, and thus     call malloc.  */  log_set_save_context (0);  logprintf (LOG_ALWAYS, _("%s: %s: Not enough memory.\n"), exec_name, what);  exit (1);}/* These functions end with _real because they need to be   distinguished from the debugging functions, and from the macros.   Explanation follows:   If memory debugging is not turned on, wget.h defines these:     #define xmalloc xmalloc_real     #define xrealloc xrealloc_real     #define xstrdup xstrdup_real     #define xfree free   In case of memory debugging, the definitions are a bit more   complex, because we want to provide more information, *and* we want   to call the debugging code.  (The former is the reason why xmalloc   and friends need to be macros in the first place.)  Then it looks   like this:     #define xmalloc(a) xmalloc_debug (a, __FILE__, __LINE__)     #define xfree(a)   xfree_debug (a, __FILE__, __LINE__)     #define xrealloc(a, b) xrealloc_debug (a, b, __FILE__, __LINE__)     #define xstrdup(a) xstrdup_debug (a, __FILE__, __LINE__)   Each of the *_debug function does its magic and calls the real one.  */#ifdef DEBUG_MALLOC# define STATIC_IF_DEBUG static#else# define STATIC_IF_DEBUG#endifSTATIC_IF_DEBUG void *xmalloc_real (size_t size){  void *ptr = malloc (size);  if (!ptr)    memfatal ("malloc");  return ptr;}STATIC_IF_DEBUG void *xrealloc_real (void *ptr, size_t newsize){  void *newptr;  /* Not all Un*xes have the feature of realloc() that calling it with     a NULL-pointer is the same as malloc(), but it is easy to     simulate.  */  if (ptr)    newptr = realloc (ptr, newsize);  else    newptr = malloc (newsize);  if (!newptr)    memfatal ("realloc");  return newptr;}STATIC_IF_DEBUG char *xstrdup_real (const char *s){  char *copy;#ifndef HAVE_STRDUP  int l = strlen (s);  copy = malloc (l + 1);  if (!copy)    memfatal ("strdup");  memcpy (copy, s, l + 1);#else  /* HAVE_STRDUP */  copy = strdup (s);  if (!copy)    memfatal ("strdup");#endif /* HAVE_STRDUP */  return copy;}#ifdef DEBUG_MALLOC/* Crude home-grown routines for debugging some malloc-related   problems.  Featured:   * Counting the number of malloc and free invocations, and reporting     the "balance", i.e. how many times more malloc was called than it     was the case with free.   * Making malloc store its entry into a simple array and free remove     stuff from that array.  At the end, print the pointers which have     not been freed, along with the source file and the line number.     This also has the side-effect of detecting freeing memory that     was never allocated.   Note that this kind of memory leak checking strongly depends on   every malloc() being followed by a free(), even if the program is   about to finish.  Wget is careful to free the data structure it   allocated in init.c.  */static int malloc_count, free_count;static struct {  char *ptr;  const char *file;  int line;} malloc_debug[100000];/* Both register_ptr and unregister_ptr take O(n) operations to run,   which can be a real problem.  It would be nice to use a hash table   for malloc_debug, but the functions in hash.c are not suitable   because they can call malloc() themselves.  Maybe it would work if   the hash table were preallocated to a huge size, and if we set the   rehash threshold to 1.0.  *//* Register PTR in malloc_debug.  Abort if this is not possible   (presumably due to the number of current allocations exceeding the   size of malloc_debug.)  */static voidregister_ptr (void *ptr, const char *file, int line){  int i;  for (i = 0; i < countof (malloc_debug); i++)    if (malloc_debug[i].ptr == NULL)      {	malloc_debug[i].ptr = ptr;	malloc_debug[i].file = file;	malloc_debug[i].line = line;	return;      }  abort ();}/* Unregister PTR from malloc_debug.  Abort if PTR is not present in   malloc_debug.  (This catches calling free() with a bogus pointer.)  */static voidunregister_ptr (void *ptr){  int i;  for (i = 0; i < countof (malloc_debug); i++)    if (malloc_debug[i].ptr == ptr)      {	malloc_debug[i].ptr = NULL;	return;      }  abort ();}/* Print the malloc debug stats that can be gathered from the above   information.  Currently this is the count of mallocs, frees, the   difference between the two, and the dump of the contents of   malloc_debug.  The last part are the memory leaks.  */voidprint_malloc_debug_stats (void){  int i;  printf ("\nMalloc:  %d\nFree:    %d\nBalance: %d\n\n",	  malloc_count, free_count, malloc_count - free_count);  for (i = 0; i < countof (malloc_debug); i++)    if (malloc_debug[i].ptr != NULL)      printf ("0x%08ld: %s:%d\n", (long)malloc_debug[i].ptr,	      malloc_debug[i].file, malloc_debug[i].line);}void *xmalloc_debug (size_t size, const char *source_file, int source_line){  void *ptr = xmalloc_real (size);  ++malloc_count;  register_ptr (ptr, source_file, source_line);  return ptr;}voidxfree_debug (void *ptr, const char *source_file, int source_line){  assert (ptr != NULL);  ++free_count;  unregister_ptr (ptr);  free (ptr);}void *xrealloc_debug (void *ptr, size_t newsize, const char *source_file, int source_line){  void *newptr = xrealloc_real (ptr, newsize);  if (!ptr)    {      ++malloc_count;      register_ptr (newptr, source_file, source_line);    }  else if (newptr != ptr)    {      unregister_ptr (ptr);      register_ptr (newptr, source_file, source_line);    }  return newptr;}char *xstrdup_debug (const char *s, const char *source_file, int source_line){  char *copy = xstrdup_real (s);  ++malloc_count;  register_ptr (copy, source_file, source_line);  return copy;}#endif /* DEBUG_MALLOC *//* Utility function: like xstrdup(), but also lowercases S.  */char *xstrdup_lower (const char *s){  char *copy = xstrdup (s);  char *p = copy;  for (; *p; p++)    *p = TOLOWER (*p);  return copy;}/* Return a count of how many times CHR occurs in STRING. */intcount_char (const char *string, char chr){  const char *p;  int count = 0;  for (p = string; *p; p++)    if (*p == chr)      ++count;  return count;}/* Copy the string formed by two pointers (one on the beginning, other   on the char after the last char) to a new, malloc-ed location.   0-terminate it.  */char *strdupdelim (const char *beg, const char *end){  char *res = (char *)xmalloc (end - beg + 1);  memcpy (res, beg, end - beg);  res[end - beg] = '\0';  return res;}/* Parse a string containing comma-separated elements, and return a   vector of char pointers with the elements.  Spaces following the   commas are ignored.  */char **sepstring (const char *s){  char **res;  const char *p;  int i = 0;  if (!s || !*s)    return NULL;  res = NULL;  p = s;  while (*s)    {      if (*s == ',')	{	  res = (char **)xrealloc (res, (i + 2) * sizeof (char *));	  res[i] = strdupdelim (p, s);	  res[++i] = NULL;	  ++s;	  /* Skip the blanks following the ','.  */	  while (ISSPACE (*s))	    ++s;	  p = s;	}      else	++s;    }  res = (char **)xrealloc (res, (i + 2) * sizeof (char *));  res[i] = strdupdelim (p, s);  res[i + 1] = NULL;  return res;}/* Return pointer to a static char[] buffer in which zero-terminated   string-representation of TM (in form hh:mm:ss) is printed.   If TM is non-NULL, the current time-in-seconds will be stored   there.   (#### This is misleading: one would expect TM would be used instead   of the current time in that case.  This design was probably   influenced by the design time(2), and should be changed at some   points.  No callers use non-NULL TM anyway.)  */char *time_str (time_t *tm){  static char output[15];  struct tm *ptm;  time_t secs = time (tm);  if (secs == -1)    {      /* In case of error, return the empty string.  Maybe we should	 just abort if this happens?  */      *output = '\0';      return output;    }  ptm = localtime (&secs);  sprintf (output, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);  return output;}/* Like the above, but include the date: YYYY-MM-DD hh:mm:ss.  */char *datetime_str (time_t *tm){  static char output[20];	/* "YYYY-MM-DD hh:mm:ss" + \0 */  struct tm *ptm;  time_t secs = time (tm);  if (secs == -1)    {      /* In case of error, return the empty string.  Maybe we should	 just abort if this happens?  */      *output = '\0';      return output;    }  ptm = localtime (&secs);  sprintf (output, "%04d-%02d-%02d %02d:%02d:%02d",	   ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,	   ptm->tm_hour, ptm->tm_min, ptm->tm_sec);  return output;}/* The Windows versions of the following two functions are defined in   mswindows.c.  */#ifndef WINDOWSvoidfork_to_background (void){  pid_t pid;  /* Whether we arrange our own version of opt.lfilename here.  */  int changedp = 0;  if (!opt.lfilename)    {      opt.lfilename = unique_name (DEFAULT_LOGFILE, 0);      changedp = 1;    }  pid = fork ();  if (pid < 0)    {      /* parent, error */      perror ("fork");      exit (1);    }  else if (pid != 0)    {      /* parent, no error */      printf (_("Continuing in background, pid %d.\n"), (int)pid);      if (changedp)	printf (_("Output will be written to `%s'.\n"), opt.lfilename);      exit (0);			/* #### should we use _exit()? */    }  /* child: give up the privileges and keep running. */  setsid ();  freopen ("/dev/null", "r", stdin);  freopen ("/dev/null", "w", stdout);  freopen ("/dev/null", "w", stderr);}#endif /* not WINDOWS *//* "Touch" FILE, i.e. make its atime and mtime equal to the time   specified with TM.  */voidtouch (const char *file, time_t tm){#ifdef HAVE_STRUCT_UTIMBUF  struct utimbuf times;  times.actime = times.modtime = tm;#else  time_t times[2];  times[0] = times[1] = tm;#endif  if (utime (file, &times) == -1)    logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));}/* Checks if FILE is a symbolic link, and removes it if it is.  Does   nothing under MS-Windows.  */int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -