⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gqlplus.c

📁 基于的linux的oracle sqlplus替代工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  Check if file 'fptr' contains an editor definition line.*/static char **file_editor(FILE *fptr, char *line){  char **editor = (char **) 0;  while (fgets(line, MAX_LINE_LENGTH, fptr) && (editor == (char **) 0))    if ((line[0] != '#') && strstr(line, DEFINE_CMD) && (strstr(line, EDITOR)))      editor = set_editor(line);  fclose(fptr);  return editor;}/*  Extract EDITOR definition from glogin.sql and login.sql files.  sqlplus takes settings from glogin.sql in  ${ORACLE_HOME}/sqlplus/admin directory first. Then it looks for  login.sql file in the local directory, followed by directories in  ${SQLPATH}. Note that as soon as login.sql is found in any of these  directories, the search stops.*/static char **file_set_editor(char *line){  int  found;  int  cntr;  char *path;  char **editor = (char **) 0;  char **sqlpath;  char *oracle_home;  FILE *fptr;  path = malloc(1024);  /*    Check local directory first.  */  found = 0;  strcpy(path, "login.sql");  fptr = fopen(path, "r");  if (fptr)    {      found = 1;      editor = file_editor(fptr, line);    }  /*    If login.sql is not found in the local directory, check SQLPATH    directories.   */  sqlpath = str_tokenize(getenv("SQLPATH"), ":");  if (sqlpath)    {      cntr = 0;      while (!found && sqlpath[cntr])	{	  sprintf(path, "%s/login.sql", sqlpath[cntr]);	  cntr++;	  fptr = fopen(path, "r");	  if (fptr)	    {	      found = 1;	      editor = file_editor(fptr, line);	    }	}      str_free(sqlpath);    }  if (!found)    {      /*	login.sql not found. Check ${ORACLE_HOME}/sqlplus/admin/gqlplus.sql.      */      oracle_home = getenv("ORACLE_HOME");      if (oracle_home)	{	  sprintf(path, "%s/sqlplus/admin/glogin.sql", oracle_home);	  fptr = fopen(path, "r");	  if (fptr)	    {	      found = 1;	      editor = file_editor(fptr, line);	    }	}    }  free(path);  return editor;}/*  Send 'xtr' to sqlplus using 'i' command.*/                        static void insert_line(int fdin, int fdout, char *xtr, char *ccmd, char *line){  char *str;  char *prompt;  if (xtr && *xtr)    {      sprintf(ccmd, "i %s\n", xtr);      write(fdout, ccmd, strlen(ccmd));      prompt = get_sqlplus(fdin, line, &str);      free(prompt);      free(str);    }}static void free_nta(char **nta){  int i;  if (nta != (char **) 0)    {      i = 0;      while (nta[i] != (char *) 0)        free(nta[i++]);      free(nta);    }}/*  Implement 'PAUSE ON' mode. Requires special processing, since during  the dialogue with sqlplus no prompt is returned.*/static void pause_cmd(int fdin, int fdout, char *line, char *sql_prompt, int first_flag){  int  result;  int  done;  int  dn;  int  llen;  int  capacity;  int  flags;  int  process_response;  int  len;  char *lx;  char *response;  char *sp;  char *prompt;  char buffer[BUF_LEN];  /*    Get sqlplus output without blocking.   */  flags = fcntl(fdin, F_GETFL, 0);  fcntl(fdin, F_SETFL, (flags | O_NDELAY));  /*    Send the command to sqlplus.   */  write(fdout, line, strlen(line));  write(fdout, "\n", 1);  if (first_flag)    process_response = 1;  else    process_response = 0;  lx = malloc((MAX_LINE_LENGTH+1)*sizeof(char));  response = malloc((INIT_LINE_LENGTH+1)*sizeof(char));  response[0] = '\0';  capacity = INIT_LINE_LENGTH;  llen = 0;  if (lx && response)    {      done = 0;      while (!done)	{	  /*	    Read and display response.	    */	  dn = 0;	  if (process_response)	    while (!dn)	      {		result = read(fdin, buffer, 1000);		if (result > 0)		  {		    if (result+llen > capacity)		      {			while (capacity <= result+llen)			  capacity += capacity;			response = realloc(response, capacity+1);		      }		    memcpy(&response[llen], buffer, result);		    llen += result;		    response[llen] = '\0';		  }		/*		  We should get out of the loop when sqlplus finishes		  sending it's response. But there is really no		  guaranteed way to know when sqlplus is done. So the		  best thing we can do here is to wait for at least one		  character; that means sqlplus has started sending, and		  with the small usleep() delay below, it probably means		  it will be done by the time we reach the next read()		  above.		  		  Again, this is not foolproof, but seems to work OK. If		  problems are encountered, increase the usleep()		  interval.		  */		else if ((!result || ((result < 0) && (errno == EAGAIN))) && (llen > 0))		  dn = 1;		else if ((result < 0) && (errno != EAGAIN))		  perror(NULL);		usleep(1);	      }	  process_response = 1;	  /*	    Verify if the response ends in user-defined prompt or	    default prompt. If so, terminate. Otherwise, display it.	  */	  if (sql_prompt)	    prompt = sql_prompt;	  else	    prompt = SQL_PROMPT;	  sp = strstr(response, prompt);	  if (sp && (strlen(sp) == strlen(prompt)))	    {	      done = 1;	      if (!first_flag)		{		  len = sp-response;		  fwrite(response, sizeof(char), len, stdout);		  fflush(stdout);		}	    }	  else	    {	      printf("%s", response);	      fflush(stdout);	      response[0] = '\0';	      llen = 0;	      /*		Get a line from keyboard and send it to sqlplus.		*/	      fgets(lx, MAX_LINE_LENGTH, stdin);	      write(fdout, lx, strlen(lx));	    }	}    }  else    perror(NULL);  /*    Reset pipe from sqlplus to O_NDELAY.   */  fcntl(fdin, F_SETFL, (flags &~ O_NDELAY));  free(lx);  free(response);}/*  Implement sqlplus 'edit' command. The command works in two modes:  first, if no 'fname' is given, it launches editing session of  afiedt.buf file, and sends the edited file to to sqlplus; if fname  is given, it opens it.*/static int edit(int fdin, int fdout, char *line, char **editor, char *fname){  int   child_stat;  int   status;  int   i;  int   xc;  int   len;  int   done;  pid_t pid;  char  *path;  char  *str;  char  *xtr;  char  *ptr;  char  *afiedt;  char  *prompt;  char  *ccmd;  char  *rname;  char  *newline;  char  **xrgs = (char **) 0;  char  **enx = (char **) 0;  FILE  *fptr;  status = 0;  str = (char *) 0;  prompt = (char *) 0;  rname = (char *) 0;  if (fname)    {      /*	Optionally add .sql extension to fname.       */      ptr = strstr(fname, SQLEXT);      if (ptr && (strlen(ptr) == strlen(SQLEXT)))	rname = strdup(fname);      else	{	  rname = malloc((strlen(fname)+strlen(SQLEXT)+1)*sizeof(char));	  sprintf(rname, "%s%s", fname, SQLEXT);	}    }  else    {      /*	Get last SQL statement from sqlplus and put it in afiedt.buf, then	open it in editor.	*/      write(fdout, LIST_CMD, strlen(LIST_CMD));      prompt = get_sqlplus(fdin, line, &str);      /* TBD: afiedt.buf filename hardcoded. */      rname = strdup(AFIEDT);    }  if (fname || !strstr(str, NO_LINES))    {      if (!fname)	fptr = fopen(rname, "w");      if (fptr || fname)        {	  if (!fname)	    {	      /*		Have to clean-up the numeric prompt (5 characters) coming back		from the LIST_CMD.		*/	      xtr = str;	      while ((ptr = strchr(xtr, '\n')) != (char *) 0)		{		  len = ptr-xtr;		  *ptr = '\0';		  fprintf(fptr, "%s\n", xtr+5);		  xtr += len+1;		}	      fprintf(fptr, "/\n");	      status = fclose(fptr);	    }          if (!status)            {              free(str);              free(prompt);              path = editor[0];              xc = 0;              while (editor[xc++] != (char *) 0);              xrgs = calloc(xc+5, sizeof(char *));              xc = 0;              xrgs[xc++] = bname(path);              i = 1;              while (editor[i] != (char *) 0)		{		  if ((newline = strchr(editor[i], '\n')))		    *newline = '\0';		  xrgs[xc++] = strdup(editor[i]);		  i++;		}              xrgs[xc++] = strdup(rname);	      /*		Launch emacs in a separate window.	      */	      if (!strcmp(xrgs[0], "emacs"))		if (!(xrgs[1] && !strcmp(xrgs[1], "-nw")))		  {		    if (getenv("DISPLAY"))		      {			xrgs[xc++] = strdup("-d");			xrgs[xc++] = strdup(getenv("DISPLAY"));		      }		  }              enx = calloc(10, sizeof(char *));              xc = 0;              enx[xc++] = get_env(TERM);              enx[xc++] = get_env(PATH);              enx[xc++] = get_env("HOME");              edit_pid = fork();              errno = 0;              if (edit_pid != 0)                {                  /*                    This is to restart waitpid() after SIGCHLD signal is                    generated (this happens when user presses Ctrl-G in                    Emacs). Perhaps we should just block the signal                    here. Also, you would expect that SA_RESTART would                    achieve this, but couldn't get it to work. Anyways,                    this is simple and it works.                    */                  done = 0;                  while (done == 0)                    {                      pid = waitpid(edit_pid, &child_stat, 0);                      if ((pid == 0) || ((pid < 0) && (errno != EINTR)))                        done = 1;                    }                }              else                 {                   if (execve(path, xrgs, enx) < 0)                     {                      str = malloc(100);                      sprintf(str, "execve() failure; %s", path);                      perror(str);                      _exit(-1);                    }                }              edit_pid = 0;              /*                Restore signal handling.                */              if (1 && !fname)                {                  /*                    Done editing. Use 'del' and 'i' commands to send contents of                    afiedt.buf to sqlplus. Algorithm: delete all lines in the                    buffer using 'del 1 LAST' command, then send all lines from                    'afiedt' to sqlplus using the 'i' command.                    */                  afiedt = read_file(AFIEDT, line);                  if (afiedt != (char *) 0)                    {                      /*                        Remove the trailing '/'.                        */                      len = strlen(afiedt);                      if (!strcmp(&(afiedt[len-3]), "\n/\n"))                        {                          len -= 3;                          afiedt[len] = '\0';                        }                      write(fdout, DEL_CMD, strlen(DEL_CMD));                      prompt = get_sqlplus(fdin, line, &str);                      free(prompt);                      free(str);                      xtr = afiedt;                      ccmd = malloc(MAX_LINE_LENGTH*sizeof(char));                      while ((ptr = strchr(xtr, '\n')) != (char *) 0)                        {                          len = ptr-xtr;                          *ptr = '\0';                          if (*xtr)                            {                              insert_line(fdin, fdout, xtr, ccmd, line);                              xtr += len+1;                            }                        }                      /*                        Last line, if not empty.                        */                      insert_line(fdin, fdout, xtr, ccmd, line);                      write(fdout, LIST_CMD, strlen(LIST_CMD));                      prompt = get_sqlplus(fdin, line, (char **) 0);                      free(prompt);                      free(ccmd);                      free(afiedt);                    }                  else                    status = -1;                }            }          else            fprintf(stderr, "%s", AFIEDT_ERRMSG);          free_nta(enx);          free_nta(xrgs);        }      else        {          fprintf(stderr, "%s", AFIEDT_ERRMSG);          status = -1;        }    }  else    write(STDOUT_FILENO, NOTHING_TO_SAVE, strlen(NOTHING_TO_SAVE));  free(rname);  return status;}FILE *open_log_file(){  char *fname;   FILE *fptr = (FILE *) 0;    fname = malloc(100*sizeof(char));  sprintf(fname, "gqlplus_%d.log", (int) getpid());  fptr = fopen(fname, "w");  free(fname);  return fptr;}struct table {  char  *name;  char  *owner;  char  **columns;};static struct table *tables;/*  Parse column names from output of 'DESCRIBE' Oracle command.*/static char **parse_columns(char *str){  int  i;  int  j;  int  cflag;  int  capacity;  int  clen;  int  idx;  char *cname;  char **columns;  char **tokens;  capacity = INIT_NUM_COLUMNS;  columns = calloc(capacity+1, sizeof(char *));   tokens = str_tokenize(str, "\n");  idx = 1;  i = 0;  cflag = 0;  while ((cname = tokens[idx]))    {      idx++;      if (cflag == 0)        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -