Пример #1
0
void ps_control_check_input(char *command, int argc)
{
    ps_command_info_t const *command_info = ps_command_infos;

    while (command_info->name)
    {
        if (strcmp(command_info->name, command) != 0)
        {
            command_info++;
            continue;
        }

        if (command_info->needs_root)
        {
            if (getuid() != 0)
                ps_log(EXIT_FAILURE, LOG_ERROR("The command [%s] requires root permission"), command);
        }

        if ((argc < command_info->argc_min) || (argc > command_info->argc_max))
            ps_log(EXIT_FAILURE, LOG_ERROR("Invallid number of parameters for command [%s]"), command);

        return;
    }

    ps_log(EXIT_FAILURE, LOG_ERROR("Unknown command [%s]"), command);
}
Пример #2
0
void ps_control_run_program(int argc, char *argv[])
{
    int i;
    char *p;
    struct winsize windowsize;

    if (argc <= 0)
        ps_log(EXIT_FAILURE, LOG_ERROR("invallid number of arguments [%d]"), argc);

    if (isatty(STDIN_FILENO))
    {
        if (ioctl(STDIN_FILENO, TIOCGWINSZ, &windowsize) == -1)
            ps_log(EXIT_FAILURE, LOG_ERROR("failed to determine window size"));
    }
    else
    {
        windowsize.ws_col=80;
        windowsize.ws_row=25;
    }

    p=ps_buffer;
    *p++=PS_MSG_RUN_PROGRAM;

    sprintf(p,"%d",windowsize.ws_col);
    p+=strlen(p)+1;

    sprintf(p,"%d",windowsize.ws_row);
    p+=strlen(p)+1;

    sprintf(p,"%d",argc);
    p+=strlen(p)+1;

    int arg_size;
    int buffer_size_left=sizeof(ps_buffer)-(p-ps_buffer);

    for (i=0; i < argc; i++)
    {
        arg_size=strlen(argv[i])+1;

        if (arg_size > buffer_size_left)
            ps_log(EXIT_FAILURE, LOG_ERROR("size of --run parameters too large for buffer."));

        sprintf(p,"%s",argv[i]);
        p+=arg_size;
        buffer_size_left-=arg_size;
    }

    if ((write(ps_fd_control, ps_buffer, p-ps_buffer)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to send PS_MSG_RUN_PROGRAM - error [%s]"), strerror(errno));

    ps_control_io_loop();
}
Пример #3
0
void ps_log_open(const char* filename)
{
    umask(0);

    if ((ps_fd_log=open(filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to open logfile [%s] - error [%s]"), filename, strerror(errno));
}
Пример #4
0
void ps_control_connect_daemon()
{
    ps_fd_control=socket(AF_UNIX, SOCK_SEQPACKET, 0);

    if (ps_fd_control == -1)
        ps_log(0, LOG_ERROR("failed to create socket - error [%s]"), strerror(errno));
    else
    {
        if (connect(ps_fd_control, (struct sockaddr *) &ps_daemon_address, sizeof(ps_daemon_address)) == -1)
        {
            ps_log(0, LOG_ERROR("failed to connect to daemon - error [%s]"), strerror(errno));
            close(ps_fd_control);
            ps_fd_control=-1;
        }
    }
}
Пример #5
0
void ps_create_directory(char *path)
{
    char *dir_start, *dir_end, *path_end;

    umask(0);
    path_end=path+strlen(path);
    dir_start=path+1;

    while (dir_start < path_end)
    {
        dir_end=strstr(dir_start,"/");

        if (dir_end)
            *dir_end=0;

        if (mkdir(path, 0755) == -1)
            if (errno != EEXIST)
                ps_log(EXIT_FAILURE, LOG_ERROR("unable to create directory [%s] - error [%s]"), path, strerror(errno));

        if (dir_end == NULL)
            break;

        *dir_end='/';
        dir_start=dir_end+1;
    }
}
Пример #6
0
void ps_terminal_send_exitcode(int fd_control, int exitcode)
{
    ps_buffer[0]=PS_MSG_EXIT_STATUS;
    sprintf(ps_buffer+1,"%d", exitcode);

    if (write(fd_control, ps_buffer, strlen(ps_buffer)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to send exitcode to controller - error [%s]"), strerror(errno));
}
Пример #7
0
void ps_control_set_terminal_raw_mode(void)
{
    struct termios terminal_attributes_raw = ps_saved_terminal_attributes;

    terminal_attributes_raw.c_lflag &= ~(ICANON | ISIG | IEXTEN |ECHO);
    terminal_attributes_raw.c_iflag &= ~(BRKINT | ICRNL |IGNBRK | IGNCR | IGNCR | INPCK | ISTRIP | IXON | PARMRK);
    terminal_attributes_raw.c_oflag &= ~OPOST;
    terminal_attributes_raw.c_cc[VMIN] = 1;
    terminal_attributes_raw.c_cc[VTIME] =0;

    if (tcsetattr(STDIN_FILENO, TCSAFLUSH /*TCSANOW*/ , &terminal_attributes_raw) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unable to put terminal in raw mode - error [%s]"), strerror(errno));
}
Пример #8
0
void ps_set_name(const char* name)
{
    if (strlen(name)+1 > sizeof(ps_name))
        ps_log(EXIT_FAILURE, LOG_ERROR("program space name [%s] is too long, max length is [%d]"), name, sizeof(ps_name)-1);

    strcpy(ps_name, name);
    ps_name[sizeof(ps_name)-1]=0;

    memset(&ps_daemon_address, 0, sizeof(ps_daemon_address));
    ps_daemon_address.sun_family=AF_UNIX;

    // name is for an abstract unix socket, ie sun_path[0] == 0 thanks to memset
    sprintf(ps_daemon_address.sun_path+1,"ps_daemon_%s", ps_name);
}
Пример #9
0
void ps_log_hex_dump(const char* function_name, int line_number, char *description, void* address, int count)
{
    ps_log(0, "Hex   ps [%s] fn [%s] ln [%d] description [%s]\n", ps_name, function_name, line_number, description);

    char hex_buffer[16*3+1];
    char ascii_buffer[16*2+1];
    char *hex_pos=hex_buffer;
    char *hex_pos_max=hex_buffer+15*3;
    char *ascii_pos=ascii_buffer;
    char *c = (char *) address;

    while (count--)
    {
        sprintf(hex_pos,"%.2x ",(unsigned char) *c);

        if (isprint(*c))
            sprintf(ascii_pos,"%c ",*c);
        else
            sprintf(ascii_pos,". ");

        c++;

        if (hex_pos < hex_pos_max)
        {
            hex_pos+=3;
            ascii_pos+=2;
            continue;
        }

        ps_log(0, "Hex   %s- %s\n", hex_buffer, ascii_buffer);
        hex_pos=hex_buffer;
        ascii_pos=ascii_buffer;
    }

    if (hex_pos != hex_buffer)
        ps_log(0, "Hex   %s - %s\n", hex_buffer, ascii_buffer);
}
Пример #10
0
void ps_daemon_run_program(int fd_listen, int fd_control, char *arguments)
{
    struct sigaction sa_sigchld;

    // fork a terminal program that creates a pseudoterminal and takes care of running the program

    int pid_terminal=fork();

    if (pid_terminal == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to create terminal program - error [%s]"), strerror(errno));

    if (pid_terminal == 0)
    {
        close(fd_listen);

        if (ps_safe_to_change_name)
        {
            ps_program_name[2]='t';
            prctl(PR_SET_NAME, (unsigned long) ps_program_name, 0, 0, 0);
        }

        // remove inherited SIGCHLD handler

        sigemptyset(&sa_sigchld.sa_mask);
        sa_sigchld.sa_handler = SIG_DFL;
        sa_sigchld.sa_flags = 0;

        if (sigaction(SIGCHLD, &sa_sigchld, 0) == -1)
            ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGCHLD handler - error [%s]"), strerror(errno));

        ps_terminal_run_program(fd_control, arguments);
        exit(EXIT_SUCCESS);
    }

    // NOTE: the daemon does not wait on pid_terminal
}
Пример #11
0
int ps_terminal_set_user(int uid)
{
    if (getuid() == uid)
        return 0;

    struct passwd *password_entry;

    // a program space can have a completely different rootfs, one in which some
    // users are not in the passwd file. do not allow these users to enter

    if ((password_entry= getpwuid(uid)) == 0)
    {
        ps_log(0, LOG_ERROR("getpwuid failed - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (setgid(password_entry->pw_gid))
    {
        ps_log(0, LOG_ERROR("setgid failed - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (setuid(uid))
    {
        ps_log(0, LOG_ERROR("setuid failed - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    // modify environment

    ps_terminal_set_environment("HOME", password_entry->pw_dir);
    ps_terminal_set_environment("SHELL", password_entry->pw_shell);
    ps_terminal_set_environment("USER", password_entry->pw_name);
    ps_terminal_set_environment("LOGNAME", password_entry->pw_name);
    return EXIT_SUCCESS;
}
Пример #12
0
int ps_control_send_receive(int size)
{
    int read_count=0;

    if (ps_fd_control == -1)
        return -1;

    if (write(ps_fd_control, ps_buffer, size) == -1)
    {
        ps_log(0, LOG_ERROR("failed to send message of type [%c] - error [%s]"), ps_buffer, strerror(errno));
        return -1;
    }

    while (1)
    {
        read_count=read(ps_fd_control, ps_buffer, sizeof(ps_buffer));

        if (read_count != -1)
            break;

        if (errno == EINTR)
            continue;

        ps_log(0, LOG_ERROR("failed to read response - error [%s]"), strerror(errno));
        break;
    }

    if (ps_buffer[0] == PS_MSG_EXIT_STATUS)
    {
        ps_buffer[read_count]=0;
        ps_log(0, LOG_INFO("received exit status [%s]"), ps_buffer+1);
        exit(strtol(ps_buffer+1, 0, 10));
    }

    return read_count;
}
Пример #13
0
/*
//
// Solve for the bound energies given by the potential. 
// energies is a buffer of energies to test.
// bound_energies is where the actual bound energies will be stored.  It should be the same size as energies.
// both buffers should be of size buf_size.
// returns the number of bound energies found, 0 or negative for error
//
////////////////////////
//Solving the 1D TISE //
////////////////////////
//
//(0)    H * Psi = E * Psi
//
//E is the eignenvalue
//H is the hamiltonian operator: H = T + V = p^2/(2m) + V  
//    ... where p is the momentum operator, p = h/i * Div
//
//Moving to the effective mass regime we no longer solve for the wavefunction
//but instead we sove for an envelope function. Careful consideration shows that 
//if mass is allowed to vary with positon, m -> m(x), then simple subsitution of 
//m(x) for m in H causes H to become non-Hermitian. 
//Fortunately that can be worked around, the result is:
//
//(1)    T * F = -h_bar^2/2 * Div * ( m_eff(x,y,E)^-1 * Div * F )
//           ...note: F is the envelope function that is replacing the role of Psi
// 
//Put it all together to get the effective mass equation that we are going to
//use:
//    +--------------------------------------------------------------+                               
//(2) |    -h_bar^2/2 * Div * (1/m_eff * Div * F) + V * F = E * F    |  
//    +--------------------------------------------------------------+----> This is the main equation
//
//Note: Skip to equations (14) & (15) to see how we are going to proceed in the actual solver we are implenting.
//
	//Rearranging (2):
	//(3)    Div * (M * Div * F) = 2*(V-E)*F/h_bar^2
	//           ... note: Let 1/m_eff(x,y,E) = M  (For compactness of these notes only, it is still the effective mass that is position dependant)
	//take the coordinate system to be cartesisian and Div becomes: Div = d/dx + d/dy   -->   Div*F = dF/dx + dF/dy
	//(4)    Div * { M(dF/dx) + M(dF/dy) } = 2*(V-E)*F/h_bar^2
	//  
	//The LHS of (4) has a (2D) divergance of 2 terms that each have a product of two functions (M, dF), both of which depend on x and y. 
	//The chain rule will get invoked and there will be quite a few terms after we expand this
	//(5)    Div*(M(dF/dx)) + Div*(M(dF/dy)) = ...     ...note: I am leaving off the RHS for awhile
	//(6)    (d/dx + d/dy)*(M(dF/dx)) + (d/dx + d/dy)*(M(dF/dy)) = ...
	//(7)    (d/dx)*(M(dF/dx)) + (d/dy)*(M(dF/dx)) + (d/dx)*(M(dF/dy)) + (d/dy)*(M(dF/dy))= ...
	//(8)    (M)(d^2F/dx^2) + (dF/dx)(dM/dx)  + (M)(d^2F/(dxdy)) + (dF/dx)(dM/dy) + (M)(d^2F/(dydx)) + (dF/dy)(dM/dx) + (M)(d^2F/dy^2) + (dF/dy)(dM/dy) = ...
	//(9)    (M)(d^2F/dx^2) + (M)(d^2F/dy^2) + 2(M)(d^2F/(dxdy)) + (dF/dx)(dM/dx) + (dF/dx)(dM/dy) + (dF/dy)(dM/dx) + (dF/dy)(dM/dy) = ...
	//
	//The next step is to expand (9) out in terms of finite differences, here are some pieces that will be used:
	//(10)   dF/dx = (F[x+dx]-F[x-dx])/(2dx)
	//(11)   d^2F/dx^2 = ((F[x+dx+dx]-F[x+dx-dx])/(2dx) - (F[x-dx+dx]-F[x-dx-dx])/(2dx)) / (2dx)
	//                 = (F[x+2dx] - 2F[x] + F[x-2dx])*(2dx)^-2
	//(12)   d^2F/(dxdy) = (d/dy) * dF/dx
	//                   = (d/dy) * (F[x+dx]-F[x-dx])/(2dx)
	//                   = ((F[x+dx,y+dy]-F[x-dx,y+dy])/(2dx) - (F[x+dx,y-dy]-F[x-dx,y-dy])/(2dx)) / (2dy)
	//                   = ((F[x+dx,y+dy]-F[x-dx,y+dy]) - (F[x+dx,y-dy]-F[x-dx,y-dy])) / (2dx2dy)
	//
	//Using the finite differencing versions (10)-(12) of the derivatives in (9) and making M & F explcit functions of x & y: 
	//(9)    (M)(d^2F/dx^2) +         --> (13)    M[x,y] * (F[x+2dx,y] - 2F[x,y] + F[x-2dx,y])*(2dx)^-2 +  
	//       (M)(d^2F/dy^2) +         -->         M[x,y] * (F[x,y+2dy] - 2F[x,y] + F[x,y-2dy])*(2dy)^-2 + 
	//       2(M)(d^2F/(dxdy)) +      -->         2*M[x,y] * ((F[x+dx,y+dy]-F[x-dx,y+dy])-(F[x+dx,y-dy]-F[x-dx,y-dy]))/(2dx2dy) +
	//       (dF/dx)(dM/dx) +         -->         (F[x+dx,y]-F[x-dx,y])/(2dx) * (M[x+dx,y]-M[x-dx,y])/(2dx) + 
	//       (dF/dx)(dM/dy) +         -->         (F[x+dx,y]-F[x-dx,y])/(2dx) * (M[x,y+dy]-M[x,y-dy])/(2dy) +
	//       (dF/dy)(dM/dx) +         -->         (F[x,y+dy]-F[x,y-dy])/(2dy) * (M[x+dx,y]-M[x-dx,y])/(2dx) +
	//       (dF/dy)(dM/dy) = ...     -->         (F[x,y+dy]-F[x,y-dy])/(2dy) * (M[x,y+dy]-M[x,y-dy])/(2dy) = 2*(V[x,y]-E)*F[x,y]/h_bar^2
	//
	//The form in (13) can be rearranged so that you can use the shooting method. 
	//
//Instead of proceeding directly with that we are going to first write the 
//orginal 2nd order differential equation (3) as a system of coupled ODEs
//(3)    Div * (1/m_eff * Div * F) = 2*(V-E)*F/h_bar^2
//
//Choose simplifying units, such as: 
//     hbar = 1
//     m_electron = 1/2  ...note: 1/m_eff = 1/(m_electron * m_relative) = 2/m_relative
//
//The equation in (3) becomes simpler:
//    Div * (1/m_r * Div * F) = (V-E)*F
//       ...note that m_relative has been shortened to m_r 
// 
//Let:  
//(14)    G = (1/m_r) * Div * F
//Then (3) becomes:
//(15)   Div * G = (V-E)*F
//
//Rearranging (14) and (15) slightly:
//      +--------------------------------------------------------------+
//(16)  |             Div*F = G * m_r                                  |
//(17)  |             Div*G = F * (V-E)                                |
//      +--------------------------------------------------------------+----> These are the useful equations the solver will implement
//
//Expanding (16) with finite differencing:
//       Div*F = G*m_r
//             = dF/dx + dF/dy = G*m_r
//(18)         = (F[x+dx,y]-F[x-dx,y])/(2dx) + (F[x,y+dy]-F[x,y-dy])/(2dy) = G[x,y]*m_r[x,y]
//
//Expanding (17) with finite differencing:
//       Div*G = F * (V-E)
//             = dG/dx + dG/dy = F * (V-E)
//(19)         = (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*(V[x,y]-E)
//
//
/////////////////////
//Initial Conditons//
/////////////////////
//
//Take the structure to start in a barrier high enough enough to warrant using:
//(20)   F[0,0] = 0
//
//As for the initial value of G: G is porportional to the slope of F (the envelope function)
//solutions for the envelope function will be approx. exponentials inside barrier regions.
//Exponentials are fast functions so any reasonable value of G will get the value of F going 
//to where it is going to converge too. i.e. the overall tragectory will not be sensitive to
//the intial value of G if we are starting deep enough inside a tall barrier.
//
//(21)   G[0,0] = 1    
//
//additional FD notes:
/////////////////////////////////////////////////////////////////////////////////////////		  
//Consider three points on the x axis separated by distance "h" and indexed by "i" ... i.e. i-1, i, i+1  -->  x-h, x, x+h
//The function F(x) has the values at those positions: F[i-1], F[i], F[i+1]
//Taylor expand F(x) at the i-1 and the i+1 point:
//(22)   F[i-1] = F[i] - dF/dx|i * h + d^2F/dx^2|i * h^2/2! - d^3F/dx^3|i * h^3/3 + ...
//(23)   F[i+1] = F[i] + dF/dx|i * h + d^2F/dx^2|i * h^2/2! + d^3F/dx^3|i * h^3/3 + ...
//        ...where  dF/dx|i means take the derivative with respect to x at point i
//If you add (22) and (23) every other term in the expansions cancel, such that:
//(24)   F[i-1] + F[i+1] = 2*F[i] + d^2F/dx^2|i * h^2 + d^4F/dx^4|i + ...
//Rearrange (24) to put the seconcd derivative of F with respect to x on the LHS  
//(25)   d^2F/dx^2|i = (F[i+1] - 2*F[i] + F[i-1]) / h^2  -  d^4F/dx^4|i + ...
//Drop the higher order corrections b/c a second order finite differencing approx of d^2F/dx^2|i is all we should need
//     +----------------------------------------------------------------+
//(26) |  d^2F/dx^2|i = (F[i+1] - 2*F[i] + F[i-1]) / h^2 + O(h^2)       |
//     +----------------------------------------------------------------+--------> 
//The error contained in O(h^2) is of the order h^2 and therefore will be small.
//BTW, subtracting (22) and (23) you can rearrange to get an accurate approx for dF/dx|i
//     +---------------------------------------------------------+
//(27) |       dF/dx|i = (F[i+1] - F[i-1]) / (2h) + O(h^2)       |
//     +---------------------------------------------------------+--------> 
*/
PS_LIST ps_solve_1D(PS_DATA potential, PS_DATA effective_mass, PS_SOLVE_PARAMETERS *params) {
	char log_message[256];
	ps_log("PsiShooter -- a shooting method solver for the time independant Schrodinger equation under the effective mass approximation.\n");
	ps_log("Iterate through Energy Eigenvalues to find the lowest bound state.\n");      
	
	PS_LIST solution_list = ps_list_create(); // This is a linked list for storing solutions

	// wavefunction storage.  
	int N = potential->xsize; // used for generating strings with sprintf for sending to ps_log
	//	double dx = potential->xstep; //cm, size of differential length (TODO: Compute dx inside loop)
	double dx = ps_data_dx_at(potential, 2); // in case 0 to 1 is wierd, this will do 1 to 2	
	
	//sanity checks, the effective mass should be on the same grid as the potential
	if(N != effective_mass->xsize) {
		//problem
		sprintf(log_message, "\tThat's wierd... there are %d elements in the x axis mesh for the potential, but %d elements in the effective mass x axis mesh. Check to make sure the files for potential and effective mass have the same mesh. \n", N, effective_mass->xsize);
		ps_log(log_message);
		return NULL;
	}
	if(dx != ps_data_dx_at(effective_mass, 2)) {
		//more problems
		sprintf(log_message, "\tThat's wierd... the step size for the potential x axis is %e nm, and the the step size for the effective mass x axis mesh is %e nm. They need the same meshes to work", dx, ps_data_dx_at(effective_mass, 2));
		ps_log(log_message);
		return NULL;
	}
	
	double F[N]; //the envelope function (wavefunction)
	double F_endpoint[params->n_iter]; // We save the last value of the envelope for each solution
	double G[N]; //the aux function
	
	//F
	//intial eqn                 -->  Div*F = G*m_r	
	//convert to finite diff eqn -->  (F[x+dx,y]-F[x-dx,y])/(2dx) + (F[x,y+dy]-F[x,y-dy])/(2dy) = G[x,y]/M[x,y]	
	//convert to 1D              -->  (F[x+dx]-F[x-dx])/(2dx) = G[x]/M[x]	
	//rearrange                  -->  F[x+dx] = (2dx)*G[x]/M[x] + F[x-dx]
	//convert to c style         -->  F[i+1] = (2dx)*G[i]*m[i] + F[i-1]
	//                                F[i+1] = F_coeff*G[i]*m[i] + F[i-1]
	double F_coeff = 2*dx; //handy prefactor that would otherwise be for every point evaluated
	
	//G
	//intial eqn                 -->  Div*G = F * 2*(V-E)/h_bar^2
	//convert to finite diff eqn -->  (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*2*(V[x,y]-E[x,y])/h_bar^2
	//convert to 1D              -->  G[x+dx]-G[x-dx]/(2dx) = F[x]*2*(V[x]-E)/h_bar^2	
	//rearrange                  -->  G[x+dx] = (2dx)*F[x]*2*(V[x]-E)/h_bar^2 + G[x-dx]
	//convert to c style         -->  G[i+1] = 4*dx/hbar^2 * F[i]*(V[i]-E) + G[i-1]
	//                                G[i+1] = G_coeff * F[i]*(V[i]-E) + G[i-1]
    //double G_coeff = 4*dx/(HBAR_PLANCK_SQ); //handy prefactor that would otherwise be computed for every point evaluated 
	double G_coeff = 4*dx*G_COEFF; // Redefined to use M_ELECTRON/HBAR^2 using assuming units of nm and eV
    
	int bound_state_count = 0;	
	int i, iter;
	double E = params->energy_min;
	double Estep = (params->energy_max - params->energy_min)/(params->n_iter); 
	double V; //eV, Current potential
	double m_eff; 
	
	for (iter = 0; iter < params->n_iter; iter++) {

		//initial conditions
		F[0] = 0;
		G[0] = 1;
		F[1] = F_coeff * G[0] * m_eff + 0;    
		G[1] = G_coeff * F[0] * (V-E) + G[0]; 
		
		for(i=1; i<N; i++) {
			V = ps_data_value(potential, 0,i); //V[i]
			m_eff = ps_data_value(effective_mass, 0,i); //m_eff[i]
			
			//Lets eliminate bad solutions by checking if the forward and backwards solutions overlap
			F[i+1] = F_coeff * G[i] * m_eff + F[i-1];  //subbed in m_eff for m[i], To Do: support a position dependant
			G[i+1] = G_coeff * F[i] * (V-E) + G[i-1];	 // mass by storing different masses at different locations (add to the PS_DATA structure probably)		
		  
		  /*  
		//Mix the bidirectional and forward derivatives to prevent two seperate solutions from forming. This
	    //Makes the upper solutions stable and oscillation free. (Probably only required on the i==1 index -jns) 
		// TODO compare results of this branching statement with IF (1==i) ... ELSE ...
	    if (i%2==1){
	      F[i+1] = F_coeff * G[i] * m_eff + F[i]; 
	      //subbed in m_eff for m[i], To Do: support a position dependant
	      // mass by storing different masses at different locations (add to the PS_DATA structure probably)
	      G[i+1] = G_coeff * F[i] * (V-E) + G[i];
	    }
	    if (i%2==0){
	      F[i+1] = 2*F_coeff * G[i] * m_eff + F[i-1]; 
	      //subbed in m_eff for m[i], To Do: support a position dependant
	      // mass by storing different masses at different locations (add to the PS_DATA structure probably)
	      G[i+1] = 2*G_coeff * F[i] * (V-E) + G[i-1];
	    }
		 */
		}
		F_endpoint[iter] = F[N-1]; //store the last point of the solution in an array, use this to bracket roots by looking for sign changes (zero crossings)
		
		//Try to detect which solutions are eigen states (bound states)
		if((iter > 0) && 
				((F_endpoint[iter] > 0 && F_endpoint[iter-1] < 0) || 
				 (F_endpoint[iter] < 0 && F_endpoint[iter-1] > 0)))
		{ 
			/*
			 
			//if there was a change in sign between the last point of the prev and current envelope function then there probably was a zero crossing and there a solution test for a sign crossing
			//in order to reject solutions that appear to just be amplified/oscillating numerical error run
			//shoot solutions backwards to see if you get basically the same enevelope function. If they really
			//are just amplified error then the shots will look like this:
			// forwards:  ----.'.'.       increasing amplitude in this direcion--> 
			// backwards: .'.'.----    <--increasing amplitude in this direcion
			F[N] = 0;
			G[N] = 1;
			F[N-1] = F_coeff * G[0] * m_eff + 0;   
			G[N-1] = G_coeff * F[0] * (V-E) + G[0];

			//Lets eliminate bad solutions by checking if the forward and backwards solutions overlap
			for(i=N-1; i>0; i--) {
				V = ps_data_value(potential, 0,i); //V[i]
				F[i-1] = F[i+1] - F_coeff * G[i] * m_eff;  //subbed in m_eff for m[i], To Do: support a position dependant
				G[i-1] = G[i+1] + G_coeff * F[i] * (E-V);	 // mass by storing different masses at different locations (add to the PS_DATA structure probably)				
			}
			
			//ToDo:
			//see if the overlap is about unity.
			
			 */
			
			
			
			
			// Add the solution to the list of bound states
			PS_DATA wavefunction = ps_data_copy(potential); // copy the potential to get the x,y coordinate stuff and sizes
			ps_data_set_data(wavefunction, F); // Overwrite the potential with the wavefunction
			PS_SOLUTION *solution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION));
			solution->energy = E;
			solution->wavefunction = wavefunction;
			ps_list_add(solution_list, solution);
			bound_state_count++;
			
			// print a log message
			sprintf(log_message, "\tBoundstate number %d with E=%e found, F[N]=%e\n", bound_state_count, solution->energy, F[N]);
			ps_log(log_message);
		}

		// Consider removing this for speed
		//  sprintf(log_message, "\tE=%g eV\tF[N-1]=%g\n", E, F[N-1]);
		// ps_log(log_message);
			  	
		E += Estep; // Increment the energy
	}    	
	
	return solution_list;
}
Пример #14
0
void ps_daemon_main(int fd_initdata)
{
    struct sigaction sa_sigchld, sa_sigterm;
    int fd;

    if (ps_safe_to_change_name)
    {
        ps_program_name[2]='d';
        prctl(PR_SET_NAME, (unsigned long) ps_program_name, 0, 0, 0);
    }

    ps_log_stderr_output=0;
    chdir("/");
    umask(0);

    // close open files

    for (fd = 0; fd < 256;  fd++)
        if (fd != fd_initdata)
            close(fd);

    // sleep(5); /* NOTE: test if controller only returns after daemon up and running */

    fd = open("/dev/null", O_RDWR);

    if (fd != STDIN_FILENO)
        return;

    if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
        return;

    if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
        return;

    // NOTE: inherted log already closed..

    ps_fd_log=-1;
    if (strcmp(ps_daemon_logfilename, "none") != 0)
        ps_log_open(ps_daemon_logfilename);

    ps_log(0, LOG_INFO("daemon started"));

    if (read(fd_initdata, &ps_pid, sizeof(ps_pid)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("did not receive daemon pid - error [%s]"), strerror(errno));

    sigemptyset(&sa_sigchld.sa_mask);
    sa_sigchld.sa_handler = &ps_daemon_sigchld_handler;
    sa_sigchld.sa_flags = SA_RESTART | SA_NOCLDSTOP;

    if (sigaction(SIGCHLD, &sa_sigchld, 0) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGCHLD handler - error [%s]"), strerror(errno));

    sigemptyset(&sa_sigterm.sa_mask);
    sa_sigterm.sa_handler = &ps_daemon_sigterm_handler;
    sa_sigterm.sa_flags = 0;

    if (sigaction(SIGTERM, &sa_sigterm, 0) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGTERM handler - error [%s]"), strerror(errno));

    // change hostname

    snprintf(ps_buffer,sizeof(ps_buffer)-1,"ps_%s", ps_name);
    ps_buffer[sizeof(ps_buffer)-1]=0;
    ps_log(0, LOG_INFO("setting hostname to [%s]"), ps_buffer);

    if (sethostname(ps_buffer, strlen(ps_buffer)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to change hostname - error [%s]"), strerror(errno));

    ps_daemon_io_loop(fd_initdata);

    ps_log(0, LOG_INFO("daemon stopped"));
}
Пример #15
0
void ps_daemon_io_loop(int fd_initdata)
{
    int fd_listen, fd_control, read_count;

    // open listening socket

    if ((fd_listen=socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to create socket - error [%s]"), strerror(errno));

    if (bind(fd_listen, (struct sockaddr *) &ps_daemon_address, sizeof(ps_daemon_address)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to bind socket - error [%s]"), strerror(errno));

    if (listen(fd_listen, 5) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to listen on socket - error [%s]"), strerror(errno));

    // send ps_pid to process that ceated the daemon

    if (write(fd_initdata, &ps_pid, sizeof(ps_pid)) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to send ps_pid to controler - error [%s]"), strerror(errno));

    close(fd_initdata);

    while (ps_daemon_run)
    {
        fd_control=accept(fd_listen, 0, 0);

        if (fd_control == -1)
        {
            if (errno == EINTR)
                continue;

            ps_log(EXIT_FAILURE, LOG_ERROR("failed to accept controller connection - error [%s]"), strerror(errno));
        }

        while ((read_count = read(fd_control, ps_buffer, sizeof(ps_buffer))))
        {
            if (read_count == -1)
            {
                if (errno == EINTR)
                    continue;

                ps_log(0, LOG_INFO("controller disconnected - error [%s]"), strerror(errno));
                break;
            }

            // process control messages

            if (ps_buffer[0] == PS_MSG_RUN_PROGRAM)
            {
                ps_daemon_run_program(fd_listen, fd_control, ps_buffer+1);
                break;
            }

            if (ps_buffer[0] == PS_MSG_GET_PID)
            {
                sprintf(ps_buffer+1,"%d", ps_pid);

                if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1)
                    ps_log(0, LOG_ERROR("failed to send PID to controller - error [%s]"), strerror(errno));

                break;
            }

            if (ps_buffer[0] == PS_MSG_CHANGE_WORKINGDIR)
            {
                ps_buffer[0]= PS_MSG_EXIT_STATUS;

                if (chdir(ps_buffer+1) == -1)
                {
                    ps_log(0, LOG_ERROR("failed to change working dir to [%s] - error [%s]"), ps_buffer+1, strerror(errno));
                    sprintf(ps_buffer+1,"%d", EXIT_FAILURE);
                }
                else
                    sprintf(ps_buffer+1,"%d", EXIT_SUCCESS);

                if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1)
                    ps_log(0, LOG_ERROR("failed to send resultcode of CWD to controller - error [%s]"), strerror(errno));

                break;
            }

            if (ps_buffer[0] == PS_MSG_UNSHARE_NETWORK)
            {
                ps_buffer[0] = PS_MSG_EXIT_STATUS;

                if (ps_daemon_network_changed)
                {
                    ps_log(0, LOG_ERROR("network already unshared"));
                    sprintf(ps_buffer+1,"%d", EXIT_FAILURE);
                }
                else
                {
                    if (unshare(CLONE_NEWNET) == -1)
                    {
                        ps_log(0, LOG_ERROR("failed to unshare network - error [%s]"), strerror(errno));
                        sprintf(ps_buffer+1,"%d", EXIT_FAILURE);
                    }
                    else
                    {
                        ps_daemon_network_changed=1;
                        sprintf(ps_buffer+1,"%d", EXIT_SUCCESS);
                    }
                }

                if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1)
                    ps_log(0, LOG_ERROR("failed to sent resultcode of UNSHARE NETWORK to controller - error [%s]"), strerror(errno));

                break;
            }

            if (ps_buffer[0] == PS_MSG_UNSHARE_IPC)
            {
                ps_buffer[0] = PS_MSG_EXIT_STATUS;

                if (ps_daemon_ipc_changed)
                {
                    ps_log(0, LOG_ERROR("ipc already unshared"));
                    sprintf(ps_buffer+1,"%d", EXIT_FAILURE);
                }
                else
                {
                    if (unshare(CLONE_NEWIPC) == -1)
                    {
                        ps_log(0, LOG_ERROR("failed to unshare ipc - error [%s]"), strerror(errno));
                        sprintf(ps_buffer+1,"%d", EXIT_FAILURE);
                    }
                    else
                    {
                        ps_daemon_ipc_changed=1;
                        sprintf(ps_buffer+1,"%d", EXIT_SUCCESS);
                    }
                }

                if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1)
                    ps_log(0, LOG_ERROR("failed to sent resultcode of UNSHARE IPC to controller - error [%s]"), strerror(errno));

                break;
            }

            if (ps_buffer[0] == PS_MSG_CHANGE_ROOTFS)
            {
                ps_buffer[0] = PS_MSG_EXIT_STATUS;
                sprintf(ps_buffer+1,"%d", ps_daemon_change_rootfs(ps_buffer+1));

                if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1)
                    ps_log(0, LOG_ERROR("failed to sent resultcode of CHROOTFS to controller - error [%s]"), strerror(errno));

                break;
            }
        }

        close(fd_control);
    }
}
Пример #16
0
int ps_daemon_change_rootfs(char *newroot)
{
    ps_log(0, LOG_INFO("change root dir to [%s]"), newroot);

    if (ps_daemon_rootfs_changed)
    {
        ps_log(0, LOG_ERROR("rootfs already changed!"));
        return EXIT_FAILURE;
    }

    if (chdir(newroot) == -1)
    {
        ps_log(0, LOG_ERROR("failed to change rootdir to [%s] - error [%s]"), newroot, strerror(errno));
        return EXIT_FAILURE;
    }

    // create a directory where pivot_root can attach us_root

    if (mkdir("./us_rootfs", 0755) == -1)
    {
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create directory /us_rootfs - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }
    }

    if (unshare(CLONE_NEWNS) == -1)
    {
        ps_log(0, LOG_ERROR("unable to unshare mount namespace - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

	if (pivot_root(".", "./us_rootfs") == -1)
    {
		ps_log(0, LOG_ERROR("pivot_root failed - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
	}

    // unmount user space rootfs

    if (mount("", "/us_rootfs", "none", MS_REC | MS_PRIVATE, "") == -1)
    {
        ps_log(0, LOG_ERROR("failed to re-mount /us_rootfs as private - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (umount2("/us_rootfs", MNT_DETACH) == -1)
    {
        ps_log(0, LOG_ERROR("failed to unmount /us_rootfs - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (rmdir("/us_rootfs") == -1)
        ps_log(0, LOG_ERROR("failed to remove directory /us_rootfs - error [%s]"), strerror(errno));


	if (chdir("/") == -1)
    {
        ps_log(0, LOG_ERROR("failed to change to / - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
	}

    if (mkdir("/proc", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /proc directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

    if (mount("", "/proc","proc", MS_NODEV | MS_NOEXEC | MS_NOSUID,"") == -1)
    {
        ps_log(0, LOG_ERROR("failed to re-mount /proc - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (mkdir("/dev", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /dev directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

    if (mkdir("/dev/pts", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /dev/pts directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

	if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL , "newinstance,ptmxmode=0666") == -1)
    {
		ps_log(0, LOG_ERROR("unable to mount /dev/pts - error [%s]"), strerror(errno));
		return EXIT_FAILURE;
	}

	if (access("/dev/ptmx", F_OK) == -1)
    {
		if (symlink("/dev/pts/ptmx", "/dev/ptmx") == -1)
            ps_log(0, LOG_ERROR("unable to create /dev/ptmx symlink - error [%s]"), strerror(errno));
	}

    ps_daemon_rootfs_changed=1;
    return EXIT_SUCCESS;
}
Пример #17
0
void ps_terminal_run_program(int fd_control, char *arguments)
{
    int fd_master, pid_program, exit_status;
    socklen_t sizeof_credentials;
    struct ucred credentials;

    // run the program under the uid of the user that connected to the server

    sizeof_credentials = sizeof(credentials);

    if(getsockopt(fd_control, SOL_SOCKET, SO_PEERCRED, &credentials, &sizeof_credentials) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to get uid of controlling user - error [%s]"), strerror(errno));

    if (ps_terminal_set_user(credentials.uid) == EXIT_FAILURE)
    {
        ps_terminal_send_exitcode(fd_control, EXIT_FAILURE);
        return;
    }

    // create a pseudoterminal

    fd_master = posix_openpt(O_RDWR | O_NOCTTY);

    if (fd_master == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("posix_openpt() failed -error [%s]"), strerror(errno));

    if (grantpt(fd_master) == -1)
        ps_log(0 /*EXIT_FAILURE*/, LOG_ERROR("grantpt() failed - error [%s]"), strerror(errno));

    if (unlockpt(fd_master) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unlockpt() failed - error [%s]"), strerror(errno));

    // fork a new process to run the program

    pid_program=fork();

    if (pid_program == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unable to fork - error [%s]"), strerror(errno));

    if (pid_program == 0)
    {
        close(fd_control);
        ps_program_exec(fd_master, arguments);
        ps_log(EXIT_FAILURE, LOG_ERROR("trespassing error!"));
    }

//  TEST for a problem with bash. It seems that bash disables cntl-d (eof) handling
//  in the pseudo terminal if there is input before it outputs its prompt. This requires
//  us to use the exit statement in a script that is inside a here-document. The sh shell
//  does not have this behaviour. Needs further investigation...
//sleep(1);

    ps_terminal_io_loop(fd_control, fd_master);

    if (waitpid(pid_program, &exit_status, 0) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("waitpid failed - error [%s]"), strerror(errno));

    // return status to controller

    ps_log(0, LOG_INFO("after wait - exit_status [%d]"), exit_status);
    ps_terminal_send_exitcode(fd_control, exit_status);
    close(fd_master);
    close(fd_control);
}
Пример #18
0
void ps_control_io_loop()
{
    // read from STDIN -> fd_control
    // read from fd_control -> STDOUT
    // stop if fd_control closed

    fd_set fdset;
    int read_count, write_count, count, stdin_closed;

    stdin_closed=0;

    while (1)
    {
        FD_ZERO(&fdset);
        FD_SET(ps_fd_control, &fdset);

        if (!stdin_closed)
            FD_SET(STDIN_FILENO, &fdset);

        if (select(ps_fd_control+1, &fdset, 0,0,0) == -1)
            ps_log(EXIT_FAILURE, LOG_ERROR("select failed - error [%s]"), strerror(errno));

        memset(ps_buffer,0,sizeof(ps_buffer));

        if (FD_ISSET(ps_fd_control, &fdset))
        {
            read_count=read(ps_fd_control, ps_buffer, sizeof(ps_buffer));

            if (read_count == 0) // EOF
                break;

            if (read_count == -1)
            {
                if (errno == EINTR)
                    continue;

                ps_log(0, LOG_ERROR("failed to read from control socket - error [%s]"), strerror(errno));
                break;
            }

            if (ps_buffer[0] == PS_MSG_EXIT_STATUS)
            {
                ps_buffer[read_count]=0;
                ps_log(0, LOG_INFO("received exit status [%s]"), ps_buffer+1);
                exit(strtol(ps_buffer+1, 0, 10));
            }

            if (ps_buffer[0] == PS_MSG_GET_PID)
            {
                ps_log(0, LOG_INFO("received pid [%s]"), ps_buffer+1);
                write(STDOUT_FILENO, ps_buffer+1, strlen(ps_buffer+1));
                write(STDOUT_FILENO, "\n", 1);
                exit(EXIT_SUCCESS);
            }

            write_count=1;

            while (write_count != read_count)
            {
                count=write(STDOUT_FILENO, ps_buffer+write_count, read_count-write_count);

                if (count == 0)
                    continue;

                if (count == -1)
                {
                    if (errno == EINTR)
                        continue;

                    ps_log(0, LOG_ERROR("failed to write to stdout - error [%s]"), strerror(errno));
                    break;
                }

                write_count+=count;
            }
        }

        if (FD_ISSET(STDIN_FILENO, &fdset))
        {
            ps_buffer[0]=PS_MSG_DATA;
            read_count=read(STDIN_FILENO, ps_buffer+1, sizeof(ps_buffer)-1);

            if (read_count == 0) // EOF
            {
                stdin_closed=1;

                // send cntrl-d to the program space terminal

                ps_buffer[0]=PS_MSG_DATA;
                ps_buffer[1]=4;

                if (write(ps_fd_control, ps_buffer, 2) == -1)
                    ps_log(0, LOG_ERROR("failed to write cntrl-d to pst - error [%s]"), strerror(errno));

                continue;
            }

            if (read_count == -1)
            {
                if (errno == EINTR)
                    continue;

                ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from terminal stdin - error [%s]"), strerror(errno));
            }

            read_count++;
            write_count=0;

            while (write_count != read_count)
            {
                count=write(ps_fd_control, ps_buffer+write_count, read_count-write_count);
                //LOG_BUFFER_HEX("sending data", ps_buffer, count);

                if (count == 0)
                    continue;

                if (count == -1)
                {
                    if (errno == EINTR)
                        continue;

                    ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to control socket - error [%s]"), strerror(errno));
                }

                write_count+=count;
            }
        }
    }
}
Пример #19
0
void ps_terminal_io_loop(int fd_control, int fd_master)
{
    fd_set fdset;
    int fd_max, read_count, write_count, count;

    ps_buffer[0]=PS_MSG_DATA;
    fd_max=(fd_control > fd_master) ? fd_control : fd_master;

    while (1)
    {
        FD_ZERO(&fdset);
        FD_SET(fd_control, &fdset);
        FD_SET(fd_master, &fdset);

        if (select(fd_max+1, &fdset, 0, 0, 0) == -1)
            ps_log(EXIT_FAILURE, LOG_ERROR("select failed - error [%s]"), strerror(errno));

        // handle data comming from pseudo terminal

        if (FD_ISSET(fd_master, &fdset))
        {
            ps_buffer[0]=PS_MSG_DATA;
            read_count=read(fd_master, ps_buffer+1, sizeof(ps_buffer)-1);

            if (read_count == 0)
            {
                ps_log(0, LOG_INFO("fd_master closed"));
                break;
            }

            if (read_count == -1)
            {
                if (errno == EINTR)
                    continue;

                if (errno == EIO)
                {   // not an error, program running in terminal has stopped
                    ps_log(0, LOG_INFO("got EIO"));
                    break;
                }

                ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from terminal - error [%s]"), strerror(errno));
            }

            count=read_count+1;

            while (1)
            {
                write_count=write(fd_control, ps_buffer, count);

                if (write_count == 0)
                    continue;

                if (write_count == -1)
                {
                    if (errno == EINTR)
                        continue;

                    ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to control socket - error [%s]"), strerror(errno));
                }

                if (write_count != count) // write must be atomic
                    ps_log(EXIT_FAILURE, LOG_ERROR("partial write to control socket"));

                break;
            }
        }

        // handle data comming from users terminal

        if (FD_ISSET(fd_control, &fdset))
        {
            read_count=read(fd_control, ps_buffer, sizeof(ps_buffer));

            if (read_count == 0)
                break;

            if (read_count == -1)
            {
                if (errno == EINTR)
                    continue;

                ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from control socket - error [%s]"), strerror(errno));
            }

            // TODO check for control messages, eg change terminal attributes
            // for now assume only data messages

            write_count=1;

            while (write_count != read_count)
            {
                count=write(fd_master, ps_buffer+write_count, read_count-write_count);
                //LOG_BUFFER_HEX("write to terminal", ps_buffer+write_count, count);

                if (count == 0)
                    continue;

                if (count == -1)
                {
                    if (errno == EINTR)
                        continue;

                    ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to terminal - error [%s]"), strerror(errno));
                }

                write_count+=count;
            }
        }
    }
}
Пример #20
0
void ps_program_exec(int fd_master, char *arguments)
{
    struct winsize windowsize;
    char *argv[64];
    char *p;
    int i, n, fd_slave;

    if (setsid() == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("setsid failed - error [%s]"), strerror(errno));

    fd_slave=open(ptsname(fd_master), O_RDWR);

    if (fd_slave == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unable to open slave with name [%s] - error [%s]"), ptsname(fd_master), strerror(errno));

    ps_log(0, LOG_INFO("fd_master [%d] fd_slave [%d] ptsname [%s]"), fd_master, fd_slave, ptsname(fd_master));

    if (dup2(fd_slave, STDIN_FILENO) != STDIN_FILENO)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDIN_FILENO - error [%s]"), strerror(errno));

    if (dup2(fd_slave, STDOUT_FILENO) != STDOUT_FILENO)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDOUT_FILENO - error [%s]"), strerror(errno));

    if (dup2(fd_slave, STDERR_FILENO) != STDERR_FILENO)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDERR_FILENO - error [%s]"), strerror(errno));

    if (fd_slave > STDERR_FILENO)
        close(fd_slave);

    close(fd_master);

    // get terminal columns and rows

    memset(&windowsize, 0, sizeof(windowsize));

    p=arguments;
    windowsize.ws_col=atoi(p);
    p+=strlen(p)+1;
    windowsize.ws_row=atoi(p);
    p+=strlen(p)+1;

    if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &windowsize) == -1)
        ps_log(0, LOG_INFO("failed to set window size to w [%d] h [%d] - error [%s]"), windowsize.ws_col, windowsize.ws_row, strerror(errno));

    // program arguments

    n=atoi(p);
    p+=strlen(p)+1;

    for (i=0; i < n; i++)
    {
        argv[i]=p;
        p+=strlen(p)+1;
    }

    argv[i]=0;
    execvp(argv[0], argv);

    // this code only executes if execvp failes
    ps_log(EXIT_FAILURE, LOG_ERROR("failed to run program [%s] - error [%s]"), argv[0], strerror(errno));
}
Пример #21
0
/*
//
//The 2D version of the solving engine.
//
//intial eqn                 
//-->  Div*F = G/M	
//
//convert to finite diff eqn, use a uniform mesh, Let, dx = dy = d  and Let P[x,y] = G[x,y]/M[x,y] = G*m
//-->  (F[x+d,y]-2F[x,y]+F[x-d,y])/d^2 + (F[x,y+d]-2F[x,y]+F[x,y-d])/d^2 = P[x,y]
//
//rearrange:
//-->  F[x+d,y] + F[x-d,y] + F[x,y+d] + F[x,y-d] - 4F[x,y] = d^2 * P[x,y]
//
//convert to c style: Let x = x0+j*d     and    y = y0+l*d 
//                  where j = 0,1,2...J  and    l = 0,1,2...L
//-->  F[j+1,l] + F[j-1,l] + F[j,l+1] + F[j,l-1] - 4F[j,l] = d^2 * P[j,l]y
//
//Goal: make a linear system of eqns in matrix form -- firstly we make a vector out of F. i.e. map j,l to a linear index 'i'
//     Let, i = j(L+1) + l   ...where j = 0,1,...J and l = 0,1,...L
//-->  F[i+L+1] + F[i-(L+1)] + F[i+1] + F[i-1] - 4F[i] = d^2 * P[i]
//    ...where this eqn holds for the interior points: j = 1,2,...,J and l = 1,2,...,L
//
//On the boundries F should be specified, i.e. where:
//    j = 0    or    i = 0, 1, 2, ..,L
//    j = J    or    i = J(L+1), J(L+1)+1, J(L+1)+2, ...,J(L+1)+L
//    l = 0    or    i = 0, (L+1), 2(L+1), ..., J(L+1)
//    l = L    or    i = L, (L+1)+L, 2(L+1)+L, ..., J(L+1)+L         */
PS_LIST ps_solve_2D(PS_DATA potential, PS_SOLVE_PARAMETERS *params) {
	
	char log_message[256];
	ps_log("PsiShooter -- a shooting method solver for the time independant Schrodinger equation under the effective mass approximation.\n");
	
    // This is a linked list for storing solutions
	PS_LIST solution_list = ps_list_create();

    ps_log("Iterate through Energy Eigenvalues to find the lowest bound state.\n");      
	
	// wavefunction storage.  
	int Nx = potential->xsize; // used for generating strings with sprintf for sending to ps_log
	int Ny = potential->ysize; // used for generating strings with sprintf for sending to ps_log
	
	//	double dx = potential->xstep; //cm, size of differential length 
	//(TODO: Compute dx inside loop in order to support meshes with non-uniform differential steps)
	double dx = ps_data_dx_at(potential, 2); 
	double dy = ps_data_dy_at(potential, 2); // 0 to 1 is wierd, maybe. 
	double dx_dy = dx/dy; 
	double dy_dx = dy/dx;
	//F
	//intial eqn                 -->  Div*F = G * m_eff	
	//convert to finite diff eqn -->  (F[x+dx,y]-F[x,y])/dx + (F[x,y]-F[x,y-dy])/dy = G[x,y]M[x,y]	
	//rearrange                  -->  F[x+dx,y]-F[x,y] + dx*(F[x,y]-F[x,y-dy])/dy = dx*G[x,y]/M[x,y]
	//                           -->  F[x+dx,y] = dx*G[x,y]/M[x,y]+F[x,y]-dx/dy*(F[x,y]-F[x,y-dy])
	//                                What does this mean for our 2D simulations? The more closely spaced the y
	//                                Coordinate mesh points are, the more significant their effects will be. That
	//                                Is pretty terrible for us. 
	//
	//                                We need to decouple the coordinates so we don't need to know future F and G from
	//                                from future calculated y mesh points...
	//                                Is there some other way we can decouple them? We can't just look back instead of forward.
	//
	//                                How about we fill the array with 1D shots across the 1 direction, and then refill
	//                                with the 2D shots? Then the array will have some approximate knowledge of the future
	//                                and the algorithm might work.
	
	//convert to c style         -->  F[x+dx,y] = F[i][j+1]
	// *****README*******    	 --> (NOTE: x is iterated over with j index. x=columns, i=rows) -jns

	//in 2D                      -->  F[i][j+1] = dx*G[i][j]/M[i][j] + F[i][j] - dx/dy*(F[i][j]-F[i-1][j])

	
	//convert to 1D              -->  (F[x+dx]-F[x-dx])/(2dx) = G[x]/M[x]	
	//rearrange                  -->  F[x+dx] = (2dx)*G[x]/M[x] + F[x-dx]
	//convert to c style         -->  F[i+1] = (2dx)*G[i]*m[i] + F[i-1]
	//                                F[i+1] = F_coeff*G[i]*m[i] + F[i-1]
	double F_coeff = dx; //handy prefactor that would otherwise be for every point evaluated
	//from dx to 2*dx jh sometime in may
	
	//G
	//intial eqn                 -->  Div*G = F * 2*(V-E)/h_bar^2
	//convert to finite diff eqn -->  (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*2*(V[x,y]-E[x,y])/h_bar^2
	//in 2d:                     -->  G[x+dx,y] = (2dx)*F[x,y]*2*(V[x,y]-e[x,y])/h_bar^2+G[x-dx][y]-(2dx)/(2dy)(G[x,y+dy]-G[x,y-dy])
	//                           -->  G[i][j+1] = G_coeff * F[i][j]*(V[i][j]-E) + G[i][j-1] - dx/dy(G[i+1][j] + G[i-1][j])
	//
	// The equivalent FWD DIFFEQ -->  G[x+dx][y] = dx*F[x,y]*2*(V[x,y] - e[x,y])/h_bar^2 + G[x,y] - dx/dy(G[x,y] - G[x,y-dy])
	// 						     -->  G[i][j+1] = dx*F[i][j]*2*(V[i][j] - e[i][j])/h_bar^2 + G[i][j] - dx/dy(G[i][j] - G[i-1][j])


	//convert to 1D              -->  G[x+dx]-G[x-dx]/(2dx) = F[x]*2*(V[x]-E)/h_bar^2	
	//rearrange                  -->  G[x+dx] = (2dx)*F[x]*2*(V[x]-E)/h_bar^2 + G[x-dx]
	//convert to c style         -->  G[i+1] = 4*dx/hbar^2 * F[i]*(V[i]-E) + G[i-1]
	//                                G[i+1] = G_coeff * F[i]*(V[i]-E) + G[i-1]
//	double G_coeff = 2*dx/(HBAR_PLANCK_SQ); //handy prefactor that would otherwise be computed for every point evaluated 
	//from 4*dx to 2*dx jh sometime in may

	double G_coeff = 2*dx*G_COEFF;
	
	//dx = dy here.
	double F[Nx][Ny]; //the envelope function (wavefunction)
	double f_cache[params->n_iter]; // We cache the last value of the envelope for each solution
	double G[Nx][Ny]; //the aux function
	int bound_state_count = 0;	
	int threshold_set_flag = 0; 
	double F_threshold = 0;
	int i, j, iter;
	double E = params->energy_min;
	double Estep = (params->energy_max - params->energy_min)/(params->n_iter); 
	double V; //meV, Current potential
//	double m_eff = MASS_ELECTRON*M_EFF_GAAS;
	double m_eff = M_EFF_GAAS;

	// To Do: make the electron mass be part of the structure that we are simulating. i.e. 
	//in general it can be a position dependant quantity just like the potential 
	//(think heterostructures with different band edge curvatures)
		
	for (iter = 0; iter < params->n_iter; iter++) {

	  //Going to try filling the array with y-direction shots and then running the 2D shots based on those.
		
	  //initial conditions
	  for (j=0; j<Nx; j++){
	    F[0][j] = 0;
	    G[0][j] = 1;
		F[1][j] = 1;
		G[1][j] = 1;
	  }
	
	  for(i=1; i<Ny-1; i++) {

		    for(j=1; j<Nx-1; j++) {
		     	V = ps_data_value(potential, i,j); //V[i][j]
				// 5-point stencil in X and Y
				F[i+1][j] = dx*dx*m_eff*G[i][j]  - F[i][j+1] - F[i][j-1] - F[i-1][j] + 4*F[i][j];
				G[i+1][j] = 2*dx*dx*G_COEFF*(V-E)*F[i][j] - G[i][j+1] - G[i][j-1] - G[i-1][j] + 4*G[i][j];
		    }
			// For First and last point, Compute slope in x direction for F and G directly

			// F[x+3] = F[x] + 3h*F'[x] + (3h)^2/2!*F''[x]  (Taylor Expansion)
			// F'[x] = 1/(12*h)*[-F[x+2] + 8*F[x+1] - 8*F[x-1] + F[x-2]]  (5-point stencil)
			// F''[x] = 1/(12*h*h)*[-F[x+2] + 16*F[x+1] -30*F[x] +16*F[x+1] - F[x-2]] (5-point stencil)
			G[i+1][j] = G[i+1][j-3] + 0.25*(-G[i+1][j-1] + 8*G[i+1][j-2] - 8*G[i+1][j-4] + G[i+1][j-5]) + 9.0/24.0*(-G[i+1][j-5] + 16*G[i+1][j-4] - 30*G[i+1][j-3] + 16*G[i+1][j-2] - G[i+1][j-1]);
			F[i+1][j] = F[i+1][j-3] + 0.25*(-F[i+1][j-1] + 8*F[i+1][j-2] - 8*F[i+1][j-4] + F[i+1][j-5]) + 9.0/24.0*(-F[i+1][j-5] + 16*F[i+1][j-4] - 30*F[i+1][j-3] + 16*F[i+1][j-2] - F[i+1][j-1]);			

			// F[x-3] = F[x] - 3h*F'[x] + (3h)^2/2!*F''[x]  (Taylor Expansion)
			// F'[x] = 1/(12*h)*[-F[x+2] + 8*F[x+1] - 8*F[x-1] + F[x-2]]
			// F''[x] = 1/(12*h*h)*[-F[x+2] + 16*F[x+1] -30*F[x] +16*F[x+1] - F[x-2]]
			G[i+1][0] = G[i+1][3] - 0.25*(-G[i+1][5] + 8*G[i+1][4] - 8*G[i+1][2] + G[i+1][1]) + 9.0/24.0*(-G[i+1][5] + 16*G[i+1][4] - 30*G[i+1][3] + 16*G[i+1][2] - G[i+1][1]);
			F[i+1][0] = F[i+1][3] - 0.25*(-F[i+1][5] + 8*F[i+1][4] - 8*F[i+1][2] + F[i+1][1]) + 9.0/24.0*(-F[i+1][5] + 16*F[i+1][4] - 30*F[i+1][3] + 16*F[i+1][2] - F[i+1][1]);			
	  }
	  //Why not just look at the change on the very last point? This definitely won't be representative, but it
	  //might be useful during debugging.
	  // It needs to check the entire boundary. (jns)
	  f_cache[iter] = F[Nx-1][Ny-1];
		
	  // Consider removing this for speed
	  //         sprintf(log_message, "\tE=%g eV\tF[N-1]=%g\n", E/EV_TO_ERGS, F[N-1]);
	  // ps_log(log_message);
		
	  //Try to detect which solutions are eigen states (bound states)
	  //if((iter > 0) && ((f_cache[iter] > 0 && f_cache[iter-1] < 0) || (f_cache[iter] < 0 && f_cache[iter-1] > 0))) { 
	    //if there was a change in sign between the last point of the prev
	    // and current envelope function then there was a zero crossing and there a solution
	    // test for a sign crossing

	    PS_DATA wavefunction = ps_data_copy(potential); // copy the potential
	    ps_data_set_data(wavefunction, (double*)F); // Overwrite the potential with the wavefunction
			
	    PS_SOLUTION *solution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION));
	    solution->energy = E;
	    solution->wavefunction = wavefunction;
			
	    // Add the solution to the list of bound states
	    ps_list_add(solution_list, solution);

		// Save the g solutions
		PS_DATA g = ps_data_copy(potential);
		ps_data_set_data(g, (double*)G);
		PS_SOLUTION *gsolution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION));
		gsolution->energy = E;
		gsolution->wavefunction = g;
		ps_list_add(g_solutions, gsolution);
		
	    // print a log message
        sprintf(log_message, "\tBoundstate number %d with E=%e found, F[Nx][Ny]=%e < F_threshold=%e\n", ++bound_state_count, solution->energy/EV_TO_ERGS, F[Nx][Ny], F_threshold);
	    ps_log(log_message);
	    //}

	  // Increment the energy
	  E += Estep;
	}    	
	
	return solution_list;
}
Пример #22
0
void ps_control_save_terminal_attributes(void)
{
    if (tcgetattr(STDIN_FILENO, &ps_saved_terminal_attributes) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("unable to save terminal attributes - error [%s]"), strerror(errno));
}
Пример #23
0
int main(int argc, char *argv[])
{
    ps_program_name=argv[0];
    ps_control_open_logfile();

    if (argc == 2)
        if ( (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0))
        {
            printf("%s", ps_control_options);
            return EXIT_SUCCESS;
        }

    if (argc < 3)
        ps_log(EXIT_FAILURE, LOG_ERROR("too few parameters"));

    ps_init();
    ps_set_name(argv[1]);
    ps_control_check_input(argv[2], argc-3);
    ps_log(0, LOG_INFO("creating controller"));

    if (strcmp(argv[2],"--create") == 0)
    {
        ps_control_prepare_daemon_logfile((argc == 4) ? argv[3] : "none");
        ps_control_create_daemon();
    }
    else
    {
        ps_control_connect_daemon();

        if (strcmp(argv[2],"--pid") == 0)
        {
            ps_pid=ps_control_get_daemon_pid();
            printf("%d\n",(ps_pid == -1) ? 0 : ps_pid);

            if (ps_pid == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("--pid: failed to receive daemon PID"));
        }

        if (strcmp(argv[2],"--kill") == 0)
        {
            ps_pid=ps_control_get_daemon_pid();

            if (ps_pid <= 1)
                ps_log(EXIT_FAILURE, LOG_ERROR("--kill : could not determine daemon PID"));

            if (kill(ps_pid, SIGTERM) == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("--kill : failed to kill daemon - error [%s]"), strerror(errno));
        }

        if (ps_fd_control == -1)
            return EXIT_FAILURE;

        if (strcmp(argv[2],"--net") == 0)
            ps_control_unshare_network();

        if (strcmp(argv[2],"--ipc") == 0)
            ps_control_unshare_ipc();

        if (strcmp(argv[2],"--chrootfs") == 0)
            ps_control_change_rootfs(argv[3]);

        if (strcmp(argv[2],"--cwd") == 0)
            ps_control_change_workingdir(argv[3]);

        if (strcmp(argv[2],"--run") == 0)
        {
            if (isatty(STDIN_FILENO))
            {
                ps_control_save_terminal_attributes();
                atexit(ps_control_restore_terminal_attributes);
                ps_control_set_terminal_raw_mode();
            }

            ps_control_run_program(argc-3, argv+3);
        }
    }

    ps_log(0, LOG_INFO("closing controller"));
    return EXIT_SUCCESS;
}
Пример #24
0
void ps_control_restore_terminal_attributes(void)
{
    if (tcsetattr(STDIN_FILENO, TCSANOW, &ps_saved_terminal_attributes) == -1)
        ps_log(0, LOG_ERROR("unable to restore terminal attributes - error [%s]"), strerror(errno));
}
Пример #25
0
//
// PsiShooter program entry point
int main(int argc, char **argv) {

	char msg[256];
	PS_DATA potential;
	PS_DATA effective_mass;
	int solver_dimension;
	PS_SOLUTION *s;
	
	if (1 == argc) {
		solver_dimension = 1;
		
		sprintf(msg, "No file specified. Using builtin potential.\n");
		ps_log(msg);
		//get a 1D test potential
		potential = test_potential_2D();
		
		FILE *f = fopen("V_2d.dat", "w");
		ps_data_write_bin(potential, f);
		fclose(f);
		
	} 
	else if (3 == argc) {
		solver_dimension = 1;
		
		// Interpret argument as file to process
		FILE *infile_potential = fopen(argv[1], "r");
		if (infile_potential == NULL) {
			sprintf(msg, "Error opening file '%s'\n", argv[1]);
			ps_log(msg);
			return PS_ERROR_FILE_NOT_FOUND;  // Exit abnormally			
		} else {
			sprintf(msg, "Using potential from file '%s'\n", argv[1]);
			ps_log(msg);
			potential = ps_data_read_bin(infile_potential);
			fclose(infile_potential);
		}
		
		FILE *infile_mass = fopen(argv[2], "r");
		if (infile_mass == NULL) {
			sprintf(msg, "Error opening file '%s'\n", argv[2]);
			ps_log(msg);			
			return PS_ERROR_FILE_NOT_FOUND;  // Exit abnormally
			
		} else {
			sprintf(msg, "Using effective mass from file '%s'\n", argv[2]);
			ps_log(msg);			
			effective_mass = ps_data_read_bin(infile_mass);
			fclose(infile_mass);
			solver_dimension = 1;
		}		
	} 
	else if (4 == argc) {
		// lets say that if there is a 4th argument, it is a 2d request.
		// Interpret argument as file to process
		FILE *infile = fopen(argv[1], "r");
		if (infile == NULL) {
			sprintf(msg, "Error opening file '%s'\n", argv[1]);
			ps_log(msg);
			return PS_ERROR_FILE_NOT_FOUND;  // Exit abnormally
		} else {
			sprintf(msg, "Using *2D* potential from file '%s'\n", argv[1]);
			ps_log(msg);
			potential = ps_data_read_bin(infile);
			fclose(infile);
			solver_dimension = 2;
		}
	}
	else {
		//unrecognized combination of arguements. Show usage.
		sprintf(msg, "Arguements not understood. Usage:\npsi_shooter potential_file.in effective_mass_file.in\n");
		ps_log(msg);
	}

	// Setup solution parameters
	PS_SOLVE_PARAMETERS params;
	params.energy_min = ps_data_min_value(potential);
	params.energy_max = ps_data_max_value(potential);
	params.n_iter = 100; // The number of energies to try
	double e_step = (params.energy_max - params.energy_min)/(params.n_iter);
		
	sprintf(msg,"Testing energies from %g to %g in %g increments\n", params.energy_min/EV_TO_ERGS, params.energy_max/EV_TO_ERGS, e_step/EV_TO_ERGS);
	ps_log(msg);
	
	// Create a list for solutions
	PS_LIST solutions = ps_list_create();
	g_solutions = ps_list_create();
	
	  // 1st pass coarse Solver
	if (1 == solver_dimension) {
		// 1d solver with coarse/fine pass
		PS_LIST coarse_solutions = ps_solve_1D(potential, effective_mass, &params);	
		 // For each solution, do a second pass with finer grained energy steps
		 s = ps_list_front(coarse_solutions);
		 while (s != NULL) {
		   // I know that ps_solve_1d looks for a sign crossing as it increases
		   // the test energy E and saves the solution for the larger energy
		   params.energy_min = s->energy - e_step;
		   params.energy_max = s->energy;
		   params.n_iter = 100;

		   // Add the fine grain solutions to the final list
		   PS_LIST e_solutions = ps_solve_1D(potential, effective_mass, &params);
		   ps_list_add_all(solutions, e_solutions);
		   ps_list_destroy(e_solutions); // Destroy the list without destroying the data.

		   // Next loop iteration
		   s = ps_list_next(coarse_solutions);
		 }
		ps_list_destroy_all(coarse_solutions);

	} else {
		// 2d solver
		PS_LIST coarse_solutions = ps_solve_2D(potential, &params);
		ps_list_add_all(solutions, coarse_solutions);
		ps_list_destroy(coarse_solutions);
	}

	// Write out solutions
	sprintf(msg, "Found %i solutions.  Writing to E.txt and BS.dat\n", ps_list_size(solutions));
	ps_log(msg);
	
	FILE *efile = fopen("E.txt", "w");
	fprintf(efile, "# Bound State Energies [eV]\n");
	FILE *bsfile = fopen("BS.dat", "w");
	s = ps_list_front(solutions);
	while (s != NULL) {
		// Write the energies to the energy file
		fprintf(efile, "%g\n", s->energy/EV_TO_ERGS);
		// Write the wavefunctions to the solutino file
		ps_data_write_bin(s->wavefunction, bsfile);
		s = ps_list_next(solutions);
	}
	fclose(bsfile);
	fclose(efile);

	FILE *gfile = fopen("G.dat", "w");
	s = ps_list_front(g_solutions);
	while (s != NULL) {
		ps_data_write_bin(s->wavefunction, gfile);
		s = ps_list_next(g_solutions);
	}
	fclose(gfile);
	ps_list_destroy_all(g_solutions);
	
	//clean up
	ps_data_destroy(potential);
	ps_list_destroy_all(solutions);

	return PS_OK;
}
Пример #26
0
void ps_control_create_daemon(void)
{
    int fd_initdata[2];

    ps_log(0, LOG_INFO("creating daemon"));
    ps_safe_to_change_name=(strcmp(ps_program_name,"psc") == 0) ? 1 : 0;

    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd_initdata) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to create socketpair for daemon initialization - error [%s]"), strerror(errno));

    // become a child of the init process by forking and closing the parent process.

    switch (fork())
    {
        case -1:
            ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 1"));

        case 0:
            // become the leader of new session

            if (setsid() == -1)
                return;

            // do another fork to prevent the daemon to open a controlling terminal in the future.
            // use the clone() function to create new PID and UTS namespaces for the child.

            long stack_size = 4*sysconf(_SC_PAGESIZE);
            char *stack;
            int  pid_daemon;

            if (!(stack = malloc(stack_size)))
                ps_log(EXIT_FAILURE, LOG_ERROR("failed to allocate stack"));

            pid_daemon=clone(ps_daemon_main_wrapper, stack+stack_size, CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD, (void *) (fd_initdata+1));

            close(fd_initdata[1]);

            if (pid_daemon == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 2"));

            // send a message to the newly created daemon

            if (write(fd_initdata[0], &pid_daemon, sizeof(pid_daemon)) == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("failed to send daemon pid to daemon - error [%s]"), strerror(errno));

            _exit(EXIT_SUCCESS);

        default:
            // wait for daemon response

            close(fd_initdata[1]);

            int read_count=read(fd_initdata[0], &ps_pid, sizeof(ps_pid));

            if (read_count < sizeof(ps_pid))
                ps_pid=0;

            sprintf(ps_buffer,"%d\n", ps_pid);
            write(STDOUT_FILENO, ps_buffer, strlen(ps_buffer));

            if (read_count < sizeof(ps_pid))
                ps_log(EXIT_FAILURE, LOG_ERROR("did not receive daemon pid"));

            // daemon created and ready to accept connections
            ps_log(0, LOG_INFO("ps_pid [%d]"), ps_pid);
    }
}