accessing sqlite with C program - c

Core dumped while running this program:
int main(void) {
sqlite3 *conn;
int error = 0;
error = sqlite3_open("cloud_db.sqlite3", &conn);
if (error) {
puts("Can not open database");
exit(0);
}
error = sqlite3_exec(conn,
"update server set servername=\'Laks\' where ipaddress=\'192.168.1.111\'",
0, 0, 0);
if (error) {
puts("Can not update table");
exit(0);
}
sqlite3_close(conn);
return 0;
}
I have tried accessing (select query) sqlite using C and it shows the contents - that's fine. How can I use queries like update? Above I'm trying to execute a query like:
update server set servername="Laks" where ipaddress="192.168.1.111";
running this query with in sqlite> works fine. How to execute (update query) it from C program?

Since you point out that the problem is there when the statement contains "servername=\'Laks\'" and leaves when you change that to "servername=Laks" I guess the backslashes cause the problem. You don't need backslashes to escape the apostrophe in string literals. Simply use "servername='Laks'". You escape quotes (") in string literals and apostrophes (') in character literals, but not vice versa.
You also need to add the semicolon (;) at the end of the query string: "whatever sql statement text;".

sharptooth is right on when he asks which statement leads to the core dump. Since you haven't answered, I'm thinking you may not know how to do that.
First off, make sure your program is compiled with debug symbols. Assuming you're using gcc, you do that by having -g on the command line.
Next, make sure your environment will write core files. Do this with the shell command ulimit -c unlimited (when running in sh, bash, etc.) or limit core unlimited (when running in csh).
Run the program and let it crash.
Next, bring up the core in gdb with gdb programname corename.
Finally, run the backtrace command in gdb to see where the crash was.

Related

Postgres ECPG: adding a function outside main() breaks the program

I have successfully connected and obtained data from Postgresql with my C application. My connector.pgc file looks like this:
#include <stdlib.h>
#include <stdio.h>
//#include "connect.h" // PROBLEM
int connect(); //NO PROBLEM
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
const char *target = "dbname#host:port";
const char *user = "user";
const char *passwd = "password";
EXEC SQL END DECLARE SECTION;
int main() {
EXEC SQL CONNECT TO :target AS con1 USER :user USING :passwd;
EXEC SQL SELECT pg_catalog.set_config('search_path', 'schema_name', false); EXEC SQL COMMIT;
EXEC SQL SET CONNECTION con1;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database is '%s'\n", dbname);
EXEC SQL DISCONNECT ALL;
// connect();
return 0;
}
// PROBLEM
//int connect(){
// printf("A\n");
// return 0;
//}
except, of course, username/password/schema_name/etc. are replaced with actual values.
I then do the following:
ecpg connector.pgc && gcc connector.c -o connectorXec -lecpg -L/usr/pgsql-12/lib && ./connectorXec
My operating system is a default CentOS 8.
ecpg --version returns ecpg (PostgreSQL) 13.2
psql --version returns psql (PostgreSQL) 12.8
The program compiles fine and I am able to connect without issues, the way I know this is printf extracts the correct database name, and I've also run other SQL SELECTS to confirm the data.
However, as soon as I uncomment the int connect() function, even without using it, it is called 3 times before the actual program, and I do not know why. To be more precise, I see the letter A being printed 3 times. Additionally, printf no longer displays the correct name, instead dbname is empty.
I tried putting int connect() function into a separate connect.c file, then linking it together with this program through connect.h, and the result is the same.
If I put the contents of main() into connect(), and then call it, the process just hangs indefinitely.
Truly, I am at a loss, and I do not have even the slightest idea of where to begin, since this situation seems impossible. I checked the connector.c file that ECPG produces and there are no additional calls. Most references I can find online contain only main() function, and in rare cases where they do not, there is no mention of any remotely similar issue.
Any ideas as to what's going on?
OK, so it turns out the connect() function is used somewhere, since renaming it solved the issue. I was renaming it in the created connector.c file, which is how I missed this obvious solution.
Laurenz Albe said that he tried this on his end and everything is fine, which means it is somehow unique to my setup.

Running cat /proc/cpuinfo in glib

