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

📄 iwordexp.c

📁 Intercom 是一个 Unix系统上灵活的语音传输软件。支持标准音频压缩比如GSM, G.711, and G.72x和其他音频编码。Intercom专为高速网络设计来传输高品质的语音
💻 C
📖 第 1 页 / 共 4 页
字号:
/* POSIX.2 wordexp implementation.   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.   The GNU C Library 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 2.1 of the License, or (at your option) any later version.   The GNU C Library 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   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  *//* Modified for Intercom by Shane Wegner <shane@cm.nu> */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <fnmatch.h>#include <glob.h>#include <paths.h>#include <pwd.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#ifdef USE_IN_LIBIO# include <wchar.h>#endif#ifdef USE_GETTEXT#ifdef HAVE_LOCALE_H#include <locale.h>#endif#include <libintl.h>#define _(String) gettext(String)#define gettext_noop(String) (String)#define N_(String) gettext_noop(String)#else#define _(String) (String)#define N_(String) (String)#endif#include "iwordexp.h"/* Undefine the following line for the production version.  *//* #define NDEBUG 1 */#include <assert.h>#ifndef internal_function#define internal_function#endifextern char **environ;#ifndef strdupa/* Duplicate S, returning an identical alloca'd string.  */# define strdupa(s)                                                           \    (({                                                                        \      __const char *__old = (s);                                              \      size_t __len = strlen (__old) + 1;                                      \      char *__new = (char *) alloca (__len);                        \      (char *) memcpy (__new, __old, __len);                                  \    }))#endif#ifndef strndupa/* Return an alloca'd copy of at most N bytes of string.  */# define strndupa(s, n)                                                       \    (({                                                                        \      __const char *__old = (s);                                              \      size_t __len = strnlen (__old, (n));                                    \      char *__new = (char *) alloca (__len + 1);                    \      __new[__len] = '\0';                                                    \      (char *) memcpy (__new, __old, __len);                                  \    }))#endif/* * This is a recursive-descent-style word expansion routine. *//* Some forward declarations */static int parse_dollars (char **word, size_t *word_length, size_t *max_length,			  const char *words, size_t *offset, int flags,			  wordexp_t *pwordexp, const char *ifs,			  const char *ifs_white, int quoted)     internal_function;static int parse_backtick (char **word, size_t *word_length,			   size_t *max_length, const char *words,			   size_t *offset, int flags, wordexp_t *pwordexp,			   const char *ifs, const char *ifs_white)     internal_function;static int parse_dquote (char **word, size_t *word_length, size_t *max_length,			 const char *words, size_t *offset, int flags,			 wordexp_t *pwordexp, const char *ifs,			 const char *ifs_white)     internal_function;static int eval_expr (char *expr, long int *result) internal_function;/* Convert VALUE into ASCII in base BASE (2..36).   Write backwards starting the character just before BUFLIM.   Return the address of the first (left-to-right) character in the number.   Use upper case letters iff UPPER_CASE is nonzero.  */static char *itoa (unsigned long long int value, char *buflim,		    unsigned int base, int upper_case);#define itoa_word itoa/* The w_*() functions manipulate word lists. */#define W_CHUNK	(100)/* Result of w_newword will be ignored if it's the last word. */static inline char *w_newword (size_t *actlen, size_t *maxlen){  *actlen = *maxlen = 0;  return NULL;}static inline char *w_addchar (char *buffer, size_t *actlen, size_t *maxlen, char ch)     /* (lengths exclude trailing zero) */{  /* Add a character to the buffer, allocating room for it if needed.   */  if (*actlen == *maxlen)    {      char *old_buffer = buffer;      assert (buffer == NULL || *maxlen != 0);      *maxlen += W_CHUNK;      buffer = realloc (buffer, 1 + *maxlen);      if (buffer == NULL)	free (old_buffer);    }  if (buffer != NULL)    {      buffer[*actlen] = ch;      buffer[++(*actlen)] = '\0';    }  return buffer;}static char *internal_functionw_addmem (char *buffer, size_t *actlen, size_t *maxlen, const char *str,	  size_t len){  /* Add a string to the buffer, allocating room for it if needed.   */  if (*actlen + len > *maxlen)    {      char *old_buffer = buffer;      assert (buffer == NULL || *maxlen != 0);      *maxlen += MAX (2 * len, W_CHUNK);      buffer = realloc (old_buffer, 1 + *maxlen);      if (buffer == NULL)	free (old_buffer);    }  if (buffer != NULL)    {      *((char *) mempcpy (&buffer[*actlen], str, len)) = '\0';      *actlen += len;    }  return buffer;}static char *internal_functionw_addstr (char *buffer, size_t *actlen, size_t *maxlen, const char *str)     /* (lengths exclude trailing zero) */{  /* Add a string to the buffer, allocating room for it if needed.   */  size_t len;  assert (str != NULL); /* w_addstr only called from this file */  len = strlen (str);  return w_addmem (buffer, actlen, maxlen, str, len);}static intinternal_functionw_addword (wordexp_t *pwordexp, char *word){  /* Add a word to the wordlist */  size_t num_p;  char **new_wordv;  /* Internally, NULL acts like "".  Convert NULLs to "" before   * the caller sees them.   */  if (word == NULL)    {      word = strdup ("");      if (word == NULL)	goto no_space;    }  num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;  new_wordv = realloc (pwordexp->we_wordv, sizeof (char *) * num_p);  if (new_wordv != NULL)    {      pwordexp->we_wordv = new_wordv;      pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc++] = word;      pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc] = NULL;      return 0;    }no_space:  return WRDE_NOSPACE;}/* The parse_*() functions should leave *offset being the offset in 'words' * to the last character processed. */static intinternal_functionparse_backslash (char **word, size_t *word_length, size_t *max_length,		 const char *words, size_t *offset){  /* We are poised _at_ a backslash, not in quotes */  switch (words[1 + *offset])    {    case 0:      /* Backslash is last character of input words */      return WRDE_SYNTAX;    case '\n':      ++(*offset);      break;    default:      *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);      if (*word == NULL)	return WRDE_NOSPACE;      ++(*offset);      break;    }  return 0;}static intinternal_functionparse_qtd_backslash (char **word, size_t *word_length, size_t *max_length,		     const char *words, size_t *offset){  /* We are poised _at_ a backslash, inside quotes */  switch (words[1 + *offset])    {    case 0:      /* Backslash is last character of input words */      return WRDE_SYNTAX;    case '\n':      ++(*offset);      break;    case '$':    case '`':    case '"':    case '\\':      *word = w_addchar (*word, word_length, max_length, words[1 + *offset]);      if (*word == NULL)	return WRDE_NOSPACE;      ++(*offset);      break;    default:      *word = w_addchar (*word, word_length, max_length, words[*offset]);      if (*word != NULL)	*word = w_addchar (*word, word_length, max_length, words[1 + *offset]);      if (*word == NULL)	return WRDE_NOSPACE;      ++(*offset);      break;    }  return 0;}static intinternal_functionparse_tilde (char **word, size_t *word_length, size_t *max_length,	     const char *words, size_t *offset, size_t wordc){  /* We are poised _at_ a tilde */  size_t i;  if (*word_length != 0)    {      if (!((*word)[*word_length - 1] == '=' && wordc == 0))	{	  if (!((*word)[*word_length - 1] == ':'		&& strchr (*word, '=') && wordc == 0))	    {	      *word = w_addchar (*word, word_length, max_length, '~');	      return *word ? 0 : WRDE_NOSPACE;	    }	}    }  for (i = 1 + *offset; words[i]; i++)    {      if (words[i] == ':' || words[i] == '/' || words[i] == ' ' ||	  words[i] == '\t' || words[i] == 0 )	break;      if (words[i] == '\\')	{	  *word = w_addchar (*word, word_length, max_length, '~');	  return *word ? 0 : WRDE_NOSPACE;	}    }  if (i == 1 + *offset)    {      /* Tilde appears on its own */      uid_t uid;      struct passwd *pwd;      char* home;      /* POSIX.2 says ~ expands to $HOME and if HOME is unset the	 results are unspecified.  We do a lookup on the uid if	 HOME is unset. */      home = getenv ("HOME");      if (home != NULL)	{	  *word = w_addstr (*word, word_length, max_length, home);	  if (*word == NULL)	    return WRDE_NOSPACE;	}      else	{	  uid = getuid ();	  if ((pwd = getpwuid (uid)) != NULL)	    {	      *word = w_addstr (*word, word_length, max_length, pwd->pw_dir);	      if (*word == NULL)		return WRDE_NOSPACE;	    }	  else	    {	      *word = w_addchar (*word, word_length, max_length, '~');	      if (*word == NULL)		return WRDE_NOSPACE;	    }	}    }  else    {      /* Look up user name in database to get home directory */      char *user = strndupa (&words[1 + *offset], i - (1 + *offset));      struct passwd *pwd;      if ((pwd = getpwnam (user)) != NULL)	*word = w_addstr (*word, word_length, max_length, pwd->pw_dir);      else	{	  /* (invalid login name) */	  *word = w_addchar (*word, word_length, max_length, '~');	  if (*word != NULL)	    *word = w_addstr (*word, word_length, max_length, user);	}      *offset = i - 1;    }  return *word ? 0 : WRDE_NOSPACE;}static intinternal_functiondo_parse_glob (const char *glob_word, char **word, size_t *word_length,	       size_t *max_length, wordexp_t *pwordexp, const char *ifs,	       const char *ifs_white){  int error;  unsigned int match;  glob_t globbuf;  error = glob (glob_word, GLOB_NOCHECK, NULL, &globbuf);  if (error != 0)    {      /* We can only run into memory problems.  */      assert (error == GLOB_NOSPACE);      return WRDE_NOSPACE;    }  if (ifs && !*ifs)    {      /* No field splitting allowed. */      assert (globbuf.gl_pathv[0] != NULL);      *word = w_addstr (*word, word_length, max_length, globbuf.gl_pathv[0]);      for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match)	{	  *word = w_addchar (*word, word_length, max_length, ' ');	  if (*word != NULL)	    *word = w_addstr (*word, word_length, max_length,			      globbuf.gl_pathv[match]);	}      globfree (&globbuf);      return *word ? 0 : WRDE_NOSPACE;    }  assert (ifs == NULL || *ifs != '\0');  if (*word != NULL)    {      free (*word);      *word = w_newword (word_length, max_length);    }  for (match = 0; match < globbuf.gl_pathc; ++match)    {      char *matching_word = strdup (globbuf.gl_pathv[match]);      if (matching_word == NULL || w_addword (pwordexp, matching_word))	{	  globfree (&globbuf);	  return WRDE_NOSPACE;	}    }  globfree (&globbuf);  return 0;}static intinternal_functionparse_glob (char **word, size_t *word_length, size_t *max_length,	    const char *words, size_t *offset, int flags,	    wordexp_t *pwordexp, const char *ifs, const char *ifs_white){  /* We are poised just after a '*', a '[' or a '?'. */  int error = WRDE_NOSPACE;  int quoted = 0; /* 1 if singly-quoted, 2 if doubly */  int i;  wordexp_t glob_list; /* List of words to glob */  glob_list.we_wordc = 0;  glob_list.we_wordv = NULL;  glob_list.we_offs = 0;  for (; words[*offset] != '\0'; ++*offset)    {      if ((ifs && strchr (ifs, words[*offset])) ||	  (!ifs && strchr (" \t\n", words[*offset])))	/* Reached IFS */	break;      /* Sort out quoting */      if (words[*offset] == '\'')	{	  if (quoted == 0)	    {	      quoted = 1;	      continue;	    }	  else if (quoted == 1)	    {	      quoted = 0;	      continue;	    }	}      else if (words[*offset] == '"')	{	  if (quoted == 0)	    {	      quoted = 2;	      continue;	    }	  else if (quoted == 2)	    {	      quoted = 0;	      continue;	    }	}      /* Sort out other special characters */      if (quoted != 1 && words[*offset] == '$')	{	  error = parse_dollars (word, word_length, max_length, words,				 offset, flags, &glob_list, ifs, ifs_white,				 quoted == 2);	  if (error)	    goto tidy_up;	  continue;	}      else if (words[*offset] == '\\')	{	  if (quoted)	    error = parse_qtd_backslash (word, word_length, max_length,					 words, offset);	  else	    error = parse_backslash (word, word_length, max_length,				     words, offset);	  if (error)	    goto tidy_up;	  continue;	}      *word = w_addchar (*word, word_length, max_length, words[*offset]);      if (*word == NULL)	goto tidy_up;    }  /* Don't forget to re-parse the character we stopped at. */  --*offset;  /* Glob the words */  error = w_addword (&glob_list, *word);  *word = w_newword (word_length, max_length);  for (i = 0; error == 0 && i < glob_list.we_wordc; i++)    error = do_parse_glob (glob_list.we_wordv[i], word, word_length,			   max_length, pwordexp, ifs, ifs_white);  /* Now tidy up */tidy_up:  iwordfree (&glob_list);  return error;}static intinternal_functionparse_squote (char **word, size_t *word_length, size_t *max_length,	      const char *words, size_t *offset){  /* We are poised just after a single quote */  for (; words[*offset]; ++(*offset))    {      if (words[*offset] != '\'')	{	  *word = w_addchar (*word, word_length, max_length, words[*offset]);	  if (*word == NULL)	    return WRDE_NOSPACE;	}      else return 0;    }  /* Unterminated string */  return WRDE_SYNTAX;}/* Functions to evaluate an arithmetic expression */static intinternal_functioneval_expr_val (char **expr, long int *result){  int sgn = +1;  char *digit;  /* Skip white space */  for (digit = *expr; digit && *digit && isspace (*digit); ++digit);  switch (*digit)    {    case '(':      /* Scan for closing paren */      for (++digit; **expr && **expr != ')'; ++(*expr));      /* Is there one? */      if (!**expr)	return WRDE_SYNTAX;

⌨️ 快捷键说明

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