Mac OSX and Unix quick questions - c++

I have 3 questions. I am making a C++ executable to launch a Perl program I made. I will compile it for Winows, Mac OSX and Linux. It's pretty much just: system("perl progam.pl");
When compiled with Mac OSX, the program starts in ~. How would I get it to start in the dir it was launched from, or is it just a problem with the compiler?
I'm using - echo -n -e "\033[0;Program\007" - in an attempt to make the windows title "Program". Is this is best way?
I'm using - echo -n -e "\033[7;30;47m" - to make the background of the window black. Is this the best way?
Thanks.

This sounds like something Finder is doing. Launching the app from a shell should work as you expect.
Use tput
See answer to 2, above.

On Mac OS/Unix, invoking system does not change the current working dir. When executing program.pl the current working directory is the same from which you executed the C++ executable. When you launch the executable using Launch Services (e.g. the Finder) the working directory should be /.

On #1 you can refer to the current directory with ./ so system("perl ./progam.pl"); should do it assuming both scripts are sitting in the same folder. ../program.pl would be one level higher.

For #1, use getcwd & then pass an explicit path to system:
cwd=getcwd(NULL, PATH_MAX);
sprintf(cmd, "perl %s/program.pl", cwd);
system(cmd);
free(cwd);
If your perl program itself relies on a specific working directory, then do this instead:
sprintf(cmd, "cd %s && perl program.pl", cwd);

This is probably a silly question, but why are you making an application to launch a perl script? Just add the following to the top of your perl script and use "chmod a+x" to make it executable:
#! /usr/bin/perl
When you use the system command from C and C++, you are basically launching the default system shell and executing the given command in that shell. Doing that is not very portable and somewhat defeats the purpose of using C or C++ (since you could simply create a shell script that does the same thing). If you want to actually do this with C++, you should probably use popen or fork+exec to launch perl. Generally speaking, it isn't nice to end users to play with their Terminal in the manner that you have proposed; most users, by default, have the Terminal configured to display the most recently executed command or their current directory or some other information of their choosing, and changing that is -- on UNIX systems such as Mac OS X and Linux -- considered improper etiquitte. If you are trying to create a terminal interface, though, you might want to look at the curses library.

Related

Open Clion from terminal

I've been trying to set a path to Clion directory in my computer in order to open this program with a command in terminal, but it didn't worked.
If you read this and asked yourself: "what?". I want to start a C++ project like I did with a normal text editor(I used to write codes with gedit).
I want something like, make a hello world:
Clion helloWorld.cpp &
And it will open a new project, named helloWorld, and then I can write down the code.
If it is impossible to do that, sorry.
In researching this question, I just discovered that there is an officially supported method for doing this is via CLion's Tools|Create Command Line Launcher... menu item.
Full details are posted here: https://www.jetbrains.com/help/clion/working-with-the-ide-features-from-command-line.html
Start CLion using the GUI interface, then start Terminal and run the following to find what process is running:
ps -ae| grep lion
Output
57257 ?? 0:20.45 /Applications/CLion.app/Contents/MacOS/clion
57434 ttys000 0:00.00 grep lion
So the command I need to use, in my case, to start CLion from the command line is:
/Applications/CLion.app/Contents/MacOS/clion
Then you need to pass the directory containing your project, so you could make a function like this:
function CLion { /Applications/CLion.app/Contents/MacOS/clion "$1"; }
Then you can just type:
Clion ~/CLionProjects/someProject
For Mac users, you need to add following row in ~/.bash_profile:
alias clion='open -na "CLion.app" --args "$#"'
Then from the terminal you can run CLion:
clion /path-to-your-project
If you use JetBrains Toolbox to manage your CLion (or other IntelliJ) apps like I do, you'll find that Toolbox installs CLion with a versioned pathname. This means every time you update CLion, the path to the clion.sh launcher script changes.
For Linux environments, you can use the following in your ~/.bash_profile to handle this:
alias clion="`find ~/.local -iname clion.sh | head -1` >/dev/null &" #Linux
or
alias clion='open -n "$(IFS=$'\n' && find "${HOME}/Library/Application Support/JetBrains/Toolbox/apps/CLion" -iname clion.app | head -1)"' #Mac OS X
If you upgrade your CLion you can restart your terminal or just run . ~/.bashrc to update the clion alias.

How can I capture group from string using regexp in shell in msysgit on Windows?

[Editor's note: The OP has later clarified that he's running bash as part of msysgit, the Git version for Windows.]
I'm trying to get last digits from the string. I have a little script but it doesn't work and i don't know why:
#!bin/bash
TAGS="MASTER_46"
re="_(\d+)"
if [[ ${TAGS}=~$re ]]; then
echo "Find"
echo ${BASH_REMATCH}
echo ${BASH_REMATCH[1]}
fi
The output:
Find
{empty}
{empty}
I am using bash
$ bash --version
GNU bash, version 3.1.20(4)-release
There are several problems:
bash doesn't support \d. Use [0-9].
Whitespace is needed around the operator: $TAGS =~ $re, otherwise bash parses it as [[ -n "$TAGS=~$re" ]].
Path to the shell is /bin/bash, not bin/bash.
Update, based on the OP's clarification re environment and his own findings:
tl;dr:
msysgit (as of version 1.9.5) comes with a bash executable that is compiled without support for =~, the regex-matching operator
A limited workaround is to use utilities such as grep, sed, and awk instead.
To solve this problem fundamentally, install a separate Unix emulation environment such as MSYS or Cygwin, and use git.exe (the core of msysgit) from there.
choroba's answer has great pointers, but let me add that, since you get the following error message:
conditional binary operator expected syntax error near =~
the implication is either that
your bash version is too old to support =~, the regex-matching operator.
your bash version was compiled without regex support
Given that =~ was introduced in bash 3.0 (see http://tiswww.case.edu/php/chet/bash/NEWS) and you're running 3.1.x, it must be the latter, which indeed turned out to be true:
The OP runs msysgit, the official Git version for Windows that comes with bash and a set of Unix utilities.
As it turns out, as of version 1.9.5, the bash executable that comes with msysgit is built without regex support, presumably due to technical difficulties - see https://groups.google.com/forum/#!topic/msysgit/yPh85MPDyfE.
Incredibly, the "Known Issues" section of the release notes does not mention this limitation.
Your best bet is to:
Install MSYS to use as your Unix emulation environment - its bash does come with =~ support (note that msysgit was originally forked from MSYS).
Alternatively, to get better Unix emulation and more tools at the expense of a larger installation footprint and possibly performance, install Cygwin instead.
In MSYS, use only git.exe from msysgit, via the Windows %PATH%.
To that end, be sure to install msysgit with the Run Git from the Windows Command Prompt option - see https://stackoverflow.com/a/5890222/45375
Alternatively, add C:\Program Files\Git\cmd (assumes the default path on 32-bit Windows, on 64-bit Windows it's C:\Program Files (x86)\Git\cmd) manually to your Windows %PATH%, OR extend $PATH in your MSYS ~/.profile file (e.g., PATH="$PATH:/c/program files/git/cmd").
You could hack your msysgit installation, but it hardly seems worth it and I don't know what the side effects are;
If you really wanted to try, do the following: Copy the following files from an MSYS installation's bin directory to msysgit's bin directory: bash.exe, sh.exe, msys-termcap-0.dll - in other words: replace msysgit's bash altogether.

How to work in batch mode

I have inherited an ANSI C++ program that: has no GUIs and is supposed to run in batch mode, generating lots of data (we are talking 100,000+ ASCII files). We are thinking that in long term we’ll run it under UNIX. For now, I have a MacBook Air running OS X 10.9.4 and I loaded Xcode 5.1.1. It compiles without errors or warnings.
I need to test a program as follows:
<prompt> myprogram datain dataout1 datout2
Where is the compiled program? In which directory? Can I copy my datain file in that directory?
For repeated execution under Windows (Command Prompt window) I normally would have a batch file of the type:
myprogram datain1 dataout11 datout12
myprogram datain2 dataout21 datout22
myprogram datain3 dataout31 datout32
........
myprogram datainn dataoutn1 datoutn2
Can I do something similar with OS X? Where can I find the applicable documentation?
You will want to look for your terminal emulation program. See http://en.wikipedia.org/wiki/Terminal_(OS_X) for how to use it, and it should be the bash shell which is one of the unix shells
You can also do a shell script see
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html for some bash shell scripting info
For such a simple operation, you can write a shell script that will look almost exactly the same as the batch file you use on Windows. The key difference between Windows' cmd.exe and *nix shells here is that the current directory is not part of the search path for executables (the way it is on Windows), so if you put the shell script in the same folder as the compiled executable, you will need to prefix the program name with ./ (to mean "look in the current directory"). For example:
#!/bin/sh
./myprogram datain1 dataout11 datout12
./myprogram datain2 dataout21 datout22
./myprogram datain3 dataout31 datout32
........
./myprogram datainn dataoutn1 datoutn2
If the shell script and executable are not in the same folder, you can use either an absolute path or an appropriate relative path.
Also, to run the script you will either need to make it executable:
$ chmod +x myscript.sh
$ ./myscript.sh
or invoke the shell with the script as an argument:
$ sh myscript.sh

What is the difference between calling a script from the shell and using system()?

I have built a bash script to start up some processes in my system. It simply calls the process and associated config file. Same as I would call from the command line.
#!/bin/bash
# Start specified process in a new session
setsid $1 &>/dev/null &
So to start up someprocess, I would call from the command line:
root#supercomputer:~# start someprocess
This works like a charm. Every process, every time. But when I make a system call from a different running C++ process, someprocess never starts up.
system( "start someprocess" )
This approach for 90% of my processes, except for one. The only difference in the working and not working processes is that the non-working one uses proprietary libraries underneath. I recently added the setsid option to the bash script in hopes that starting a new session would help, but it made no difference. I've also tried popen, and execv. No change.
So my question is what is the difference between calling something with system() and just making that same call from the command line?
All processes are written in C++ on Linux.
.bashrc is only invoked if bash is run as interactive, non-login shell. If it's invoked as non-interactive shell, as when using system() on a script with a bash shebang, it only reads the configuration file pointed to by $BASH_ENV.
That means you have the following options:
add -l to the shebang - causes the shell to read ~/.profile at startup
set $BASH_ENV to the script you want sourced before calling system()
add -i to the shebang - invokes bash as interactive shell and causes it to read ~/.bashrc, but will also effect how bash handles input/output.
I'd recommend the first option.
You can find a detailed explanation of how bash reads it's startup files here. I'm not sure this will solve your problem completely, but it may at leas shed some light on that part of the issue.
Check the environment variables that are used in the system() call. For example, call system to print out some of the variables, and see if they match what you see from the command line.
Likely they are not being sourced correctly.

How can I detect when I'm on a system running Unity?

In order to choose between what type of app indicators to use for a program, I need to detect whether I'm in a Unity desktop or not. Is this possible? Is it possible when I don't have access to the environment?
It looks like there's also XDG_CURRENT_DESKTOP:
rubiojr#rubiojr-VirtualBox:~$ echo $XDG_CURRENT_DESKTOP
Unity
See https://askubuntu.com/questions/70296/is-there-an-environment-variable-that-is-set-for-unity
In Ubuntu you can use following commands:
echo $DESKTOP_SESSION: This command return ubuntu when you are using Unity and ubuntu-2d when you are using Unity 2D and ...
sudo grep "Starting session" /var/log/lightdm/lightdm.log: Because of last version of Ubuntu use lightdm as display manager you can see last line of the lightdm.log file.
Just shell execute ps aux | grep unity, this is cross-plattform for linux. Even works on ARM cores.
On my 11.04 Ubuntu running unity it returns unity-2d-panel, unity-2d-launcher and more processes. Can't confirm if this is true on every linux platform.
Look in the list of environment variables for unity by running this command line:
env | grep -i unity
If as in this answer you see XDG_CURRENT_DESKTOP=Unity then you know it is in use. Alternatively, you could of course check for desktop rather than unity.