Build new binary from C program - c

I'm working on a C program, it's a custom shell that asks the user to set different options (IP, port, ...) and then allow the user to build a binary based on these informations. I was wondering what is the best way to build a new binary from within an existing program ?
EDIT: My question may have been a bit unclear. The new compiled binary is a simple TCP client that will connect to the specified IP and Port. I don't want this new binary to be dependant of a config file. How can i build this from my existing C program ? Should i write the IP and Port to a .c file and then compile it using system("/bin/gcc ...") ?

I think you are describing code generation and programmatically compiling a new executable. There are many ways to do what you have described. Here is a very simple (and very rough draft of a) set of steps to code gen, and compile:
1) Use printf, fgets calls from existing program to prompt user for a specific set of input values
2) Convert command line numeric input values if necessary. (Using atoi(), or strtod() for example)
3) Open a file for write, (eg FILE *fp = fopen(filespec, "w");)
4) Using fputs(), send a series of lines to the file comprised of a C source file, including values from steps 1&2 from the user input.
eg. fputs("#include _some file_", fp); (and other header files as needed)
eg, fputs("int main(int argc, char *argv[]) {", fp);
fputs(...) (all of the rest of your lines to make up the complete user defined code.)
fputs("return 0; }", fp);
5) close the file: fclose(fp);
6) Construct a gcc command line compile string to be used on command line on the file you just created.
7) Using popen() (If available) or system() or if using Windows, something like this to send a command to the OS, to execute gcc (or other compiler) on the command line to create your executable.

If you have ready code in C all the options (like ip or other parameters write to the another file for example userdata.c
#include "userdata.h"
unsigned char IP[4] = {212,34,56,78};
const char IPstring[] = "212.34.56.78";
const char DNSIPstring[] = "4.4.4.4";
const char defaultGatewayIPstring[] = "212.34.56.1";
/* etc etc */
and userdata.h
#ifndef USERTATA_H
#define USERTATA_H
extern unsigned char IP[];
extern const char IPstring[];
extern const char DNSIPstring[];
extern const char defaultGatewayIPstring[];
/* etc etc */
#endif
In your main program files just include the .h file. Do not forget to compile and link the .c file as well :)

Related

Is it possible to embed binary data into DOS EXEs made in Turbo C?

I've set up a DOSBox development environment with Turbo C++ intending to make a game with my friends.
I'm using C code, and am wondering how I'd link binary data into the EXE. (All my previous experience with C is libGBA, sorry if that's not actually possible in the way I think it'd be.)
If it isn't possible, then what would be an alternative option for embedding binary data? (I don't really want to need a bunch of binary files in the game directory...)
Can't find much third party documentation for Turbo C, especially considering I'm using the other, supported, but not main language for my IDE which was last updated in the early 2000s after moving to another OS entirely.
An easy solution used by programs such as self-extracting .zip files, is to simply append the data onto the end of the .exe file. The size of the .exe can be calculated from values in the header, which will give you the offset where the appended data begins. Here is an example C program that compiles with Borland Turbo C v2.01 (available as freeware) - note that I have omitted error checking for clarity:
#include <stdio.h>
int main(int argc, const char *argv[])
{
FILE *fSelf;
unsigned short lenFinalBlock, numBlocks;
unsigned long offEnd;
char trailing[256];
int len;
/* Open our own .exe file */
fSelf = fopen(argv[0], "rb");
/* Read part of the .exe header */
fseek(fSelf, 2, SEEK_SET);
fread(&lenFinalBlock, 2, 1, fSelf);
fread(&numBlocks, 2, 1, fSelf);
/* Calculate the size of the .exe from the header values */
offEnd = numBlocks * 512;
if (lenFinalBlock) offEnd -= 512 - lenFinalBlock;
/* Jump to the end of the .exe and read what's there */
fseek(fSelf, offEnd, SEEK_SET);
/* Just read it as a string - you'd presumably be using
some custom data format here instead */
len = fread(trailing, 1, 256, fSelf);
trailing[len] = 0;
printf("Trailing data (%d bytes # 0x%lX):\n%s", len, offEnd, trailing);
fclose(fSelf);
return 0;
}
Once compiled to trailing.exe you can use it like this:
C:\>trailing
Trailing data (0 bytes # 0x2528):
I'm on Linux so I will append some example data using the shell:
$ echo Hello >> trailing.exe
Running it again shows it picking up the trailing data:
C:\>trailing
Trailing data (6 bytes # 0x2528):
Hello
It should be possible to use the BGIOBJ.EXE utility which is included with Turbo C++ to achieve what you want.
BGIOBJ can convert a binary file to an .obj file which then can be linked into the .exe file. Its primary purpose is to include BGI drivers and fonts in the .exe, but it shouldn't put any restrictions on the file (except for size).
Unfortunately I can't tell you exactly how to get the memory address where the file is loaded at run-time, but that shouldn't be too difficult. BGIOBJ supports parameters for public name, segment name and segment class so you can refer to these.

Creating a new file every time a programme is run in c

I'm creating a programme that writes the results of a questionnaire to a .txt file and wondered if there was any way to create a new file with a new name every time the programme was run?
FILE *fp;
fp = fopen("results.txt","w");
How can the file reults.txt be saved under a different name each time?
so ive done the below which lets a user save the name of their results.
int main(int argc, char *argv[])
{
printf("Please enter a filename to save your results to\n");
char c;
FILE *fp;
if (argc >= 2){
fp = fopen(argv[1], "w");}
while ((c = getchar()) != EOF)
{
putc(c, fp);
}
but i get a core fault.
Use the standard C function meant to be used for this very purpose.
7.21.4.4 The tmpnam function
#include <stdio.h>
char *tmpnam(char *s);
The tmpnam function generates a string that is a valid file name and that is not the same
as the name of an existing file.
Notably, this family of functions have some security concerns addressed by CERT-C here. C11 provides safer versions called tmpfile_s and tmpnam_s, as part of the optional bounds-checking interface. But if your beginner-lever questionnaire program does not need commercial production quality protection against hackers, this shouldn't be a concern.
There is many ways to do this.
You can take the file name as an argument.
You can get the process id (with getpid()), and add it to the end of the name.
You can add an number at the end of the file and increment it each time the program is run (by looking into the directory)
...
Edit:
Answer to your first edit
You only open the file if argv < 2, so what will append if argv >= 2 ? What do you think will append when you do putc(c, fp); ?
If you want your program only run if there is enough arguments, check it at the beging, and exit if it's not ok, with a message to tell why it's not ok. :)
And, always check the return of functions like fopen, malloc,... To be sure everything is ok.
You can generate random number by using rand() function in C and append it to the filename at the end ! Or you can append currentmillis to your file name to get unique name every time ! Of course there are many ways of doing it !
Or char *tmpnam(char *str); can also be used!

Reading a directory file in C

I'm trying to write a small program to show me the internal representation of a directory in linux (debian, specifically). The idea was a small C program using open(".", O_RDONLY), but this seems to give no output. The program is the following:
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char** argv)
{
int fd = open(argv[1],O_RDONLY,0 );
char buf;
printf("%i\n",fd);
while(read(fd, &buf, 1) > 0)
printf("%x ", buf);
putchar('\n');
}
When I run it on regular files it works as expected, but on a directory such as ".", it gives no output. The value of fd is 3 (as expected) but the call to read returns -1.
Why isn't this working, and how could I achieve to read the internal representation?
Thanks!
For handling directories, you need to use opendir/readdir/closedir. Read the corresponding man pages for more infos.
To check whether a filename corresponds to a directory, you first need to call stat for the filename and check whether it's a directory (S_ISDIR(myStatStruc.st_mode)).
Directories are a filesystem specific representation and are part of the file system. On extfs, they are a table of string/inode pairs, unlike files which have blocks of data(that you read using your code above).
To read directory-specific information in C, you need to use dirent.h .
Look at this page for more information
http://pubs.opengroup.org/onlinepubs/7908799/xsh/dirent.h.html
On POSIX systems, the system call "stat" would give you all the information about an inode on the filesystem(file/directory/etc.)

Transfer files in C

How do I transfer files from one folder to another, where both folders are present in oracle home directory?
int main(int argc, char *argv[]){
char *home, *tmp2;
home = getenv("ORACLE_HOME");
temp2 = getenv("ORACLE_HOME");
strcat (home,"A");
strcat (tmp2,"B");
//transfer files from home to tmp2
}
strcat doesn't seem to work. Here, I see tmp2 pointer doesn't get updated correctly.
Edit: OS is a UNIX based machine. Code edited.
I require a binary file which does this copying, with the intention that the real code cannot be viewed. Hence I didn't consider using shell script as an option. The files in A are encrypted and then copied to B, decrypted in B and run. As the files are in perl, I intend to use system command to run them in the same C code.
Using the system(3) command is probably a good idea since you get the convenience of a shell interpreter to expand filenames (via *) but avoids the hassle of computing the exact length of buffer needed to print the command by using a fixed length buffer and ensuring it cannot overflow:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFSZ 0xFFF
int main(void)
{
char * ohome = getenv("ORACLE_HOME"), cmd[BUFSZ];
char * fmt="/bin/mv %s/%s/* %s/%s";
int written = snprintf(cmd, BUFSZ, fmt, ohome, "A", ohome, "B"), ret;
if ((written < 0) || (written >= (BUFSZ-1))) {
/* ERROR: print error or ORACLE_HOME env var too long for BUFSZ. */
}
if ((ret = system(cmd)) == 0) {
/* OK, move succeeded. */
}
return 0;
}
As commenter Paul Kuliniewicz points out, unexpected results may ensue if your ORACLE_HOME contains spaces or other special characters which may be interpreted by the subshell in the "system" command. Using one of the execl or execv family will let you build the arguments without worrying about the shell interpreter doing it's own interpretation but at the expense of using wildcards.
First of all as pointed out before, this "security" of yours is completely useless. It is trivial to intercept the files being copied (there are plenty of tools to monitor file system changes and such), but that is another story.
This is how you could do it, for the first part. To do the actual copying, you'd have to either use system() or read the whole file and then write it again, which is kind of long for this kind of quick copy.
int main(int argc, char *argv[]){
char *home, *tmp2;
home = strdup(getenv("ORACLE_HOME"));
tmp2 = strdup(getenv("ORACLE_HOME"));
home = realloc(home, strlen(home)+strlen("A")+1);
tmp2 = realloc(tmp2, strlen(tmp2)+strlen("B")+1);
strcat (home,"A");
strcat (tmp2,"B");
}
By the way, if you could stand just moving the file, it would be much easier, you could just do:
rename(home,tmp2);
Not realted to what you are asking, but a comment on your code:
You probably won't be able to strcat to the results of a getenv, because getenv might (in some environments) return a pointer to read-only memory. Instead, make a new buffer and strcpy the results of the getenv into it, and then strcat the rest of the file name.
The quick-n-dirty way to do the transferring is to use the cp shell command to do the copying, but invoke it using the system command instead of using a shell script.
Or, have your C program create a shell script to do the copying, run the shell script, and then delete it.

How to open .ttcn file using C file open functions?

I am working on TTCN-3 (Testing and Test Control Notation) scripting language. I wanted to prepare on guideline checker for this code files.
For that I want to read lines of TTCN-3 script file( some thing like file.ttcn ) one by one into a buffer. But for me fopen / sopen / open / fgetc / fscanf are not able to work properly and are not reading the file correctly. It is giving NULL. Is there any way I can read characters of it into a buffer. I think C cannot read files with more than three extension characters (like .ttcn). Forgive me if my assumption is wrong.
My Environment is Turbo C on windows.
Edit:
Yes I checked those errors also but they are giving unknown error for read()
and no such file or directory exists.
My code is as follows
#include <errno.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
int main(void)
{
int handle;
int status;
int i=0;
char ch;
FILE *fp;
char *buffer;
char *buf;
clrscr();
handle = sopen("c:\\tc\\bin\\hi.ttcn", O_BINARY, SH_DENYNONE, S_IREAD);
/here even I used O_TEXT and others/
if (!handle)
{
printf("sopen failed\n");
// exit(1);
}
printf("\nObtained string %s #",buf);
close(handle);
fp=fopen("c:\\tc\\bin\\hi.ttcn","r"); \\sorry for the old version of one slash
if(fp==NULL) \\I was doing it with argv[1] for opening
{ \\user given file name
printf("\nCannot open file");
}
ch=fgetc(fp);
i=0;
while(i<10)
{
printf("\ncharacter is %c %d",ch,ch);
i++; //Here I wanted to take characters into
ch=fgetc(fp); //buffer
}
getch();
return 0;
}
The most likely culprit is your Turbo C, an ancient compiler. It's techincally a DOS compiler, not Windows. That would limit it's RunTme Library to 8.3 filenames. Upgrade to something newer - Turbo C++ seems like a logical successor, but Microsoft's VC++ Express would work as well.
Your assumption is wrong about extensions. If fopen is returning NULL, you should output the result of strerror(errno) or use the perror() function to see why it failed.
Edit: The problem is probably because you have "c:\tc\bin\hi.ttcn". in C, "\t" is interpreted as tab, for example.
You could do
"c:\\tc\\bin\\hi.ttcn"
But this is extremely ugly, and your system should accept:
"c:/tc/bin/hi.ttcn"
MS-DOS does not know about long file names, thos including files with extensions longer than 3 characters. Therefore, the CRT provided by Turbo C most probably does not look for the name you are providing, but a truncated one - or something else.
Windows conveniently provides a short (i.e. matching the 8.3 format, most of the time ending in ~1 unless you play with files having the same 8-character prefix) file name for those; one way to discover it is to open a console window and to run "dir /x" in the folder your file is stored.
Find the short name associated to your file and patch it into your C source file.
Edit: Darn, I'll read the comments next time. All credits to j_random_hacker.
Now that you've posted the code, another problem comes to light.
The following line:
fp=fopen("c:\tc\bin\hi.ttcn","r");
Should instead read:
fp=fopen("c:\\tc\\bin\\hi.ttcn","r");
In C strings, the backslash (\) is an escape character that is used to encode special characters (e.g. \n represents a newline character, \t a tab character). To actually use a literal backslash, you need to double it. As it stands, the compiler is actually trying to open a file named "C:<tab>c<backspace>in\hi.ttcn" -- needless to say, no such file exists!

Resources