/* utility wrapper */ static void spawned_shell(void *targ) { rtems_status_code sc; FILE *nstd[3]={0}; FILE *ostd[3]={ stdin, stdout, stderr }; int i=0; struct shell_args *arg = targ; bool login_failed = false; bool start = true; sc=rtems_libio_set_private_env(); /* newlib hack/workaround. Before we change stdin/out/err we must make * sure the internal data are initialized (fileno(stdout) has this sideeffect). * This should probably be done from RTEMS' libc support layer... * (T.S., newlibc-1.13; 2005/10) */ fileno(stdout); if (RTEMS_SUCCESSFUL != sc) { rtems_error(sc,"rtems_libio_set_private_env"); goto cleanup; } /* redirect stdio */ for (i=0; i<3; i++) { if ( !(nstd[i]=fopen(arg->devname,"r+")) ) { perror("unable to open stdio"); goto cleanup; } } stdin = nstd[0]; stdout = nstd[1]; stderr = nstd[2]; #if 0 printk("STDOUT is now %x (%x) (FD %i/%i)\n", stdout,nstd[1],fileno(stdout),fileno(nstd[1])); printf("hello\n"); write(fileno(stdout),"hellofd\n",8); #endif /* call their routine */ if (rtems_telnetd_config.login_check != NULL) { start = rtems_shell_login_prompt( stdin, stderr, arg->devname, rtems_telnetd_config.login_check ); login_failed = !start; } if (start) { rtems_telnetd_config.command( arg->devname, arg->arg); } stdin = ostd[0]; stdout = ostd[1]; stderr = ostd[2]; if (login_failed) { syslog( LOG_AUTHPRIV | LOG_WARNING, "telnetd: to many wrong passwords entered from %s", arg->peername ); } cleanup: release_a_Connection(arg->devname, arg->peername, nstd, i); free(arg); }
static bool rtems_shell_login(FILE * in,FILE * out) { FILE *fd; int c; time_t t; rtems_shell_init_issue(); setuid(0); setgid(0); rtems_current_user_env->euid = rtems_current_user_env->egid =0; if (out) { if ((rtems_current_shell_env->devname[5]!='p')|| (rtems_current_shell_env->devname[6]!='t')|| (rtems_current_shell_env->devname[7]!='y')) { fd = fopen("/etc/issue","r"); if (fd) { while ((c=fgetc(fd))!=EOF) { if (c=='@') { switch(c=fgetc(fd)) { case 'L': fprintf(out,"%s",rtems_current_shell_env->devname); break; case 'B': fprintf(out,"0"); break; case 'T': case 'D': time(&t); fprintf(out,"%s",ctime(&t)); break; case 'S': fprintf(out,"RTEMS"); break; case 'V': fprintf(out,"%s\n%s",_RTEMS_version, _Copyright_Notice); break; case '@': fprintf(out,"@"); break; default : fprintf(out,"@%c",c); break; } } else if (c=='\\') { switch(c=fgetc(fd)) { case '\\': fprintf(out,"\\"); break; case 'b': fprintf(out,"\b"); break; case 'f': fprintf(out,"\f"); break; case 'n': fprintf(out,"\n"); break; case 'r': fprintf(out,"\r"); break; case 's': fprintf(out," "); break; case 't': fprintf(out,"\t"); break; case '@': fprintf(out,"@"); break; } } else { fputc(c,out); } } fclose(fd); } } else { fd = fopen("/etc/issue.net","r"); if (fd) { while ((c=fgetc(fd))!=EOF) { if (c=='%') { switch(c=fgetc(fd)) { case 't': fprintf(out,"%s",rtems_current_shell_env->devname); break; case 'h': fprintf(out,"0"); break; case 'D': fprintf(out," "); break; case 'd': time(&t); fprintf(out,"%s",ctime(&t)); break; case 's': fprintf(out,"RTEMS"); break; case 'm': fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")"); break; case 'r': fprintf(out,_RTEMS_version); break; case 'v': fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice); break; case '%':fprintf(out,"%%"); break; default: fprintf(out,"%%%c",c); break; } } else { fputc(c,out); } } fclose(fd); } } } return rtems_shell_login_prompt( in, out, rtems_current_shell_env->devname, rtems_current_shell_env->login_check ); }
static void rtems_task_telnetd(void *task_argument) { int des_socket; uni_sa srv; char *devname; char peername[16]; int i=1; int size_adr; struct shell_args *arg = NULL; if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { perror("telnetd:socket"); telnetd_task_id = RTEMS_ID_NONE; rtems_task_delete(RTEMS_SELF); }; setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i)); memset(&srv,0,sizeof(srv)); srv.sin.sin_family=AF_INET; srv.sin.sin_port=htons(23); size_adr=sizeof(srv.sin); if ((bind(des_socket,&srv.sa,size_adr))<0) { perror("telnetd:bind"); close(des_socket); telnetd_task_id = RTEMS_ID_NONE; rtems_task_delete(RTEMS_SELF); }; if ((listen(des_socket,5))<0) { perror("telnetd:listen"); close(des_socket); telnetd_task_id = RTEMS_ID_NONE; rtems_task_delete(RTEMS_SELF); }; /* we don't redirect stdio as this probably * was started from the console anyways.. */ do { if (rtems_telnetd_config.keep_stdio) { bool start = true; char device_name [32]; ttyname_r( 1, device_name, sizeof( device_name)); if (rtems_telnetd_config.login_check != NULL) { start = rtems_shell_login_prompt( stdin, stderr, device_name, rtems_telnetd_config.login_check ); } if (start) { rtems_telnetd_config.command( device_name, arg->arg); } else { syslog( LOG_AUTHPRIV | LOG_WARNING, "telnetd: to many wrong passwords entered from %s", device_name ); } } else { devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); if ( !devname ) { /* if something went wrong, sleep for some time */ sleep(10); continue; } arg = malloc( sizeof(*arg) ); arg->devname = devname; arg->arg = rtems_telnetd_config.arg; strncpy(arg->peername, peername, sizeof(arg->peername)); telnetd_task_id = telnetd_spawn_task( devname, rtems_telnetd_config.priority, rtems_telnetd_config.stack_size, spawned_shell, arg ); if (telnetd_task_id == RTEMS_ID_NONE) { FILE *dummy; if ( telnetd_spawn_task != telnetd_dflt_spawn ) { fprintf(stderr,"Telnetd: Unable to spawn child task\n"); } /* hmm - the pty driver slot can only be * released by opening and subsequently * closing the PTY - this also closes * the underlying socket. So we mock up * a stream... */ if ( !(dummy=fopen(devname,"r+")) ) perror("Unable to dummy open the pty, losing a slot :-("); release_a_Connection(devname, peername, &dummy, 1); free(arg); sleep(2); /* don't accept connections too fast */ } } } while(1); /* TODO: how to free the connection semaphore? But then - * stopping the daemon is probably only needed during * development/debugging. * Finalizer code should collect all the connection semaphore * counts and eventually clean up... */ close(des_socket); telnetd_task_id = RTEMS_ID_NONE; }