blob: 02edcd63c0c12361b80e2b97804bdd5ae55d5d66 [file] [log] [blame]
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
*
***************************************************************************/
/* CL interface program to curl cli tool. */
#include <stdio.h>
#include <stdlib.h>
#include <milib.h>
#include <miptrnam.h>
#include <mih/callpgmv.h>
#ifndef CURLPGM
#define CURLPGM "CURL"
#endif
/* Variable-length string, with 16-bit length. */
struct vary2 {
short len;
char string[5000];
};
/* Arguments from CL command. */
struct arguments {
char *pgm; /* Program name. */
struct vary2 *cmdargs; /* Command line arguments. */
};
static int
is_ifs(char c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
static int
parse_command_line(const char *cmdargs, size_t len,
size_t *argc, char **argv,
size_t *argsize, char *argbuf)
{
const char *endline = cmdargs + len;
char quote = '\0';
int inarg = 0;
*argc = 0;
*argsize = 0;
while(cmdargs < endline) {
char c = *cmdargs++;
if(!inarg) {
/* Skip argument separator. */
if(is_ifs(c))
continue;
/* Start a new argument. */
++*argc;
if(argv)
*argv++ = argbuf;
inarg = 1;
}
/* Check for quoting end. */
if(quote && quote == c) {
quote = '\0';
continue;
}
/* Check for backslash-escaping. */
if(quote != '\'' && c == '\\') {
if(cmdargs >= endline) {
fputs("Trailing backslash in command\n", stderr);
return -1;
}
c = *cmdargs++;
}
else if(!quote && is_ifs(c)) { /* Check for end of argument. */
inarg = 0;
c = '\0'; /* Will store a string terminator. */
}
/* Store argument character and count it. */
if(argbuf)
*argbuf++ = c;
++*argsize;
}
if(quote) {
fprintf(stderr, "Unterminated quote: %c\n", quote);
return -1;
}
/* Terminate last argument. */
if(inarg) {
if(argbuf)
*argbuf = '\0';
++*argsize;
}
/* Terminate argument list. */
if(argv)
*argv = NULL;
return 0;
}
int
main(int argsc, struct arguments *args)
{
size_t argc;
char **argv;
size_t argsize;
int i;
int exitcode;
char library[11];
/* Extract current program library name. */
for(i = 0; i < 10; i++) {
char c = args->pgm[i];
if(!c || c == '/')
break;
library[i] = c;
}
library[i] = '\0';
/* Measure arguments size. */
exitcode = parse_command_line(args->cmdargs->string, args->cmdargs->len,
&argc, NULL, &argsize, NULL);
if(!exitcode) {
/* Allocate space for parsed arguments. */
argv = (char **) malloc((argc + 1) * sizeof(*argv) + argsize);
if(!argv) {
fputs("Memory allocation error\n", stderr);
exitcode = -2;
}
else {
_SYSPTR pgmptr = rslvsp(WLI_PGM, (char *) CURLPGM, library, _AUTH_NONE);
_LU_Work_Area_T *luwrka = (_LU_Work_Area_T *) _LUWRKA();
parse_command_line(args->cmdargs->string, args->cmdargs->len,
&argc, argv, &argsize, (char *) (argv + argc + 1));
/* Call program. */
_CALLPGMV((void *) &pgmptr, argv, argc);
exitcode = luwrka->LU_RC;
free(argv);
}
}
return exitcode;
}