|
|
/*
* gcc -Wall -O2 xctrld.c -o /sbin/xctrld * * --- ROCK-COPYRIGHT-NOTE-BEGIN --- * * This copyright note is auto-generated by ./scripts/Create-CopyPatch. * Please add additional copyright information _after_ the line containing * the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by * the ./scripts/Create-CopyPatch script. Do not edit this copyright text! * * ROCK Linux: rock-src/misc/archive/xctrld.c * ROCK Linux is Copyright (C) 1998 - 2003 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. A copy of the GNU General Public * License can be found at Documentation/COPYING. * * Many people helped and are helping developing ROCK Linux. Please * have a look at http://www.rocklinux.org/ and the Documentation/TEAM
* file for details. * * --- ROCK-COPYRIGHT-NOTE-END --- */
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#define PORT 2225
#define BUFSIZE 1024
FILE * out = NULL;
#define xprf(format, args... ) fprintf(out,"Cliffords Control-Daemon: " format "\r", ## args)
/* This function is very dirty - but it seams to to the only way that
* works without using pty devices. making the netfd directly the stdin * stdout and stderr channels of /bin/sh caused a lot of problems ... */ void do_session(int netfd) { int p_in[2],p_out[2]; int rc,maxfd,pid,c; struct timeval tv; char buf[BUFSIZE]; fd_set rfds; snprintf(buf,BUFSIZE,"\n" "Hello! This is a mini telnet daemon which is not using a pty device.\n" "So you wont have job control or other things where ptys are needed.\n" "\nThis session has the PID %d. Have fun.\n\n",(int)getpid()); write(netfd,buf,strlen(buf)); pipe(p_in); pipe(p_out); if (signal(SIGCHLD,SIG_DFL) == SIG_ERR) xprf("signal: %s",strerror(errno)); if ( (pid=fork()) == 0 ) { close(0); dup2(p_in[0],0); close(1); dup2(p_out[1],1); close(2); dup2(p_out[1],2); close(p_in[0]); close(p_in[1]); close(p_out[0]); close(p_out[1]); close(netfd); setenv("USER","root",1); setenv("HOME","/root",1); setenv("LOGNAME","root",1); setenv("TERM","linux",1); execl("/bin/sh","/bin/sh","--login","-i",NULL); xprf("execl: %s",strerror(errno)); exit(1); } close(p_in[0]); close(p_out[1]); while (waitpid(pid,NULL,WNOHANG) != pid) { FD_ZERO(&rfds); FD_SET(netfd,&rfds); FD_SET(p_out[0],&rfds); maxfd = netfd>p_out[0] ? netfd : p_out[0]; tv.tv_sec=1; tv.tv_usec=0; rc=select(maxfd+1, &rfds, NULL, NULL, NULL); if (rc == -1) { xprf("select: %s",strerror(errno)); return; } if (FD_ISSET(netfd, &rfds)) { rc=read(netfd,buf,BUFSIZE); for (c=0; c<rc; c++) if (buf[c]!='\r') write(p_in[1],buf+c,1); } if (FD_ISSET(p_out[0], &rfds)) { rc=read(p_out[0],buf,BUFSIZE); for (c=0; c<rc; c+=write(netfd,buf,rc)) ; } } }
int main(int argc, char ** argv) { struct sockaddr_in addr; int listenfd,fd; if (argc != 2 || argv[1][0] == '-') { fprintf(stderr,"Usage: %s < log-file | tty-device >\n",argv[0]); return 1; } if ( (out=fopen(argv[1],"a+")) == NULL ) { fprintf(stderr,"Can't open log file '%s': %s",argv[1],strerror(errno)); return 1; } setvbuf(out,NULL,_IONBF,0); chdir("/");
printf("Cliffords Remote Control Daemon starting in 3 seconds ...\n"); if (fork()) return 0; sleep(3);
fprintf(out,"\n\n\r"); xprf("Binding port %d and waiting for connections ...\n",PORT); if (signal(SIGCHLD,SIG_IGN) == SIG_ERR) xprf("signal: %s",strerror(errno)); if ((listenfd=socket(AF_INET,SOCK_STREAM,0)) == -1) xprf("socket: %s",strerror(errno)); bzero(&addr,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(PORT);
if (bind(listenfd,&addr,sizeof(addr)) == -1) xprf("bind: %s",strerror(errno)); if (listen(listenfd,5)==-1) xprf("listen: %s",strerror(errno)); while (1) { if ((fd=accept(listenfd,NULL,NULL)) == -1) xprf("accept: %s",strerror(errno)); if (!fork()) { xprf("connection %d opened.\n",(int)getpid()); do_session(fd); xprf("connection %d closed.\n",(int)getpid()); return 0; } else close(fd); } return 0; }
|