Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9749721
argproc.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Subscribers
None
argproc.c
View Options
/*
* $Id$
*
* 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 lint
char
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
();
int
getredirection
(
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
);
}
/* vi:set tabstop=4 shiftwidth=4: */
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Aug 25, 6:09 PM (1 d, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3464473
Attached To
rPUC universal-ctags debian packaging
Event Timeline
Log In to Comment