Hi, everyone!
I want to make the user authentication for mysql database. I write the code and test it, but can't run. Let's I talk about my project idea first.
I have a server, a client and a mysql database. Before entering the server, the user must login first, After login, he can access the database using his privileges (can create databases,tables, insert , update and retrieve data). After finishing the desired tasks, he can log out, then the server will reflects his status as log out.

My code for authentication part is :

static char *opt_host_name = NULL;
static char *opt_user_name = NULL;      /* username (default=login name) */
static char *opt_password = NULL;       /* password (default=none) */
static char *opt_db_name = NULL;        /* database name (default=none) */

int main((int argc, char *argv[]){
        printf("Enter host name : ");
	fflush(stdin);
	gets(opt_host_name);
	printf("Enter user name : ");
	fflush(stdin);
	gets(opt_user_name);
	printf("Enter password : ");
	fflush(stdin);
	gets(opt_password);
	printf("and database : ");
	fflush(stdin);
	gets(opt_db_name);

	if((mysql=mysql_init(mysql))==NULL) {
   		 printf("\nFailed to initate MySQL connection");
   		 exit(1);
 	 }
           if (!mysql_real_connect(mysql,opt_host_name,opt_user_name,opt_password, 
opt_db_name,0,NULL,0))
       {
                 printf( "Failed to connect to MySQL: Error: %s\n", mysql_error(mysql));
   	         exit(1);
  	}
	 printf("\nLogged on to database sucessfully\n\n");
.....
}

I write like the above code, it does not work. But if I replace the host, username and password by the string, it works. But I don't want the constant username and password, because many users will log in to the server. So what do I need to do? Please help me with the example code, if any.
Also when the password is entered, I want it to be invisible to the others, what should I add in?
And if the user has few databases, can I let him log in first, without choosing the database? After login, he can work on the wanted database (same when working with mysql monitor screen, choosing database name by command) Because of the mysql_real_connect definition, I can't let databasename blank, but it may be difficult for the user, if he does not remember all the databases he has.

Thank a lot for your help and your time.

Nevermind the database, you need to work on the basics of C programming.

> int main((int argc, char *argv[]){
Mis-matched.
You didn't even compile this before posting did you.

> fflush(stdin);
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351

> gets(opt_host_name);
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1049157810&id=1043284351
Not only that, where is opt_host_name pointing?
Answer - nowhere.

Practice reading input using char arrays and calls to fgets() for a while.

Ok. I know my mistakes in those 2 calls now (I always use like this, thank you for correcting). But your question about the opt_host_name, where is the pointer pointing, I want to ask another question (I'm not so good at programming). The mysql_real_connect definition is :

mysql_real_connect : (* if MYSQL_VERSION_ID >= 32200 *)
	 mysql
	 -> string	(* const char* host  *)
	 -> string	(* const char* user *)
	 -> string	(* const char* passwd *)
	 -> string 	(* const char* db *)
	 -> int 	(* unsigned int port *)
	 -> string	(* const char* unix_socket *)
	 -> int		(* unsigned int client_flag *)
	 -> mysql

All the parameters are pointer. If I don't declare variable as a pointer, all those will be incompatible. (is it right? This is my thinking that they must be the same in type of variable). If not correct, how can I change them?

Say you have void foo ( const char *param ); You can call it with ALL of these

char buff[100];
const char cbuff[] = "hello";
char *pbuff = buff;
const char *pcbuff = cbuff;

foo ( buff );
foo ( cbuff );
foo ( pbuff );
foo ( pcbuff );
foo( "hello world" );

In the context of a function formal parameter (or a prototype), what it is telling you is that the function will NOT change it.

void bar ( const int *p, int *q ) {
  *p = 0; // NOT allowed, p is a pointer to const
  *q = 0; // this one is OK
}

It means that whatever was in your array before the call will still be there after the call.

What you call it with doesn't have to be const as well.

Similarly, when you call a function expecting an int pointer (for example), then this is what it usually means

int result;
func ( &result );

Now you can declare a pointer it you want, but you need to initialise it.

int result;
int *pa = &result;
func ( pa );

But this is definitely wrong

int *pa;
func ( pa );

Wherever you have a pointer, you need to be thinking about where the memory is, and have you initialised it to point to some suitable memory. Simply declaring variables with the correct type will keep the compiler from complaining (sure the types are right), but it will always blow up as soon as you run it.

Ok. I know my mistakes in those 2 calls now (I always use like this, thank you for correcting). But your question about the opt_host_name, where is the pointer pointing, I want to ask another question (I'm not so good at programming). The mysql_real_connect definition is :

mysql_real_connect : (* if MYSQL_VERSION_ID >= 32200 *)
	 mysql
	 -> string	(* const char* host  *)
	 -> string	(* const char* user *)
	 -> string	(* const char* passwd *)
	 -> string 	(* const char* db *)
	 -> int 	(* unsigned int port *)
	 -> string	(* const char* unix_socket *)
	 -> int		(* unsigned int client_flag *)
	 -> mysql

All the parameters are pointer. If I don't declare variable as a pointer, all those will be incompatible. (is it right? This is my thinking that they must be the same in type of variable). If not correct, how can I change them?

P/S : Sorry for second post of the same content, just a mistake. Thank for your reply. Anything else don't understand I'll re-post. Hope it don't bother you.

You declare your strings as char arrays.
When you pass your strings to a function, they will be compatible with "const char *" without you having to do anything special.

Just look at how you use strcpy() for example.

Er...I have one problem with mysql database. Hope you can guide me, Salem.

if (mysql_query(conn, "show tables")) {
      	fprintf(stderr, "%s\n", mysql_error(conn));
        exit(1);
}

The second parameter is a string. But in this case it's hard-coded. I want to take the user input and assign to the second parameter. I wrote the code like this :

char sQuery[1000];
         printf("msyql>");
	fgets(sQuery, sizeof sQuery, stdin);
        if (mysql_query(conn, sQuery)) {
      	fprintf(stderr, "%s\n", mysql_error(conn));
        exit(1);
       if(mysql_query(conn, sQuery) !=0)
       {
	  	print_error (conn, "UPDATE statement failed");
       }
       else
       {
		printf("CREATE statement succeeded.");
       }

But it even not let me to enter anything, directly go to SQL statement (but of course can't work). I write the code to get the user input separate, to another file to test, it works. So what's the problem here?

Probably the "\n" which is at the end of the line returned by fgets().
Remove the \n (plenty of examples of how to do this are around).

I copy those lines :

char sQuery[1000];
         printf("msyql>");
	fgets(sQuery, sizeof sQuery, stdin);
       printf("%s", sQuery); //to see if fgets() works

to another text editor. Result is, it can display what I enter. But put together with the SQL statement, can't work. I just don't know what the reason is. Also try remove the "\n", the problem's still there.

Do you call any other input routines like say scanf ?
Because that can mess you up as well.

Eg.

scanf( "%d", &myint );
fgets( buff, sizeof buff, stdin );  // this will "appear" to be skipped.

Ideally, you should use fgets() for ALL input, then use say sscanf(), or whatever else to parse the input.

But in the absense of that, try calling this between scanf() and fgets() calls.

int skipToEOL ( FILE *s ) {
  int ch;
  while ( (ch=fgetc(s)) != EOF && ch != '\n' );
  return ch;
}
This article has been dead for over six months. Start a new discussion instead.