Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Getting MAC Address (popen method) within C++-program in Windows 2000

15 views
Skip to first unread message

Alex Vinokur

unread,
Sep 10, 2002, 3:11:41 PM9/10/02
to
##################################################################
Getting MAC Address via popen() within C++-program in Windows 2000
##################################################################


==========================================
Windows 2000 Professional
--------------------
DJGPP 2.03
GNU gcc/gpp version 3.1
--------------------
MINGW-2.0.0-1
GNU gcc/g++ version 3.2 (mingw special 20020817-1)
--------------------
--------------------
GNU Make version 3.79.1
==========================================


########## C++ code : BEGIN ##########

// ------ File #1 of 5 :: popen.h :: BEGIN ------

#ifndef _POPEN_H
#define _POPEN_H


#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

#include <iostream>
#include <string>
#include <vector>
using namespace std;


bool popen_cplusplus_wrapper (
const string& command_line_i,
vector<string>& out_result_o,
vector<string>& err_result_o
);

#endif

// ------ File #1 of 5 :: popen.h :: END --------


// ------ File #2 of 5 :: popen.cpp :: BEGIN ------

// =======================================
// C++Wrapper around popen
// that recognaizes invalid command_line.
// =======================================

// ================
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

// ================
#include <iostream>
#include <string>
#include <vector>
using namespace std;


// ==================
// =====================================
#define FATAL_MSG(msg) \
cout << msg \
<< " : " \
<< (strerror (errno)) \
<< " [ " \
<< __FILE__ \
<< ", #" \
<< __LINE__ \
<< " ]" \
<< endl

#define ERROR_MSG(msg) \
cout << msg \
<< " : " \
<< " [ " \
<< __FILE__ \
<< ", #" \
<< __LINE__ \
<< " ]" \
<< endl


// =====================================
bool popen_cplusplus_wrapper (
const string& command_line_i,
vector<string>& out_result_o,
vector<string>& err_result_o
)
{
bool ret_boolValue = true;

FILE* fp_outfile;
FILE* fp_errfile;

const int SIZEBUF = 1234;
char buf [SIZEBUF];

const int FD_STDERR = 2;
int fd_errfile;
int fd_new_errfile;
int fd_save_error;

string cur_string;


// ################################################
// ######## Redirection : stderr to errfile #######
// ################################################
// ======================
if ((fp_errfile = tmpfile ()) == NULL)
{
FATAL_MSG ("Cannot execute tmpfile ()");
}
fd_errfile = fileno (fp_errfile);
// ======================

// ======================
// redirect error to file
if ((fd_save_error = dup (FD_STDERR)) == -1)
{
FATAL_MSG ("Cannot execute dup");
}
// Now fd_save_error and 2 are descriptors of the screen
// ======================


// ======================
// Close screen
if (close (FD_STDERR) == -1)
{
FATAL_MSG ("Cannot close descriptor");
}
// Now descriptor 2 (FD_STDERR) is vacant
// ======================

// ======================
if ((fd_new_errfile = dup (fd_errfile)) == -1)
{
FATAL_MSG ("Cannot execute dup");
}
// Now fd_errfile and 2 are descriptors of the errfile
// ======================


// ##########################
/* This is in comment
// ======================
if (close (fd_errfile) == -1)
{
FATAL_MSG ("Cannot close descriptor");
}
// Now only descriptor 2 (FD_STDERR) is descriptor of the errfile
// ======================
*/
// ##########################


// ################################################
// ################# popen ########################
// ################################################
if ((fp_outfile = popen(command_line_i.c_str (), "r")) == NULL)
{
FATAL_MSG ("Files or processes cannot be created");
ret_boolValue = false;
}


// ################################################
// ### Get out stream ############################
// ################################################
// ================================
out_result_o = vector<string> ();
// ================================
if (ret_boolValue)
{
while (fgets(buf, sizeof (buf), fp_outfile))
{
cur_string = buf;
if (cur_string [cur_string.size () - 1] != '\n')
{
ERROR_MSG ("SIZEBUF too small ("
<< SIZEBUF
<< ") or missing '\\n'"
);
out_result_o.push_back ("!!! Cannot get this out_line !!!");
ret_boolValue = false;
break;
}

// ------------------------------------
assert (cur_string [cur_string.size () - 1] =='\n');
out_result_o.push_back (cur_string.substr (0, cur_string.size () - 1));
// ------------------------------------
} // while (fgets(buf, sizeof (buf), fp_outfile))

// ================================
if (pclose(fp_outfile) == -1)
{
FATAL_MSG ("Cannot execute pclose");
ret_boolValue = false;
}
} // if (ret_boolValue)

// ======================
// Close screen
if (close (FD_STDERR) == -1)
{
FATAL_MSG ("Cannot close descriptor");
}
// Now descriptor 2 (FD_STDERR) is vacant
// ======================

// ======================
if ((fd_new_errfile = dup (fd_errfile)) == -1)
{
FATAL_MSG ("Cannot execute dup");
}
// Now fd_errfile and 2 are descriptors of the errfile
// ======================

// ################################################
// ### Restore : error stream to screen ###########
// ################################################
// ======================
// redirect (restore) error to screen
// Close screen
if (close (FD_STDERR) == -1)
{
FATAL_MSG ("Cannot close descriptor");
}
// Now descriptor 2 (FD_STDERR) is vacant
// ======================

// ======================
if (dup (fd_save_error) == -1)
{
FATAL_MSG ("Cannot execute dup");
}
// Now fd_save_error and 2 are descriptors of the screen
// ======================

// ======================
if (close (fd_save_error) == -1)
{
FATAL_MSG ("Cannot close descriptor");
}
// Now only descriptor 2 (FD_STDERR) is descriptor of the screen

// ======================


// ################################################
// ### Get error stream ###########################
// ################################################
// ================================
err_result_o = vector<string> ();
// ================================
rewind (fp_errfile);
while (fgets(buf, sizeof (buf), fp_errfile))
{
cur_string = buf;
if (cur_string [cur_string.size () - 1] != '\n')
{
ERROR_MSG ("SIZEBUF too small ("
<< SIZEBUF
<< ") or missing '\\n'"
);
err_result_o.push_back ("!!! Cannot get this error-line !!!");
ret_boolValue = false;
break;
}

// ------------------------------------
assert (cur_string [cur_string.size () - 1] == '\n');
err_result_o.push_back (cur_string.substr (0, cur_string.size () - 1));
// ------------------------------------
} // while (fgets(buf, sizeof (buf), fp_errfile))

if (!err_result_o.empty ())
{
ret_boolValue = false;
}

// ===================
return ret_boolValue;
// ===================

} // bool popen_cplusplus_wrapper (...)

