package com.metasploit.meterpreter.stdapi;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;

/**
 * Ported from PHP meterpreter.
 *
 * # Works, but not very portable.  There doesn't appear to be a PHP way of
 * # getting a list of processes, so we just shell out to ps/tasklist.exe.  I need
 * # to decide what options to send to ps for portability and for information
 * # usefulness.
 */
public class stdapi_sys_process_get_processes implements Command {

    public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
        List processes = new ArrayList();
        if (File.pathSeparatorChar == ';') {
            Process proc = Runtime.getRuntime().exec(new String[]{"tasklist.exe", "/v", "/fo", "csv", "/nh"});
            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                if (line.length() == 0) {
                    continue;
                }
                line = line.substring(1, line.length() - 1); // strip quotes
                List parts = new ArrayList();
                int pos;
                // Ghetto CSV parsing
                while ((pos = line.indexOf("\",\"")) != -1) {
                    parts.add(line.substring(0, pos));
                    line = line.substring(pos + 3);
                }
                parts.add(line);
                while (parts.size() < 7) {
                    parts.add("");
                }
                processes.add(new String[]{(String) parts.get(1), (String) parts.get(6), (String) parts.get(0)});
            }
            br.close();
            proc.waitFor();
        } else {
            Process proc = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "ps ax -w -o pid=,user=,command= 2>/dev/null"});
            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                line = line.replace('\t', ' ').trim();
                String[] process = new String[3];
                for (int i = 0; i < 2; i++) {
                    int pos = line.indexOf(" ");
                    process[i] = line.substring(0, pos);
                    line = line.substring(pos).trim();
                }
                process[2] = line;
                processes.add(process);
            }
        }
        for (int i = 0; i < processes.size(); i++) {
            String[] proc = (String[]) processes.get(i);
            TLVPacket grp = new TLVPacket();
            grp.add(TLVType.TLV_TYPE_PID, new Integer(proc[0]));
            grp.add(TLVType.TLV_TYPE_USER_NAME, proc[1]);
            String procName = proc[2];
            if (File.pathSeparatorChar != ';' && procName.indexOf(' ') != -1) {
                procName = procName.substring(0, procName.indexOf(' '));
            }
            grp.add(TLVType.TLV_TYPE_PROCESS_NAME, procName);
            grp.add(TLVType.TLV_TYPE_PROCESS_PATH, proc[2]);
            response.addOverflow(TLVType.TLV_TYPE_PROCESS_GROUP, grp);
        }
        return ERROR_SUCCESS;
    }
}
