GCC (C) - error: 'x' redeclared as different kind of symbol - c

I'm writing a package manager for the Termux terminal emulator on android using the APK format. The program is written in C and uses various arguments like 'sync', and 'remove'. However, the function I have written doesn't recognize the argument I have written for the name of the package to 'sync'. 'sync' is meant to download an apk from the fdroid repositories and open it using xdg-open (not yet implemented) using the name of the apk given in the arguments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void syncapk(char * apkname);
int main(int argc, char **argv)
{
if(argc==1) {
printf("Displaying help screen.\n");
} else if(argc>=2) {
if(strncmp(argv[1], "sync\n", 4) == 0) {
syncapk(argv[2]);
} else if(strncmp(argv[1], "upgrade", 7) == 0) {
printf("Upgrading all packages!\n");
} else if(strncmp(argv[1], "remove", 6) == 0) {
printf("Removing package!\n");
}
}
return 0;
}
void syncapk(char * apkname) {
printf("Syncing package: %s!\n", apkname);
char * synccmd = "fdroidcl download %s", apkname;
system(synccmd);
}
GCC (my compiler) says that the argument (the name of the apk I wish to download from the repositories) is 'redeclared as a different symbol'. I am fairly new to writing programs in C so feel free to critique other things, not just the problem itself and whether I could take a different approach completely.

This doesn't do what you think it does:
char * synccmd = "fdroidcl download %s", apkname;
This is defining a variable of type char * named synccmd and a variable of type char named apkname. The latter conflicts with the parameter of the same name, hence the error.
If you want to build a formatted string, you need to use sprintf to do that:
char synccmd[100];
sprintf(synccmd, "fdroidcl download %s", apkname);

Related

ImportError and PyExc_SystemError while embedding Python Script within C for PAM modules (.so files)

