Нарезка командной строки
От: Аноним  
Дата: 23.08.05 11:42
Оценка:
Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников.

Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре.

Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке.

Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.
Re: Нарезка командной строки
От: aka50 Россия  
Дата: 23.08.05 11:47
Оценка:
Здравствуйте, Аноним, Вы писали:

<skip>

А>Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.


Не указан язык, но я так пронимаю С.
Не знаю поможет или нет .
Я этим очень давно под С пользовался. Понимает кавычки разные, можно указать чем разбито и т.д.
Ну и собственно никакой отвественности не несу .

 
/* Splits line into parts.*/
int
splitline(char *line,char **args,int maxargs,char *delim)
{
 int argcnt = 0;

 char c,s;
 char *d;
 char q = 0;
 
 int qs = 0;

 if (line == NULL || delim == NULL)
  return argcnt;

 for (d = delim; (s = *d++) != 0; ) {
  if (s == '\'' || s == '\"') {
   qs++;
   break;
  }
 }

 /* skip leading delimiters */
cont:
 c = *line++;
 if (c == 0) 
  goto done;

 for (d = delim; (s = *d++) != 0; ){
  /* here we found string in quotes */
  if (qs && (c == '\'' || c == '\"')) {
   q = c;
   c = *line++;
   break;
  }

  if (c == s) 
   goto cont;  /* if ok, try to find next delimiter */
 }

 if (c == 0)
  goto done;

 args[argcnt++] = line-1;
 if (argcnt == maxargs)
  goto done;

 for(;;) {
  c = *line++;
  if (c == 0)
   goto done;

  if (q && c!= q)
   continue; /* check for quote */

  if (q)
   q = 0; /* if we passed throught quote zero it */

  for (d = delim; (s = *d++)!= 0; ) {
   if (c == s) {
    char *w = line - 1;
    *w = '\0';
    goto cont;
   }
  }
 }

 if (q)
  argcnt = 0;

done:
 return argcnt;
}
Re[2]: Нарезка командной строки
От: Аноним  
Дата: 23.08.05 12:00
Оценка:
Спасибо, но так я и сам умею. Именно этого и хотелось избежать.
Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки, входящий в большинство UNIX-реализаций.
Программа должна работать под 6 различными UNIX-платформами и под виндами (в данном случае винды не рассматриваем).

P.S. Прошу прощения, что сразу не указал, язык программирования C++.
Re[3]: Нарезка командной строки
От: Gleb Alexeev  
Дата: 23.08.05 12:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Спасибо, но так я и сам умею. Именно этого и хотелось избежать.

А>Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки, входящий в большинство UNIX-реализаций.
А>Программа должна работать под 6 различными UNIX-платформами и под виндами (в данном случае винды не рассматриваем).

А>P.S. Прошу прощения, что сразу не указал, язык программирования C++.

Прошу прощения, что лезу в чужой монастырь (Юниксов в глаза не видал), но Boost.Program_options -- возможно то, что вам надо.
Re[3]: Нарезка командной строки
От: aka50 Россия  
Дата: 23.08.05 12:46
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Спасибо, но так я и сам умею. Именно этого и хотелось избежать.

А>Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки,

входящий в большинство UNIX-реализаций.

Такой думаю нет. Сам С++ вообще-то не очень стандартен для юниксов .
Хотя если интересует просто распространенная библиотека которую _можно_
поставить на любой юникс, то думаю стоит посмотреть на ACE. Ибо я
думаю вам еще много чего может понадобится .

А>P.S. Прошу прощения, что сразу не указал, язык программирования C++.

Во. АСЕ как раз С++ .
Re[4]: Нарезка командной строки
От: Аноним  
Дата: 23.08.05 12:57
Оценка:
Да, я смотрел Boost.Program_Options.
Там есть parse_command_line, parse_config_file и parse_evironment.
Первый парсер сам принимает аргументами argc и argv, а последние два по смыслу не подходят.
Возможно я там что-то недосмотрел, поэтому буду благодарен, если меня ткнут носом.

P.S. Срочность задачи (как обычно ) заставила меня создать эту ветку до того момента, как мне пришло письмо c данными для активации акаунта на этом форуме. Теперь я активировался. Мой позывной — аэропанк
Re[4]: Нарезка командной строки
От: aeropunk  
Дата: 23.08.05 13:01
Оценка:
К сожалению, я не знаком с ACE, буду благодарен за ссылочку
Re[4]: Нарезка командной строки
От: aeropunk  
Дата: 23.08.05 13:17
Оценка:
Здравствуйте, aka50, Вы писали:

A>Такой думаю нет.


Есть масса различных командных оболочек, многие из них существуют уже очень давно, все они как-то решают вставшую передо мной задачу. Синтаксис многих командных оболочек весьма похож, если не идентичен.
Это размышление и натолкнуло меня на мысль, что должна существовать какая-то стандартная для POSIX библиотека, решающая эту задачу.
Re: Нарезка командной строки
От: MaximE Великобритания  
Дата: 23.08.05 13:18
Оценка:
wrote:

> Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников.

>
> Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре.

