Демон оболочки c pipe с возможностью регистрации не работает - PullRequest
0 голосов
/ 10 марта 2012

У меня есть следующий код:

#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>



int main (void) {
int fd_s=socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
struct sockaddr_in info_s = {.sin_family=AF_INET,.sin_port=htons(1024),.sin_zero={0,0,0,0,0,0,0},.sin_addr.s_addr=0};
bind(fd_s,&info_s,sizeof(info_s));
listen(fd_s,1);
int info_s_len=sizeof(struct sockaddr_in);
int fd_c;
struct sockaddr_in info_c;
while((fd_c=accept(fd_s, &info_c,&info_s_len))){
printf("client connected.\n");
if(!fork()){
int fd=open("log", O_RDWR|O_CREAT|O_APPEND|O_SYNC);
int p0[2],p1[2],p2[2];pipe2(p0, O_NONBLOCK);pipe2(p1, O_NONBLOCK);pipe2(p2, O_NONBLOCK);
dup2(p0[0], 0);
dup2(p1[1], 1);
dup2(p2[1], 2);
if(!fork()){
system("/bin/sh");
close(p0[0]);close(p0[1]);close(p1[0]);close(p1[1]);close(p2[0]);close(p2[1]);
close(fd_c);
close(fd);
printf("client disconnected.");
exit(0);
}else{
fd_set rd,wr;int on=1;//fcntl(fd_c, O_NONBLOCK, &on);
//char b[50];fwrite("ls;",3,1,fp_);fgets(b,50,fp_);printf(b);
FD_ZERO(&rd);FD_ZERO(&wr);
FD_SET(p1[0], &rd);FD_SET(p2[1],&rd);FD_SET(p0[1],&wr);FD_SET(fd_c, &rd);FD_SET(fd_c,&wr);
char *b=0; int bl,i;
while(select(p2[1]+1,&rd,&wr,0,0)){
char c;
if(FD_ISSET(fd_c,&rd)) {
b=realloc(b, 1*sizeof(char));
for(i=0,bl=1*sizeof(char);recv(fd_c,b+i,1,0)==1;i++,bl+=sizeof(char)){b=realloc(b, bl);}
write(p0[1],b,bl);
write(fd,b,bl);
free(b);
b=0;
}else if(FD_ISSET(p1[0],&rd)){
b=realloc(b, 1*sizeof(char));
for(i=0,bl=0;read(p0[0],b+i,1)>0;i++,bl+=sizeof(char)){b=realloc(b, bl);}
send(fd_c,b,bl,0);
write(fd,b,bl);
free(b);b=0;
}else if(FD_ISSET(p2[0],&rd)){
for(i=0,bl=0;read(p2[0],b+i,1)>0;i++,bl+=sizeof(char)){b=realloc(b, bl);}
send(fd_c,b,bl,0);
write(fd,b,bl);
free(b);b=0;
}
FD_ZERO(&rd);FD_ZERO(&wr);
FD_SET(p1[0], &rd);FD_SET(p2[1],&rd);FD_SET(p0[1],&wr);FD_SET(fd_c, &rd);FD_SET(fd_c,&wr);
}
}
}
}
return 0;
}

Когда я делаю

telnet localhost 1024

мой демон порождает /bin/sh, и все отправленные команды сохраняются в файле log. Но когда я пишу (в примере): id; У меня нет ответа от моего демона на стороне клиента и в файл log.

Чего мне не хватает?

P.D: код нуждается в некоторых, когда клиент отключил закрывающие функции, которые я добавлю, когда будет найдена заливка.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 12 марта 2012

Как следует из моего решения.

#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>

