1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 *
24 ***************************************************************************/
25
26 /* CL interface program to curl cli tool. */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include <milib.h>
32 #include <miptrnam.h>
33 #include <mih/callpgmv.h>
34
35 #ifndef CURLPGM
36 #define CURLPGM "CURL"
37 #endif
38
39 /* Variable-length string, with 16-bit length. */
40 struct vary2 {
41 short len;
42 char string[5000];
43 };
44
45 /* Arguments from CL command. */
46 struct arguments {
47 char *pgm; /* Program name. */
48 struct vary2 *cmdargs; /* Command line arguments. */
49 };
50
51 static int
is_ifs(char c)52 is_ifs(char c)
53 {
54 return c == ' ' || c == '\t' || c == '\r' || c == '\n';
55 }
56
57 static int
parse_command_line(const char * cmdargs,size_t len,size_t * argc,char ** argv,size_t * argsize,char * argbuf)58 parse_command_line(const char *cmdargs, size_t len,
59 size_t *argc, char **argv,
60 size_t *argsize, char *argbuf)
61 {
62 const char *endline = cmdargs + len;
63 char quote = '\0';
64 int inarg = 0;
65
66 *argc = 0;
67 *argsize = 0;
68
69 while(cmdargs < endline) {
70 char c = *cmdargs++;
71
72 if(!inarg) {
73 /* Skip argument separator. */
74 if(is_ifs(c))
75 continue;
76
77 /* Start a new argument. */
78 ++*argc;
79 if(argv)
80 *argv++ = argbuf;
81 inarg = 1;
82 }
83
84 /* Check for quoting end. */
85 if(quote && quote == c) {
86 quote = '\0';
87 continue;
88 }
89
90 /* Check for backslash-escaping. */
91 if(quote != '\'' && c == '\\') {
92 if(cmdargs >= endline) {
93 fputs("Trailing backslash in command\n", stderr);
94 return -1;
95 }
96 c = *cmdargs++;
97 }
98 else if(!quote && is_ifs(c)) { /* Check for end of argument. */
99 inarg = 0;
100 c = '\0'; /* Will store a string terminator. */
101 }
102
103 /* Store argument character and count it. */
104 if(argbuf)
105 *argbuf++ = c;
106 ++*argsize;
107 }
108
109 if(quote) {
110 fprintf(stderr, "Unterminated quote: %c\n", quote);
111 return -1;
112 }
113
114 /* Terminate last argument. */
115 if(inarg) {
116 if(argbuf)
117 *argbuf = '\0';
118 ++*argsize;
119 }
120
121 /* Terminate argument list. */
122 if(argv)
123 *argv = NULL;
124
125 return 0;
126 }
127
128
129 int
main(int argsc,struct arguments * args)130 main(int argsc, struct arguments *args)
131 {
132 size_t argc;
133 char **argv;
134 size_t argsize;
135 int i;
136 int exitcode;
137 char library[11];
138
139 /* Extract current program library name. */
140 for(i = 0; i < 10; i++) {
141 char c = args->pgm[i];
142
143 if(!c || c == '/')
144 break;
145
146 library[i] = c;
147 }
148 library[i] = '\0';
149
150 /* Measure arguments size. */
151 exitcode = parse_command_line(args->cmdargs->string, args->cmdargs->len,
152 &argc, NULL, &argsize, NULL);
153
154 if(!exitcode) {
155 /* Allocate space for parsed arguments. */
156 argv = (char **) malloc((argc + 1) * sizeof(*argv) + argsize);
157 if(!argv) {
158 fputs("Memory allocation error\n", stderr);
159 exitcode = -2;
160 }
161 else {
162 _SYSPTR pgmptr = rslvsp(WLI_PGM, (char *) CURLPGM, library, _AUTH_NONE);
163 _LU_Work_Area_T *luwrka = (_LU_Work_Area_T *) _LUWRKA();
164
165 parse_command_line(args->cmdargs->string, args->cmdargs->len,
166 &argc, argv, &argsize, (char *) (argv + argc + 1));
167
168 /* Call program. */
169 _CALLPGMV((void *) &pgmptr, argv, argc);
170 exitcode = luwrka->LU_RC;
171
172 free(argv);
173 }
174 }
175
176 return exitcode;
177 }
178