#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #ifdef __linux__ #include #include #endif #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #define LOGIN "/bin/login" #define KILLTIME 5 #define CONFFILE "/etc/conlogind.conf" #define PIDFILE "/var/run/conlogind.pid" struct conlogin { char *tty; char *line; char id[3]; pid_t pid; unsigned short vt; }; extern int dotermreset(const char *tty); struct conlogin *conlogins; int nvcons = 0; sig_atomic_t doquit = 0; void *xmalloc(size_t size){ void *p; p = malloc(size); if(p==NULL){ fprintf(stderr,"malloc() failure\n"); exit(EXIT_FAILURE); } return(p); } struct conlogin* setup(int n){ struct conlogin *conlogins; struct conlogin *l; int i; char buf[16]; conlogins = xmalloc(sizeof(struct conlogin)*n); for(i=0;ivt = i + 1; snprintf(buf,sizeof(buf),"/dev/vc/%i",l->vt); l->tty = xmalloc(strlen(buf)+1); strcpy(l->tty,buf); l->line = l->tty + 5; /* "/dev/" */ snprintf(l->id,sizeof(l->id),"%02d",l->vt); l->pid = 0; } return(conlogins); } void write_utmp_wtmp(struct conlogin *l, short int type){ struct utmp utmp; memset(&utmp,'\0',sizeof(utmp)); strncpy(utmp.ut_id,l->id,MIN(sizeof(utmp.ut_id),sizeof(l->id))); strncpy(utmp.ut_line,l->line,UT_LINESIZE); utmp.ut_type = type; utmp.ut_pid = l->pid; utmp.ut_time = time(NULL); setutent(); pututline(&utmp); endutent(); updwtmp(_PATH_WTMP,&utmp); } void startlogin(struct conlogin *l){ pid_t pid; int i; int fd; char *argv[] = { LOGIN, NULL }; pid = fork(); if(pid > 0) { l->pid = pid; write_utmp_wtmp(l,LOGIN_PROCESS); } else if(pid == 0) { for(i=0;itty,O_RDWR); if(fd >= 0) { for(i=2;i>=0;i--){ close(i); dup(fd); } close(fd); execv(argv[0],argv); perror(LOGIN); } else { perror("open"); } sleep(5); /* So we don't get runaway respawning */ _exit(127); } else { perror("fork"); } } void endlogin(struct conlogin *l){ write_utmp_wtmp(l,DEAD_PROCESS); l->pid = 0; if(!doquit || l->vt != 1 ) dotermreset(l->tty); /* Clean up the terminal */ } void sendkill(int n){ int serrno = errno; int i; for(i=0;i 0){ /* Parent */ if((fp = fopen(PIDFILE,"w"))){ fprintf(fp,"%i\n",pid); fclose(fp); } exit(EXIT_SUCCESS); } /* Child */ setsid(); chdir("/"); /* We want stdout to spam to when something goes bad, but no stdin */ close(0); open("/dev/null",O_RDWR); for(i=0;i0) break; if(i