I'm trying to write a demo PAM module in C, which uses Embedding Python in C concept to run a script written in python (2.7), inside pam_sm_authenticate() function, which is written in C file (pam_auth.c).
This is the python script: test.py
import math
import numpy
def test_func():
a = "test"
return a
The path for test.py is /usr/lib/Python2.7/ so that I can easily import it.
This is the C file:
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_appl.h>
#include<python2.7/Python.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NOBODY "nobody"
/*PAM Stuffs*/
PAM_EXTERN int pam_sm_authenticate(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
const char *user;
int retval;
user = NULL;
retval = pam_get_user(pamh, &user, NULL);
if(retval != PAM_SUCCESS)
{
fprintf(stderr, "%s", pam_strerror(pamh, retval));
// return (retval);
}
fprintf(stdout, "retval= %d user=%s\n", retval,user);
if (user == NULL || *user =='\0')
pam_set_item(pamh, PAM_USER, (const char*)NOBODY);
/* Python Wrapper */
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_setcred(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_open_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_close_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_chauthtok(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
The C-file is just a modification of pam_permit.c. The C file is compiled using gcc ( gcc -shared -o pam_auth.so -fPIC pam_auth.c -I/usr/include/python2.7 -lpython2.7 ) to obtain an .so file (pam_auth.so) and is put inside the folder /lib/security/
I changed the PAM configuration of 'sudo' file in /etc/pam.d as follows:
#%PAM-1.0
auth required pam_env.so readenv=1 user_readenv=0
auth required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
##include common-auth #this line is commented to make it use my pam module
auth required pam_auth.so
#include common-account
#include common-session-noninteractive
The line "auth required pam_auth.so" forces the system to use my module for authentication everytime I use the command "sudo". (for ex- sudo nautilus)
Now the problem is:
This line in C file " pModule = PyImport_Import(pName); " gives an import error, which is printed by PyErr_Print() as follows:
stitches#Andromida:~$ sudo nautilus
retval= 0 user=stitches
Traceback (most recent call last):
File "/usr/lib/python2.7/subho_auth.py", line 8, in <module>
import numpy
File "/usr/lib/python2.7/dist-packages/numpy/__init__.py", line 153, in <module>
from . import add_newdocs
File "/usr/lib/python2.7/dist-packages/numpy/add_newdocs.py", line 13, in <module>
from numpy.lib import add_newdoc
File "/usr/lib/python2.7/dist-packages/numpy/lib/__init__.py", line 8, in <module>
from .type_check import *
File "/usr/lib/python2.7/dist-packages/numpy/lib/type_check.py", line 11, in <module>
import numpy.core.numeric as _nx
File "/usr/lib/python2.7/dist-packages/numpy/core/__init__.py", line 6, in <module>
from . import multiarray
ImportError: /usr/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbol: PyExc_SystemError
Segmentation fault (core dumped)
As per I can understand,it fails to import numpy library as specified in test.py file. How to solve this problem of ImportError & PyExc_SystemError?
The python script works as charm if I run in as follows:
#include <Python.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
return 0;
}
If it works under general python embedding examples, why its not working in PAM-based embedding examples (where .so files are used)?
PS: I'm importing numpy for a particular reason. Don't ask why I've not used in anywhere in python script as this is just a demo script of what I'm trying to achieve. Moreover, import math doesn't give any import error. I get import error for SciPY too.
PPS: Numpy and Scipy packages works perfect in python scripts and is installed under /usr/lib/python2.7/dist-packages/. I'm using ubuntu 14.04.
Please help!!!!
I don't know the answer to your question, but I am wondering why it didn't fail earlier. The host application does not know your PAM module will be needed using libpython2.7.so.1, so somehow that must being loaded dynamically otherwise the Py_Initialize() call would fail with the same error.
Given you say it doesn't fail there it must be loaded. However from the error you are getting we can deduce the symbols it contains (such as PyExc_SystemError) are not visible to dynamic libraries subsequently loaded. This is the default when libraries are loaded using dlopen() (see RTLD_LOCAL in man 3 dlopen). To override it, you must pass RTLD_GLOBAL to dlopen(). Maybe that's your problem.
Other comments about your code:
Calling Py_Initialise() for each pm_sm_...() call is going to be expensive and possibly surprising to the python modules. It means all data the python module accumulated within one call (like say voice or the user name) will be discarded when the next call is made. You are better off loading libpython2.7.so.1 and initialising PAM once, then using the cleanup function of pam_set_data() to unload it when you are done.
In a related issue, your PAM module isn't usable from Python programs because you always call Py_Initialise() (and I presume the matching call to Py_Finalize()).
If you program hadn't fallen over where it did, it would have fallen over on the line printf("Result is %s\n",PyString_AsString(pResult)) because pResult isn't initialised.
As I think you know, all the boilerplate you have here to let you wring PAM modules in Python is provided by pam-python - no C required. Since you are evidently writing your PAM module in Python anyway, you are already exposed to the overheads it incurs but are missing out on the features it provides like logging uncaught Python exceptions. And most importantly, using it means you can avoid C entirely. Your PAM module will be loaded into programs that guard the security of the machine - programs like login, sudo, and xdm/gdm3. Avoiding C means also avoiding the legions of security bugs C programs can have that are impossible in Python - buffer overruns, uninitialised pointers and accessing free'ed memory. Since you have one of those bugs in your the C code you posted here, avoiding it sounds like a good idea.

connection gwan with aerospike db in C

Hello.
First I'm sorry for my ita-english.
I want use gwan with aerospike but when run the servlet...problem.
I start with this example.c of aerospike. In file example.c I put gwan.h and this is the output ./gwan:
loading
hello.cs: to use .cs scripts, install C#..
hello.lua: to use .lua scripts, install Lua
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Linking example.c: undefined symbol: g_namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To run G-WAN, you must fix the error(s) or remove this Servlet.
Inside example.c:
#include "gwan.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <aerospike/aerospike.h>
#include <aerospike/aerospike_key.h>
#include <aerospike/aerospike_query.h>
#include <aerospike/as_error.h>
#include <aerospike/as_key.h>
#include <aerospike/as_query.h>
#include <aerospike/as_record.h>
#include <aerospike/as_status.h>
#include <aerospike/as_val.h>
#include "example_utils.h"
const char TEST_INDEX_NAME[] = "test-bin-index";
bool query_cb(const as_val* p_val, void* udata);
void cleanup(aerospike* p_as);
bool insert_records(aerospike* p_as);
int
main(int argc, char* argv[])
{
if (! example_get_opts(argc, argv, EXAMPLE_MULTI_KEY_OPTS)) {
exit(-1);
}
aerospike as;
example_connect_to_aerospike(&as);
example_remove_test_records(&as);
example_remove_index(&as, TEST_INDEX_NAME);
if (! example_create_integer_index(&as, "test-bin", TEST_INDEX_NAME))
{
cleanup(&as);
exit(-1);
}
if (! insert_records(&as)) {
cleanup(&as);
exit(-1);
}
if (! example_read_test_records(&as)) {
cleanup(&as);
exit(-1);
}
as_error err;
as_query query;
as_query_init(&query, g_namespace, g_set);
as_query_where_inita(&query, 1);
as_query_where(&query, "test-bin", as_integer_equals(7));
LOG("executing query: where test-bin = 7");
if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL)
!= AEROSPIKE_OK) {
LOG("aerospike_query_foreach() returned %d - %s", err.code,
err.message);
as_query_destroy(&query);
cleanup(&as);
exit(-1);
}
LOG("query executed");
as_query_destroy(&query);
cleanup(&as);
LOG("simple query example successfully completed");
return 0;
}
bool
query_cb(const as_val* p_val, void* udata)
{
if (! p_val) {
LOG("query callback returned null - query is complete");
return true;
}
as_record* p_rec = as_record_fromval(p_val);
if (! p_rec) {
LOG("query callback returned non-as_record object");
return true;
}
LOG("query callback returned record:");
example_dump_record(p_rec);
return true;
}
void
cleanup(aerospike* p_as)
{
example_remove_test_records(p_as);
example_remove_index(p_as, TEST_INDEX_NAME);
example_cleanup(p_as);
}
bool
insert_records(aerospike* p_as)
{
set
as_record rec;
as_record_inita(&rec, 1);
for (uint32_t i = 0; i < g_n_keys; i++) {
as_error err;
as_key key;
as_key_init_int64(&key, g_namespace, g_set, (int64_t)i);
as_record_set_int64(&rec, "test-bin", (int64_t)i);
if (aerospike_key_put(p_as, &err, NULL, &key, &rec) != AEROSPIKE_OK) {
LOG("aerospike_key_put() returned %d - %s", err.code, err.message);
return false;
}
}
LOG("insert succeeded");
return true;
}
how can connect aerospike with gwan?
Thank you
You need to #pragma link your aerospike library, and make sure all your required header files are in the right place. See G-WAN FAQ or read example code in the G-WAN tarball.
Also, in G-WAN the return code of the main function will be used as HTTP response code, so avoid return -1;.
undefined symbol: g_namespace
the error message is clear. As long as this variable is undefined your C servlet won't compile.
I don't know your library but this variable is probably defined in a library include file - or must be defined by the end user (you). Check the library documentation.
Detailed steps to run Aerospike C-client example with G-WAN,
Download and extract G-WAN server tar on your system
You can start the G-WAN server using ./gwan script present in extracted folder, e.g. ./gwan_linux64-bit/
Get Aerospike C-client from https://github.com/aerospike/aerospike-client-c, and install on your system
Copy example.c to ./gwan_linux64-bit/0.0.0.0_8080/#0.0.0.0/csp/
Make following changes to example.c,
Add following #pragma directive,
#pragma include "/home/user/aerospike-client-c/examples/utils/src/include/"
This will help search example_utils.h, which is necessary for all the example scripts in C-client.
Add following #pragma directive,
#pragma link "/home/user/aerospike-client-c/examples/utils/src/main/example_utils.c"
We shall have to link example_utils.c, as it has definitions of all util functions used in example scripts.
Make changes to the return values. Retun proper HTTP error codes.
Now, you are good to go. Run ./gwan server and access your webservice through browser, http://127.0.0.1:8080/?example.c

