Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
2 / 2 / 1
Регистрация: 21.11.2015
Сообщений: 26

Передача данных дочернему процессу посредством pipe(): иммитация нажатия enter через терминал

26.01.2019, 18:10. Показов 2597. Ответов 7

Студворк — интернет-сервис помощи студентам
Всем привет. Столкнулся с такой проблемой: есть программа, считывающая логин и пароль (последовательно, сначала логин, после ввода запрос на пароль, и собственно пароль). Я написал программу, которая вызывает первую прогу и посредством дескрипторов от pipe() редиректит инпут первой программы так, чтобы у меня был дескриптор этого инпута. Вот в коде это выглядит как-то так:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main(void)
{
    int pipes[2];
    pipe(pipes);
    pid_t pid = fork();
    if (!pid)
    {
        close(pipes[1]); // закрываем дескриптор на запись
        dup2(pipes[0], 0); // копируем дескриптор на чтение и заменяем стандартный дескриптор инпута
        execl(...);
    }
    else if (pid > 0)
    {
        close(pipes[0]);
        ...
        write(pipes[1], "username\n", 9);
        write(pipes[1], "password\n", 9);
    }
    else
    { ... }
    return 0;
}
Проблема в том, что как "username\n" так и "password\n" считываются в поле логина, а до пароля так и не доходит. Предположительно в вызываемой программе считка идет подобным образом:

C
1
2
3
4
read(0, buff_login. 1024);
...
read(0, buff_password, 1024);
...
Если запускать вызываемую программу из терминала, то считка ведет себя правильно: при нажатии на энтер первый read() возвращает управление программой и записывает в буфер все что ввел пользователь. Когда же ввод идет из родительской программы '\n' такого эффекта не имеет, и первый read() продолжает считку и считывает разом и пароль. Ну, и собственно логику программы реализовать не удается.

Как можно заставить read в дочернем процессе прекратить считывать и вернуть только тот кусок что уже записан в дескриптор?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.01.2019, 18:10
Ответы с готовыми решениями:

Передача строки от родителя к дочернему процессу блоками через пайп
Имеется строка из 100 символов.Как правильно поставить цикл,чтобы родитель передавал её в трубу по 5 байт? в конечном итоге он должен будет...

Передача данных другому процессу через именованные каналы
Вся группа не может решить задание от нашего зав. кафедры, необходима ваша помощь! Само задание: Написать программу, передающую...

Передача данных через терминал по порту
Всем привет!Появился такой вопрос.Допустим я поставил через netcat программу которая записывает введеные данные в текстовый файл file.txt. ...

7
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
26.01.2019, 19:04
rostl, а можете показать выхлопы ltrace и strace для программы которую мучает ваша обертка?
0
2 / 2 / 1
Регистрация: 21.11.2015
Сообщений: 26
26.01.2019, 19:16  [ТС]
Цитата Сообщение от prik Посмотреть сообщение
rostl, а можете показать выхлопы ltrace и strace для программы которую мучает ваша обертка?
Да,к слову это openvpn с опенсорсом, но я не смог добиться результата когда искал как реализована считка.

