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

📄 expression.c

📁 devfsd 驱动对linux的补丁支持
💻 C
字号:
/*LINTLIBRARY*//*  expression.c    This code provides Borne Shell-like expression expansion.    Copyright (C) 1997-1999  Richard Gooch    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This 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    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    Richard Gooch may be reached by email at  karma-request@atnf.csiro.au    The postal address is:      Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.*//*  This file contains shell-like expression expansion routines.    Written by      Richard Gooch   9-OCT-1997    Updated by      Richard Gooch   4-DEC-1997: Added support for  "${var:-word}" expressions.    Updated by      Richard Gooch   17-SEP-1998: Took account of some CONST  declarations in <r> package.    Last updated by Richard Gooch   8-JUN-1999: Changed <st_expr_expand> to  support getting variable values from supplied function.*/#include <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <pwd.h>#include <karma.h>#ifdef __KARMA__#  include <karma_st.h>#  include <karma_r.h>#endif#define BUF_SIZE 16384#ifndef __KARMA__#  define r_getenv getenv#endif/*  Private functions  */STATIC_FUNCTION (CONST char *expand_variable,		 (char *buffer, unsigned int length, unsigned int *out_pos,		  CONST char *input,		  CONST char *(*func) (CONST char *variable, void *info),		  void *info, FILE *errfp) );STATIC_FUNCTION (CONST char *get_variable,		 (CONST char *variable,		  CONST char *(*func) (CONST char *variable, void *info),		  void *info) );/*  Public functions follow  *//*EXPERIMENTAL_FUNCTION*/flag st_expr_expand (char *output, unsigned int length, CONST char *input,		     CONST char *(*get_variable) (CONST char *variable,						  void *info),		     void *info, FILE *errfp)/*  [SUMMARY] Expand an expression using Borne Shell-like unquoted rules.    <output> The output expanded expression is written here.    <length> The size of the output buffer.    <input> The input expression. This may equal <<output>>.    <get_variable> A function which will be used to get variable values. If    this returns NULL, the environment is searched instead. If this is NULL,    only the environment is searched.    <info> An arbitrary pointer passed to <<get_variable>>.    <errfp> Diagnostic messages are written here. If this is NULL the global    stderr is used instead.    [RETURNS] TRUE on success, else FALSE.*/{    char ch;    unsigned int len;    unsigned int out_pos = 0;    CONST char *env;    CONST char *ptr;    struct passwd *pwent;    char buffer[BUF_SIZE], tmp[STRING_LENGTH];    static char function_name[] = "st_expr_expand";    if (errfp == NULL) errfp = stderr;    if (length > BUF_SIZE) length = BUF_SIZE;    for (; TRUE; ++input)    {	switch (ch = *input)	{	  case '$':	    /*  Variable expansion  */	    input = expand_variable (buffer, length, &out_pos, ++input,				     get_variable, info, errfp);	    if (input == NULL) return (FALSE);	    break;	  case '~':	    /*  Home directory expansion  */	    ch = input[1];	    if ( isspace (ch) || (ch == '/') || (ch == '\0') )	    {		/* User's own home directory: leave separator for next time */		if ( ( env = r_getenv ("HOME") ) == NULL )		{		    fprintf (errfp,			     "%s: environment variable: \"HOME\" not found\n",			     function_name);		    return (FALSE);		}		len = strlen (env);		if (len + out_pos >= length)		{		    fprintf (errfp, "%s: output buffer too small\n",			     function_name);		    return (FALSE);		}		memcpy (buffer + out_pos, env, len + 1);		out_pos += len;		continue;	    }	    /*  Someone else's home directory  */	    for (ptr = ++input; !isspace (ch) && (ch != '/') && (ch != '\0');		 ch = *++ptr);	    len = ptr - input;	    if (len >= sizeof tmp)	    {		fprintf (errfp, "%s: username buffer too small\n",			 function_name);		return (FALSE);	    }	    memcpy (tmp, input, len);	    tmp[len] = '\0';	    input = ptr - 1;	    if ( ( pwent = getpwnam (tmp) ) == NULL )	    {		fprintf (errfp, "%s: error getting pwent for user: \"%s\"\n",			 function_name, tmp);		return (FALSE);	    }	    len = strlen (pwent->pw_dir);	    if (len + out_pos >= length)	    {		fprintf (errfp, "%s: output buffer too small\n",function_name);		return (FALSE);	    }	    memcpy (buffer + out_pos, pwent->pw_dir, len + 1);	    out_pos += len;	    break;	  case '\0':	  default:	    if (out_pos >= length)	    {		fprintf (errfp, "%s: output buffer too small\n",function_name);		return (FALSE);	    }	    buffer[out_pos++] = ch;	    if (ch == '\0')	    {		memcpy (output, buffer, out_pos);		return (TRUE);	    }	    break;	}    }    return (FALSE);}   /*  End Function st_expr_expand  *//*  Private functions follow  */static CONST char *expand_variable (char *buffer, unsigned int length,				    unsigned int *out_pos, CONST char *input,				    CONST char *(*func) (CONST char *variable,							 void *info),				    void *info, FILE *errfp)/*  [SUMMARY] Expand a variable.    <buffer> The buffer to write to.    <length> The length of the output buffer.    <out_pos> The current output position. This is updated.    <input> A pointer to the input character pointer.    <func> A function which will be used to get variable values. If this    returns NULL, the environment is searched instead. If this is NULL, only    the environment is searched.    <info> An arbitrary pointer passed to <<func>>.    <errfp> Diagnostic messages are written here.    [RETURNS] A pointer to the end of this subexpression on success, else NULL.*/{    char ch;    int len;    unsigned int open_braces;    CONST char *env, *ptr;    char tmp[STRING_LENGTH];    static char function_name[] = "_st_expr_expand_variable";    ch = input[0];    if (ch == '$')    {	/*  Special case for "$$": PID  */	sprintf ( tmp, "%d", (int) getpid () );	len = strlen (tmp);	if (len + *out_pos >= length)	{	    fprintf (errfp, "%s: output buffer too small\n", function_name);	    return (NULL);	}	memcpy (buffer + *out_pos, tmp, len + 1);	*out_pos += len;	return (input);    }    /*  Ordinary variable expansion, possibly in braces  */    if (ch != '{')    {	/*  Simple variable expansion  */	for (ptr = input; isalnum (ch) || (ch == '_') || (ch == ':');	     ch = *++ptr);	len = ptr - input;	if (len >= sizeof tmp)	{	    fprintf (errfp, "%s: temporary buffer too small\n", function_name);	    return (NULL);	}	memcpy (tmp, input, len);	tmp[len] = '\0';	input = ptr - 1;	if ( ( env = get_variable (tmp, func, info) ) == NULL )	{	    fprintf (errfp, "%s: variable: \"%s\" not found\n",		     function_name, tmp);	    return (NULL);	}	len = strlen (env);	if (len + *out_pos >= length)	{	    fprintf (errfp, "%s: output buffer too small\n", function_name);	    return (NULL);	}	memcpy (buffer + *out_pos, env, len + 1);	*out_pos += len;	return (input);    }    /*  Variable in braces: check for ':' tricks  */    ch = *++input;    for (ptr = input; isalnum (ch) || (ch == '_'); ch = *++ptr);    if (ch == '}')    {	/*  Must be simple variable expansion with "${var}"  */	len = ptr - input;	if (len >= sizeof tmp)	{	    fprintf (errfp, "%s: temporary buffer too small\n", function_name);	    return (NULL);	}	memcpy (tmp, input, len);	tmp[len] = '\0';	ptr = expand_variable (buffer, length, out_pos, tmp, func, info,errfp);	if (ptr == NULL) return (NULL);	return (input + len);    }    if (ch != ':')    {	fprintf (errfp, "%s: illegal character: '%c' in variable name\n",		 function_name, ch);	return (NULL);    }    if (ptr[1] != '-')    {	fprintf (errfp, "%s: illegal character: '%c' in variable name\n",		 function_name, ptr[1]);	return (NULL);    }    /*  It's that handy "${var:-word}" expression. Check if var is defined  */    len = ptr - input;    if (len >= sizeof tmp)    {	fprintf (errfp, "%s: temporary buffer too small\n", function_name);	return (NULL);    }    memcpy (tmp, input, len);    tmp[len] = '\0';    /*  Move input pointer to ':'  */    input = ptr;    /*  First skip to closing brace, taking note of nested expressions  */    ptr += 2;    ch = ptr[0];    for (open_braces = 1; open_braces > 0; ch = *++ptr)    {	switch (ch)	{	  case '{':	    ++open_braces;	    break;	  case '}':	    --open_braces;	    break;	  case '\0':	    fprintf (errfp, "%s: closing brace not found in: \"%s\"\n",		     function_name, input);	    return (NULL);	    /*break;*/	  default:	    break;	}    }    --ptr;    /*  At this point ptr should point to closing brace of "${var:-word}"  */    if ( ( env = get_variable (tmp, func, info) ) != NULL )    {	/*  Found environment variable, so skip the input to the closing brace	    and return the variable  */	input = ptr;	len = strlen (env);	if (len + *out_pos >= length)	{	    fprintf (errfp, "%s: output buffer too small\n", function_name);	    return (NULL);	}	memcpy (buffer + *out_pos, env, len + 1);	*out_pos += len;	return (input);    }    /*  Environment variable was not found, so process word. Advance input	pointer to start of word in "${var:-word}"  */    input += 2;    len = ptr - input;    if (len >= sizeof tmp)    {	fprintf (errfp, "%s: temporary buffer too small for word\n",		 function_name);	return (NULL);    }    memcpy (tmp, input, len);    tmp[len] = '\0';    input = ptr;    if ( !st_expr_expand (tmp, STRING_LENGTH, tmp, func, info, errfp) )	return (NULL);    len = strlen (tmp);    if (len + *out_pos >= length)    {	fprintf (errfp, "%s: output buffer too small\n", function_name);	return (NULL);    }    memcpy (buffer + *out_pos, tmp, len + 1);    *out_pos += len;    return (input);}   /*  End Function expand_variable  */static CONST char *get_variable (CONST char *variable,				 CONST char *(*func) (CONST char *variable,						      void *info),				 void *info)/*  [SUMMARY] Get a variable from the environment or .    <variable> The variable name.    <func> A function which will be used to get the variable. If this returns    NULL, the environment is searched instead. If this is NULL, only the    environment is searched.    [RETURNS] The value of the variable on success, else NULL.*/{    CONST char *value;    if (func != NULL)    {	value = (*func) (variable, info);	if (value != NULL) return (value);    }    return r_getenv (variable);}   /*  End Function get_variable  */

⌨️ 快捷键说明

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