From 6fa18fa7522c39aebfeb982c1f9b00bc7cbc4046 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 8 Sep 2004 21:18:59 +0000 Subject: [PATCH] - Add first cut of UTF-8 support to conio. It seems to be working pretty well. Moving by words will definitely not work though. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1590 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 70 ++--------- bacula/src/console/conio.c | 232 +++++++++++++++++++++++++++---------- 2 files changed, 177 insertions(+), 125 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 09b22fd96c..89f2f18b7c 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 07 Septermber 2004 + 08 Septermber 2004 Major development: Project Developer @@ -20,6 +20,9 @@ Version 1.35 Kern (see below) you lost/broke the Catalog -- do the same for "I know my file is there how do I get it back?". +- Add "Multiple connections = yes/no" to catalog resource. +- Add "Rerun failed levels = yes/no" to Job resource. + Maybe for 1.35: - Look at patches/bacula_db.b2z postgresql that loops during restore. @@ -128,8 +131,8 @@ Wish list: - Minimal autochanger handling in Bacula and in btape. - Look into how tar does not save sockets and the possiblity of not saving them in Bacula (Martin Simmons reported this). - The next two lines will show them. - localmounts=`awk '/ext/ { print $2 }' /proc/mounts` # or whatever +- Add All Local Partitions = yes to new style saves. +- localmounts=`awk '/ext/ { print $2 }' /proc/mounts` # or whatever find $localmounts -xdev -type s -ls - Fix restore jobs so that multiple jobs can run if they are not using the same tape(s). @@ -188,14 +191,12 @@ Wish list: - look at mxt-changer.html - Make ? do a help command (no return needed). - Implement restore directory. -- Add All Local Partitions = yes to new style saves. - Document streams and how to implement them. - Possibly implement "Ensure Full Backup = yes" looks for a failed full backup and upgrades the current backup if one exists. - Check that barcode reading and update slots scan works. - Try not to re-backup a file if a new hard link is added. - Add feature to backup hard links only, but not the data. -- Add "All Local = yes" option to save to include all local partitions. - Fix stream handling to be simpler. - Add Priority and Bootstrap to Run a Job. - Eliminate Restore "Run Restore Job" prompt by allowing new "run command @@ -207,13 +208,8 @@ Wish list: - Add display of total selected files to Restore window. - Add tree pane to left of window. - Add progress meter. -- Polling does not work for restore. It tries a number of times, - gives up, and crashes the SD. -- Lock jcr_chain when doing attach/detach in acquire.c -- Add assert in free_jcr if attach/detach chain active. - Max wait time or max run time causes seg fault -- see runtime-bug.txt - Document writing to a CD/DVD with Bacula. -- Add check for tape alerts. - Add a "base" package to the window installer for pthreadsVCE.dll which is needed by all packages. - Add message to user to check for fixed block size when the forward @@ -223,14 +219,10 @@ Wish list: - Possibly implement: Action = Unmount Device="TapeDrive1" in Admin jobs. - Setup lrrd graphs: (http://www.linpro.no/projects/lrrd/) Mike Acar. - Revisit the question of multiple Volumes (disk) on a single device. -- Finish SIGHUP work. -- Check that all change in wait status in the SD are - signaled to the Director. - Add a block copy option to bcopy. - Investigate adding Mac Resource Forks. - Finish work on Gnome restore GUI. - Fix "llist jobid=xx" where no fileset or client exists. -- Check pruning of restore jobs. - From Chris Hull: it seems to be complaining about 12:00pm which should be a valid 12 hour time. I changed the time to 11:59am and everything works fine. @@ -243,26 +235,14 @@ Wish list: then list last 20 backups. - Add all pools in Dir conf to DB also update them to catch changed LabelFormats and such. -- Update volumes FromPool=xxx does all volumes. - Pass Director resource name as an option to the Console. - Add a "batch" mode to the Console (no unsolicited queries, ...). -- Add code to check for tape alerts -- tapeinfo. -- Make sure list of Volumes needed is in correct order for restore. - See havana. -- Remove paths (and files that reference them) that have no trailing slash - in dbcheck -- or add a trailing slash. -- Remove Filenames (and files that reference them) that have a trailing - slash in dbcheck -- or remove the trailing slash. -- Remove orphaned paths/filenames by copying them to a new table with a - reference count, then mark all referenced files/paths and remove unreferenced - ones. - Add a .list all files in the restore tree (probably also a list all files) Do both a long and short form. - Allow browsing the catalog to see all versions of a file (with stat data on each file). - Restore attributes of directory if replace=never set but directory did not exist. -- Allow "delete job jobid=xxx,yyy,aaa-bbb" i.e. list + ranges. - Use SHA1 on authentication if possible. - See comtest-xxx.zip for Windows code to talk to USB. - Make btape accept Device Names in addition to Archive names. @@ -283,40 +263,23 @@ Wish list: - Add disk seeking on restore. - Allow for optional cancelling of SD and FD in case DIR gets a fatal error. Requested by Jesse Guardiani -- Bizarre message: Error: Could not open WriteBootstrap file: -- Build console in client only build. - Add "limit=n" for "list jobs" - Check new HAVE_WIN32 open bits. - Check if the tape has moved before writing. - Handling removable disks -- see below: -- Multiple drive autochanger support -- see below. - Keep track of tape use time, and report when cleaning is necessary. -- Fix FreeBSD mt_count problem. - Add FromClient and ToClient keywords on restore command (or BackupClient RestoreClient). -- Automatic "update slots" on user configuration directive when a - slot error occurs. - Implement a JobSet, which groups any number of jobs. If the JobSet is started, all the jobs are started together. Allow Pool, Level, and Schedule overrides. - Enhance cancel to timeout BSOCK packets after a specific delay. -- When I restore to Windows the Created, Accessed and Modifiedtimes are - those of the time of the restore, not those of the originalfile. - The dates you will find in your restore log seem to be the original - creation dates -- Volume "add"ed to Pool gets recycled in first use. VolBytes=0 -- If a tape is recycled while it is mounted, Stanislav Tvrudy must do an - additional mount to deblock the job. -- From Johan Decock: - bscan: sql_update.c:65 UPDATE File SET MD5='Ij+5kwN6TFIxK+8l8+/I+A' WHERE FileId=0 - bscan: bscan.c:1074 Could not add MD5/SHA1 to File record. ERR=sql_update.c:65 Update problem: affected_rows=0 - Do scheduling by UTC using gmtime_r() in run_conf, scheduler, and ua_status.!!! Thanks to Alan Brown for this tip. - Look at updating Volume Jobs so that Max Volume Jobs = 1 will work correctly for multiple simultaneous jobs. - Correct code so that FileSet MD5 is calculated for < and | filename generation. -- Mark Volume in error on error from WEOF. - Implement the Media record flag that indicates that the Volume does disk addressing. - Implement VolAddr, which is used when Volume is addressed like a disk, @@ -327,8 +290,6 @@ Wish list: - Fix fast block rejection (stored/read_record.c:118). It passes a null pointer (rec) to try_repositioning(). - Look at extracting Win data from BackupRead. -- Having dashes in filenames apparently creates problems for restore - by filename??? hard to believe. - Implement RestoreJobRetention? Maybe better "JobRetention" in a Job, which would take precidence over the Catalog "JobRetention". - Implement Label Format in Add and Label console commands. @@ -340,7 +301,6 @@ Wish list: resources, like Level? If so, I think I'd make it an optional directive in Job, Client, and Pool, with precedence such that Job overrides Client which in turn overrides Pool. -- Print a message when a job starts if the conf file is not current. - Spooling ideas taken from Volker Sauer's and other's emails: > IMHO job spooling should be turned on @@ -439,20 +399,10 @@ Ideas from Jerry Scharf: even more important, it's not flaky it has an open access catalog, opening many possibilities it's pushing toward heterogeneous systems capability - simple things: - I don't remember an include file directive for config files - (not filesets, actual config directives) - can you check the configs without starting the daemon? - some warnings about possible common mistakes big things: - doing the testing and blessing of concurrent backup writes - this is absolutely necessary in the enterprise - easy user recovery GUI with full access checking Macintosh file client macs are an interesting niche, but I fear a server is a rathole working bare iron recovery for windows - much better handling on running config changes - thinking through the logic of what happens to jobs in progress the option for inc/diff backups not reset on fileset revision a) use both change and inode update time against base time b) do the full catalog check (expensive but accurate) @@ -505,9 +455,7 @@ Ideas from Jerry Scharf: to the user, who would then use "mount" as described above once he had actually inserted the disk. - Implement dump/print label to UA -- Implement disk spooling. Two parts: 1. Spool to disk then - immediately to tape to speed up tape operations. 2. Spool to - disk only when the tape is full, then when a tape is hung move +- Spool to disk only when the tape is full, then when a tape is hung move it to tape. - Scratch Pool where the volumes can be re-assigned to any Pool. - bextract is sending everything to the log file ****FIXME**** @@ -824,12 +772,8 @@ Ideas from Jerry Scharf: if full status requested or if some level of debug on. - Make database type selectable by .conf files i.e. at runtime - Set flag for uname -a. Add to Volume label. -- Implement throttled work queue. - Restore files modified after date - SET LD_RUN_PATH=$HOME/mysql/lib/mysql -- Implement Restore FileSet= -- Create a protocol.h and protocol.c where all protocol messages - are concentrated. - Remove duplicate fields from jcr (e.g. jcr.level and jcr.jr.Level, ...). - Timout a job or terminate if link goes down, or reopen link and query. - Concept of precious tapes (cannot be reused). diff --git a/bacula/src/console/conio.c b/bacula/src/console/conio.c index 372310b692..9b866c317a 100755 --- a/bacula/src/console/conio.c +++ b/bacula/src/console/conio.c @@ -29,6 +29,15 @@ */ +/* + * UTF-8 + * If the top bit of a UTF-8 string is 0 (8 bits), then it + * is a normal ASCII character. + * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then + * it is the start of a series of chars (up to 5) + * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80) + */ + #ifdef TEST_PROGRAM #include @@ -192,11 +201,12 @@ static short char_map[600]= { /* Function Prototypes */ -static int input_char(void); -static int t_gnc(void); +static unsigned int input_char(void); +static unsigned int t_gnc(void); static void insert_space(char *curline, int line_len); -static void forward(int i, char *str, int str_len); -static void backup(int i); +static void insert_hole(char *curline, int line_len); +static void forward(char *str, int str_len); +static void backup(char *curline); static void delchr(int cnt, char *curline, int line_len); static int iswordc(char c); static int next_word(char *ldb_buf); @@ -210,7 +220,7 @@ static void t_honk_horn(void); static void t_insert_line(void); static void t_delete_line(void); static void t_clrline(int pos, int width); -void t_sendl(char *msg, int len); +void t_sendl(const char *msg, int len); void t_send(char *msg); void t_char(char c); static void asclrs(); @@ -218,7 +228,7 @@ static void ascurs(int y, int x); static void rawmode(FILE *input); static void normode(void); -static int t_getch(); +static unsigned t_getch(); static void asclrl(int pos, int width); static void asinsl(); static void asdell(); @@ -295,22 +305,23 @@ char *bstrncpy(char *dest, const char *src, int maxlen) /* * New style string mapping to function code */ -static int do_smap(int c) +static unsigned do_smap(unsigned c) { char str[MAX_STAB]; int len = 0; stab_t *tstab; int i, found; + unsigned cm; len = 1; str[0] = c; str[1] = 0; - if (c != 27) { - c = char_map[c]; - } - if (c <= 0) { + cm = char_map[c]; + if (cm == 0) { return c; + } else { + c = cm; } for ( ;; ) { found = 0; @@ -397,10 +408,10 @@ static void add_smap(char *str, int func) /* Get the next character from the terminal - performs table lookup on the character to do the desired translation */ -static int +static unsigned int input_char() { - int c; + unsigned c; if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */ c = do_smap(c); @@ -428,7 +439,9 @@ input_line(char *string, int length) { char curline[2000]; /* edit buffer */ int noline; - int c; + unsigned c; + int more; + int i; if (first) { poolinit(); /* build line pool */ @@ -440,7 +453,7 @@ input_line(char *string, int length) clrbrk(); break; } - switch (c=(int)input_char()) { + switch (c=input_char()) { case F_RETURN: /* CR */ t_sendl("\r\n", 2); /* yes, print it and */ goto done; /* get out */ @@ -469,13 +482,13 @@ input_line(char *string, int length) delchr(1, curline, sizeof(curline)); /* delete one character */ break; case F_CSRLFT: /* Backspace */ - backup(1); + backup(curline); break; case F_CSRRGT: - forward(1,curline, sizeof(curline)); + forward(curline, sizeof(curline)); break; case F_ERSCHR: /* Rubout */ - backup(1); + backup(curline); delchr(1, curline, sizeof(curline)); break; case F_DELEOL: @@ -484,10 +497,16 @@ input_line(char *string, int length) cl = cp; break; case F_NXTWRD: - forward(next_word(curline),curline, sizeof(curline)); + i = next_word(curline); + while (i--) { + forward(curline, sizeof(curline)); + } break; case F_PRVWRD: - backup(prev_word(curline)); + i = prev_word(curline); + while (i--) { + backup(curline); + } break; case F_DELWRD: delchr(next_word(curline), curline, sizeof(curline)); /* delete word */ @@ -500,20 +519,24 @@ input_line(char *string, int length) /* Note fall through */ case F_DELLIN: case F_ERSLIN: - backup(cp); /* backup to beginning of line */ + while (cp > 0) { + backup(curline); /* backup to beginning of line */ + } t_clrline(0,t_width); /* erase line */ cp = 0; cl = 0; /* reset cursor counter */ break; case F_SOL: - backup(cp); + while (cp > 0) { + backup(curline); + } break; case F_EOL: while (cp < cl) { - forward(1,curline, sizeof(curline)); + forward(curline, sizeof(curline)); } while (cp > cl) { - backup(1); + backup(curline); } break; case F_TINS: /* toggle insert mode */ @@ -527,13 +550,35 @@ input_line(char *string, int length) } t_honk_horn(); /* complain */ } else { + if ((c & 0xC0) == 0xC0) { + if ((c & 0xFC) == 0xFC) { + more = 5; + } else if ((c & 0xF8) == 0xF8) { + more = 4; + } else if ((c & 0xF0) == 0xF0) { + more = 3; + } else if ((c & 0xE0) == 0xE0) { + more = 2; + } else { + more = 1; + } + } else { + more = 0; + } if (mode_insert) { insert_space(curline, sizeof(curline)); } curline[cp++] = c; /* store character in line being built */ - t_char((char)c); /* echo character to terminal */ + t_char(c); /* echo character to terminal */ + while (more--) { + c= input_char(); + insert_hole(curline, sizeof(curline)); + curline[cp++] = c; /* store character in line being built */ + t_char(c); /* echo character to terminal */ + } if (cp > cl) { cl = cp; /* keep current length */ + curline[cp] = 0; } } break; @@ -555,60 +600,121 @@ insert_space(char *curline, int curline_len) { int i; - if (cp > cl || cl+1 > curline_len) return; + if (cp > cl || cl+1 > curline_len) { + return; + } /* Note! source and destination overlap */ memmove(&curline[cp+1],&curline[cp],i=cl-cp); cl++; - i++; curline[cp] = ' '; - forward(i,curline, curline_len); - backup(i); + i = 0; + while (cl > cp) { + forward(curline, curline_len); + i++; + } + while (i--) { + backup(curline); + } +} + + +static void +insert_hole(char *curline, int curline_len) +{ + int i; + + if (cp > cl || cl+1 > curline_len) { + return; + } + /* Note! source and destination overlap */ + memmove(&curline[cp+1], &curline[cp], i=cl-cp); + cl++; + curline[cl] = 0; } /* Move cursor forward keeping characters under it */ static void -forward(int i, char *str, int str_len) +forward(char *str, int str_len) { - while (i--) { - if (cp > str_len) { - return; - } - if (cp>=cl) { - t_char(' '); - str[cp+1] = ' '; - } else { - t_char(str[cp]); + if (cp > str_len) { + return; + } + if (cp >= cl) { + t_char(' '); + str[cp+1] = ' '; + str[cp+2] = 0; + } else { + t_char(str[cp]); + if ((str[cp] & 0xC0) == 0xC0) { + cp++; + while ((str[cp] & 0xC0) == 0x80) { + t_char(str[cp]); + cp++; + } + cp--; + } + } + cp++; +} + +/* How many characters under the cursor */ +static int +char_count(int cptr, char *str) +{ + int cnt = 1; + if (cptr > cl) { + return 0; + } + if ((str[cptr] & 0xC0) == 0xC0) { + cptr++; + while ((str[cptr] & 0xC0) == 0x80) { + cnt++; + cptr++; } - cp++; } + return cnt; } /* Backup cursor keeping characters under it */ static void -backup(int i) +backup(char *str) { - for ( ; i && cp; i--,cp--) { - t_char('\010'); + if (cp == 0) { + return; + } + while ((str[cp] & 0xC0) == 0x80) { + cp--; } + t_char('\010'); + cp--; } /* Delete the character under the cursor */ static void -delchr(int cnt, char *curline, int line_len) +delchr(int del, char *curline, int line_len) { - register int i; + int i, cnt; - if (cp > cl) + if (cp > cl || del == 0) { return; - if ((i=cl-cp-cnt+1) > 0) { - memcpy(&curline[cp], &curline[cp+cnt],i); } - curline[cl -= cnt] = EOS; - t_clrline(0,t_width); - if (cl > cp) { - forward(i=cl-cp,curline, line_len); - backup(i); + while (del-- && cp > 0) { + cnt = char_count(cp, curline); + if ((i=cl-cp-cnt) > 0) { + memcpy(&curline[cp], &curline[cp+cnt], i); + } + cl -= cnt; + curline[cl] = EOS; + t_clrline(0, t_width); + i = 0; + while (cl > cp) { + forward(curline, line_len); + i++; + } + while (i--) { + backup(curline); + } } } @@ -619,9 +725,9 @@ iswordc(char c) if (mode_wspace) return !isspace(c); if (c >= '0' && c <= '9') - return TRUE; + return true; if (c == '$' || c == '%') - return TRUE; + return true; return isalpha(c); } @@ -668,10 +774,12 @@ prev_word(char *ldb_buf) static void prtcur(char *str) { - backup(cp); + while (cp > 0) { + backup(str); + } t_clrline(0,t_width); cp = cl = strlen(str); - t_sendl(str,cl); + t_sendl(str, cl); } @@ -920,7 +1028,7 @@ static void normode() } /* Get next character from terminal/script file/unget buffer */ -static int +static unsigned t_gnc() { return t_getch(); @@ -928,19 +1036,19 @@ t_gnc() /* Get next character from OS */ -static int t_getch(void) +static unsigned t_getch(void) { - char c; + unsigned char c; if (read(0, &c, 1) != 1) { c = 0; } - return (int)c; + return (unsigned)c; } /* Send message to terminal - primitive routine */ void -t_sendl(char *msg, int len) +t_sendl(const char *msg, int len) { write(1, msg, len); } -- 2.39.5