global static variable not changeable within a function? (gcc-89, uclinux) - c

I hope this is no duplicate but I had no idea what to search for. I have a strange behavieour with a c program and a static variable.
About the program: I am configuring a serial port and change the serial file descriptor in a configure_tty(int *fd_ptr) function.The program is an application for an embedded linux running microblaze uclinux. I am programming and cross compiling under Ubuntu 14.
I stripped it down to the following example:
#include <stdio.h>
static int fd;
static void config_tty(int *fd_ptr);
static void config_tty(int *fd_ptr){
int desc = 5; // here was open(serial port)
*fd_ptr = desc;
}
void main(){
printf("before: %i\n", fd);
config_tty(&fd);
printf("after: %i\n", fd);
}
This gives me `before: 0` and then `after: 5` what is what I expected.
I have to mention that my original program is cross-compiled with gcc -89 parameter and the compiler for microblaze uclinux.
I found the problem thanks to gdbserver and gdb over TCP. Within the config_tty everything is fine but right after *fd_ptr = desc; fd didn't change.
So I tried different things and now comes my question:
Changing static int fd; to int fd; fixed it.
Can anyone tell me what is the reason for this and why it is no problem in my example on Codelite for Windows? Is it compiler-specific?

Related

How to color output in C for cross-platform app

I am new and I know how to color output only in Unix/Linux systems:
#include <stdio.h>
int main(void) {
printf("\033[1;31mRed Message\033[0m.");
}
But this is not works in Windows cmd.exe, only in Unix terminal.
I am writing cross-platform app and want to know how can I do this in Windows cmd.exe too.
This also does not works:
1.
#include <stdio.h>
int main(void) {
printf("%c[1;31mRed Message%c[0m", 27, 27);
}
2.
#include <stdio.h>
int main(void) {
printf("[1;31m Red Message [0m");
}
This works, but I think this is just a bug:
If I type system(""); before printf then it works.
#include <stdio.h>
int main(void) {
system("");
printf("\033[1;31m Red Message \033[0m");
}
Thanks
If you want to make your library crossplatform, I would use the following approach:
Have a library, with the same functions, let's say:
void printInRed(const char* string). (In a headerfile)
After that you write two or more implementations.
One for windows:
//TODO: Errorchecking
void printInRed(const char* string){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//TODO: Extract magic number
//See https://stackoverflow.com/a/4053879/13912132
SetConsoleTextAttribute(hConsole, 12);
puts(string);
}
And another one for unix-like OS:
//TODO: Errorchecking
void printInRed(const char* string){
printf("\033[1;31m%s\033[0m.", string);
}
Then you can check at compile time, which version to compile.
The first approach is to use #ifdefs, but this will make the code a bit messy.
Another approach would be to use a build-system like CMake to select at build time, which one to build. A buildsystem requires a bit of learning, but will help you to make maintaining a crossplatform library simpler.

getpgid not implemented with valgrind

Considering this example :
#include <stdio.h>
#include <unistd.h>
int main()
{
int pgid;
if ((pgid = getpgid(0)) == -1)
perror("getpgid");
else
printf("pgid : %d\n", pgid);
}
When I'm running this program without valgrind, everything is going right, and the pgid is printed.
Whenever I'm using valgrind, perror will print getpgid: Function not implemented.
Is it normal that getpgid is not available under valgrind ?
Is there any alternative to get the pgid of a specific pid (excluding
getpgrp) ?
I'm using macOS Sierra 10.12.6 and valgrind-3.15.0.
It seem that valgrind could have some trouble to perform some syscall.
In the valgrind trace, I'm having :
--17135-- WARNING: unhandled amd64-darwin syscall: unix:151
--17135-- You may be able to write your own handler.
--17135-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
--17135-- Nevertheless we consider this a bug. Please report
--17135-- it at http://valgrind.org/support/bug_reports.html.
So I need to create a wrapper for the function, and it should work.
I will report the bug to the support.
You shouldn't test via valgrind on Mac OS X because after Sierra, it is not supported. Instead, also it is what I do, install ubuntu via an virtual machine software then run valgrind.
macOS Mojave 10.14.6's unistd.h has the following part,
#if __DARWIN_UNIX03
void encrypt(char *, int) __DARWIN_ALIAS(encrypt);
#else /* !__DARWIN_UNIX03 */
int encrypt(char *, int);
#endif /* __DARWIN_UNIX03 */
int fchdir(int);
long gethostid(void);
pid_t getpgid(pid_t);
pid_t getsid(pid_t);
Rule of thumb, always try to be portable!
Incidentally, as #Andrew Henle mentions, pid_t can be of system-dependent type. But, it shouldn't be unsigned type to preserve portability since it can be returned as -1 in the case of a failure. Moreover, on Mac OS X its type is int, as seen below
typedef int __int32_t;
typedef __int32_t __darwin_pid_t; /* [???] process and group IDs */
typedef __darwin_pid_t pid_t;

