Re: psql \i handling ~ in specified file name - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: psql \i handling ~ in specified file name |
Date | |
Msg-id | 200401081804.i08I4Ce11805@candle.pha.pa.us Whole thread Raw |
In response to | Re: psql \i handling ~ in specified file name (Zach Irmen <zirmen@shaw.ca>) |
List | pgsql-patches |
Zach Irmen wrote: > Bruce Momjian wrote: > > Here is a patch that handles "~" in all the file cases. > > Beat me to it. :) > > I do have a few issues that I was trying to sort out myself > regarding this, but I guess now is as good a time as any to ask > them here. > > First off, there should be a check after the malloc to make sure > NULL wasn't returned in the expand_tilde function. I missed that > one. OK, test added. I see no way to recover from a malloc failure in this case because we can't honor their specification of file name, so we have to exit. > Secondly, there are a couple of SQL commands (like COPY and > LOAD) and psql commands handled outside command.c (like \copy) > which also take filenames. I'm guessing that eventually you'll > want substitution in those cases as well. So does this mean that > the expand_tilde function probably should not be in command.c? > Placing it in common.c seems the logical place to make it at > least available to all the psql commands (\copy included). Yes, seems like that will be required. Please use my attached version to make the adjustments. > And finally, I was wondering if arguments with leading pipes > (e.g. "|~/file") should also get substituted. Yep, that too. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/bin/psql/command.c =================================================================== RCS file: /cvsroot/pgsql-server/src/bin/psql/command.c,v retrieving revision 1.108 diff -c -c -r1.108 command.c *** src/bin/psql/command.c 1 Dec 2003 22:21:54 -0000 1.108 --- src/bin/psql/command.c 8 Jan 2004 18:01:55 -0000 *************** *** 65,70 **** --- 65,72 ---- static bool do_connect(const char *new_dbname, const char *new_user); static bool do_shell(const char *command); + static char *expand_tilde(char **filename); + /*---------- * HandleSlashCmds: * *************** *** 413,418 **** --- 415,421 ---- else { fname = scan_option(&string, OT_NORMAL, NULL, true); + expand_tilde(&fname); status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR; free(fname); } *************** *** 494,500 **** --- 497,506 ---- if (!fname) pset.gfname = NULL; else + { + expand_tilde(&fname); pset.gfname = xstrdup(fname); + } free(fname); status = CMD_SEND; } *************** *** 531,536 **** --- 537,543 ---- } else { + expand_tilde(&fname); success = (process_file(fname) == EXIT_SUCCESS); free(fname); } *************** *** 602,607 **** --- 609,615 ---- { char *fname = scan_option(&string, OT_FILEPIPE, NULL, true); + expand_tilde(&fname); success = setQFout(fname); free(fname); } *************** *** 653,658 **** --- 661,667 ---- { char *fname = scan_option(&string, OT_NORMAL, NULL, true); + expand_tilde(&fname); success = saveHistory(fname ? fname : "/dev/tty"); if (success && !quiet && fname) *************** *** 771,776 **** --- 780,786 ---- else { fname = scan_option(&string, OT_FILEPIPE, NULL, true); + expand_tilde(&fname); if (!fname) { *************** *** 1678,1683 **** --- 1688,1753 ---- } + /* expand_tilde + * + * substitute '~' with HOME or '~username' with username's home dir + * + */ + static char * + expand_tilde(char **filename) + { + if (!filename || !(*filename)) + return NULL; + + /* MSDOS uses tilde for short versions of long file names, so skip it. */ + #ifndef WIN32 + + /* try tilde expansion */ + if (**filename == '~') + { + char *fn; + char *home; + char oldp, + *p; + struct passwd *pw; + + fn = *filename; + home = NULL; + + p = fn + 1; + while (*p != '/' && *p != '\0') + p++; + + oldp = *p; + *p = '\0'; + + if (*(fn + 1) == '\0') + home = getenv("HOME"); + else if ((pw = getpwnam(fn + 1)) != NULL) + home = pw->pw_dir; + + *p = oldp; + if (home) + { + char *newfn; + + newfn = malloc(strlen(home) + strlen(p) + 1); + if (!newfn) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + strcpy(newfn, home); + strcat(newfn, p); + + free(fn); + *filename = newfn; + } + } + #endif + + return *filename; + } /* * process_file
pgsql-patches by date: