/*

PROCESS TABLE LISTING PROGRAM...

Author: Matthew W. Coan (mcoan@slack.net) http://slack.net/~mcoan/
Date: 

*/

#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <list>
#include <vector>
#include <cmath>
#include <algorithm>
#include <sstream>
#include "str.h"
#include "st.h"

using namespace std;
using namespace string_tools;

class Proc {
public:
    long pid;
    string name;
    Proc(const long id, const string & pname) {
       name = pname;
       pid = id;
    }
};

typedef list< Proc* > proc_list_type;

template< class T >
string to_string(const T & val)
{
   stringstream ss;
   ss << val;
   size_t sz;
   ss >> sz;
   return ss.str(); 
}

int max0(const int a,
         const int b)
{
   if(a > b)
      return a;
   else 
      return b;
}

class Stricmp {
   string name;

public:
   Stricmp() {
   }

   Stricmp(const string & n) : name(n) {

   }
    
   Stricmp(const Stricmp & cp)
   : name(cp.name) {

   }

   const Stricmp & operator=(const Stricmp & right) {
      name = right.name;
      return *this;
   }

   bool operator()(const string & str) const {
      int rc = 0;
      rc = _stricmp(name.c_str(), str.c_str());
      return rc == 0;
   }
};

void ListProcessTable(const vector< string > & name_list, bool all) 
{
   string compare;
   bool procRunning = false;
   proc_list_type proc_list;

   HANDLE hProcessSnap;
   PROCESSENTRY32 pe32;
   hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(hProcessSnap == INVALID_HANDLE_VALUE) {
      procRunning = false;
   } 
   else {
      pe32.dwSize = sizeof(PROCESSENTRY32);
      if(Process32First(hProcessSnap, &pe32)) { // Gets first running process
         while(Process32Next(hProcessSnap, &pe32)) { 
			 bool flag = false;
			 for (int index = 0; index < name_list.size(); index++) {
				 if (name_list[index] == pe32.szExeFile) {
					 flag = true;
					 break;
				 }
			 }
			 if (flag || name_list.size() == 0) {
				 if (all) {
                stringstream ss;
					 ss << setw(8) << left << pe32.th32ProcessID << " " << pe32.szExeFile << endl;
                cout << ss.str() << flush;
				 }
				 else {
					 cout << pe32.szExeFile << endl;
				 }
			 }
         }
      }
	  CloseHandle(hProcessSnap);
   }
}


#ifdef NO_MAIN
extern "C" {
extern int ps_main(int argc, char ** argv);
}
int ps_main(int argc, char ** argv)
#else
int main(int argc, char ** argv)
#endif
{
   string name; 
   vector< string > name_list;
   bool all = false;
   for(int i = 1; i < argc; i++) {
      if(strstr(argv[i], "-") == argv[i]) {
         size_t sz = strlen(argv[i]);
         for(size_t j = 1; j < sz; j++) {
            switch(argv[i][j]) {
            case 'a':
               all = true;
            break;
            }
         }
      }
      else {
         if(ends_with(argv[i], ".exe")) {
            name_list.push_back(argv[i]);
         }
         else {
            name_list.push_back(argv[i] + string(".exe"));
         }
      }
   }
   ListProcessTable(name_list, all);
   return 0;
}
