/***************************************************************************1* _ _ ____ _2* Project ___| | | | _ \| |3* / __| | | | |_) | |4* | (__| |_| | _ <| |___5* \___|\___/|_| \_\_____|6*7* Copyright (C) Daniel Stenberg, <[email protected]>, et al.8*9* This software is licensed as described in the file COPYING, which10* you should have received as part of this distribution. The terms11* are also available at https://curl.se/docs/copyright.html.12*13* You may opt to use, copy, modify, merge, publish, distribute and/or sell14* copies of the Software, and permit persons to whom the Software is15* furnished to do so, under the terms of the COPYING file.16*17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY18* KIND, either express or implied.19*20* SPDX-License-Identifier: curl21*22*23***************************************************************************/2425/* CL interface program to curl cli tool. */2627#include <stdio.h>28#include <stdlib.h>2930#include <milib.h>31#include <miptrnam.h>32#include <mih/callpgmv.h>3334#ifndef CURLPGM35#define CURLPGM "CURL"36#endif3738/* Variable-length string, with 16-bit length. */39struct vary2 {40short len;41char string[5000];42};4344/* Arguments from CL command. */45struct arguments {46char *pgm; /* Program name. */47struct vary2 *cmdargs; /* Command line arguments. */48};4950static int51is_ifs(char c)52{53return c == ' ' || c == '\t' || c == '\r' || c == '\n';54}5556static int57parse_command_line(const char *cmdargs, size_t len,58size_t *argc, char **argv,59size_t *argsize, char *argbuf)60{61const char *endline = cmdargs + len;62char quote = '\0';63int inarg = 0;6465*argc = 0;66*argsize = 0;6768while(cmdargs < endline) {69char c = *cmdargs++;7071if(!inarg) {72/* Skip argument separator. */73if(is_ifs(c))74continue;7576/* Start a new argument. */77++*argc;78if(argv)79*argv++ = argbuf;80inarg = 1;81}8283/* Check for quoting end. */84if(quote && quote == c) {85quote = '\0';86continue;87}8889/* Check for backslash-escaping. */90if(quote != '\'' && c == '\\') {91if(cmdargs >= endline) {92fputs("Trailing backslash in command\n", stderr);93return -1;94}95c = *cmdargs++;96}97else if(!quote && is_ifs(c)) { /* Check for end of argument. */98inarg = 0;99c = '\0'; /* Will store a string terminator. */100}101102/* Store argument character and count it. */103if(argbuf)104*argbuf++ = c;105++*argsize;106}107108if(quote) {109fprintf(stderr, "Unterminated quote: %c\n", quote);110return -1;111}112113/* Terminate last argument. */114if(inarg) {115if(argbuf)116*argbuf = '\0';117++*argsize;118}119120/* Terminate argument list. */121if(argv)122*argv = NULL;123124return 0;125}126127128int129main(int argsc, struct arguments *args)130{131size_t argc;132char **argv;133size_t argsize;134int i;135int exitcode;136char library[11];137138/* Extract current program library name. */139for(i = 0; i < 10; i++) {140char c = args->pgm[i];141142if(!c || c == '/')143break;144145library[i] = c;146}147library[i] = '\0';148149/* Measure arguments size. */150exitcode = parse_command_line(args->cmdargs->string, args->cmdargs->len,151&argc, NULL, &argsize, NULL);152153if(!exitcode) {154/* Allocate space for parsed arguments. */155argv = (char **) malloc((argc + 1) * sizeof(*argv) + argsize);156if(!argv) {157fputs("Memory allocation error\n", stderr);158exitcode = -2;159}160else {161_SYSPTR pgmptr = rslvsp(WLI_PGM, (char *) CURLPGM, library, _AUTH_NONE);162_LU_Work_Area_T *luwrka = (_LU_Work_Area_T *) _LUWRKA();163164parse_command_line(args->cmdargs->string, args->cmdargs->len,165&argc, argv, &argsize, (char *) (argv + argc + 1));166167/* Call program. */168_CALLPGMV((void *) &pgmptr, argv, argc);169exitcode = luwrka->LU_RC;170171free(argv);172}173}174175return exitcode;176}177178179