int
main (void)
{
  int fd_s = socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
  struct sockaddr_in info_s = {.sin_family = AF_INET,.sin_port =
      htons (1024),.sin_zero = {0, 0, 0, 0, 0, 0, 0},.sin_addr.s_addr = 0
  };
  bind (fd_s, &info_s, sizeof (info_s));
  listen (fd_s, 1);
  int info_s_len = sizeof (struct sockaddr_in);
  int fd_c;
  struct sockaddr_in info_c;
  while ((fd_c = accept (fd_s, &info_c, &info_s_len)))
    {
      printf ("client connected.\n");
      if (!fork ())
    {
      int fd = open ("log", O_WRONLY | O_CREAT | O_APPEND);
      int pty, tty;
      char *name;
      openpty (&pty, &tty, NULL, NULL, NULL);
      name = ttyname (tty);
      int p0[2], p1[2], p2[2];
      pipe (p0);
      pipe2 (p1, O_NONBLOCK);
      pipe2 (p2, O_NONBLOCK);
      dup2 (tty, 0);
      dup2 (tty, 1);
      dup2 (tty, 2);
      dup2 (p0[0], 0);
      dup2 (p1[1], 1);
      dup2 (p2[1], 2);
      if (!fork ())
        {
          system ("/bin/sh");
          close (p0[0]);
          close (p0[1]);
          close (p1[0]);
          close (p1[1]);
          close (p2[0]);
          close (p2[1]);
          close (fd_c);
          close (fd);
          // some log
          exit (0);
        }
      else
        {
          fd_set rd, wr;
          fcntl (fd_c, F_SETFL, O_NONBLOCK);
          FD_ZERO (&rd);
          FD_ZERO (&wr);
          FD_SET (p1[0], &rd);
          FD_SET (p2[0], &rd);
          FD_SET (fd_c, &rd);
          char *b = 0;
          int bl, i;
          while (select (p2[1] + 1, &rd, &wr, 0, 0))
        {
          char c;
          if (FD_ISSET (fd_c, &rd))
            {
              for (i = bl = b = 0; 1; i++)
            {
              char c;
              int ret = recv (fd_c, &c, sizeof (c), 0);
              if (ret == sizeof (c))
                {
                  bl += sizeof (char);
                  b = realloc (b, bl);
                  b[i] = c;
                }
              else if (ret == 0)
                {
                  close (fd_c);
                  free (b);
                  exit (0);
                }
              else if (ret == -1)
                {
                  write (p0[1], b, bl);
                  write (fd, b, bl);
                  free (b);
                  break;
                }
            }
            }
          else if (FD_ISSET (p1[0], &rd))
            {
              for (i = bl = b = 0; 1; i++)
            {
              char c;
              int ret = read (p1[0], &c, sizeof (c));
              if (ret == sizeof (c))
                {
                  bl += sizeof (c);
                  b = realloc (b, bl);
                  b[i] = c;
                }
              else if (ret == -1)
                {
                  send (fd_c, b, bl, 0);
                  write (fd, b, bl);
                  free (b);
                  break;
                }
              else
                {
                }
            }
            }
          else if (FD_ISSET (p2[0], &rd))
            {
              for (i = bl = b = 0; 1; i++)
            {
              char c;
              int ret = read (p2[0], &c, sizeof (c));
              if (ret == sizeof (c))
                {
                  bl += sizeof (c);
                  b = realloc (b, bl);
                  b[i] = c;
                }
              else if (ret == -1)
                {
                  send (fd_c, b, bl, 0);
                  write (fd, b, bl);
                  free (b);
                  break;
                }
            }
            }
          FD_ZERO (&rd);
          FD_ZERO (&wr);
          FD_SET (p1[0], &rd);
          FD_SET (p2[0], &rd);
          FD_SET (fd_c, &rd);
        }
        }
    }
    }
  return 0;
}

В любом случае, спасибо ...

0 голосов
/ 10 марта 2012

execve() не возвращается, если не произошла ошибка. следовательно, ни одна из строк ниже этого вызова никогда не достигается.

Используйте system(), чтобы продолжить после выхода ребенка:

   The value returned is -1 on  error  (e.g.   fork(2)  failed),  and  the
   return  status  of the command otherwise.  This latter return status is
   in the format specified in wait(2).  Thus, the exit code of the command
   will  be  WEXITSTATUS(status).   In case /bin/sh could not be executed,
   the exit status will be that of a command that does exit(127).

   If the value of command is NULL, system() returns nonzero if the  shell
   is available, and zero if not.

   system() does not affect the wait status of any other children.
...