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

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

26.01.2019, 18:10. Показов 2552. Ответов 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 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru