Please have a look on this code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *process_fp = popen("make -f -", "w");
if (process_fp == NULL) {
printf("[ERR] make not found!\n");
} else {
char txt[1024] = "all:\n\t#echo Hello World!\n";
fwrite(txt, sizeof(char), strlen(txt), process_fp);
pclose(process_fp);
}
}
This program will print "Hello World!". It works on the Linux platform, but failed on Solaris, where it complains: make: *** fopen (temporary file): No such file or directory. Stop..
How can I solve this problem?
Try to run make -f - manually; it probably doesn't work on Solaris. Try gmake (for GNU make) instead.
Related
I have been successfully using the following code in C++ on Windows (via CodeBlocks) and have recently attempted to use the same code on Linux (Ubuntu 18.04) also via CodeBlocks. The code appears to compile fine but fails on execution.
The purpose of the code is to import a comma delimited text file of numbers into an array.
In both Windows and Linux I am using the GNU GCC Compiler.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <cstdio>
#include <stdlib.h>
using namespace std;
typedef vector <double> record_t;
typedef vector <record_t> data_t;
istream& operator >> ( istream& ins, record_t& record)
{
record.clear();
string line;
getline( ins, line );
stringstream ss( line );
string field;
while (getline( ss, field, ',' ))
{
stringstream fs( field );
double f = 0.0;
fs >> f;
record.push_back( f );
}
return ins;
}
//-----------------------------------------------------------------------------
istream& operator >> ( istream& ins, data_t& data )
{
data.clear();
record_t record;
while (ins >> record)
{
data.push_back( record );
}
return ins;
}
//-----------------------------------------------------------------------------
int main()
{
data_t data;
ifstream infile( "Import File.txt" );
infile >> data;
if (!infile.eof())
{
cout << "Unsuccessful Import!\n";
return 1;
}
infile.close();
cout << "Your file contains " << data.size()-1 << " records.\n";
return 0;
}
I've checked that the necessary header files exist on Linux and that appears to be the case.
If I comment out the EOF check the console returns the message that
Process returned 49 (0x31)
A snippet of the import file which fails under Linux is:
1138,1139,1137.25,1138.5
1138.25,1138.75,1138.25,1138.5
1138.75,1139,1138.5,1138.75
1138.75,1138.75,1138.25,1138.25
1138.25,1138.25,1137.5,1137.5
1137.5,1138.75,1137.5,1138.5
1138.75,1143.75,1138.75,1143
1143.25,1145.75,1143.25,1144.5
1144.5,1144.75,1143,1143.25
1143.5,1144.5,1143.25,1144.25
Grateful for any help in finding a solution.
That return 4321; in main reports an unsuccessful return code to the OS. Only 0 return code (aka EXIT_SUCCESS) is considered successful.
Change it to return 0 or completely remove that return statement (in C++ main has implicit return 0).
I just make a mistake about the macro LINUX_VERSION_CODE.
Here is what I want to do,when execute the code,the code run different branch due to the machine ,which is running.
I just realized,the result is not change,since I compile my code always in the same server.For example I compile the belw code in kernel version of 2.6.18,then the LINUX_VERSION_CODE marco is always 132626 .
If there is any way ,let the run different branch due to the version of which it runs?
#include <stdio.h>
#include <linux/version.h>
int main()
{
printf("kernel version(2.6.32) = %d\n",KERNEL_VERSION(2,6,32));
printf("LINUX_VERSION_CODE = %d\n",LINUX_VERSION_CODE);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
printf("Hello,world.\n");
#else
printf("Fine,thank you.\n");
#endif
return 0;
}
So you want to run a different code depending on kernel version. But you don't want to decide on that using a compile time constant - you want that at runtime.
Nothing simpler, but a call to uname:
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
struct utsname name;
if (uname(&name)) {
fprintf(stderr, "Uname failed!\n");
exit(-1);
}
printf("%s\n", name.release);
if (!memcmp(&name.release, "4.18.9-", sizeof("4.18.9-") - 1)) {
printf("Och, kernel 4.18.9 found!\n");
} else {
printf("Och, you've got a different kernel...\n");
}
}
On my machine:
$ cat 1.c | gcc -xc - && ./a.out
4.18.9-arch1-1-ARCH
Och, kernel 4.18.9 found!
On my friends machine:
cat 1.c | ssh friend 'gcc -xc - && ./a.out'
4.12.14-lp150.11-default
Och, you've got a different kernel...
I will leave it to the OP, to call strtoll or sscanf(&name.release, "%d.%d.%d-", &major, &minor, &release) to get the kernel version as integer number.
But you can get way more hardcore than that. On runtime, you can just do anything, so just read the content of /usr/include/linux/version.h file:
#define _GNU_SOURCE 1
#include <linux/version.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *f;
f = fopen("/usr/include/linux/version.h", "r");
if (f == NULL) return -__LINE__;
char *line = NULL;
size_t linelen = 0;
char *found = NULL;
while (getline(&line, &linelen, f) > 0) {
if ((found = strstr(line, "LINUX_VERSION_CODE")) != NULL) {
break;
}
}
if (found == NULL) return -__LINE__;
fclose(f);
found += sizeof("LINUX_VERSION_CODE") - 1;
errno = 0;
const long long kv = strtoll(found, NULL, 10);
if (errno) return -__LINE__;
free(line);
printf("%ld.%ld.%ld\n", kv>>16&0xff, kv>>8&0xff, kv&0xff);
if (kv > KERNEL_VERSION(4,17,0)) {
printf("Och, kernel api greater then 4.17.0 found!\n");
} else {
printf("Och, kernel api below 4.17.0 found!\n");
}
}
And on my machine this outputs:
$ cat 1.c | gcc -xc - && ./a.out
4.17.11
Och, kernel api greater then 4.17.0 found!
And on my friends:
$ cat 1.c | ssh friend 'gcc -xc - && ./a.out'
4.15.0
Och, kernel api below 4.17.0 found!
We can also see, that uname -a != grep "LINUX_VERSION_CODE" /usr/include/linux/version.h.
My code :
main.cpp
#include <iostream>
namespace file {
#include "file.cpp"
}
namespace file2 {
#include "file1.cpp"
}
int main() {
file::hello();
return 0;
}
file.cpp
#include <iostream>
void hello() {
std::cout << "hello";
}
file1.cpp
#include <iostream>
void hello() {
std::cout << "hello world";
}
My problem:
I use virtual studio, and i don't know why this does not work.I try it allready on CodeBlock and it was fine. But in VS i have error with at least one repeatedly defined symbol has been found.
Sorry for my english.
Since VS still builds and links file.cpp and file1.cpp to the executable you get the errors. You can exclude them from the project by changing its properties or make them regular header files and include them as such.
The include will literally just copy the content of the file into the name space declaration of main.cpp.
I am trying to call inotify_add_watch to watch a file. I would like to specify the file relative to an O_PATH | O_DIRECTORY file descriptor, a la symlinkat, fstatat, or openat.
Is this possible? It doesn't look like it is. Anyone know of a workaround?
EDIT
The closest thing seems to be the "trick" described at man 2 open under "Rationale for openat". See the answer by user1643723 for an example.
You can use symlinks, provided by procfs to achieve the functionality of most *at calls. Open a directory descriptor and use /proc/self/fd/<dir descriptor>/filename instead of the full path to filename:
#define _GNU_SOURCE
#include <sys/stat.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main() {
int inotify = inotify_init();
mkdir("tmp", 0777);
mknod("tmp/foo", 0777 | S_IFREG, 0);
int dirFd = open("tmp", O_DIRECTORY | O_PATH);
char buf[40] = { '\0' };
sprintf(buf, "/proc/self/fd/%d/foo", dirFd);
int watchd = inotify_add_watch(inotify, buf, IN_MOVE | IN_ATTRIB);
if (watchd < 0) {
printf("Failed: %s", strerror(errno));
} else {
printf("ok");
}
}
The program above prints "ok" on Linux 4.4.x.
I'm new to C++ programming. So, which libraries or functions should I use in retrieving this info from the registry? Just give me a brief idea about the steps involved in retrieving the java version number from registry. I'm using VC++.
If java paths are properly set, you could just run java -version from code:
Using the code described here How to execute a command and get output of command within C++ using POSIX? :
#include <string>
#include <iostream>
#include <stdio.h>
std::string exec(char* cmd) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
using like:
int main(void) {
std::cout << exec("java -version");
return 0;
}