File Finder in C

First of all Sorry for my bad English. I am not native English.
I am going to write a program that list all available logical disk drives. Then ask the user to select a drive. then takes a file extension and searches that file type in given drive (including directories and sub-directories). Program should be able to run on windows xp and onward. It should be single stand alone application. I am not expert in C. I have some hands on C#. i have following questions in this regard.
1. Is there any IDE/Tool in which i can write C# like code that directly compiles to single stand alone application for windows?
2. Can you recommend some libs that i can use state forward for this purpose like using in C#? (I have seen dirent and studying it.)
I coppied some code that i am testing as a startup.
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>
#include<conio.h>
#include<dirent.h>
//------------------- Get list of all fixed drives in char array. only drive letter is get. not path.
// add ":\" to build path.
char AllDrives[26];
DWORD GetAllDrives()
{
int AvlDrives=0;
DWORD WorkState=-1;
//TCHAR DrivePath[] = _T("A:\\"); //Orignal Type
//start getting for drive a:\ to onward.
char DrivePath[] = {"A:\\"};
//http://www.tenouk.com/cpluscodesnippet/getdrivetype.html
ULONG uDriveMask = _getdrives();
if (uDriveMask == 0)
{
WorkState=GetLastError();
printf("\r\nFailed to Get drives. Error Details : %lu", WorkState);
return WorkState;
}
else
{
WorkState=0xFF;
printf("The following logical drives are being used:\n");
while (uDriveMask) {
if (uDriveMask & 1)
{
UINT drvType=0;
drvType = GetDriveType(DrivePath);
if(drvType==3)
{
AllDrives[AvlDrives]= DrivePath[0];
AvlDrives++;
printf("\r\n%s",DrivePath);
}
}
++DrivePath[0]; //Scan to all scanable number of drives.
uDriveMask >>= 1;
}
}
return WorkState;
}
int main(int argc, char* argv[]) {
char DrivePath[]={"C:\\"};
char CurrentDrive[]={"C:\\"};
DWORD Drives=-1;
int d=0;
for( d=0; d<26; d++)
AllDrives[d]=' ';
Drives=GetAllDrives();
if(Drives >0)
{
int Length= sizeof(AllDrives);
for(int x=0; x<26; x++)
{
if(AllDrives[x]!=' ')
{
printf("\r\nFixed Drive : %c",AllDrives[x]);
}
}
}
getch();
}
You can use visual studio compiler to compile C and C++ in Windows, and it is available with its own IDE. When you install visual studio, it will install required libraries also to compile the C/C++ program. There are other IDEs and compilers available compatible with Windows like DevC++,CodeBlocks.

