1 /* vms_cli.c -- interface to CLI$xxx routines for fetching command line components
2
3 Copyright (C) 1991-1993, 2003, 2011, 2014, 2016, 2022, 2023,
4 the Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20
21 /*
22 * vms_cli.c - command line interface routines.
23 * Pat Rankin, Nov'89
24 * Routines called from vms_gawk.c for DCL parsing.
25 */
26
27 #include "config.h" /* in case we want to suppress 'const' &c */
28 #include "vms.h"
29 #ifndef _STRING_H
30 #include <string.h>
31 #endif
32
33 extern U_Long CLI$PRESENT(const struct dsc$descriptor_s *);
34 extern U_Long CLI$GET_VALUE(const struct dsc$descriptor_s *,
35 struct dsc$descriptor_s *, short *);
36 extern U_Long CLI$DCL_PARSE(const struct dsc$descriptor_s *, const void *, ...);
37 extern U_Long SYS$CLI(void *, ...);
38 extern U_Long SYS$FILESCAN(const struct dsc$descriptor_s *, void *, long *);
39 extern void *LIB$ESTABLISH(U_Long (*handler)(void *, void *));
40 extern U_Long LIB$SIG_TO_RET(void *, void *); /* condition handler */
41
42 /* Cli_Present() - call CLI$PRESENT to determine whether a parameter or */
43 /* qualifier is present on the [already parsed] command line */
44 U_Long
45 Cli_Present( const char *item )
46 {
47 struct dsc$descriptor_s item_dsc;
48 (void)LIB$ESTABLISH(LIB$SIG_TO_RET);
49
50 item_dsc.dsc$w_length = strlen(item_dsc.dsc$a_pointer = (char *)item);
51 item_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
52 item_dsc.dsc$b_class = DSC$K_CLASS_S;
53 return CLI$PRESENT(&item_dsc);
54 }
55
56 /* Cli_Get_Value() - call CLI$GET_VALUE to retreive the value of a */
57 /* parameter or qualifier from the command line */
58 U_Long
59 Cli_Get_Value( const char *item, char *result, int size )
60 {
61 struct dsc$descriptor_s item_dsc, res_dsc;
62 U_Long sts;
63 short len = 0;
64 (void)LIB$ESTABLISH(LIB$SIG_TO_RET);
65
66 item_dsc.dsc$w_length = strlen(item_dsc.dsc$a_pointer = (char *)item);
67 item_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
68 item_dsc.dsc$b_class = DSC$K_CLASS_S;
69 res_dsc.dsc$w_length = size;
70 res_dsc.dsc$a_pointer = result;
71 res_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
72 res_dsc.dsc$b_class = DSC$K_CLASS_S;
73 sts = CLI$GET_VALUE(&item_dsc, &res_dsc, &len);
74 result[len] = '\0';
75 return sts;
76 }
77
78 /* Cli_Parse_Command() - use the $CLI system service (undocumented) to */
79 /* retreive the actual command line (which might be */
80 /* "run prog" or "mcr prog [params]") and then call */
81 /* CLI$DCL_PARSE to parse it using specified tables */
82 U_Long
83 Cli_Parse_Command( const void *cmd_tables, const char *cmd_verb )
84 {
85 struct { short len, code; void *adr; } fscn[2];
86 struct { char rqtype, rqindx, rqflags, rqstat; unsigned :32;
87 struct dsc$descriptor_s rdesc;
88 unsigned :32; unsigned :32; unsigned :32; } cmd;
89 U_Long sts;
90 int ltmp;
91 char longbuf[8200];
92 (void)LIB$ESTABLISH(LIB$SIG_TO_RET);
93
94 memset(&cmd, 0, sizeof cmd);
95 cmd.rqtype = CLI$K_GETCMD; /* command line minus the verb */
96 sts = SYS$CLI(&cmd, (void *)0, (void *)0); /* get actual command line */
97
98 if (vmswork(sts)) { /* ok => cli available & verb wasn't "RUN" */
99 /* invoked via symbol => have command line (which might be empty) */
100 /* [might also be invoked via mcr or dcl; that's ok] */
101 if (cmd.rqstat == CLI$K_VERB_MCR) {
102 /* need to strip image name from MCR invocation */
103 memset(fscn, 0, sizeof fscn);
104 fscn[0].code = FSCN$_FILESPEC; /* full file specification */
105 (void)SYS$FILESCAN(&cmd.rdesc, fscn, (long *)0);
106 cmd.rdesc.dsc$w_length -= fscn[0].len; /* shrink size */
107 cmd.rdesc.dsc$a_pointer += fscn[0].len; /* advance ptr */
108 }
109 /* prepend verb and then parse the command line */
110 strcat(strcpy(longbuf, cmd_verb), " "), ltmp = strlen(longbuf);
111 if (cmd.rdesc.dsc$w_length + ltmp > sizeof longbuf)
112 cmd.rdesc.dsc$w_length = sizeof longbuf - ltmp;
113 strncpy(&longbuf[ltmp],
114 cmd.rdesc.dsc$a_pointer, cmd.rdesc.dsc$w_length);
115 cmd.rdesc.dsc$w_length += ltmp, cmd.rdesc.dsc$a_pointer = longbuf;
116 sts = CLI$DCL_PARSE(&cmd.rdesc, cmd_tables);
117 }
118
119 return sts;
120 }