I am trying to write some C code which extracts the MAC no of a computer and prints it. Following is my code.
#ifndef WINVER
#define WINVER 0x0600
#endif
#include <stdlib.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <assert.h>
#pragma comment(lib, "IPHLPAPI.lib")
// BYTE has been typedefined as unsigned char
// DWORD has been typedefined as 32 bit unsigned long
static void PrintMACaddress(unsigned char MACData[])
{
printf("MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n",
MACData[0], MACData[1], MACData[2], MACData[3], MACData[4], MACData[5]);
}
// Fetches the MAC address and prints it
static void GetMACaddress(void){
IP_ADAPTER_ADDRESSES AdapterInfo[16]; // Allocate information for up to 16 NICs
DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
// Arguments for GetAdapterAddresses:
DWORD dwStatus = GetAdaptersAddresses(0, 0, NULL, AdapterInfo, &dwBufLen);
// [out] buffer to receive data
// [in] size of receive data buffer
assert(dwStatus == ERROR_SUCCESS); // Verify return value is valid, no buffer overflow
PIP_ADAPTER_ADDRESSES pAdapterInfo = AdapterInfo; // Contains pointer to current adapter info
do {
PrintMACaddress(pAdapterInfo->Address); // Print MAC address
pAdapterInfo = pAdapterInfo->Next; // Progress through linked list
}while(pAdapterInfo); // Terminate if last adapter
}
int main(){
GetMACaddress();
return 0;
}
But when I run my code it gives the following error :
Error : undefined reference to `GetAdaptersAddresses#20'
All though the GetAdaptersAddresses() function is included in iphlpapi.h library.
I also tried running the code using the GetAdaptersInfo() function but also gives the same kind of error.
I am using CodeBlocks to compile my code using the GNU GCC C++ 98 compiler version.
The operating system which I am working on is Windows 7.
Can anybody point out the reason for this kind of error.
GCC does not support #pragma comment and there is no equivalent. You will need to update your project settings to specifically link with the Iphlpapi.lib library.
Related
I am trying to write a simple program using the Contiki-ng operating system for IoT platforms. First tests were ok, but something weird happens when trying to allocate dynamic memory. The test code I'm using is the following:
#include "contiki.h"
#include <stdio.h>
#include <stdlib.h>
PROCESS(main_process, "main_process");
AUTOSTART_PROCESSES(&main_process);
PROCESS_THREAD(main_process, ev, data) {
uint8_t *nonce;
int i;
PROCESS_BEGIN();
nonce = (uint8_t *) malloc(32 * sizeof(uint8_t));
if (nonce != NULL) {
for (i = 0; i < 32; i++)
nonce[i] = 0;
printf("Todo OK\n");
} else {
printf("Todo mal\n");
}
PROCESS_END();
}
When building the project, an error rises stating that "In funtion _sbrk_r: undefined reference to _sbrk". After looking some forums on internet, I managed to solve this problem by including the following line into the Makefile of the project:
MODULES += os/lib/newlib
This solves the problem because inside the path os/lib/newlib there is a file, syscalls.c, which implements the mentioned _sbrk function. However, the following error rises now:
I have not found anyone over the internet with the same problem, so I got stuck here. Additionally, I don't know why but since then, removing the line "MODULES += os/lib/newlib" from the Makefile does nothing, and the problem with _eheap and _heap persists without returning to the undefined _sbrk error. However, I believe that this weird error is due to something wrong with Eclipse IDE cleaning the project. The code from syscalls.c, if needed, is the following:
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/*---------------------------------------------------------------------------*/
/**
* \brief Enlarges the allocated heap space
* \param incr Number of bytes by which to increase the heap space
* \return The previous end of heap on success (which is also a pointer to the
* start of the newly allocated memory if \p incr is positive), or
* <tt>(caddr_t)-1</tt> with \c errno set to \c ENOMEM on error
*/
caddr_t
_sbrk(int incr)
{
/*
* Newlib's _sbrk_r() assumes that this global errno variable is used here,
* which is different from the errno definition provided by <errno.h>.
*/
#undef errno
extern int errno;
/* Heap boundaries from linker script. */
extern uint8_t _heap;
extern uint8_t _eheap;
static uint8_t *heap_end = &_heap;
uint8_t *prev_heap_end = heap_end;
if(heap_end + incr > &_eheap) {
PRINTF("Out of heap space!\n");
errno = ENOMEM;
return (caddr_t)-1;
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}
I hope someone could help me. I have read that Contiki gives more ways of using dynamic memory, but I need to do it this way because other parts of the code rely on the use of malloc and cannot be changed.
Thanks.
The short is that you almost certainly don't need and don't want to use malloc() on a Contiki-NG microcontroller. Use Contiki's memb module instead.
The long answer is that you can add the _heap symbol by using a linker script. Check example linker scripts provided by Contiki-NG on how to do that. For example, the script arch/cpu/cc26x0-cc13x0/cc26xx.ld (for the cc26x0-cc13x0 platform) places _heap immediately after the BSS segment:
.bss :
{
/* ... */
} > SRAM
_end = .; /* End of the .bss segment. */
/* ... */
_stack = .;
_heap = _stack;
Can anyone tell me how to get the path of the current working directory on Windows?
The Windows API function GetCurrentDirectory will give you the current directory for the current process.
Alternatively, you may want to use the function getcwd or _getcwd, especially if you seek compatibility with POSIX platforms such as Linux.
Here is an example for using the function GetCurrentDirectory:
#include <windows.h>
int main( void )
{
TCHAR tszBuffer[MAX_PATH];
DWORD dwRet;
dwRet = GetCurrentDirectory( MAX_PATH, tszBuffer );
if ( dwRet == 0 )
{
//TODO: handle error
}
// The buffer now contains the path of the
// current directory and can be inspected.
}
MAX_PATH is defined when you #include <windows.h>.
TCHAR is just a typedef for char if you are compiling in ASCII mode, or for a wide-character WCHAR if you are compiling in UNICODE mode. DWORD is just a typedef for an unsigned long. These typedefs are declared when you #include <windows.h>.
Here is an example for using the function getcwd:
#include <stdio.h>
#include <direct.h>
// Microsoft wants us to use _getcwd instead of getcwd, which breaks POSIX
// compatibility. See the following link for more information:
// https://stackoverflow.com/questions/7582394/strdup-or-strdup
// Therefore we must disable the compiler warning if we want to use getcwd
// to maintain POSIX compatibility. This is accomplished with the following
// line.
#pragma warning(disable : 4996)
// We can't use the constant MAX_PATH in this program because it is not
// defined. This is because we have not included windows.h. Since MAX_PATH
// has the value 260, we will use that value.
#define BUF_SIZE 260
int main()
{
char buffer[BUF_SIZE];
char *p;
p = getcwd( buffer, BUF_SIZE );
if ( p == NULL )
{
//TODO: handle error
}
printf( "The current directory is: %s", buffer );
}
In contrast to the function GetCurrentDirectory, the functions getcwd and _getcwd allow you to pass NULL as the buffer parameter. In that case, it will allocate the memory for you with malloc and return a pointer to that memory buffer. Therefore, you must call free when you are finished with the buffer, to prevent a memory leak. Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
// Microsoft wants us to use _getcwd instead of getcwd, which breaks POSIX
// compatibility. See the following link for more information:
// https://stackoverflow.com/questions/7582394/strdup-or-strdup
// Therefore we must disable the compiler warning if we want to use getcwd
// to maintain POSIX compatibility. This is accomplished with the following
// line.
#pragma warning(disable : 4996)
int main()
{
char *p;
p = getcwd( NULL, 0 );
if ( p == NULL )
{
//TODO: handle error
}
printf( "The current directory is: %s", p );
free( p );
}
I am debugging faulty serial connection on TrueSTM Atollic IDE.
Watch window, Expressions requires me to select a variable and display it as an array. Drawback is that I need to reselect that on each recompile, it gets very slow for +100 values and it doesn't look very clear to me.
So I have created function which simply prints out the bytes held in one of the buffers, those are then displayed to me over to SWV Console.
freertos.c
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "stdbool.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
uint8_t X [4] = {0xFF,0xFF,0xFF,0xFF};
uint8_t * xt = X;
osThreadDef(CAN_Producer, FrameExtractorNEW, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(CAN_Producer), NULL);
void FrameExtractorNEW(void const * argument){
Print_Bytes(xt,4); // fails
printf("Cheese\n") // fails
}
main.c
#include "main.h"
#include "cmsis_os.h"
#include "can.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_CAN2_Init();
MX_CAN1_Init();
MX_USART3_UART_Init();
MX_FREERTOS_Init();
osKernelStart();
while (1)
{}
}
// accept pointer to first element, and number of consecutive byte values to display
void Print_Bytes(uint8_t * a1, int bytes_to_read){
for (int i = 0; i<bytes_to_read; i++){
printf("0x%02X " , *(a1+i));
}
}
Easy and straight forward stuff so far, or so it seems.
My problem is that if I try to use the function Print_Bytes() in the freertos.c it will work, but only provided that it has been invoked at least once prior in main.c. Printing out anything using printf() in main.c at least once will also make it work elsewhere in other files.
Without that 'enabling' program execution goes to HardFault_Handler() with following faults.
I have necessary includes for printf() and Print_Bytes() for the functions that call them but it doesn't seem to be enough to get it to work as I expect it should work.
I bet that the printf on the first run initializes some internal variables. In the main it uses the main program heap and the stack. If you use for the first time in the task it does it on the task heap and stack and none of the standard allocations may do not work in this context (printf uses the malloc function).
Personally I have written my own freeRTOS safe versions of this family of functions. It is very bad practice to use thread unsafe functions in the multi thread environment.
likely your minimal heap size is not big enough (ld file ide option ...)
default lib (nano etc ..) will call sbrake" to split stack en enlarge heap but it is nto mean to be used in rtos context so it wan't work if the stack pointer is not the main stack :(
So if you do a first print or malloc etc ...inside main before oskernel start it will help (sp is main stack) by enlarging your heap .
If you do it first time in a thread it wan't succeed cos "sp" use by sbrake is freertos task memory not the "main stack" thus printf fail to alloc mem
You may notice that printf rely or std lib malloc that is not re-entrant nor multi thread safe ... a safer formated print can be done via vsnprintf formating string to a task owned buffer.
I want to write a program using the new SCHED_DEADLINE scheduling policy available since Linux 3.14.
I start out with a simple program trying to use the sched_setattr function.
#include <sched.h>
int main(void)
{
// struct sched_attr attr;
// attr.size = sizeof(struct sched_attr);
// attr.sched_policy = SCHED_DEADLINE;
sched_setattr(0, (void*)0, 0);
return 0;
}
However when compiling I get the following error:
$gcc dead.c
dead.c: In function ‘main’:
dead.c:8:2: warning: implicit declaration of function ‘sched_setattr’ [-Wimplicit-function-declaration]
sched_setattr(0, (void*)0, 0);
^~~~~~~~~~~~~
/tmp/ccGxWxZE.o: In function `main':
dead.c:(.text+0x19): undefined reference to `sched_setattr'
collect2: error: ld returned 1 exit status
My system is running Ubuntu 16.10 Yakkety, with kernel 4.8.0-59-generic. The sched.h file included is found in /usr/include/sched.h and is provided by the package libc6-dev. This headerfile does not contain the function sched_setattr and friends that I am trying to use.
However the kernel (and kernel headers) I have installed comes with a sched.h header file containing the definitions I need. It is located at /usr/src/linux-headers-4.8.0-58/include/linux/sched.h, on my system.
So I naively think lets just build against the newer linux headers instead of the libc6-dev provided headers. My program will only run on this or newer kernels, but that is just fine.
I modify the first line to be: #include <linux/sched.h> and execute:
gcc -I/usr/src/linux-headers-$(uname -r)/include -I/usr/src/linux-headers-$(unam -r)/arch/x86/include dead.c
Now I am getting page after page of errors and warning. This does not seem the way to go.
What is the correct way to build a userspace program against a newer Linux headers than those that are provided by libc?
And subsequently how do I build the program above?
sched_setattr() is a syscall and doesn't seem to have one-to-one libc wrapper. You could do the wrapper yourself, something like this:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <linux/sched.h>
#include <sys/syscall.h>
#include <sys/types.h>
struct sched_attr {
uint32_t size; /* Size of this structure */
uint32_t sched_policy; /* Policy (SCHED_*) */
uint64_t sched_flags; /* Flags */
int32_t sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */
uint32_t sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) */
/* Remaining fields are for SCHED_DEADLINE */
uint64_t sched_runtime;
uint64_t sched_deadline;
uint64_t sched_period;
};
static int sched_setattr (pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
return syscall (SYS_sched_setattr, pid, attr, flags);
}
int main (int argc, char *argv[])
{
struct sched_attr attr;
int res;
memset (&attr, 0, sizeof (struct sched_attr));
attr.size = sizeof (struct sched_attr);
res = sched_setattr (getpid (), &attr, 0);
if (res < 0) {
perror ("sched_setattr");
return 1;
}
return 0;
}
Looking at the errors reported when trying to include kernel header files required to get the definition of struct sched_attr and reading the comments found by Googling "kernel headers in user space", I really can't suggest trying to include kernel header files just for this.
As a preporatory task for a computer lab in school, we are asked to write a c program that simulates the login process in UNIX. The program should read username and password from a terminal, compare it to hashed values in a local file that is supposed to resemble /etc/passwd.
Here's what I've got:
/*
* Program mylogin.c
*
* This program prompts the user for a login name and password
*
*/
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
/* define some error constants */
#define NOUSER -1
/* define max size of a username */
#define USERNAME_SIZE 32
#define PASSWORD_SIZE 32
#define HASH_SIZE 32
#define FAILED_LIMIT 5
#define AGE_LIMIT 10
int read_username(char *username)
{
printf("login: ");
fgets(username,USERNAME_SIZE,stdin);
/* remove the CR included by getline() */
username[strlen(username)-1]='\0';
return(0);
}
int read_password(char *password)
{
printf("password: ");
fgets(password,PASSWORD_SIZE,stdin);
//getpass(password);
/* remove the CR included by getline() */
password[strlen(password)-1]='\0';
return(0);
}
int user_exists(const char *username)
{
struct pwdb_passwd *pw_entry;
pw_entry=getpwnam(username);
return((pw_entry)!=NULL);
}
int main(int argc,char **argv)
{
char username[USERNAME_SIZE];
char* password;
/* write "login:" and read user input */
read_username(username);
read_password(password);
if (!user_exists(username))
{
printf("Unknown user or authentication\n");
main(argc, argv);
}
struct pwdb_passwd *pw_entry = getpwnam(username);
char* hashed_password = crypt(password,pw_entry->pw_passwd);
if(strcmp(hashed_password, pw_entry->pw_passwd)==0)
{
if((pw_entry->pw_failed)<FAILED_LIMIT)
{
printf("User authenticated successfully\n");
pw_entry->pw_age++;
pw_entry->pw_failed = 0;
pwdb_update_user(pw_entry);
}else{
printf("User account locked\n");
main(argc, argv);
}
}
else
{
printf("Unknown user or authentication\n");
pw_entry->pw_failed++;
if(pw_entry->pw_failed>5){
printf("Too many failed attempts. Username now locked\n");
}
pwdb_update_user(pw_entry);
main(argc, argv);
}
return(0);
}
The struct pwdb_passwd is defined in the files pwdb_lib.c and pwdb_lib.h, which are already written.
When I compile the program, I get a couple of errors. For example on line 73, I get: "error: dereferencing pointer to incomplete type"
I don't understand why. It doesn't seem to like pw_entry->pw_passwd and things like that. More to the point, I get different errors when compiling under Windows with Code::Blocks (using gcc) than under Ubuntu with gcc. I find this pretty strange. I suspect it could be because I import pwd.h and that it only exists on Linux and not Windows. Could this be right? I tried creating my own pwd.h file and save it in the same directory, but it still didn't work. Moving to an ubuntu computer, I dont get errors from the pwd.h thing, but instead get errors on: "dereferencing pointer to incomplete type"
What's wrong with my code?
I also suspect memory leak in the user_exists function, but I'm not sure if it affects the overall program.
Even though pwdb_lib.c is already written, you need to include it in your source file.
Add
#include "pwdb_lib.h"
to your source and make sure you compile/link against pwdb_lib.c
By #includeing this file, you let your source file know about the definitions within it without providing it the implementation. At the end, when you compile your program with pwdb_lib.c (or link its object file, if that's what you're doing), you let any source which included these definitions know where they are implemented (and thus, give them the ability to use them).
If the header is named pwdb_lib.h, then why isn't your program doing an #include of it? It seems to include a different header (pwd.h), which is it?
The error you're getting is the one you'd expect if the declarations were missing.