Develop C with multiple main entry points

I used to develop Java project by Eclipse.
A Java project can contain many code files with the main function (the entry point), so we can run each code file which has a main function.
But now I want to develop C project by Eclipse CDT.
In a C project we can have only one main function. Can I have many code files with a main function and run each file just like I would in Java?
P.S.: I don't like to write Make Target for each file by main self
Javas option to have a main in every object is highly irritating and does not make sense to me.
I assume you want to train a bit in c and want to find a way to have all training lessons in one file. Here is an option that would do that for you in a crude way. This would not be reasonable to do as an application but you can use this to execute different options.
To use this you would call your program like 'progname 1'.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int ProgrammingLesson001(void);
int main(int argc, char * argv[])
{
int i;
int option;
int e = 0;
printf("%i\n", argc);
for(i = 0; i < argc; ++i)
{
printf("%s\n", argv[i]);
}
if(2 == argc)
{
option = atoi(argv[1]);
printf("Your Option was '%s' interpreted as %i\n", argv[1], option);
}
else
{
option = 0;
e |= 1;
}
switch(option)
{
case 0:
printf("zero is an error\n");
e |= 1;
break;
case 1:
e |= ProgrammingLesson001();
break;
default:
break;
}
if(0 != e)
{
printf("an error has occureed\n");
}
return e;
}
int ProgrammingLesson001(void)
{
printf("This could behave like a main for training purposes\n");
}
If you spent some time programming in c take a second look at makefiles.
You can create a makefile that will fit all your programs.
This reduces the actual work you need to put into this so much that maintaining the switch construct is harder than creating a new project.
Thank Clifford to fixed my quest and guys who replied
I have solved this problem by myself
Here is my solution:
#!/bin/bash
SourceFile=$1
Path="$(dirname "$SourceFile")"
ParentPath="$(dirname "$Path")"
OutputPath="$ParentPath/bin"
OutputFile="$OutputPath/a.out"
mkdir -p $OutputPath
rm -f $OutputFile
gcc -w $SourceFile -lm -o $OutputFile
$OutputFile
This bash's name is gcc.sh
In eclipse run -> external tools -> external tools configurations -> new a configuration
Location: /home/xxxxx/gcc.sh
Working Directory: (just let it be empty)
arguments: ${resource_loc}
Then you can run C file by your customize command