А нельзя ли переписать кофигурационный файл так, чтобы каждый аргумент был на отдельной строке? Тогда его и парсить не нужно.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[5]: Нарезка командной строки
От: aka50 Россия  
Дата: 23.08.05 13:21
Оценка:
Здравствуйте, aeropunk, Вы писали:

A>К сожалению, я не знаком с ACE, буду благодарен за ссылочку

http://www.cs.wustl.edu/~schmidt/ACE.html

А вообще пришло мне тут в голову... а почему бы yacc/lex не воспользоваться?
Есть везде... да и либ особых не тянет. Проверено временем .
Re[5]: Нарезка командной строки
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.05 13:27
Оценка:
Здравствуйте, aeropunk, Вы писали:

A>К сожалению, я не знаком с ACE, буду благодарен за ссылочку


Сама библиотека: здесь

А вот то, что тебе нужно, имхо: ACE_ARGV:

Builds a counted argument vector (ala argc/argv) from either a string or a set of separate tokens. Can substitute environment variable values for tokens that are environment variable references.

... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Нарезка командной строки
От: MaximE Великобритания  
Дата: 23.08.05 13:27
Оценка: 1 (1) +1
wrote:

> Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников.

>
> Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре.
>
> Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке.
>
> Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.

/* Execute LINE as a shell command, returning its status.  */
static int
do_system (const char *line)
{
...
#ifdef FORK
   pid = FORK ();
#else
   pid = __fork ();
#endif
   if (pid == (pid_t) 0)
     {
       /* Child side.  */
       const char *new_argv[4];
       new_argv[0] = SHELL_NAME;
       new_argv[1] = "-c";
       new_argv[2] = line;
       new_argv[3] = NULL;

       /* Restore the signals.  */
       (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
       (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
       (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
       INIT_LOCK ();

       /* Exec the shell.  */
       (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
       _exit (127);
     }
...


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[2]: Нарезка командной строки
От: aeropunk  
Дата: 23.08.05 13:30
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>wrote:



ME>А нельзя ли переписать кофигурационный файл так, чтобы каждый аргумент был на отдельной строке? Тогда его и парсить не нужно.


ME>--

ME>Maxim Yegorushkin

Вообще можно, но по нескольким причинам не стоит это делать.
1. Заказчик уже приучен к данному формату конфигурационного файла, и он будет недоволен его изменением.
2. По причине 1 нужно веское обоснование изменению формата конфигурационного файла. Привести объяснение вроде "мы не умеем" — означает признаться в своем непрофессионализме.
3. Просто интересно (самому или в вашей помощью) найти красивое решение этой задачи.
Re[2]: Нарезка командной строки
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.05 13:33
Оценка:
Здравствуйте, MaximE, Вы писали:

<...код поскипан...>

Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Нарезка командной строки
От: MaximE Великобритания  
Дата: 23.08.05 13:35
Оценка:
eao197 wrote:

> Здравствуйте, MaximE, Вы писали:

>
> <...код поскипан...>
>
> Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.

Забыл подписать — код выдран их glibc-2.3.5

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[6]: Нарезка командной строки
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.05 13:40
Оценка: +1
Здравствуйте, aka50, Вы писали:

A>>К сожалению, я не знаком с ACE, буду благодарен за ссылочку

A>http://www.cs.wustl.edu/~schmidt/ACE.html

A>А вообще пришло мне тут в голову... а почему бы yacc/lex не воспользоваться?

A>Есть везде... да и либ особых не тянет. Проверено временем .

А готовая грамматика для yacc/lex для парсинга аргументов командной строки откуда возмется?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Нарезка командной строки
От: MaximE Великобритания  
Дата: 23.08.05 13:43
Оценка:
eao197 wrote:

> Здравствуйте, MaximE, Вы писали:

>
> <...код поскипан...>
>
> Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.

У них там есть spawn — похоже на fork() + exec(). http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_process_and_environment_control.asp

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[2]: Нарезка командной строки
От: aeropunk  
Дата: 23.08.05 13:43
Оценка:
Спасибо! Да, использование default shell — это лучший из имеющихся у меня вариантов.
Но еще красивее было бы решить задачу без его использования.
М.б. все-таки есть библиотека?
Re[3]: Нарезка командной строки
От: aeropunk  
Дата: 23.08.05 13:50
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, MaximE, Вы писали:


E><...код поскипан...>


E>Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.


На Wiondows можно не отвлекаться.

Там в отдельной обвязке:
#ifdef WIN32
...
#endif
идет вызов CreateProcess, который как раз принимает все аргументы одной строкой.
Re[4]: Нарезка командной строки
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.05 14:02
Оценка: +1
Здравствуйте, MaximE, Вы писали:

>> <...код поскипан...>

>>
>> Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.

ME>У них там есть spawn — похоже на fork() + exec(). http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_process_and_environment_control.asp


Что-то я запутался в трех соснах. В исходном сообщении:

Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке.


Т.е., раз exec, значит нужно запустить новый процесс вместо старого. Тогда вообще ничего мудрить не нужно -- через exec зовем shell и скармливаем ему всю строку параметров, без fork-а.

Или же не вся задача была озвучена.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.