Can I get SSID and MAC address from C code in Linux?

I am writing a C backup program for my Majaro Linux. It must backup files at a certain time in my home local server only if I am connecting to my home network. So I need to get an SSID and a MAC address a current network to decide if it is my network or not.
Is there Linux(Arch) default commands, C library functions or files, contain this information?
I already tried some Linux tools, ifconfig for example, but it is useless for me.
Help!
Done
Thank you all for your help, especially to Iliya Iliev and to this library.
It works perfectly.
It exactly what I've been searching for!
I just add it to my main project.
#include "../wifi_scan.h"
#include <stdio.h>
#include <unistd.h>
const char *bssid_to_string(const uint8_t bssid[BSSID_LENGTH], char bssid_string[BSSID_STRING_LENGTH])
{
snprintf(bssid_string, BSSID_STRING_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
printf("%x\n", bssid[5]);
return bssid_string;
}
int main(int argc, char **argv){
struct wifi_scan *wifi=NULL;
struct station_info station;
char mac[BSSID_STRING_LENGTH];
wifi=wifi_scan_init(argv[1]);
wifi_scan_station(wifi, &station);
printf("ssid = %s mac = %s \n", station.ssid, bssid_to_string(station.bssid, mac));
wifi_scan_close(wifi);
}

How do I properly allocate a memory buffer to apply double buffering in dosbox using turbo c?

Okay so I am trying to apply a double buffering technique in an emulated environment (DosBox) while using the IDE Turbo C++ 3.0 I am running windows 7 64bit(Not sure if that matters) and I have no clue how to properly execute the buffering routine in this environment.
The main problem I am having is that I can't seem to execute the following assignment statement:
double_buffer = (byte_t far*)farmalloc((unsigned long)320*200);
(Note that 320 and 200 are the screen sizes)...
I just get NULL for the assignment.
I tried changing the default RAM usage of the DosBox to 32 instead of 16, but that didn't do anything. I'm not sure if it's the emulator or there is something wrong with the code for Turbo C. (Note that it complies just fine).
Here is a sample program I found online:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <alloc.h>
typedef unsigned char byte_t;
byte_t far* video_buffer = (byte_t far*)0xA0000000;
void vid_mode(byte_t mode){
union REGS regs;
regs.h.ah = 0;
regs.h.al = mode;
int86(0x10,&regs,&regs);
}
void blit(byte_t far* what){
_fmemcpy(video_buffer,what,320*200);
}
int main(){
int x,y;
byte_t far* double_buffer;
double_buffer = (byte_t far*)farmalloc((unsigned long)320*200);
if(double_buffer == NULL){
printf("sorry, not enough memory.\n");
return 1;
}
_fmemset(double_buffer,0,(unsigned long)320*200);
vid_mode(0x13);
while(!kbhit()){
x = rand()%320;
y = rand()%200;
double_buffer[y * 320 + x] = (byte_t)(rand()%256);
blit(double_buffer);
}
vid_mode(0x03);
farfree(double_buffer);
return 0;
}
Your problem is related to running your application within the Turbo-C IDE debugger. If you compile it and then exit the IDE and run it directly from the DosBox command line without the IDE it should work as expected.
When running via the IDE, the default debug option is to only allocate an additional 64KiB memory for your program's heap. This isn't enough to handle your request for the 64000 bytes (320*200). In the Turbo-C IDE pull down the options menu, click on debugger. You should get a screen that looks like this:
The default value for Program Heap Size is 64. Change it to the maximum 640 and then click Ok. Rerun your program and it should display randomly colored pixels on the display at random locations.

Can the size of a structure change after compiled?

suppose you have the following structure:
#include <windows.h> // BOOL is here.
#include <stdio.h>
typedef struct {
BOOL someBool;
char someCharArray[100];
int someIntValue;
BOOL moreBools, anotherOne, yetAgain;
char someOthercharArray[23];
int otherInt;
} Test;
int main(void) {
printf("Structure size: %d, BOOL size: %d.\n", sizeof(Test), sizeof(BOOL));
}
When I compile this piece of code in my machine (32-bit OS) the output is the following:
Structure size: 148, BOOL size: 4.
I would like to know if, once compiled, these values may change depending on the machine which runs the program. E.g.: if I ran this program in a 64-bit machine, would the output be the same? Or once it's compiled it'll always be the same?
Thank you very much, and forgive me if the answer to this question is obvious...
It is fixed and will not change once compiled. On a 64-bit machine, it will still run as a 32-bit application.
They won't change, unless Chuck Norris says so.

Resources