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

📄 argproc.c

📁 ctags-5.5.4.tar.gz,一个很好的代码开发以及编辑源码
💻 C
字号:
/**   $Id: argproc.c,v 1.1 2001/11/02 04:53:42 darren Exp $**   Copyright (c) 1989, Mark Pizzolato (mark@infopiz.uucp)**   This source code is released for free distribution under the terms of the*   GNU General Public License.**   Provided by Stephen P. Wall <swall@redcom.com>*   Extracted from the VMS port of GNU patch-2.1.**   This module provides redirection support for the VAX DECC port of*   Exuberant Ctags.*//* * @(#)argproc.c 1.0 89/02/01		Mark Pizzolato (mark@infopiz.uucp) */#ifndef lintchar argproc_version [] = "@(#)argproc.c VMS uucp Version infopiz-1.0";#endif#include <ctype.h>#include <descrip.h>#include <dvidef.h>#include <errno.h>#include <iodef.h>#include <lib$routines.h>#include <starlet.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <syidef.h>		/* System Information Definitions	*/#define EXIT_OK 1		/* image exit code */#define EXIT_ERR 0x10000000	/* image exit code *//* * getredirection() is intended to aid in porting C programs * to VMS (Vax-11 C) which does not support '>' and '<' * I/O redirection, along with a command line pipe mechanism * using the '|' AND background command execution '&'. * The piping mechanism will probably work with almost any 'filter' type * of program.  With suitable modification, it may useful for other * portability problems as well. * * Author:  Mark Pizzolato	mark@infopiz.UUCP * Mods:    Steve Wall		Don't return a full path unless the *				original filename included a path. */struct list_item    {    struct list_item *next;    char *value;    };static expand_wild_cards ();static char *pipe_and_fork ();intgetredirection (ac, av)int		*ac;char		***av;/* * Process vms redirection arg's.  Exit if any error is seen. * If getredirection() processes an argument, it is erased * from the vector.  getredirection () returns a new argc and argv value. * In the event that a background command is requested (by a trailing "&"), * this routine creates a background subprocess, and simply exits the program. * * Warning: do not try to simplify the code for vms.  The code * presupposes that getredirection() is called before any data is * read from stdin or written to stdout. * * Normal usage is as follows: * *	main (argc, argv) *	int		argc; *	char		*argv []; *	{ *		getredirection (&argc, &argv); *	} */{    int			argc = *ac;	/* Argument Count	  */    char		**argv = *av;	/* Argument Vector	  */    char		*ap;		/* Argument pointer	  */    int			j;		/* argv [] index		  */    extern int		errno;		/* Last vms i/o error	  */    int			item_count = 0;	/* Count of Items in List */    struct list_item	*list_head = 0;	/* First Item in List	    */    struct list_item	*list_tail;	/* Last Item in List	    */    char		*in = NULL;	/* Input File Name	    */    char		*out = NULL;	/* Output File Name	    */    char		*outmode = "w";	/* Mode to Open Output File */    int			cmargc = 0;	/* Piped Command Arg Count  */    char		**cmargv = NULL;/* Piped Command Arg Vector */    /*     * First handle the case where the last thing on the line ends with     * a '&'.  This indicates the desire for the command to be run in a     * subprocess, so we satisfy that desire.     */    {    extern background_process ();    ap = argv [argc-1];    if (0 == strcmp ("&", ap))	exit (background_process (--argc, argv));    if ('&' == ap [strlen (ap)-1])	{	ap [strlen (ap)-1] = '\0';	exit (background_process (argc, argv));	}    }    /*     * Now we handle the general redirection cases that involve '>', '>>',     * '<', and pipes '|'.     */    for (j = 0; j < argc; ++j)	{	if (0 == strcmp ("<", argv [j]))	    {	    if (j+1 >= argc)		{		errno = EINVAL;		perror ("No input file");		exit (EXIT_ERR);		}	    in = argv [++j];	    continue;	    }	if ('<' == *(ap = argv [j]))	    {	    in = 1 + ap;	    continue;	    }	if (0 == strcmp (">", ap))	    {	    if (j+1 >= argc)		{		errno = EINVAL;		perror ("No output file");		exit (EXIT_ERR);		}	    out = argv [++j];	    continue;	    }	if ('>' == *ap)	    {	    if ('>' == ap [1])		{		outmode = "a";		if ('\0' == ap [2])		    out = argv [++j];		else		    out = 2 + ap;		}	    else		out = 1 + ap;	    continue;	    }	if (0 == strcmp ("|", argv [j]))	    {	    if (j+1 >= argc)		{		errno = EPIPE;		perror ("No command to Pipe to");		exit (EXIT_ERR);		}	    cmargc = argc- (j+1);	    cmargv = &argv [j+1];	    argc = j;	    continue;	    }	if ('|' == *(ap = argv [j]))	    {	    ++argv [j];	    cmargc = argc-j;	    cmargv = &argv [j];	    argc = j;	    continue;	    }	expand_wild_cards (ap, &list_head, &list_tail, &item_count);	}    /*     * Allocate and fill in the new argument vector, Some Unix's terminate     * the list with an extra null pointer.     */    argv = *av = calloc (item_count+1, sizeof (char *));    for (j = 0; j < item_count; ++j, list_head = list_head->next)	argv [j] = list_head->value;    *ac = item_count;    if (cmargv != NULL)	{	char subcmd [1024];	if (out != NULL)	    {	    errno = EINVAL;	    perror ("Invalid '|' and '>' specified");	    exit (EXIT_ERR);	    }	strcpy (subcmd, cmargv [0]);	for (j = 1; j < cmargc; ++j)	    {	    strcat (subcmd, " \"");	    strcat (subcmd, cmargv [j]);	    strcat (subcmd, "\"");	    }	out = pipe_and_fork (subcmd);	}    if ((in != NULL) && (NULL == freopen (in, "r", stdin, "mbc=32", "mbf=2")))	{	perror (in);		/* Can't find file		*/	exit (EXIT_ERR);		/* Is a fatal error		*/	}    if ((out != NULL) && (NULL == freopen (out, outmode, stdout, "mbc=32", "mbf=2")))	{	perror (ap);		/* Error, can't write or append	*/	exit (EXIT_ERR);		/* Is a fatal error		*/	}#ifdef DEBUG    fprintf (stderr, "Arglist:\n");    for (j = 0; j < *ac;  ++j)	fprintf (stderr, "argv[%d] = '%s'\n", j, argv [j]);#endif    return 0;}static add_item (head, tail, value, count)struct list_item **head;struct list_item **tail;char *value;int *count;{    if (*head == 0)	{	if (NULL == (*head = calloc (1, sizeof (**head))))	    {	    errno = ENOMEM;	    perror ("");	    exit (EXIT_ERR);	    }	*tail = *head;	}    else	if (NULL == ((*tail)->next = calloc (1, sizeof (**head))))	    {	    errno = ENOMEM;	    perror ("");	    exit (EXIT_ERR);	    }	else	    *tail = (*tail)->next;    (*tail)->value = value;    ++ (*count);}static expand_wild_cards (item, head, tail, count)char *item;struct list_item **head;struct list_item **tail;int *count;{int expcount = 0;int context = 0;int status;int status_value;char *had_version;int had_path;$DESCRIPTOR (filespec, item);/*$DESCRIPTOR (defaultspec, "SYS$DISK:[]*.*;");*/$DESCRIPTOR (defaultspec, "");$DESCRIPTOR (resultspec, "");    if (strcspn (item, "*%") == strlen (item))	{	add_item (head, tail, item, count);	return;	}    resultspec.dsc$b_dtype = DSC$K_DTYPE_T;    resultspec.dsc$b_class = DSC$K_CLASS_D;    resultspec.dsc$a_pointer = NULL;    filespec.dsc$w_length = strlen (item);    /*     * Only return version specs, if the caller specified a version     */    had_version = strchr (item, ';');    /*     * Only return full path if the caller specified a path     */    had_path = (strchr (item, ']') || strchr (item, ':'));    while (1 == (1&lib$find_file (&filespec, &resultspec, &context,				 &defaultspec, 0, &status_value, &0)))	{	char *string;	char *c;	if (NULL == (string = calloc (1, resultspec.dsc$w_length+1)))	    {	    errno = ENOMEM;	    perror ("");	    exit (EXIT_ERR);	    }	strncpy (string, resultspec.dsc$a_pointer, resultspec.dsc$w_length);	string [resultspec.dsc$w_length] = '\0';	if (NULL == had_version)	    *((char *) strrchr (string, ';')) = '\0';	if (!had_path) {	    char *s = strrchr (string, ']');	    if ( s == NULL ) s = strrchr (string, ':');	    if ( s != NULL ) strcpy (string, s+1);	}	/*	 * Be consistent with what the C RTL has already done to the rest of	 * the argv items and lowercase all of these names.	 */	for (c = string; *c; ++c)	    if (isupper (*c))		*c = tolower (*c);	add_item (head, tail, string, count);	++expcount;	}    if (expcount == 0)	add_item (head, tail, item, count);    lib$sfree1_dd (&resultspec);    lib$find_file_end (&context);}static int child_st [2];	/* Event Flag set when child process completes	*/static short child_chan;/* I/O Channel for Pipe Mailbox			*/static exit_handler (status)int *status;{short iosb [4];    if (0 == child_st [0])	{#ifdef DEBUG	fprintf (stderr, "Waiting for Child Process to Finnish . . .\n");#endif	sys$qiow (0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0);	sys$dassgn (child_chan);	fclose (stdout);	sys$synch (0, child_st);	}}static sig_child (chan)int chan;{#ifdef DEBUG    fprintf (stderr, "Child Completion AST\n");#endif    if (child_st [0] == 0)	child_st [0] = 1;}static struct exit_control_block    {    struct exit_control_block *flink;    int	(*exit_routine) ();    int arg_count;    int *status_address;    int exit_status;    } exit_block =    {    0,    exit_handler,    1,    &exit_block.exit_status,    0    };static char *pipe_and_fork (cmd)char *cmd;{    $DESCRIPTOR (cmddsc, cmd);    static char mbxname [64];    $DESCRIPTOR (mbxdsc, mbxname);    short iosb [4];    int status;    int pid;    struct	{	short dna_buflen;	short dna_itmcod;	char *dna_buffer;	unsigned short *dna_retlen;	int listend;	} itmlst =	{	sizeof (mbxname),	DVI$_DEVNAM,	mbxname,	&mbxdsc.dsc$w_length,	0	};    int mbxsize;    struct	{	short mbf_buflen;	short mbf_itmcod;	int *mbf_maxbuf;	unsigned short *mbf_retlen;	int listend;	} syiitmlst =	{	sizeof (mbxsize),	SYI$_MAXBUF,	&mbxsize,	0,	0	};    cmddsc.dsc$w_length = strlen (cmd);    /*     * Get the SYSGEN parameter MAXBUF, and the smaller of it and 2048 as     * the size of the 'pipe' mailbox.     */    if (1 == (1& (vaxc$errno = sys$getsyiw (0, 0, 0, &syiitmlst, iosb, 0, 0, 0))))	vaxc$errno = iosb [0];    if (0 == (1&vaxc$errno))	{	errno = EVMSERR;	perror ("Can't get SYSGEN parameter value for MAXBUF");	exit (EXIT_ERR);	}    if (mbxsize > 2048)	mbxsize = 2048;    if (0 == (1& (vaxc$errno = sys$crembx (0, &child_chan, mbxsize, mbxsize, 0, 0, 0))))	{	errno = EVMSERR;	perror ("Can't create pipe mailbox");	exit (EXIT_ERR);	}    if (1 == (1& (vaxc$errno = sys$getdviw (0, child_chan, 0, &itmlst, iosb,					  0, 0, 0))))	vaxc$errno = iosb [0];    if (0 == (1&vaxc$errno))	{	errno = EVMSERR;	perror ("Can't get pipe mailbox device name");	exit (EXIT_ERR);	}    mbxname [mbxdsc.dsc$w_length] = '\0';#ifdef DEBUG    fprintf (stderr, "Pipe Mailbox Name = '%s'\n", mbxname);#endif    if (0 == (1& (vaxc$errno = lib$spawn (&cmddsc, &mbxdsc, 0, &1,					0, &pid, child_st, &0, sig_child,					&child_chan))))	{	errno = EVMSERR;	perror ("Can't spawn subprocess");	exit (EXIT_ERR);	}#ifdef DEBUG    fprintf (stderr, "Subprocess's Pid = %08X\n", pid);#endif    sys$dclexh (&exit_block);    return (mbxname);}background_process (argc, argv)int argc;char **argv;{char command [2048] = "$";$DESCRIPTOR (value, command);$DESCRIPTOR (cmd, "BACKGROUND$COMMAND");$DESCRIPTOR (null, "NLA0:");int pid;    strcat (command, argv [0]);    while (--argc)	{	strcat (command, " \"");	strcat (command, *(++argv));	strcat (command, "\"");	}    value.dsc$w_length = strlen (command);    if (0 == (1& (vaxc$errno = lib$set_symbol (&cmd, &value))))	{	errno = EVMSERR;	perror ("Can't create symbol for subprocess command");	exit (EXIT_ERR);	}    if (0 == (1& (vaxc$errno = lib$spawn (&cmd, &null, 0, &17, 0, &pid))))	{	errno = EVMSERR;	perror ("Can't spawn subprocess");	exit (EXIT_ERR);	}#ifdef DEBUG    fprintf (stderr, "%s\n", command);#endif    fprintf (stderr, "%08X\n", pid);    return (EXIT_OK);}/* eof */

⌨️ 快捷键说明

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