strace (приблизительное место где идет считка данных):

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2097, ...}) = 0 
write(1, "Sat Jan 26 18:07:52 2019 library"..., 80Sat Jan 26 18:07:52 2019 library versions: OpenSSL 1.1.0g  2 Nov 2017, LZO 2.08
) = 80
newfstatat(AT_FDCWD, "/run/systemd/system/", {st_mode=S_IFDIR|0755, st_size=40, ...}, AT_SYMLINK_NOFOLLOW) = 0
stat("/bin/systemd-ask-password", {st_mode=S_IFREG|0755, st_size=10320, ...}) = 0
pipe([3, 4])                            = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fdd7ffcbed0) = 20957
close(4)                                = 0
wait4(20957, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 20957
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20957, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
read(3, "login\n", 4095)                = 6
close(3)                                = 0
pipe([3, 4])                            = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fdd7ffcbed0) = 20958
close(4)                                = 0
wait4(20958, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 20958
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20958, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
read(3, "password\n", 4095)             = 9
close(3)                                = 0
getpid()                                = 20956
futex(0x7fdd7f54a82c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
getpid()                                = 20956
futex(0x7fdd7f54a394, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7fdd7f54a230, FUTEX_WAKE_PRIVATE, 2147483647) = 0 
getpid()                                = 20956
openat(AT_FDCWD, "/dev/urandom", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 3
...

ltrace (приблизительное место где идет считка данных):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
malloc(16)                                       = 0x55b64993e1a0
memset(0x55b64993e1a8, '\0', 8)                  = 0x55b64993e1a8
pipe(0x7ffec01e13f0)                             = 0
fork()                                           = 21085
close(4)                                         = 0
waitpid(21085, 0x7ffec01e13dc, 0 <no return ...>
--- SIGCHLD (Child exited) ---
<... waitpid resumed> )                          = 21085
free(0x55b64993e1a0)                             = <void>
memset(0x55b647ab02e4, '\0', 4096)               = 0x55b647ab02e4
read(3, "login\n", 4095)                         = 6
strlen("login\n")                                = 6
strchr("\r\n", '\n')                             = "\n"
strlen("login")                                  = 5
strchr("\r\n", 'n')                              = nil
close(3)                                         = 0
free(0x55b64993e100)                             = <void>
free(0x55b64993e0e0)                             = <void>
free(0x55b64993e130)                             = <void>
free(0x55b64993e180)                             = <void>
free(0x55b64993e1c0)                             = <void>
free(0x55b64993dee0)                             = <void>
free(0)                                          = <void>
malloc(8)                                        = 0x55b64993e1c0
memset(0x55b64993e1c0, '\0', 8)                  = 0x55b64993e1c0
free(0)                                          = <void>
__ctype_b_loc()                                  = 0x7f7f30c07b10
malloc(26)                                       = 0x55b64993e100
memcpy(0x55b64993e100, "/bin/systemd-ask-password", 25) = 0x55b64993e100
malloc(16)                                       = 0x55b64993e180
memset(0x55b64993e180, '\0', 16)                 = 0x55b64993e180
free(0x55b64993e1c0)                             = <void>
__ctype_b_loc()                                  = 0x7f7f30c07b10
malloc(7)                                        = 0x55b64993e1c0
memcpy(0x55b64993e1c0, "--icon", 6)              = 0x55b64993e1c0
malloc(32)                                       = 0x55b64993e150
memset(0x55b64993e150, '\0', 32)                 = 0x55b64993e150
free(0x55b64993e180)                             = <void>
__ctype_b_loc()                                  = 0x7f7f30c07b10
malloc(12)                                       = 0x55b64993e180
memcpy(0x55b64993e180, "network-vpn", 11)        = 0x55b64993e180
__ctype_b_loc()                                  = 0x7f7f30c07b10
malloc(3)                                        = 0x55b64993e130
memcpy(0x55b64993e130, "%s", 2)                  = 0x55b64993e130
strlen("Enter Auth Password:")                   = 20
calloc(1, 21)                                    = 0x55b64993e1e0
memcpy(0x55b64993e1e0, "Enter Auth Password:\0", 21) = 0x55b64993e1e0
malloc(64)                                       = 0x55b64993dee0
memset(0x55b64993dee0, '\0', 64)                 = 0x55b64993dee0
free(0x55b64993e150)                             = <void>
free(0x55b64993e130)                             = <void>
malloc(16)                                       = 0x55b64993e130
memset(0x55b64993e138, '\0', 8)                  = 0x55b64993e138
pipe(0x7ffec01e13f0)                             = 0
fork()                                           = 21086
close(4)                                         = 0
waitpid(21086, 0x7ffec01e13dc, 0 <no return ...> 
--- SIGCHLD (Child exited) ---
<... waitpid resumed> )                          = 21086
free(0x55b64993e130)                             = <void>
memset(0x55b647ab12e4, '\0', 4096)               = 0x55b647ab12e4
read(3, "password\n", 4095)                      = 9
strlen("password\n")                             = 9
strchr("\r\n", '\n')                             = "\n"
strlen("password")                               = 8
strchr("\r\n", 'd')                              = nil
close(3)                                         = 0
free(0x55b64993e100)                             = <void>
free(0x55b64993e1c0)                             = <void>
free(0x55b64993e180)                             = <void>
free(0x55b64993e1e0)                             = <void>
free(0x55b64993dee0)                             = <void>
free(0x55b64993e050)                             = <void>
free(0x55b649912380)                             = <void>
sd_notify(0, 0x55b64787a5a2, 0x55b649912010, 0)  = 0
memset(0x55b6499321f8, '\0', 8368)               = 0x55b6499321f8
free(0)                                          = <void>
memset(0x55b649930150, '\0', 8360)               = 0x55b649930150
free(0x55b64993de60)                             = <void>
free(0x55b64993e010)                             = <void>
free(0x55b6499342d0)                             = <void>
free(0x55b6499342b0)                             = <void>
free(0x55b649936880)                             = <void>
free(0x55b649936860)                             = <void>
free(0x55b649938e30)                             = <void>
free(0x55b649938e10)                             = <void>
free(0x55b649930080)                             = <void>
strlen("config")                                 = 6
strlen("config")                                 = 6
malloc(15)                                       = 0x55b6499342b0
memcpy(0x55b6499342b8, "config\0", 7)            = 0x55b6499342b8
...
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
26.01.2019, 19:28
Цитата Сообщение от rostl Посмотреть сообщение
Да,к слову это openvpn с опенсорсом,
Так судя по выхлопу, ковыряться надо не с openvpn, а с systemd-ask-password
0
2 / 2 / 1
Регистрация: 21.11.2015
Сообщений: 26
26.01.2019, 19:39  [ТС]
Цитата Сообщение от prik Посмотреть сообщение
Так судя по выхлопу, ковыряться надо не с openvpn, а с systemd-ask-password
Ну, насколько я понимаю, тут не суть что именно просит пароль и логин. Если я напишу банальную программу которая требует логин и пароль таким вот образом:
C
1
2
3
4
read(0, buff_login. 1024);
...
read(0, buff_password, 1024);
...
то я и ей не смогу нормально передать логин и пароль. А судя по трейсам там так и происходит считка, только буфер 4096.
Тут вопрос в том как так работает read() что после нажатия enter-а в терминале он возвращает управление программы считав меньшее кол-во байт, ну и нужно повторить это поведение при вводе с родительской программы.
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
26.01.2019, 19:53
Лучший ответ Сообщение было отмечено rostl как решение

Решение

просто воткните sleep(1) между вашими write()
1
2 / 2 / 1
Регистрация: 21.11.2015
Сообщений: 26
26.01.2019, 20:04  [ТС]
Цитата Сообщение от prik Посмотреть сообщение
просто воткните sleep(1) между вашими write()
И вправду! Спасибо большое!! Конечно я всё равно не понимаю как это работает и почему так, не хватает теории. Серьезной литературы по юниксу еще не читал. Может посоветуете что-то? В планах есть UNIX. Профессиональное программирование. Надеюсь там об этом поведении подробно будет описано.
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
26.01.2019, 20:16
про поведение read() при чтении из пайпа можно почитать тут http://pubs.opengroup.org/onli... /read.html
Я просто предполагал, что программа которую вы оборачиваете хочет именно терминал.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.01.2019, 20:16
Помогаю со студенческими работами здесь

управление через терминал устройствами посредством PB
Всем привет. Есть устройство, c выводами RX TX (обычный GPS модуль, который без конца в порт данные шлет), возможно ли его подключить...

Как передать CredHandle дочернему процессу?
Добрый день. Пишу Web-сервер вроде IIS. Реализовал расширения cgi и isapi. По http все великолепно работает. Но с https какие-то...

Как дочернему процессу вернуть значение в родительский?
Подскажите, как дочернему процессу вернуть значение в родительский?

Передача сообщений через pipe
Прошу помочь с реализацией курсового проекта. Я очень плохо шарю в c++, поэтому ничего не могу понять( Нужно через pipe реализовать...

Как подменить дочернему процессу стандартные потоки ввода/вывода?
Операционная система: Windows Задача: создать pipe и запустить два процесса, перенаправив стандартный вывод одного из них в стандартный...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru