/*********************************************** * * File: * init.c * * Purpose: * init will be the init process on the * EBSA, it will remount the filesystem * in read/write state, mount the proc * filesystem, run the init script, * it will then launch a shell and * monitor the shell, if it exits init * will restart the shell. * Added the ability to have the init * process send its debugging and status * info back over a socket to the host. * * Written by: * Benjamin Stocks * Paul Raisanen * * Modified by: * Benjamin Stocks 01/30/2000 * Added the socket stuff for sending the * errors and status back over a socket * connection. * **********************************************/ /* System includes */ #include#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*********************************************** * * Function: * remount * * Purpose: * remount will fork off a process to * call the mount command to remount the * filesystem in read/write state. * All status messages and error messages * will be written to the file descriptor * passed in, it should be socket connection * in this version of init. * * Calls: * sprintf() * fork() * execlp() * wait() * memset() * write() * * Parameters: * sockfd - A file descriptor to an open * socket for debugging and error * messages. * * Returns: * An integer containing the error returned * from the execlp if any, zero otherwise. * * Written by: * Benjamin Stocks * Paul Raisanen * * Modified by: * Benjamin Stocks 01/30/2000 * Added the socket writing code. * **********************************************/ int remount(int sockfd) { pid_t childpid; int status; char message[50]; int error = 0; if((childpid = fork()) == 0) { memset(message,'\0',sizeof(message)); sprintf(message,"remounting filesystem\n"); if(sockfd > 0) { write(sockfd,message,strlen(message)); } error = execlp("mount","mount","-o","remount", "-rw","/",0); if(error < 0) { memset(message,'\0',sizeof(message)); if(sockfd > 0) { sprintf(message,"remount error: %s\n",strerror(error)); write(sockfd,message,strlen(message)); } } } wait(&status); return error; } /*********************************************** * * Function: * runinitscript * * Purpose: * runinitscript will run the /etc/rc * init script and capture its output for * writing to the socket passed in. * * Calls: * memset() * popen() * fread() * pclose() * sprintf() * write() * * Parameters: * sockfd - The open socket connection * for the status and error * messages. * * Returns: * An integer containing the error returned * if any. * * Written by: * Benjamin Stocks * * Modified by: * Benjamin Stocks 01/30/2000 * Added the socket writing code. * **********************************************/ int runinitscript(int sockfd) { FILE *read_fp; char buffer[BUFSIZ + 1]; int chars_read; int error = 0; memset(buffer,'\0',sizeof(buffer)); sprintf(buffer,"running init scripts\n"); if(sockfd > 0) { write(sockfd,buffer,strlen(buffer)); } memset(buffer,'\0',sizeof(buffer)); read_fp = popen("/bin/sh /etc/rc 2>&1","r"); if(read_fp != NULL) { chars_read = fread(buffer,sizeof(char),BUFSIZ,read_fp); while(chars_read > 0) { memset(buffer,'\0',sizeof(buffer)); chars_read = fread(buffer,sizeof(char),BUFSIZ, read_fp); if(sockfd > 0) { write(sockfd,buffer,strlen(buffer)); } } pclose(read_fp); } return error; } /*********************************************** * * Function: * mountproc * * Purpose: * mountproc will mount the proc file- * system and pass off any status or * error messages to the open socket * passed into it. * * Calls: * mount() * memset() * write() * * Parameters: * sockfd - An open file descriptor to * the socket to write to. * * Returns: * An integer containing the error returned * from the mount if any, zero otherwise. * * Written by: * Benjamin Stocks * * Modified by: * Benjamin Stocks 01/30/2000 * Added the socket writing code. * **********************************************/ int mountproc(int sockfd) { char message[50]; int error = 0; memset(message,'\0',sizeof(message)); sprintf(message,"mounting proc filesystem\n"); if(sockfd > 0) { write(sockfd,message,strlen(message)); } error = mount("proc","/proc","proc",0,0); if((error < 0) && (sockfd > 0)) { memset(message,'\0',sizeof(message)); sprintf(message,"mount of proc error: %s\n",strerror(error)); write(sockfd,message,strlen(message)); } return error; } /*********************************************** * * Function: * startshell * * Purpose: * startshell will fork off a process to * launch a shell * * Calls: * fork() * execlp() * printf() * * Parameters: NONE * * Returns: * An integer containing the error returned * from the execlp if any, zero otherwise. * * Written by: * Benjamin Stocks * Paul Raisanen * * Modified by: * **********************************************/ pid_t startshell() { pid_t childpid; int error = 0; if((childpid = fork()) == 0) { printf("starting ash...\n"); error = execlp("/bin/sh","sh",0); if(error < 0) { printf("exec of shell error: %s\n",strerror(error)); } } return childpid; } /*********************************************** * * Function: * main * * Purpose: * main will call the functions to * remount the filesystem in read/write * state, mount the proc filesystem, * run the init script, launch the shell * and monitor it for exit status and * setup some environmental variables * that we need. * * Calls: * remount() * mountproc() * setenv() * runinitscript() * startshell() * waitpid() * * Parameters: * argc - The count of command line * arguments. * argv - A pointer to an array of the * command line arguments. * * Returns: * An integer containg a zero * * Written by: * Benjamin Stocks * Paul Raisanen * * Modified by: * **********************************************/ int main(argc,argv) int argc; char** argv; { struct sockaddr_in servaddr; pid_t sh_pid; int status; int sockfd; sockfd = socket(AF_INET,SOCK_STREAM,0); memset(&servaddr,'\0',sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(31337); inet_pton(AF_INET,"192.16.0.1",&servaddr.sin_addr); if(connect(sockfd,(struct sockaddr_in*)&servaddr,sizeof(servaddr)) < 0) { printf("Error connection to host.\n"); } remount(sockfd); mountproc(sockfd); setenv("PVM_ROOT","/pvm3",1); setenv("PATH","/usr/bin:/bin:/sbin",1); runinitscript(sockfd); close(sockfd); for(;;) { sh_pid = startshell(); waitpid(sh_pid,&status,0); } return 0; }