Имеется программка под винду - вызывается из ком. строки и отправляет конфигурацию компьютера на указанную машину. Требуется написать демона, который бы данные от нее принимал и писал в файл.
Затык произошел в том, что данные пишутся в файл в странном виде. Но это точно не кодировка: коверкаются все символы, даже латиница, а iconv выдает: iconv: illegal input sequence at position 737.
К тому же, когда я слежу за сетью сниффером - все выглядит нормально, то есть читабельным текстом.
Прошу помочь - не знаю где копать.
Вы что издеваетесь или действительно считаете всех способными на расстоянии прочитать ваш код, поток данных и результирующий файл?
>Вы что издеваетесь или действительно считаете всех способными на расстоянии прочитать ваш
>код, поток данных и результирующий файл?Виноват, протупил. Вот код. Использовал мануалы отсюда: http://symmetrica.net/unix-linux
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <signal.h>int BecomeDaemonProcess (void);
int DoCleanup (void);
int ConfigureSignalHandlers (void);
int BindPassiveSocket (int, int *const);
int AcceptConnection (const int);
int HandleConnection (const int);
int WriteToSocket (const int, const char *const, const size_t);
int ReadLine (const int, char *const, const size_t, size_t *const);
void Handler (int);volatile sig_atomic_t GracefulShutdown = 0;
volatile sig_atomic_t HupSignalCaught = 0;
const char* cApplicationName = "Computer Configuration Storage Daemon";
const char* cLockFilePath = "/var/run/ccsd.pid";
char cOutputBuffer[16];
int iLockFileDescriptor = -1;
int iResult;
int BlockSignals[] = {SIGUSR2, SIGALRM, SIGPIPE, SIGTSTP, SIGPROF, SIGCHLD};
int HandleSignals[] = {SIGUSR1, SIGHUP, SIGTERM, SIGILL, SIGTRAP, SIGQUIT, SIGABRT, SIGIOT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT, SIGCONT, SIGPWR, SIGSYS};
int gMasterSocket = -1;
const int iListenPort = 9997;
volatile pid_t DaemonPID;
volatile int iMaxFileDescriptors = 0;
struct sigaction SignalAction;
sigset_t SigMask;int main (int argc, char *argv[]) {
if (argc > 1) {
int fd, len;
char pid_buf[16];
if ((fd = open (cLockFilePath, O_RDONLY)) < 0) {
perror ("Couldn't find lock file");
exit (fd);
}
len = read (fd, pid_buf, 16);
syslog (LOG_LOCAL0|LOG_INFO, "%c", pid_buf);
pid_buf [len] = 0;
DaemonPID = atoi (pid_buf);
if (!strcmp (argv[1], "stop")) {
syslog (LOG_LOCAL0|LOG_INFO, "Received STOP command - %d.", DaemonPID);
kill (DaemonPID, SIGTERM);
exit (EXIT_SUCCESS);
}
if (!strcmp (argv[1], "restart")) {
kill (DaemonPID, SIGHUP);
exit (EXIT_SUCCESS);
}
printf ("Usage: %s [stop|restart]\n", argv[0]);
exit (EXIT_FAILURE);
}
if ((iResult = BecomeDaemonProcess ()) < 0) {
perror ("Failed to deamonize.");
unlink (cLockFilePath);
exit (EXIT_FAILURE);
}
if ((iResult = ConfigureSignalHandlers()) < 0) {
perror ("Failed to configure signal handlers.");
unlink (cLockFilePath);
exit (EXIT_FAILURE);
}
if ((iResult = BindPassiveSocket(iListenPort, &gMasterSocket)) < 0) {
perror ("Failed to bind passive socket.");
unlink (cLockFilePath);
exit (EXIT_FAILURE);
}
do {
//action
if ((AcceptConnection (gMasterSocket)) < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "AcceptConnection failed, ERROR #%d", errno);
unlink (cLockFilePath);
exit (EXIT_FAILURE);
}
if ((GracefulShutdown == 1) && (HupSignalCaught == 0)) {
break;
}
GracefulShutdown = HupSignalCaught = 0;
} while (1);
}int BecomeDaemonProcess (void) {
char cPIDString[7];
int iCurrentPID;
int LockResult;
int i, j, k;
struct flock Lock;
iMaxFileDescriptors = sysconf (_SC_OPEN_MAX);
switch (iCurrentPID = fork ()) {
case 0:
//Child process
break;
case -1:
fprintf (stderr, "Error: initial fork failed: %s\n", strerror (errno));
return -1;
break;
default:
exit (0);
break;
}
//umask (0);
DaemonPID = (int) getpid();
sprintf (cPIDString, "%d\n", DaemonPID);
openlog (cApplicationName, LOG_NOWAIT, LOG_LOCAL0);
if ((iLockFileDescriptor = creat (cLockFilePath, 0644)) < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't open lock file, ERROR #%d", errno);
return EXIT_FAILURE;
}
Lock.l_type = F_WRLCK;
Lock.l_whence = SEEK_SET;
Lock.l_start = Lock.l_start = 0;
Lock.l_pid = 0;
if ((LockResult = fcntl (iLockFileDescriptor, F_SETLK, &Lock)) < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't set lock to file %s, ERROR #%d", cLockFilePath, errno);
}
if (write (iLockFileDescriptor, cPIDString, strlen(cPIDString)) <= 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't write PID to lock file, ERROR #%d", errno);
}
if (setsid () < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't get session ID (SID) from Kernel, ERROR #%d", errno);
return EXIT_FAILURE;
}
if (chdir ("/") < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't change directory to /, ERROR #%d", errno);
return EXIT_FAILURE;
}// Specific Daemon Initialization
syslog (LOG_LOCAL0|LOG_INFO, "Started with PID #%d", DaemonPID);
return EXIT_SUCCESS;
}int DoCleanup (void) {
int i, j, k;
for (i = 0; i <= iMaxFileDescriptors; i++) {
if (i != iLockFileDescriptor) {
close (i);
}
}
// TODO: Add socket close
closelog ();
}int ConfigureSignalHandlers (void) {
int i, j, k;sigemptyset (&SigMask);
for (i = 0; i < 7; i++) {
sigaddset (&SigMask, *(BlockSignals + i));
}
SignalAction.sa_handler = Handler;
SignalAction.sa_mask = SigMask;
SignalAction.sa_flags = 0;
sigaction (SIGUSR1, &SignalAction, NULL);
for (i = 0; i < 16; i++) {
sigaction (*(HandleSignals + i), &SignalAction, NULL);
}
return EXIT_SUCCESS;
}void Handler (int Signal) {
syslog (LOG_LOCAL0|LOG_INFO, "Received signal %d", Signal);
switch (Signal) {
case SIGUSR1:
syslog (LOG_LOCAL0|LOG_INFO, "Stopped gracefully");
GracefulShutdown = 1;
break;
case SIGHUP:
syslog (LOG_LOCAL0|LOG_INFO, "HUP signal caught");
GracefulShutdown = HupSignalCaught = 1;
break;
case SIGTERM:
DoCleanup();
exit (EXIT_SUCCESS);
break;
default:
#ifdef _GNU_SOURCE
syslog (LOG_LOCAL0|LOG_INFO, "Caught signal %s - exiting", strsignal(Signal));
#else
syslog (LOG_LOCAL0|LOG_INFO, "Caught signal %d - exiting", Signal);
#endif
DoCleanup ();
exit (0);
break;
}
}int BindPassiveSocket (int Port, int *const BoundSocket) {
struct sockaddr_in SocketAddrIn;
int Socket, OptionValue;
size_t OptionLength;
memset (&SocketAddrIn.sin_zero, 0, 8);
SocketAddrIn.sin_port = htons (Port);
SocketAddrIn.sin_family = AF_INET;
SocketAddrIn.sin_addr.s_addr = htonl (INADDR_ANY);
if ((Socket = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
return -1;
}
OptionValue = 1;
OptionLength = sizeof(int);
setsockopt (Socket, SOL_SOCKET, SO_REUSEADDR, &OptionValue, OptionLength);
if ((bind (Socket, (struct sockaddr *)&SocketAddrIn, sizeof (struct sockaddr_in))) < 0) {
return -1;
}
if ((listen (Socket, SOMAXCONN)) < 0) {
return -1;
}
*BoundSocket = Socket;
return 0;
}int AcceptConnection (const int Master) {
int Proceed = 1, Slave, ReturnValue = 0;
struct sockaddr_in Client;
socklen_t ClientLength;
while ((Proceed == 1) && (GracefulShutdown == 0)) {
ClientLength = sizeof (Client);
Slave = accept (Master, (struct sockaddr *)&Client, &ClientLength);
if (Slave < 0) {
if (errno == EINTR) {
continue;
}
syslog (LOG_LOCAL0|LOG_INFO, "accept() failed: %m\n");
Proceed = 0;
ReturnValue = -1;
} else {
ReturnValue = HandleConnection (Slave);
if (ReturnValue) {
Proceed = 0;
}
}
}
return ReturnValue;
}int HandleConnection (const int Slave) {
char ReadBuffer[1025];
const char * DataFile = "/home/nikitad/cppapp/data.txt";
size_t BytesRead;
const size_t BufferLength = 1025;
int ReturnValue;
int DataFileDescr;
DataFileDescr = open (DataFile, O_WRONLY|O_CREAT);
ReturnValue = ReadLine (Slave, ReadBuffer, BufferLength, &BytesRead);
if ((write (DataFileDescr, ReadBuffer, BufferLength)) < 0) {
syslog (LOG_LOCAL0|LOG_INFO, "Couldn't write data to file, ERROR #%d: %s", errno, strerror (errno));
}
if (ReturnValue == 0) {
WriteToSocket (Slave, ReadBuffer, BytesRead);
}
return ReturnValue;
}int ReadLine (const int Socket, char *const Buffer, const size_t Length, size_t *const Read) {
int Done = 0, ReturnValue = 0;
char Character, LastCharacter = 0;
size_t BytesSoFar = 0;
ssize_t ReadResult;
do {
ReadResult = recv (Socket, &Character, 1, 0);
switch (ReadResult) {
case -1:
if (errno = EINTR) {
Done = 1;
ReturnValue = -1;
}
break;
case 0:
Done = 1;
ReturnValue = 0;
break;
case 1:
Buffer[BytesSoFar] = Character;
BytesSoFar += ReadResult;
if (BytesSoFar >= Length) {
Done = 1;
ReturnValue = -1;
}
if ((Character == '\n') && (LastCharacter == '\r')) {
Done = 1;
}
LastCharacter = Character;
break;
}
} while (!Done);
Buffer[BytesSoFar] = 0;
*Read = BytesSoFar;
return ReturnValue;
}int WriteToSocket (const int Socket, const char *const Buffer, const size_t Length) {
size_t BytesWritten = 0;
ssize_t WriteResult;
int ReturnValue = 0, Done = 0;
do {
WriteResult = send (Socket, Buffer + BytesWritten, Length - BytesWritten, 0);
if (WriteResult == -1) {
if (errno == EINTR) {
WriteResult = 0;
} else {
Done = 1;
ReturnValue = 1;
}
} else {
BytesWritten += WriteResult;
if (WriteResult = 0) {
Done = 1;
}
}
} while (!Done);
return ReturnValue;
}
* Аплодирую стоя автору этого кода. (равно как и автору поста)...Это наверное самая сложная реализация такой простой задачи, которую только мог родить человеческий мозг.
По существу же:
> ReturnValue = ReadLine (Slave, ReadBuffer, BufferLength, &BytesRead);
> if ((write (DataFileDescr, ReadBuffer, BufferLength)) < 0) {Тут нужно использовать в качестве третьего агрумента write(2) не BufferLength, а BytesRead. Тогда всё будет в порядке: HandleConnection() читает одну(!) строчку и записывает её в файл - всё, как написано и результат (приведённый вами ниже) это подтверждает. Остальная часть записанного файла - просто мусор из оперативной памяти.
NOTE: То, что вам что-то ответили (я имею в виду этот ответ) - это скорее всего чистая случайность. Просто мне было немного скучно и я решил почитать этот огромный и бестолковый код. Ничего личного.
>[оверквотинг удален]
>Тут нужно использовать в качестве третьего агрумента write(2) не BufferLength, а BytesRead.
>Тогда всё будет в порядке: HandleConnection() читает одну(!) строчку и записывает
>её в файл - всё, как написано и результат (приведённый вами
>ниже) это подтверждает. Остальная часть записанного файла - просто мусор из
>оперативной памяти.
>
>NOTE: То, что вам что-то ответили (я имею в виду этот ответ)
>- это скорее всего чистая случайность. Просто мне было немного скучно
>и я решил почитать этот огромный и бестолковый код. Ничего личного.
>Да ничего, хорошо что сказал, ибо я подозревал, что тут афтор перемудрил. Сейчас буду переделывать чтобы выглядело не так страшно.
Файл.
[General]
��������ܐ�5��qZ�������ܐ�hܐ��ܐ�3
�������ݐ�E��qZ���ܐ������qZ������4���������ܐ�m?�������ݐ�7���ݐ�,���,����� ݐ�
�z��hݐ�y����<���<�� ��/�<��ii
����#F�������ݐ�B�����������я췀��ݐ��ݐ��ސ�à=Xû· (\æ·° €ˆø·� ”± í ¨û·Xû·ç·¨çæ·ø≥æ· ô¿ü·û·œÞ�¿ôïù·│ HÞ│Ìæ·„Þ�¿≤«û·Ô<ç·Å†¹Éü·¬Éü·8û· �¿␋üû·├…¸Éü·ô¿ü· äÞ�¿ôïù·Ï†␋␋
û· ß�¿B¯û·␋üû·├…¸Éü·ô¿ü· ┐Å ÔÞ�¿ÔÞ�¿Äß�¿µéZñXû· (\æ·\Uæ·ôÞ�¿´éZñäß�¿FX78��X��u���������������ߐ��ߐ������ߐ�<���8�����ߐ�<���8���ߐ����������u� ����Z� �������S�FX7!@8���ߐ�ա��H���X��N�x���X������������������R�������u���x�����������x���C��d���x���
>iconv: illegal input sequence at position 737iconv так обычно жалуется когда в одной локали нет символов из другой. Например, в cp1251 есть специальные ёлочные кавычки, а в koi8-r их нет. Соответственно он не знает как перекодировать. Помогает ключик -c, обычно (или '-r ?').