// ------ File #2 of 5 :: popen.cpp :: END --------

// ------ File #3 of 5 :: mac.h :: BEGIN ------

#ifndef _MAC_H
#define _MAC_H

#include "popen.h"

string get_mac_via_popen ();

#endif

// ------ File #3 of 5 :: mac.h :: END --------

// ------ File #4 of 5 :: mac.cpp :: BEGIN ------

#include "mac.h"

// ##################################################################
// Getting MAC Address via popen() within C++-program in Windows 2000
// ##################################################################

#define MAC_ADDRESS_SIZE 17


// =====================================
string get_mac_via_popen ()
{
const string command_line = "ipconfig /all";
const string delim_str (": ");
const string str_physical_address ("Physical Address");
vector<string> out_result;
vector<string> err_result;
vector<string> physical_address_result;
string ret_string_value;

bool ret_bool = popen_cplusplus_wrapper (command_line, out_result, err_result);

if (!ret_bool) return string();
if (!err_result.empty ()) return string();
if (out_result.empty ()) return string();

for (unsigned int i = 0; i < out_result.size(); i++)
{
if (!(out_result[i].find (str_physical_address) == string::npos))
{
physical_address_result.push_back(out_result[i]);
}
}
assert (physical_address_result.size() > 0);

string mac_line = physical_address_result.front();
string::size_type find_index = mac_line.find_last_of (delim_str);

if (find_index == string::npos) return string();
ret_string_value = mac_line.substr(find_index + delim_str.size(), MAC_ADDRESS_SIZE);
assert (ret_string_value.size() == MAC_ADDRESS_SIZE);
return ret_string_value;

} // get_mac_via_popen

// ------ File #4 of 5 :: mac.cpp :: END --------

// ------ File #5 of 5 :: main.cpp :: BEGIN ------

#include "mac.h"

// ==========================
int main ()
{
string mac_address = get_mac_via_popen();
if (mac_address.empty())
{
cout << "Unable to get MAC address" << endl;
}
else
{
cout << "MAC address = " << get_mac_via_popen() << endl;
}
return 0;
}


// ------ File #5 of 5 :: main.cpp :: END --------


########## C++ code : END ############


########## Makefile : BEGIN ##########

SRC = popen.cpp mac.cpp main.cpp
CC_DJ = C:/djgpp/bin/gpp
CC_MG = C:/mingw/bin/g++
RM = rm -f
ECHO = echo

all: d m

d:
@$(ECHO)
@$(ECHO) " === DJGPP ==="
$(RM) *.o
$(CC_DJ) $(SRC) -o $@.exe
$@.exe

m:
@$(ECHO)
@$(ECHO) " === MINGW ==="
$(RM) *.o
$(CC_MG) $(SRC) -o $@.exe
$@.exe

clean:
$(RM) *.exe *.out *.o

version:
@$(ECHO)
@$(ECHO) " === DJGPP ==="
$(CC_DJ) -v
@$(ECHO)
@$(ECHO) " === MINGW ==="
$(CC_MG) -v

########## Makefile : END ############

========= Compilation & Run
: BEGIN
=========

%make

=== DJGPP ===
rm -f *.o
C:/djgpp/bin/gpp popen.cpp mac.cpp main.cpp -o d.exe
d.exe
MAC address = 12-34-56-78-9A-BC

=== MINGW ===
rm -f *.o
C:/mingw/bin/g++ popen.cpp mac.cpp main.cpp -o m.exe
m.exe
MAC address = 12-34-56-78-9A-BC


========= Compilation & Run : END ===========

==================
Alex Vinokur
mailto:ale...@go.to
http://up.to/alexvn
==================


0 new messages