I've been trying to look for questions on how to use g_spawn_sync() and they said that it is good to use when you want to execute a command in the terminal besides using pipes.
The only thing I can't figure out now is why the command cat /proc/cpuinfo doesn't work. error->message returns (No such file or directory)but if I use commands like ls or cat alone, it works. I also tried running cd /proc && cat cpuinfo but it gives me the same error.
I'm not an expert of glib but I read in the manual that I can use G_SPAWN_SEARCH_PATH so that it will check my PATH for the commands I can use without including the absolute path for the command.
I have the following code:
gchar *argv[] = { "cat /proc/cpuinfo", NULL };
char *output = NULL; // will contain command output
GError *error = NULL;
int exit_status = 0;
if (!g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
&output, NULL, &exit_status, &error))
{
printf("[getHardwareInfo] DEBUG: Error on g_spawn_sync %s.\n", error->message);
}
tl;dr: Do not use g_spawn_command_line_sync() unless you really know what you are doing.
Firstly, the actual problem you are hitting: John Szakmeister’s comment was correct: g_spawn_sync() takes an array of arguments, the first one of which is the path to the program to execute (or to look for in $PATH, if you’ve specified G_SPAWN_SEARCH_PATH). By passing the array { "cat /proc/cpuinfo", NULL }, you are saying that you want to run the program cat /proc/cpuinfo with no arguments, not the program cat with the argument /proc/cpuinfo.
However, there are many other problems here, and I think it’s important to mention them before people start cargo-culting this code, because they have security implications:
As LegalProgrammer says, why are you spawning cat when you could just call g_file_get_contents()?
Failing that, use GSubprocess instead of g_spawn_*(). It’s a more modern API, which allows you to monitor the lifecycle of the spawned process more easily, as well as getting streaming I/O in and out of the subprocess.
Do not ignore the warnings in the manual about the security implications of using g_spawn_command_line_sync(). There are several:
It will run the first matching program found in your $PATH, so if an attacker has control of your $PATH, or write access to any directory in that $PATH (such as ~/.local/bin), you will end up running an attacker-controlled program.
It’s a synchronous function, so will block on the subprocess completing, which could take unbounded time. Your program will be unresponsive for that time.
It returns the output in a single allocation, rather than as a stream, so if the subprocess returns many megabytes of output, you may hit allocation failures and abort.
The obvious next step from “g_spawn_command_line_sync() seems to do what I want” is “let’s use g_strdup_printf() to put together a command to run with it”, and then you have shell injection vulnerabilities, where an attacker who controls any of the parameters to that printf() can twist the entire shell command to execute their arbitrary code.
I'm answering my question here. After reading the manual again, I decided to use another function, g_spawn_command_line_sync, which is simpler to use than g_spawn_sync.
A simple version of g_spawn_sync() with little-used parameters removed, taking a command line instead of an argument vector. See g_spawn_sync() for full details. command_line will be parsed by g_shell_parse_argv(). Unlike g_spawn_sync(), the G_SPAWN_SEARCH_PATH flag is enabled. Note that G_SPAWN_SEARCH_PATH can have security implications, so consider using g_spawn_sync() directly if appropriate. Possible errors are those from g_spawn_sync() and those from g_shell_parse_argv().
Here is my new code:
char *output = NULL; // will contain command output
GError *error = NULL;
gint exit_status = 0;
if (!g_spawn_command_line_sync("cat /proc/cpuinfo", &output, NULL, &exit_status, &error))
{
printf("[getHardwareInfo] DEBUG: Error on g_spawn_command_line_sync %s.\n", error->message);

CLion won't show output in Debug

When I start up the program, this is the output:
-------------------- HASHMAP MANAGEMENT BOOT MENU -------------------------
Would you like to:
(a) create a new hashmap
(b) load an existing one
(q) exit
>
However, when debugging, none of this shows up. Checking the debug, it does go over the printf() commands, but it just refuses to let them show up in the console. Input registers, but output never comes.
int main(void){
bool on = true;
char choice = ' ';
int status = 0;
while(on){
if(status == -1){
printf("\n[ERROR] : HASHMAP NOT INITIALISED\n");
}
printf("\n-------------------- HASHMAP MANAGEMENT BOOT MENU -------------------------\n");
printf("Would you like to:\n(a) create a new hashmap\n(b) load an existing one\n(q) exit\n> ");
scanf("%c",&choice);
...
...
}
}
This is how the start of the code is, excluding all the #includes. Also, for some reason, CLion says the code I'm building is task2-a.c | Debug if that's any help. task2-a.c being the name of the C file that's being built. I dunno what's going on...
Update: Debugging works great on Ubuntu 17.04 Clion 2017.2. It just doesn't work on Windows 10 CLion 2017.3.
Putting setbuf(stdout, 0); before any printf statement or any output happens fixed this problem.
If you don't care to use the built-in clion console, you can solve the issue by changing the default debugger used by clion.
Under Settings => Toolchain => <your compiler> => Debugger change Bundled GDB to your compiler's debugger, e.g. MinGW:

C program exits giving error ORA-12162: TNS:net service name is incorrectly specified

I am working on a remote red-hat server and there I'm developing a c application to insert data in to a remote oracle database. So first i installed the OCI instant client rpm on the server and tried to compile a sample program. after certain linkages I could compile it. But then when I am going to run it. It exits giving an error saying
ORA-12162: TNS:net service name is incorrectly specified
The sample code I used is from the blog (refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post) René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle
(refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post)
In the code I added some prints to check for the error And it seems like It gets stuck in the OCIServerAttach() function r gives a printed walue of -1
r=OCIServerAttach(srv, err, dbname, strlen(dbname), (ub4) OCI_DEFAULT);
printf("r value %d",r);
if (r != OCI_SUCCESS) {
checkerr(err, r);
goto clean_up;
}
Another point is that in the compilation process it gives a warning saying that a certain libry is not include. but the exicutable file is created. Here is the massage I get in the compilation process.
[laksithe#loancust ~]$ gcc -L$ORACLE_HOME/lib/ -L$ORACLE_HOME/rdbms/lib/ -o oci_test oci_test.o -L/usr/lib/oracle/12.1/client64/lib -lclntsh `cat $ORACLE_HOME/lib/sysliblist`
cat: /lib/sysliblist: No such file or directory
Going through the web I found that by creating a tnsnames.ora file with the connection details I could solve the problem. But even It didn't work for me. Here is the link for that blog blog
It has been a week since this error and I cold'nt solve it. could someone please help me.
connection string format I used is abc.ghi.com:1521/JKLMN
My recommendation is to bypass tnsnames completely. Oracle has always allowed you to put in the direct connection details, but EZConnect makes that even easier.
When you format your connection string, instead of listing the TNS name, use the actual connection properties in the following format:
servername:port/service name
For Example
MyOracle.MyCompany.Com:1521/SalesReporting
Your connection string might also require direct=true, but I'm honestly not sure.
I like the idea of tnsnames, but it's a double edged sword. When it works, it's great. When it doesn't, you want to throw something. With EZConnect, it always works.
By the way, if you don't know the properties of the three items above, find a machine that connect via tnsnames and:
tnsping <your TNS-named database>

C script running as cron giving permission denied error

I have a .c file compiled and would like to run via a cron job but I end up getting this error:
/bin/sh: /usr/local/bin/get1Receive.c: Permission denied.
What is causing this error and how do I fix it?
Should I be running the .c file in cron or a different compiled file?
Results from /tmp/myvars
GROUPS=()
HOME=/root
HOSTNAME=capture
HOSTTYPE=x86_64
IFS='
'
LOGNAME=root
MACHTYPE=x86_64-redhat-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/bin:/bin
POSIXLY_CORRECT=y
PPID=11086
PS4='+ '
PWD=/root
SHELL=/bin/sh
SHELLOPTS=braceexpand:hashall:interactive-comments:posix
SHLVL=1
TERM=dumb
UID=0
USER=root
_=/bin/sh
Results from file get1Receive.c
file get1Receive.c
get1Receive.c: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
Snippet of codes.
sprintf(queryBuf1,"SELECT ipDest, macDest,portDest, sum(totalBits) FROM dataReceive WHERE timeStampID between '%s' And '%s' GROUP BY ipDest, macDest, portDest ",buff1,buff2);
printf("\nQuery receive %s",queryBuf1);
if(mysql_query(localConn, queryBuf1))
{
//fprintf(stderr, "%s\n", mysql_error(localConn));
printf("Error in first query of select %s\n",mysql_error(localConn));
exit(1);
}
localRes1 = mysql_store_result(localConn);
int num_fields = mysql_num_fields(localRes1);
printf("\nNumf of fields : %d",num_fields);
printf("\nNof of row : %lu",mysql_num_rows(localRes1));
If the output of this command:
file get1Receive1.c
shows that file name to be a valid executable that part is very unusual, but okay.
Assuming you are using biz14 (or your real username's ) crontab try this:
use the command crontab -e to create this line in your crontab:
* * * * * set > /tmp/myvars
Wait a few minutes, go back into crontab -e and delete that entry.
Use the set command from the command line to see what variables and aliases exist.
Compare that with that you see in /tmp/myvars You have to change how your C code executes by changing the variables and aliases the cron job runs with.
If you are running the cron job in someone else's crontab, then you have a bigger problem. Check file permissions on get1Receive1.c. and the directory it lives in. That other user (the one who wons the crontab) has to have permissions set on your directory and get1Receive1.c so the job can run.
Example crontab entry:
0 10 * * 1-5 /path/to/get1Receive1.c > /tmp/outputfile
Read /tmp/outputfile to see what you got. You are using printf in your code. printf only writes to the controlling terminal. There is no controlling terminal, so redirect the printf stuff to a file.
Last effort on this problem:
Check return codes on EVERYTHING. All C functions like fread(), any db function, etc. If a return code gives a fail response ( these are different for different function calls) then report the error number the line number and function - gcc provides LINE and func. Example:
printf("error on line %d in my code %s, error message =%s\n", __LINE__, __func__, [string of error message]);
If you do not check return codes you are writing very poor C code.
CHECK return codes, please, now!
Permission wise you could have two issues.
1. The 'c' file's permissions don't allow who you are running it as to run it.
2. You are running the cron with a script which doesn't have permissions.
Here's a helpful post: How to give permission for the cron job file?
The fact that you are running a 'c' file and referring to it as a script makes me think you're using C shell and not writing it as a C language program which would need to be compiled and have the generated executable run by the cron. If you're not using gcc or have never called gcc on your 'C' script then it's not C and call it C shell to avoid confusion.

Resources