113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci *
2413498266Sopenharmony_ci ***************************************************************************/
2513498266Sopenharmony_ci
2613498266Sopenharmony_ci/* CL interface program to curl cli tool. */
2713498266Sopenharmony_ci
2813498266Sopenharmony_ci#include <stdio.h>
2913498266Sopenharmony_ci#include <stdlib.h>
3013498266Sopenharmony_ci
3113498266Sopenharmony_ci#include <milib.h>
3213498266Sopenharmony_ci#include <miptrnam.h>
3313498266Sopenharmony_ci#include <mih/callpgmv.h>
3413498266Sopenharmony_ci
3513498266Sopenharmony_ci#ifndef CURLPGM
3613498266Sopenharmony_ci#define CURLPGM "CURL"
3713498266Sopenharmony_ci#endif
3813498266Sopenharmony_ci
3913498266Sopenharmony_ci/* Variable-length string, with 16-bit length. */
4013498266Sopenharmony_cistruct vary2 {
4113498266Sopenharmony_ci  short len;
4213498266Sopenharmony_ci  char  string[5000];
4313498266Sopenharmony_ci};
4413498266Sopenharmony_ci
4513498266Sopenharmony_ci/* Arguments from CL command. */
4613498266Sopenharmony_cistruct arguments {
4713498266Sopenharmony_ci  char         *pgm;            /* Program name. */
4813498266Sopenharmony_ci  struct vary2 *cmdargs;        /* Command line arguments. */
4913498266Sopenharmony_ci};
5013498266Sopenharmony_ci
5113498266Sopenharmony_cistatic int
5213498266Sopenharmony_ciis_ifs(char c)
5313498266Sopenharmony_ci{
5413498266Sopenharmony_ci  return c == ' ' || c == '\t' || c == '\r' || c == '\n';
5513498266Sopenharmony_ci}
5613498266Sopenharmony_ci
5713498266Sopenharmony_cistatic int
5813498266Sopenharmony_ciparse_command_line(const char *cmdargs, size_t len,
5913498266Sopenharmony_ci                   size_t *argc, char **argv,
6013498266Sopenharmony_ci                   size_t *argsize, char *argbuf)
6113498266Sopenharmony_ci{
6213498266Sopenharmony_ci  const char *endline = cmdargs + len;
6313498266Sopenharmony_ci  char quote = '\0';
6413498266Sopenharmony_ci  int inarg = 0;
6513498266Sopenharmony_ci
6613498266Sopenharmony_ci  *argc = 0;
6713498266Sopenharmony_ci  *argsize = 0;
6813498266Sopenharmony_ci
6913498266Sopenharmony_ci  while(cmdargs < endline) {
7013498266Sopenharmony_ci    char c = *cmdargs++;
7113498266Sopenharmony_ci
7213498266Sopenharmony_ci    if(!inarg) {
7313498266Sopenharmony_ci      /* Skip argument separator. */
7413498266Sopenharmony_ci      if(is_ifs(c))
7513498266Sopenharmony_ci        continue;
7613498266Sopenharmony_ci
7713498266Sopenharmony_ci      /* Start a new argument. */
7813498266Sopenharmony_ci      ++*argc;
7913498266Sopenharmony_ci      if(argv)
8013498266Sopenharmony_ci        *argv++ = argbuf;
8113498266Sopenharmony_ci      inarg = 1;
8213498266Sopenharmony_ci    }
8313498266Sopenharmony_ci
8413498266Sopenharmony_ci    /* Check for quoting end. */
8513498266Sopenharmony_ci    if(quote && quote == c) {
8613498266Sopenharmony_ci      quote = '\0';
8713498266Sopenharmony_ci      continue;
8813498266Sopenharmony_ci    }
8913498266Sopenharmony_ci
9013498266Sopenharmony_ci    /* Check for backslash-escaping. */
9113498266Sopenharmony_ci    if(quote != '\'' && c == '\\') {
9213498266Sopenharmony_ci      if(cmdargs >= endline) {
9313498266Sopenharmony_ci        fputs("Trailing backslash in command\n", stderr);
9413498266Sopenharmony_ci        return -1;
9513498266Sopenharmony_ci      }
9613498266Sopenharmony_ci      c = *cmdargs++;
9713498266Sopenharmony_ci    }
9813498266Sopenharmony_ci    else if(!quote && is_ifs(c)) {      /* Check for end of argument. */
9913498266Sopenharmony_ci      inarg = 0;
10013498266Sopenharmony_ci      c = '\0';         /* Will store a string terminator. */
10113498266Sopenharmony_ci    }
10213498266Sopenharmony_ci
10313498266Sopenharmony_ci    /* Store argument character and count it. */
10413498266Sopenharmony_ci    if(argbuf)
10513498266Sopenharmony_ci      *argbuf++ = c;
10613498266Sopenharmony_ci    ++*argsize;
10713498266Sopenharmony_ci  }
10813498266Sopenharmony_ci
10913498266Sopenharmony_ci  if(quote) {
11013498266Sopenharmony_ci    fprintf(stderr, "Unterminated quote: %c\n", quote);
11113498266Sopenharmony_ci    return -1;
11213498266Sopenharmony_ci  }
11313498266Sopenharmony_ci
11413498266Sopenharmony_ci  /* Terminate last argument. */
11513498266Sopenharmony_ci  if(inarg) {
11613498266Sopenharmony_ci    if(argbuf)
11713498266Sopenharmony_ci      *argbuf = '\0';
11813498266Sopenharmony_ci    ++*argsize;
11913498266Sopenharmony_ci  }
12013498266Sopenharmony_ci
12113498266Sopenharmony_ci  /* Terminate argument list. */
12213498266Sopenharmony_ci  if(argv)
12313498266Sopenharmony_ci    *argv = NULL;
12413498266Sopenharmony_ci
12513498266Sopenharmony_ci  return 0;
12613498266Sopenharmony_ci}
12713498266Sopenharmony_ci
12813498266Sopenharmony_ci
12913498266Sopenharmony_ciint
13013498266Sopenharmony_cimain(int argsc, struct arguments *args)
13113498266Sopenharmony_ci{
13213498266Sopenharmony_ci  size_t argc;
13313498266Sopenharmony_ci  char **argv;
13413498266Sopenharmony_ci  size_t argsize;
13513498266Sopenharmony_ci  int i;
13613498266Sopenharmony_ci  int exitcode;
13713498266Sopenharmony_ci  char library[11];
13813498266Sopenharmony_ci
13913498266Sopenharmony_ci  /* Extract current program library name. */
14013498266Sopenharmony_ci  for(i = 0; i < 10; i++) {
14113498266Sopenharmony_ci    char c = args->pgm[i];
14213498266Sopenharmony_ci
14313498266Sopenharmony_ci    if(!c || c == '/')
14413498266Sopenharmony_ci      break;
14513498266Sopenharmony_ci
14613498266Sopenharmony_ci    library[i] = c;
14713498266Sopenharmony_ci  }
14813498266Sopenharmony_ci  library[i] = '\0';
14913498266Sopenharmony_ci
15013498266Sopenharmony_ci  /* Measure arguments size. */
15113498266Sopenharmony_ci  exitcode = parse_command_line(args->cmdargs->string, args->cmdargs->len,
15213498266Sopenharmony_ci                                &argc, NULL, &argsize, NULL);
15313498266Sopenharmony_ci
15413498266Sopenharmony_ci  if(!exitcode) {
15513498266Sopenharmony_ci    /* Allocate space for parsed arguments. */
15613498266Sopenharmony_ci    argv = (char **) malloc((argc + 1) * sizeof(*argv) + argsize);
15713498266Sopenharmony_ci    if(!argv) {
15813498266Sopenharmony_ci      fputs("Memory allocation error\n", stderr);
15913498266Sopenharmony_ci      exitcode = -2;
16013498266Sopenharmony_ci    }
16113498266Sopenharmony_ci    else {
16213498266Sopenharmony_ci      _SYSPTR pgmptr = rslvsp(WLI_PGM, (char *) CURLPGM, library, _AUTH_NONE);
16313498266Sopenharmony_ci      _LU_Work_Area_T *luwrka = (_LU_Work_Area_T *) _LUWRKA();
16413498266Sopenharmony_ci
16513498266Sopenharmony_ci      parse_command_line(args->cmdargs->string, args->cmdargs->len,
16613498266Sopenharmony_ci                         &argc, argv, &argsize, (char *) (argv + argc + 1));
16713498266Sopenharmony_ci
16813498266Sopenharmony_ci      /* Call program. */
16913498266Sopenharmony_ci      _CALLPGMV((void *) &pgmptr, argv, argc);
17013498266Sopenharmony_ci      exitcode = luwrka->LU_RC;
17113498266Sopenharmony_ci
17213498266Sopenharmony_ci      free(argv);
17313498266Sopenharmony_ci    }
17413498266Sopenharmony_ci  }
17513498266Sopenharmony_ci
17613498266Sopenharmony_ci  return exitcode;
17713498266Sopenharmony_ci}
178