C library gives '__gxx_personality_v0 ' error in Postgres

I'm building a new 64bit Debian Squeeze server, and Postgres 8.4 reports the well documented 'undefined __gxx_personality_v0' error when I try to restore a database.
The lib builds/installs fine.
However, the source is c, not c++ which seems to be where __gxx_personality_v0 belongs.
The code is from a 32bit Etch/postgres 8.1 environmnet.
I'm kind of stuck - but I bet the solution is very simple!
Test to see whether the issue is actually related to PostgreSQL, or if it is a problem with your library build. Here's a simple program you can use to dlopen() your library and resolve a symbol. Compile it with:
gcc dlopentest.c -o dlopentest -ldl
... and run it as:
./dlopentest /path/to/my/lib.so somesymbol
or for more info prefix LD_DEBUG=symbols (for other options LD_DEBUG=help) eg:
LD_DEBUG=symbols ./dlopentest /path/to/my/lib somesymbol
Which symbol to look for depends on your code and what it's for. You haven't provided enough information to say.
This test program won't work with any library that requires symbols from the postgresql executable in order to load and init, so if your code is (for example) a procedural language it won't load. Most simple modules load fine, though.
You should also examine the output of:
ldd /path/to/your/library.so
to see if it's linking to libstdc++ or anything else you don't expect.
Here's the test program:
// Compile with a c99 compiler; I don't use oldstyle declarations
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char * argv[]) {
if (argc != 3) {
printf("Usage: %s /path/to/lib/to/load symbol_to_resolve\n", argv[0]);
printf(" eg: %s libc.so.6 gettimeofday\n", argv[0]);
return 1;
}
char * err;
const char * const libname = argv[1];
const char * const symname = argv[2];
dlerror(); // clear dl error state before starting work
void * libhandle = dlopen(libname, RTLD_LAZY);
if ( (err = dlerror()) != NULL ) {
printf("Failed to load library: %s\n", err);
return 2;
}
void * symhandle = dlsym(libhandle, symname);
if ( (err = dlerror()) != NULL ) {
printf("Failed to load symbol: %s\n", err);
return 2;
}
printf("Successfully retrieved symbol %s from library %s\n", symname, libname);
// Optional since we're existing, but good for testing:
if ( (err = dlerror()) != NULL ) {
printf("Failed to close lib during exit: %s\n", err);
return 2;
}
return 0;
}

Resources