I have a newlib 4.9.3 2014q4 application that runs fine on my Cortex-M4 platform. All output to the serial console uses either iprintf or a custom send_str functions. The send_str is just writing bytes to the serial peripheral tx buffer (looping call to my fputc).
int _write(int fd, char *buf, int nbytes)
{
int i;
for (i = 0; i < nbytes; i++) {
if (*(buf + i) == '\n') {
/* fd is incorrectly passed as arguments, as FILE is not used, but needed for build */
fputc('\r', (FILE *) & fd);
}
/* fd is incorrectly passed as arguments, as FILE is not used, but needed for build */
fputc(*(buf + i), (FILE *) & fd);
}
return nbytes;
}
int fputc(int ch, FILE * f)
{
unsigned char tempch = ch;
sendchar(&tempch);
return ch;
}
void send_str(unsigned char* buff)
{
while(*buff != 0){
sendchar(buff);
buff++;
}
}
In my application's main (after init of data relocation and bss zero'ing) I print a banner. When I use newlib-nano(--specs=nano.specs) this works if I use send_str, but not if I use iprintf.
int main(int argc, char ** argv)
{
int i = 0;
char str[] = "Hello from Cortex-M4!\n";
init_uart((void*)UART2_BASE_PTR, 115200);
send_str(str);
}
versus
int main(int argc, char ** argv)
{
int i = 0;
char str[] = "Hello from Cortex-M4!\n";
init_uart((void*)UART2_BASE_PTR, 115200);
iprintf("%s", str);
}
Using just newlib (not nano) both functions work.
Everything I've been reading suggests that changes to my application should not be required to swap between the two. Is there an exception to this?
Related
I'm trying to be able to decode encoded strings that were encoded using a perl script. The reason I can't just change the perl script is because a lot of important data already exists that was saved via the perl script and it would be too much to decode in perl and recode another way. It's easier just to keep things in place (for now). However, the compiled perl code is 2MB. I want to write it in C so the executable will be a smaller size.
What I have so far is below. It won't work though. It basically gives me junk output. The problem I think is that the perl script used a hex-based encryption. How do I go about decoding that? Can someone point me to where I went wrong?
/*
Test to decode perl-encrypted string.
NOTE: Not all code written by me. Function code is either written by or derived
from code from other people in response to similar questions found on the
internet.
Required Lib: crypt (-lcrypt)
Perl Code from existing script (that is being converted to C):
use Crypt::CBC;
use Crypt::DES;
my $text = "thisisalongtest";
my $salt_key = "fOagmJOKu2SF";
my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
my $enc_text = $cipher->encrypt_hex($text);
Perl crypt functions require libcrypt-cbc-perl & libcrypt-des-perl
Data:
Original Text: thisisalongtest
Salt Key: fOagmJOKu2SF
Resulting Encrypted String: 53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1
Resulting output:
Decrypted: (unprintable junk characters)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>
#define BUFFSIZE 420
int encrypt(char key[9], char salt[9], char pass[BUFFSIZE], int mode);
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]);
int hex_to_int(char c);
int hex_to_ascii(char c, char d);
int main (int argc, char *argv[]) {
int err;
char passwd[BUFFSIZE];
char result[BUFFSIZE];
char key[13];
sprintf(key,"fOagmJOKu2SF");
/* Change this from hex pairs to ASCII */
sprintf(passwd, "53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1");
enc_from_hex(passwd, result);
/* Decrypt */
err = encrypt(key, "", result, 1); /* DO NOT use 'NULL' for 2nd parameter! */
if(err != 0) {
printf("Error.\n");
} else {
printf("Decrypted: %s\n", result);
}
return 0;
}
/* Encryption */
int encrypt(char key[13], char salt[13], char pass[BUFFSIZE], int mode){
char temp[13];
strcpy(temp, salt);
int buffsize;
int errcode;
des_setparity(key);
buffsize = strlen(pass);
/* Pad pass to ensure size is divisable by 8.*/
while (buffsize % 8 && buffsize<BUFFSIZE) {
pass[buffsize++] = '\0';
}
/* Determine Function */
if(mode == 1) {
errcode = cbc_crypt(key, pass, buffsize, DES_DECRYPT | DES_SW, temp);
} else {
errcode = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, temp);
}
if (DES_FAILED(errcode) || strcmp(pass, "") == 0) {
return errcode;
}
return errcode;
}
/* Hex conversion functions */
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]) {
char temp[2];
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++) {
if(i % 2 != 0) {
sprintf(temp, "%c", hex_to_ascii(buf, st[i]));
strcat(ret_result, temp);
} else {
buf = st[i];
}
}
}
int hex_to_int(char c) {
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d) {
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
As #ikegami points out in the comments the value passed to key Crypt::CBC is not really a key. This value is passed to another function which combines it with a random salt then hashes it to generate the real key and initialization vector. The random salt is saved with the cypher text the idea being if you encrypt the same data with the same key more than once the output will be different every time.
If you convert your encrypted string to ascii you will notice the first eight characters spell Salted__, this corresponds to the format used by OpenSSL.
See below for a somewhat crude example using OpenSSL's EVP api:
//
// compile with: gcc -o crypt crypt.c -lssl -lcrypto
//
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main(int argc, char *argv[]){
char pass[]="fOagmJOKu2SF";
char text[]="53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1";
int i = 0;
char *pos=text;
while(*pos){ // converts hex string to binary in place
sscanf(pos, "%2hhx", &text[i++]);
pos += 2;
} text[i]=0;
EVP_CIPHER_CTX ctx;
unsigned char key[8] = {0};
unsigned char iv[8] = {0};
int len;
char *clear = malloc(strlen(text));
// v-> First Charicter after 'Salted__'
EVP_BytesToKey(EVP_des_cbc(), EVP_md5(), &text[8], pass, strlen(pass), 1, key, iv);
EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
// v-> Cypertext starts after salt
EVP_DecryptUpdate(&ctx, clear, &len, &text[16], strlen(text)-15);
EVP_DecryptFinal(&ctx, clear, &len);
printf("%s\n", clear);
return 0;
}
http://www.ict.griffith.edu.au/anthony/info/crypto/openssl.hints
https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
https://www.openssl.org/docs/manmaster/crypto/EVP_EncryptInit.html
While debugging when I jump to function parseLayerFile filename is (char **) 0x40a04e <_Jv_RegisterClasses+4235342>... How to correct the declaration to get valid filename value?
void parseArgs(WRAPPER_t *w, int argc, char *argv[])
{
int i;
for (i=1 ;i<argc ;i++) {
if (strcmp(argv[i],"-layers") == 0) {
i++;
parseLayerFile(argv[i]);
}
} // for
}
int parseLayerFile(WRAPPER_t * w, char*filename[]){
unsigned char * buffer; size_t size;
size = get_fileContent(filename, &buffer);
}
int main(int argc, char **argv)
{
WRAPPER_t * w;
w = create_wrapper(); // w - main object
threads_init(w);
parseArgs(w, argc, argv);
return 0;
}
int parseLayerFile(WRAPPER_t * w, char*filename[])
expects two parameters.
You are calling it with only one parameter:
parseLayerFile(argv[i]);
As none of the argument suit your needs, fix the function as follows:
int parseLayerFile(const char * filename)
{
unsigned char * buffer;
size_t size = get_fileContent(filename, &buffer);
}
I am trying to create a shared library in Linux. How can I pass an argument to function my_load() when library is loaded? In my C application, I make a call to test_func() then it automatically executes my_load() first before the called function then lastly it executes my_unload()
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
Your dynamic library can always read /proc/self/cmdline to see what the command-line parameters used to execute the current executable are. example.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
static char **get_argv(int *const argcptr)
{
char **argv;
char *data = NULL;
size_t size = 0; /* Allocated to data */
size_t used = 0;
size_t argc, i;
ssize_t bytes;
int fd;
if (argcptr)
*argcptr = 0;
do {
fd = open("/proc/self/cmdline", O_RDONLY | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd == -1)
return NULL;
while (1) {
if (used >= size) {
char *old_data = data;
size = (used | 4095) + 4096;
data = realloc(data, size + 1);
if (data == NULL) {
free(old_data);
close(fd);
errno = ENOMEM;
return NULL;
}
}
do {
bytes = read(fd, data + used, size - used);
} while (bytes == (ssize_t)-1 && errno == EINTR);
if (bytes < (ssize_t)0) {
free(data);
close(fd);
errno = EIO;
return NULL;
} else
if (bytes == (ssize_t)0)
break;
else
used += bytes;
}
if (close(fd)) {
free(data);
errno = EIO;
return NULL;
}
/* Let's be safe and overallocate one pointer here. */
argc = 1;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argc++;
/* Reallocate to accommodate both pointers and data. */
argv = realloc(data, (argc + 1) * sizeof (char *) + used + 1);
if (argv == NULL) {
free(data);
errno = ENOMEM;
return NULL;
}
data = (char *)(argv + argc + 1);
memmove(data, argv, used);
/* In case the input lacked a trailing NUL byte. */
data[used] = '\0';
/* Assign the pointers. */
argv[0] = data;
argc = 0;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argv[++argc] = data + i + 1;
/* Final pointer points to past data. Make it end the array. */
argv[argc] = NULL;
if (argcptr)
*argcptr = (int)argc;
return argv;
}
/* Example standard error functions, that avoid the use of stdio.h.
*/
static void wrerr(const char *p)
{
if (p != NULL) {
const char *const q = p + strlen(p);
ssize_t n;
while (p < q) {
n = write(STDERR_FILENO, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1)
return;
else
if (errno != EINTR)
return;
}
}
}
static void wrerrint(const int i)
{
char buffer[32];
char *p = buffer + sizeof buffer;
unsigned int u;
if (i < 0)
u = (unsigned int)(-i);
else
u = (unsigned int)i;
*(--p) = '\0';
do {
*(--p) = '0' + (u % 10U);
u /= 10U;
} while (u > 0U);
if (i < 0)
*(--p) = '-';
wrerr(p);
}
static void init(void) __attribute__((constructor));
static void init(void)
{
int argc, i, saved_errno;
char **argv;
saved_errno = errno;
argv = get_argv(&argc);
if (argv == NULL) {
const char *const errmsg = strerror(errno);
wrerr("libexample.so: get_argv() failed: ");
wrerr(errmsg);
wrerr(".\n");
errno = saved_errno;
return;
}
for (i = 0; i < argc; i++) {
wrerr("libexample.so: argv[");
wrerrint((int)i);
wrerr("] = '");
wrerr(argv[i]);
wrerr("'\n");
}
free(argv);
errno = saved_errno;
return;
}
Compile using e.g.
gcc -Wall -fPIC -shared example.c -ldl -Wl,-soname,libexample.so -o libexample.so
and test using e.g.
LD_PRELOAD=./libexample.so /bin/echo foo bar baz baaz
(Note that plain echo is a shell built-in, and you need to execute another binary like /bin/echo to load the preload library.)
However, most dynamic libraries take arguments in environment variables instead; for example, YOURLIB_MEM for some memory size hint, or YOURLIB_DEBUG for enabling verbose debugging output during runtime.
(My example code does not use stdio.h output, because not all binaries use it, especially if written in some other language. Instead, the wrerr() and wrerrint() are small stupid helper functions that use low-level unistd.h I/O to write directly to standard error; this always works, and causes minimal side effects at run time.)
Questions?
You can't.
__attribute__((constructor)) simply doesn't support this.
There doesn't seem to be any reason you can't just call my_load(argc, argv) at the very beginning of main().
You can use atexit to register a function to be called when your program exits normally, or returns from main.
int main(int argc, char **argv)
{
my_load(argc, argv);
atexit(my_unload);
// ...
}
AFAIK, there is no way to pass arguments to gcc constructor and destructor functions. The best you can do is to use global variables.
In you example, you could try :
In main :
int Argc;
char *Argv[];
int main(int argc, char *argv[]) {
Argc = argc;
Argv = argv;
...
}
In shared library :
extern int Argc;
...
void __attribute__ ((constructor)) my_load();
...
void my_load() {
printf("my_load: %d\n", Argc);
}
But anyway, it can only work if you explicitely load the shared library through dlopen. It it is directly referenced at link time, the constructor function will be called before first instruction in main and you will always find the original value or 0 in Argc.
Sorry to resurrect an oldie here but I just tested this on both Linux and Mac OS:
$ gcc -x c -o test_prog -
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
int main() { return 0; }
And it prints this result on both systems:
$ ./test_prog foo bar baz
my_load: 4
my_unload
In order for it to work as a shared library I did have to add the linker option -Wl,--no-gc-sections because it otherwise aggressively removed the constructor & destructor. But otherwise yeah this works already.
This doesn’t use the __attribute__ ((constructor)) syntax, but if you specify a custom _init function, you can do so:
// foo.c
#include <stdio.h>
void my_constructor(int argc, char**argv) {
printf("my_constructor init: %s\n", argv[1]);
}
To do so you need to pass ld -init my_constructor or gcc -Wl,-init,my_constructor, e.g.
gcc foo.c -shared -o libfoo.so -Wl,-init,my_constructor
I try to convert a Linux program in C to DOS. Since the DOS command line allows only 128 bytes I try to read in the arguments from a file. This file has one line for each argument.
So I read in the arguments from the file into a string array and want to override the *argv[] address with the address of my string array.
But I get confused with pointers to pointers. What shall I do to correctly override the *argv[] address in my function?
This program is called with "argvtest.exe commands.dat"
Here is my test code:
#include <stdio.h>
#include <string.h>
void read_cmd_file(int *argc,char *argv[]){
if (*argc != 2 ) return;
char buf[256];
char arguments[30][256];
int line_nr=0,i;
FILE *fp=(FILE *) NULL;
/* open the file */
fp=fopen(argv[1],"r");
if (fp == (FILE *) NULL)
{
printf("Could not open command file: %s",argv[1]);
return;
}
while (fgets(buf,sizeof(buf)-1,fp) && !feof(fp))
{
line_nr++;
strcpy(arguments[line_nr],buf);
//printf("Argument read: %s\n",buf);
}
if (fp != (FILE *) NULL)
(void) fclose(fp);
for (i=1;i<=line_nr;i++) printf("%d,%s\n",i,arguments[i]);
*argv=&arguments[0][0];
*argc=line_nr;
return;
}
int main(int argc,char **argv)
{
int i;
read_cmd_file(&argc,argv);
printf("argc=%d\n",argc);
for (i=0;i<argc;i++) printf("%d,%s\n",i,argv[i]);
}
There are two things you should do. First, you will need a pointer to pointer to pointer:
void read_cmd_file(int *argc,char ***argv)
{
...
fp=fopen((*argv)[1],"r");
...
*argv = result;
}
...
read_cmd_file(&argc,&argv);
Then, you shall never try to return a reference to a local variable from a function: in your code
*argv=&arguments[0][0];
is a sign of evil and shall not be used...
Instead, you will have to allocate memory in the function, and then release it after use. Something like:
void read_cmd_file(int *argc,char ***argv)
{
char **arguments;
...
arguments = calloc(30, sizeof(*arguments)); // 30 args
...
while (fgets(buf,sizeof(buf)-1,fp) && !feof(fp))
{
line_nr++;
arguments[line_nr] = strdup(buf); // allocates memory on heap
}
...
*argv=arguments;
}
...
int main(int argc,char **argv)
{
int i;
read_cmd_file(&argc,&argv);
for (i=0;i<argc;i++) printf("%d,%s\n",i,argv[i]);
...
for (i = 0; i <argc; i++)
{
free(argv[i]);
}
free(argv);
}
Im making an application that uses of API-threads in C, The program takes N-files (N>2) with names disordered,per each file is generated a thread of execution which sort the files using the function qsort, after being ordered files, each thread should create a file keeping the original file intact and displaying the sorted file to another file with the extension <.sorted>. The program sorts the numbers without problems, even if I put standard output displays the result on screen, but when I try to create the output file with extension .sorted the program breaks out.
this is my code file.c
#include <stdio.h> /* Standard buffered input/output */
#include <stdlib.h> /* Standard library functions */
#include <string.h> /* String operations */
#include <pthread.h> /* Thread related functions */
#include "pf1.h" /* Header specific to this app */
pthread_attr_t attr;
void *thread_worker(void *name_file)
{
FILE *entrada, *salida;
char* nombres = (char*)name_file;
int numero;
char temp [10000];
int i;
stats_t estadisticas;
printf ("File_name:%s\n", nombres);
entrada = fopen(nombres, "r");
salida = fopen (strcat(nombres, ".sorted"), "w");
while (!feof(entrada)){
fscanf (entrada, "%s\n",temp);
numero++;
}
char* lista[numero]; //array to sort the file
rewind (entrada);
for (i=0;i<numero;i++)
{
fscanf(entrada," %[^\n]", temp);
lista[i] = (char*)malloc((strlen(temp)+1)*sizeof(char));
strcpy(lista[i], temp);
}
size_t large = sizeof(lista) / sizeof(char *);
qsort(lista,large ,sizeof(char *) ,cstring_cmp );
printf ("Archivo Ordenado\n", i+1);
for (i=0;i<large;i++)
printf("%s\n",lista[i]);
pthread_exit(NULL);
}
int main(int argc, char *argv [])
{
stats_t **stats;
int i, rc;
pthread_t my_threads[argc-1];
pthread_attr_init(&attr);
if (argc <3) {
printf ("|files| > 2\n");
}else{
printf("files to sorted: %d\n", argc - 1);
for (i = 1; i < argc; i++){
//printf("%s%s\n", argv[i], (i < argc-1) ? " " : "");
rc = pthread_create(&my_threads[i], &attr, thread_worker, (void *)argv[i]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n",rc);
return -1;
}
}
}
return 0;
} /*end main */
this is mi file.h
#ifndef PF1_H_
#define PF1_H_
typedef struct _stats_t
{
char *longest, *shortest;
unsigned int numlines;
} stats_t;
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* strcmp functions works exactly as expected from
comparison function */
}
void print_cstring_array(char **array, size_t len)
{
size_t i;
for(i=0; i<len; i++)
printf("%s | ", array[i]);
putchar('\n');
}
#endif /* PF1_1_H_ */
I would like some help with this problem because I can not see which is the fault ... thanks to all in advance and excuse my English
This line here may be your problem:
salida = fopen (strcat(nombres, ".sorted"), "w");
From what I can tell, that nombres variable is coming from argv. Since you're not the one allocating memory for argv, you don't know that there will be extra space for the ".sorted" (and there probably won't be). If you strcpy it to your own buffer with space for the ".sorted", you should be fine.
#define EXT_LEN 7
#define MAX_TOTAL_LEN 250
#define MAX_FILE_LEN 242 //MAX_TOTAL_LEN - EXT_LEN - 1
char *name_ptr;
char nombres[MAX_TOTAL_LEN];
int len;
name_ptr = (char*)name_file;
len = strlen(name_ptr);
if (len > MAX_FILE_LEN) {
len = MAX_FILE_LEN;
}
strncpy(nombres, name_ptr, len);
strcpy(nombres+len, ".sorted");
salida = fopen (nombres, "w");
I once had issues about not passing an int identifier while calling thread execution functions. Try building a struct with both an integer identifier and the filename, then pass it as a parameter to your thread_worker() function.