msvc compiled programs output differently under cygwin tty - c

Under Cygwin: How can I stop output from msvc compiled programs from being transcoded in the tty.
Under Cygwin: gcc vs msvc compiled programs appear to run differently to each other under a tty. Specifically, I am seeing some strange character set translations from only msvc generated binaries output under a tty when the character's 8th bit is set. I'd really like to know how to turn off this annoying behaviour please. Consider:
screen-cap of terminal output (duplicated in a code quote below)
! pwd
/tmp/demo_dir
! echo $LC_ALL "," $LANG "," $LC_CTYPE
, ,
! ./compiled_with_gcc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_msvc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_gcc.exe
▒▒▒▒!
! ./compiled_with_msvc.exe
╬╬╬╬!
The problem is the last line. The output from the msvc compiled version is not as expected. The two programs are demonstrated above to be outputting the same data: so the last two outputs should be the same. But the tty version (without the pipe) gets changed in only the msvc case. gcc compiled program outputs are passed through the tty unharmed. The output presented here is from the cygwin terminal, but I see exactly the same output difference in xterm.
I am confident it is happenning in the tty not the terminal: because I written a standalone cygwin program in C that runs either the gcc and msvc compiled programs, either under a pipe or under a tty that is not connected to a terminal. The program logs the actual bytes received from the tty.
When running the gcc compiled one, the tty gives the '0xce's bytes as expected.
But a sequence of '0x8ec3' patterns is instead received from the msvc compiled program when listening to it via an identical tty.
When using a pipe instead of a tty, they both output '0xce's.
This notes that the msvc compiled program's output via a tty has an increased width. Given cygwin's preference for UTF-8: it is easy to suspect something is going wrong here and cygwin is causing an extra transcoding that does not happen with gcc compiled programs. I wish to turn that off... How do I successfully disable UTF-8 translations in todays cygwin.
I note that LC_ALL does not appear to be respected to stop this happenning for msvc compiled binaries accessed via a tty. Even when the C program begins with setlocale(0,"");
The output-generating program (to be alternately compiled with the two compilers for the test) is exactly as you'd expect it to be. The same C source in both cases. It simply calls printf or write with some bytes. The msvc version is compiled with Visual Studio 2019 cl.exe (all running on Windows10).
reproduce with:
#ifndef __CYGWIN__
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <io.h>
#include <fcntl.h>
#include <locale.h>
int main()
{
if(!setlocale(LC_ALL, "")) {
return 77; //historically: non-filesystem permission-denied exit-code
}
#ifndef __CYGWIN__
//Irrelevent: But avoids stackexchange users asking for it.
_setmode(1,_O_BINARY);
_set_fmode(_O_BINARY);
#endif
char *dat="\316\316\316\316";
write(1,dat,4); // printf/fflush here gives same results.
return 0;
}
#echo off
:: ugly msvc build script. ms_cl.bat
:: full of M$ hardcoded paths. Likely includes some unused libraries.
:: Load compilation environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
:: Invoke compiler with any options passed to this batch file
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x64\cl.exe" /std:c17 %* kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Build msvc version with:
! ms_cl.bat code.c
Run in terminal with:
! ./code.exe | hexdump
! ./code.exe
Build gcc version with:
! gcc code.c
Run in terminal with:
! ./a.exe | hexdump
! ./a.exe
Note identical programs, with identical output in a hex, have output transcoded differently. The msvc one being 'wrong' in my usage case.
I obviously, suspected M$ was doing some translation: so I have tried every combination of _fmode setmode() and more to set binary mode. I suspected some failed cygwin UTF-8 detection situation, so tried setting LC_ALL etc. to plain "C" mode with export in the shell. I similarly tried setting the locale within the msvc source.
Cygwin does a lot of work to make a unix-like environment under windows. Given the hexdumps above I can only guess Cygwin (or some hidden msvc console layer) are doing something quite specialised here and getting in my way. It maybe related to cygwin's migration to ConPty. Either way. I'd like help turning it off.

OP: It's been a little while. And the problem presented in the question presently remains unsolved. However, I have discovered a hacky hack hack from the planet hack that allows for avoiding the problem without solving it. I am posting this non-answer problem-avoidance-hack as an answer and will (eventually) mark it as the solution.. But only if no actual solutions to the problem can be found..
To avoid the output of msvc-compiled program from being transcoded in the tty: first pipe the output of the msvc-compiled program to a gcc compiled program that simply repeats it (such as 'cat' or 'tail -f') and connect that gcc-compiled program to the tty instead.
This hides whatever is going on in the msvc case by seperating it from the tty. The environment is then respected. The tty only knows it is connected to a gcc-compiled program -and works right.
! ./compiled_with_gcc.exe # gcc_compiled->tty = good
▒▒▒▒!
! ./compiled_with_msvc.exe # msvc_compiled->tty = bad
╬╬╬╬!
! ./compiled_with_msvc.exe|cat # msvc_compiled->gcc_compiled->tty = hacky but good
▒▒▒▒!

Related

run a C program at startup [Red Pitaya]

I have a C program that needs to run when I turn on my machine (Red Pitaya).
the beginning of the program presented here:
//my_test program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "redpitaya/rp.h"
int main(int argc, char **argv){
int jj=1;
while(1) {
printf("Ready for experiment number %i\n",jj);
int i, D;
int32_t TrigDly;
and so on...
the program is executable with a run.sh file called uri_test.sh, that contains the following:
cat /opt/redpitaya/fpga/fpga_0.94.bit>/dev/xdevcfg
LD_LIBRARY_PATH=/opt/redpitaya/lib ./my_test
both files are located in a directory under /root. the program is working perfectly when run manually on PuTTY terminal-
/RedPitaya/Examples/C/Uri# ./my_test
or
/RedPitaya/Examples/C/Uri# ./uri_test.sh
I tried to follow the solution presented here :
https://askubuntu.com/questions/9853/how-can-i-make-rc-local-run-on-startup
without success.
any suggestions? Thank you.
There are several ways to have a program running at startup, and it depends upon your init subsystem (are you using systemd or a SysV-style init?).
BTW, a source program in C is not a script and you generally compile it (using gcc -Wall -Wextra -g) into some executable. In your case, you probably want to set up its rpath at build time (in particular to avoid the LD_LIBRARY_PATH madness), perhaps by passing something like -Wl,-rpath,/opt/redpitaya/lib to your linking gcc command.
Perhaps a crontab(5) entry with #reboot could be enough.
Whatever way you are starting your program at startup time, it generally is the case that its stdin, stdout, stderr streams are redirected (e.g. to /dev/null, see null(4)) or not available. So it is likely that your printf output go nowhere. You might redirect stdout in your script, and I would recommend using syslog(3) in your C program, and logger(1) in your shell script (then look also into some *.log file under /var/log/). BTW, its environment is not the same as in some interactive shell (see environ(7)...), so your program is probably failing very early (perhaps at dynamic linking time, see ld-linux.so(8), since LD_LIBRARY_PATH might not be set to what you want it to be...).
You should consider handing program arguments in your C program (perhaps with getopt_long(3)) and might perhaps have some option (e.g. --daemonize) which would call daemon(3).
You certainly should read Advanced Linux Programming or something similar.
I recommend to first be able to successfully build then run some "hello-world" like program at startup which uses syslog(3). Later on, you could improve that program to make it work with your Red Pitaya thing.

[Makefile]Adding colors doesn't work on OS X

I recently switched to a Macbook Air and thus to OS X.
I imported some of my current projects to it and tried to compile them with my Makefile.
My Makefile has some custom imput adding colors with /bin/echo -e "\033[0;31m" for example + the text. It's working great on my old computer (OpenSuse distrib) but it doesn't even compile my binary anymore on my Mac.
Here's what I get when I try to prompt a custom line through my Makefile :
-e \033[0;31m (MY TEXT) \033[00m
As I use custom imput when compiling my .o files, none of them are get compiled so my project build fail.
My Makefile work great without these custom output but I'd like to know why they don't work on OS X.
I can post my Makefile code if some people request it for further investigation.
This is similar, but not quite a duplicate of Color termcaps Konsole?. The problem is that -e is not an option of OSX echo (which follows POSIX). If you take out the -e, it will work as you expect.
The -e option is used in some implementations to allow \e as a synonym for \033 (but your example uses the latter anyway).
Whether you use echo or printf for POSIX scripts is largely a matter of taste, since both accept the same set of backslash sequences. For example printf, of course, accepts % sequences for formatting numbers, but C++ programmers have gotten into the habit of (cout vs echo) not using the printf-style calls.
For reference.
printf - write formatted output
echo - write arguments to standard output

Problems with linking a library with a c program in linux

I want to run serial commands from a Bealgebone to a 4Dsystems display. Therefore I copied the c library found here into a directory and created a test program main.c:
#include "Picaso_const4D.h"
#include "Picaso_Serial_4DLibrary.h"
int main(int argc,char *argv[])
{
OpenComm("/dev/ttyUSB0", B115200); // Matches with the display "Comms" rate
gfx_BGcolour(0xFFFF);
gfx_Cls();
gfx_CircleFilled(120,160,80,BLUE);
while (1) {}
}
Now when I do gcc -o main main.c its says
main.c:2:37: fatal error: Picaso_Serial_4DLibrary.h: No such file or
directory
So I try linking it:
gcc main.c -L. -lPICASO_SERIAL_4DLIBRARY
which gives me the same error. Then I tried to create a static library:
gcc -Wall -g -c -o PICASO_SERIAL_4DLIBRARY PICASO_SERIAL_4DLIBRARY.C
which gives me this:
PICASO_SERIAL_4DLIBRARY.C:1:21: fatal error: windows.h: No such file
or directory compilation terminated.
What am I doing wrong? the git page clearly says this library is created for people who do not run windows.
Thanks in advance!
You're not getting a linker error; you're getting a preprocessor error. Specifically, your preprocessor can't find Picaso_Serial_4DLibrary.h. Make sure that it's in your include path; you can add directories to your include path using the -I argument to gcc.
You've had two problems. First was the picaso_whatever.h file that couldn't be found. You fixed that with the -I you added. But, now, the picaso.h wants windows.h
What are you building on? WinX or BSD/Linux?
If you're compiling on WinX, you need to install the "platform sdk" for visual studio.
If you're using mingw or cygwin, you need to do something else.
If on WinX, cd to the C: directory. Do find . -type f -name windows.h and add a -I for the containing directory.
If under Linux, repeat the find at the source tree top level. Otherwise, there is probably some compatibility cross-build library that you need to install.
Or, you'll have to find WinX that has it as Picaso clearly includes it. You could try commenting out one or more of the #include's for it and see if things are better or worse.
If you can't find a real one, create an empty windows.h and add -I to it and see how bad [or good] things are.
You may need the mingw cross-compiler. See https://forums.wxwidgets.org/viewtopic.php?t=7729
UPDATE:
Okay ... Wow ... You are on the right track and close, but this is, IMO, ugly WinX stuff.
The primary need of Picaso is getting a serial comm port connection, so the need from within windows.h is [thankfully] minimal. It needs basic boilerplate definitions for WORD, DWORD, etc.
mingw or cygwin will provide their own copies of windows.h. These are "clean room" reimplementations, so no copyright issues.
mingw is a collection of compile/build tools that let you use gcc/ld/make build utilities.
cygwin is more like: I'd like a complete shell-like environment similar to BSD/Linux. You get bash, ls, gcc, tar, and just about any GNU utility you want.
Caveat: I use cygwin, but have never used mingw. The mingw version of windows.h [and a suite of .h files that it includes underneath], being open source, can be reused by other projects (e.g. cygwin, wine).
Under Linux, wine (windows emulator) is a program/suite that attempts to allow you to run WinX binaries under Linux (e.g. wine mywinpgm).
I git cloned the Picaso library and after some fiddling, I was able to get it to compile after pointing it to wine's version of windows.h
Picaso's OpenComm is doing CreateFile [a win32 API call]. So, you'll probably need cygwin. You're opening /dev/ttyUSB0. /dev/* implies cygwin. But, /dev/ttyUSB0 is a Linux-like name. You may need some WinX-style name like "COM:" or whatever. Under the cygwin terminal [which gives you a bash prompt], do ls /dev and see what's available.
You can get cygwin from: http://cygwin.com/ If you have a 64 bit system, be sure to use the 64 bit version of the installer: setup-x86_64.exe It's semi-graphical and will want two directories, one for the "root" FS and one to store packages. On my system, I use C:\cygwin64 and C:\cygwin64_packages--YMMV.
Note that the installer won't install gcc by default. You can [graphically] select which packages to install. You may also need some "devel" packages. They have libraries and .h files that a non-developer wouldn't need. As, docs mention, you can rerun the installer as often as you need. You can add packages that you forgot to specify or even remove ones that you installed that you don't need anymore.
Remember that you'll need to adjust makefile -I and/or -L option appropriately. Also, when building the picaso library, gcc generated a ton of warnings about overflow of a "large integer". The code was doing:
#define control_code -279
unsigned char buf[2];
buf[0] = control_code >> 8;
buf[1] = control_code;
The code is okay, and the warning is correct [because the code is sloppy]. If the code had done:
#define control_code -279
unsigned char buf[2];
buf[0] = (unsigned) control_code >> 8;
buf[1] = (unsigned) control_code;
it probably would have been silent. Use -Wno-overflow in your Makefile to get rid of the warnings rather that edit 50 or so lines

Daemon on embedded Linux device using Busybox be written in C or as a script

Should a daemon on an embedded device using Busybox be written in C or as a script?
All the examples I have seen use #! /bin/ash at the top of the file and that is for scripting? But in the device I'm writing to has only complied C files (I think) and symbolic links in /usr/bin.
Every way I try to compile a C file with #include </bin/ash> (e.g. gcc -Wall -o daemon_busybox daemon_busybox.c) I get error after error report in /bin/ash:
/bin/ash:174:1: error: stray ‘\213’ in program
/bin/ash:174:1: error: stray ‘\10’ in program
/bin/ash:174:1: error: stray ‘\273’ in program
/bin/ash:174:1: error: stray ‘\204’ in program
/bin/ash:174:1: error: stray ‘\342’ in program
Note I have set this: /bin/ash -> busybox
Any ideas which way I should go?
Update:
I've been given the task trying to see if a daemon can be run on a small device that runs Linux (2.6.35-at-alpha4) and Java (SE Embedded Runtime Environment) with very limited memory (i.e. a 10 second wait to get java -version to report back).
Two weeks ago I didn't know much about daemons — only knew the word. So, this is all new to me.
On my development machine I have built two different daemon files, one in C and one as a script. Both run very nicely on my Linux machine.
But because of the very small size of the target device there is only busybox (no /lib/lsb/init-functions). So I'm trying to build a 3rd daemon file. I believe it should be written in C for this device, but all examples for busybox point to scripting.
Once your question is edited so that the file name you're trying to #include is visible, the problem becomes self-evident:
#include </bin/ash>
This tries to make the C compiler include the binary of busybox (via the symlink /bin/ash) into the code to be compiled. The average binary is not a valid C source file; this is doomed to failure.
Perhaps you simply need to drop that line — the C compiler stands a better chance of working if it is given header files and source files to compile. Maybe there's more work needed; we don't have enough information to help there.
Many daemons are written as C programs, but a carefully written shell script could be used instead.
Personally, I would like to do this as a script (I've never liked C). But on the device everything in the /usr/sbin folder looks like a C file. So, the conservative coder in me says C is the way to go. I know: ask the guys developed the device — but they're long gone. Right now my daemon is just a test (i.e. printf("Hello World\n"); ). I'm trying to get printf passed to Busybox. But so far I cannot get this file to compile. I just need a simple daemon in C to start.
OK; your C code for that should be just:
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
Save it in hw_daemon.c. Compile it using:
gcc -o hw_daemon hw_daemon.c
If that won't compile, then you've not got a workable C development environment for the target machine. If that will compile, you should be able to run it with:
./hw_daemon
and you should see the infamous 'Hello World' message appear.
If that does not work, then you can go with the script version instead, in a file hw_script.sh:
#!/bin/ash
printf "Hello World\n"
You should be able to run that with:
Predicted output — not output observed on a machine.
$ ash hw_script.sh
Hello World
$ chmod +x hw_script.sh
$ ./hw_script.sh
Hello World
$
If neither of those works at all, then you've got major problems on the system (maybe Busybox doesn't provide a printf command workalike, for example, and you need to use echo "Hello World" instead of the printf).

run c program - stdio.h where do i get it?

Looking into learning C. As I understand it when I say #include <stdio.h> it grabs stdio.h from the default location...usually a directory inside your working directory called include. How do I actually get the file stdio.h? Do I need to download a bunch of .h files and move them from project to project inside the include directory? I did the following in a test.c file. I then ran make test and it outputted a binary. When I ran ./test I did not see hello print onto my screen. I thought I wasn't seeing output maybe because it doesn't find the stdio.h library. But then again if I remove the greater than or less than signs in stdio the compiler gives me an error. Any ideas?
I'm on a Mac running this from the command line. I am using: GNU Make 3.81. This program built for i386-apple-darwin10.0
#include <stdio.h>
main()
{
printf("hello");
}
Edit: I have updated my code to include a datatype for the main function and to return 0. I still get the same result...compiles without error and when I run the file ./test it doesn't print anything on screen.
#include <stdio.h>
int main()
{
printf("hello");
return 0;
}
Update:
If I add a \n inside of the printf it works! so this will work:
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
Your code should have preferably
printf("hello\n");
or
puts("hello");
If you want to know where does the standard header file <stdio.h> comes from, you could run your compiler with appropriate flags. If it is gcc, try compiling with
gcc -H -v -Wall hello.c -o hello
Pedantically, a standard header file is even not required to exist as a file; the standard permits an implementation which would process the #include <stdio.h> without accessing the file system (but e.g. by retrieving internal resources inside the compiler, or from a database...). Few compilers behave that way, most really access something in the file system.
If you didn't have the file, you'd get a compilation error.
My guess is the text was printed, but the console closed before you got the chance to see it.
Also, main returns an int, and you should return 0; to signal successful completion.
#include <header.h>, with angle brackets, searches in standard system locations, known to the compiler-- not in your project's subdirectories. In Unix systems (including your Mac, I believe), stdio.h is typically in /usr/include. If you use #include "header.h", you're searching subdirectories first and then the same places as with <header.h>.
But you don't need to find or copy the header to run your program. It is read at compilation time, so your ./test doesn't need it at all. Your program looks like it should have worked. Is it possible that you just typed "test", not "./test", and got the system command "test"? (Suggestion: Don't name your programs "test".)
Just going to leave this here : STILL! in 2018, December... Linux Mint 18.3
has no support for C development.
innocent / # cc ThoseSorts.c
ThoseSorts.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
innocent / # gcc ThoseSorts.c
ThoseSorts.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
innocent / # apt show libc6
(Abbreviated)::
Package: libc6
Version: 2.23-0ubuntu10
Priority: required
Section: libs
Source: glibc
Origin: Ubuntu
Installed-Size: 11.2 MB
Depends: libgcc1
Homepage: http://www.gnu.org/software/libc/libc.html
Description: GNU C Library: Shared libraries
Contains the standard libraries that are used by nearly all programs on
the system. This package includes shared versions of the standard C library
and the standard math library, as well as many others.
innocent / # apt-get install libc6-dev libc-dev
So, magic... and a minute later they are all installed on the
computer and then things work as they should.
Not all distros bundle up all the C support libs in each ISO.
Hunh.
hardlyinnocent / # gcc ThoseSorts.c
hardlyinnocent / # ./a.out
20
18
17
16
... ... ...

Resources