source: util.c @ dab82f29

owl
Last change on this file since dab82f29 was dab82f29, checked in by James M. Kretchmar <kretch@mit.edu>, 15 years ago
Don't crash on mobile device AIM messages [BZ 20] Don't crash when sending to someone not on AIM buddy list [BZ 94] Fix overflow vulerability in zwrite.c and zcrypt.c Add stack protector and -D_FORTIFY_SOURCE=2 where possible Fix hang [barnowl 4c46dfdebc294ca24fef59924f01688b8ee07dee] Fix segfault on missing subs [barnowl 99dabeed7de6d19acb50f1e73aa0bfe5f9469c02] Fix zcrypt bufffer size bug [barnowl 559076cd86edc3a8317819814dd5877b8bc7c3cb] Fix double free [barnowl e97c4a306ae2c9d2147d83da29fee59918198e70] Memory leak fix [barnowl c0a90c2c7ab97b9465c9873757faf312faa0021e] Memory leak fix [barnowl 95caa16b2e9ba10770d87d0955198c14c2d0e16a] Memory leak fix [barnowl 1716fed8c2650e46892cf6571555eac937266c6e] Add getstyle command [barnowl 216c73421653e3ef0e957aa9a9804e208a77c80e] Binary search for msgid [barnowl 0c8ab5eadbb6ecc97a120c91b9a824b33538c764] File-handle leak [barnowl e78397d6ac5da0de31a4e269c0ba7f3d691857a3] Fix delay in jump from top to bottom [barnowl 801b7ac63b962640debbcfd422cb9a60da5fea31] Load subs in chunks [barnowl 93e883d60051b80bf6d35391f9d76fd7dfd198e3] Load subs in chunks [barnowl f6050ee9b0a171a5031f84409eb181062afacd18] Better zsig logging [barnowl d857b667a5a9b108b1a2a26b4a5513bef2b53f80] free() -> owlfree() [barnowl d524c838ac7c115628424b8ac171c3489622ea3a] Escape AIM users in smartfilters [barnowl af9b92e3e7ccb7de276a94b5c7e5861b24e71eff] Better regex escape chars [barnowl 80e54a7631f091be8c9762adb9746bad38104738] Deal with quotes in smart filters [barnowl 4099cf83702763fa8d1efc4f1582a605431bdb77] Deal with 0 length zephyr fields [barnowl 128171aaf7cefa91a4bb1eada93a19d8fd0c355c] Deal with 0 length zephyr fields [barnowl 50e29e35c64d64e223d378d350a7bc4f038d78f5] Deal with 0 length zephyr fields [barnowl 804ab8af8b6d00bcd7e2402df892db8fbd61a3ec] Leave curmsg on screen after resize [barnowl c0f9e3009bc03e80a44de64cd5f2b4033290236e] Rip out brower stuff [barnowl 8e5935d11c699a7ce5a3e6e9a47799564c696d6a] Rip out browser stuff [barnowl 4f15e8e9ceada0d4b2cc969ebf43b0a1fb3709ea] No passwords in command history [barnowl 6e400cc71aa59e041dce677aadf50dc1f25228e2] Format NOC mssages [barnowl a1bb1980e4bca23b8329cc0e7c0bd5027055ea0a] Expand ~ in loadsubs [barnowl 27d8d835dc6d58c08fae10e75aae306c49215143] Expand ~ in source [barnowl 10d67d57cb29221f63a43a30643c697fc7b38911] Only use resizeterm() if it's available Debian backports Change license to GPLv3
  • Property mode set to 100644
File size: 19.2 KB
Line 
1/* Copyright (c) 2002,2003,2004,2009 James M. Kretchmar
2 *
3 * This file is part of Owl.
4 *
5 * Owl is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Owl is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Owl.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 * ---------------------------------------------------------------
19 *
20 * As of Owl version 2.1.12 there are patches contributed by
21 * developers of the the branched BarnOwl project, Copyright (c)
22 * 2006-2008 The BarnOwl Developers. All rights reserved.
23 */
24
25#include "owl.h"
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include <ctype.h>
30#include <pwd.h>
31
32static const char fileIdent[] = "$Id$";
33
34void sepbar(char *in)
35{
36  char buff[1024];
37  WINDOW *sepwin;
38  owl_messagelist *ml;
39  owl_view *v;
40  int x, y, i;
41  char *foo, *appendtosepbar;
42
43  sepwin=owl_global_get_curs_sepwin(&g);
44  ml=owl_global_get_msglist(&g);
45  v=owl_global_get_current_view(&g);
46
47  werase(sepwin);
48  wattron(sepwin, A_REVERSE);
49  if (owl_global_is_fancylines(&g)) {
50    whline(sepwin, ACS_HLINE, owl_global_get_cols(&g));
51  } else {
52    whline(sepwin, '-', owl_global_get_cols(&g));
53  }
54
55  if (owl_global_is_sepbar_disable(&g)) {
56    getyx(sepwin, y, x);
57    wmove(sepwin, y, owl_global_get_cols(&g)-1);
58    return;
59  }
60
61  wmove(sepwin, 0, 2); 
62
63  if (owl_messagelist_get_size(ml)==0) {
64    strcpy(buff, " (-/-) ");
65  } else {
66    snprintf(buff, 1024, " (%i/%i/%i) ", owl_global_get_curmsg(&g)+1,
67            owl_view_get_size(v),
68            owl_messagelist_get_size(ml));
69  }
70  waddstr(sepwin, buff);
71
72  foo=owl_view_get_filtname(v);
73  if (strcmp(foo, owl_global_get_view_home(&g))) wattroff(sepwin, A_REVERSE);
74  waddstr(sepwin, " ");
75  waddstr(sepwin, owl_view_get_filtname(v));
76  waddstr(sepwin, " ");
77  if (strcmp(foo, owl_global_get_view_home(&g))) wattron(sepwin, A_REVERSE);
78
79  if (owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
80    getyx(sepwin, y, x);
81    wmove(sepwin, y, x+2);
82    wattron(sepwin, A_BOLD);
83    waddstr(sepwin, " <truncated> ");
84    wattroff(sepwin, A_BOLD);
85  }
86
87  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
88  if ((i != -1) &&
89      (i < owl_view_get_size(v)-1)) {
90    getyx(sepwin, y, x);
91    wmove(sepwin, y, x+2);
92    wattron(sepwin, A_BOLD);
93    waddstr(sepwin, " <more> ");
94    wattroff(sepwin, A_BOLD);
95  }
96
97  if (owl_global_get_rightshift(&g)>0) {
98    getyx(sepwin, y, x);
99    wmove(sepwin, y, x+2);
100    snprintf(buff, 1024, " right: %i ", owl_global_get_rightshift(&g));
101    waddstr(sepwin, buff);
102  }
103
104  if (owl_global_is_zaway(&g) || owl_global_is_aaway(&g)) {
105    getyx(sepwin, y, x);
106    wmove(sepwin, y, x+2);
107    wattron(sepwin, A_BOLD);
108    wattroff(sepwin, A_REVERSE);
109    if (owl_global_is_zaway(&g) && owl_global_is_aaway(&g)) {
110      waddstr(sepwin, " AWAY ");
111    } else if (owl_global_is_zaway(&g)) {
112      waddstr(sepwin, " Z-AWAY ");
113    } else if (owl_global_is_aaway(&g)) {
114      waddstr(sepwin, " A-AWAY ");
115    }
116    wattron(sepwin, A_REVERSE);
117    wattroff(sepwin, A_BOLD);
118  }
119
120  if (owl_global_get_curmsg_vert_offset(&g)) {
121    getyx(sepwin, y, x);
122    wmove(sepwin, y, x+2);
123    wattron(sepwin, A_BOLD);
124    wattroff(sepwin, A_REVERSE);
125    waddstr(sepwin, " SCROLL ");
126    wattron(sepwin, A_REVERSE);
127    wattroff(sepwin, A_BOLD);
128  }
129 
130  if (in) {
131    getyx(sepwin, y, x);
132    wmove(sepwin, y, x+2);
133    waddstr(sepwin, in);
134  }
135
136  appendtosepbar = owl_global_get_appendtosepbar(&g);
137  if (appendtosepbar && *appendtosepbar) {
138    getyx(sepwin, y, x);
139    wmove(sepwin, y, x+2);
140    waddstr(sepwin, " ");
141    waddstr(sepwin, owl_global_get_appendtosepbar(&g));
142    waddstr(sepwin, " ");
143  }
144
145  getyx(sepwin, y, x);
146  wmove(sepwin, y, owl_global_get_cols(&g)-1);
147   
148  wattroff(sepwin, A_BOLD);
149  wattroff(sepwin, A_REVERSE);
150  wnoutrefresh(sepwin);
151}
152
153
154void pophandler_quit(int ch)
155{
156  if (ch=='q') {
157    owl_popwin_close(owl_global_get_popwin(&g));
158  }
159}
160
161char **atokenize(char *buffer, char *sep, int *i)
162{
163  /* each element of return must be freed by user */
164  char **args;
165  char *workbuff, *foo;
166  int done=0, first=1, count=0;
167
168  workbuff=owl_malloc(strlen(buffer)+1);
169  memcpy(workbuff, buffer, strlen(buffer)+1);
170
171  args=NULL;
172  while (!done) {
173    if (first) {
174      first=0;
175      foo=(char *)strtok(workbuff, sep);
176    } else {
177      foo=(char *)strtok(NULL, sep);
178    }
179    if (foo==NULL) {
180      done=1;
181    } else {
182      args=(char **)owl_realloc(args, sizeof(char *) * (count+1));
183      args[count]=owl_malloc(strlen(foo)+1);
184      strcpy(args[count], foo);
185      count++;
186    }
187  }
188  *i=count;
189  owl_free(workbuff);
190  return(args);
191}
192
193char *skiptokens(char *buff, int n) {
194  /* skips n tokens and returns where that would be.
195   * TODO: handle quotes more sanely. */
196 
197  int inquotes=0;
198  while (*buff && n>0) {
199      while (*buff == ' ') buff++;
200      while (*buff && (inquotes || *buff != ' ')) { 
201        if (*buff == '"' || *buff == '\'') inquotes=!inquotes;
202        buff++;
203      }
204      while (*buff == ' ') buff++;
205      n--;
206  }
207  return buff;
208}
209
210/* Return a "nice" version of the path.  Tilde expansion is done, and
211 * duplicate slashes are removed.  Caller must free the return.
212 */
213char *owl_util_makepath(char *in)
214{
215  int i, j, x;
216  char *out, user[MAXPATHLEN];
217  struct passwd *pw;
218
219  out=owl_malloc(MAXPATHLEN+1);
220  out[0]='\0';
221  j=strlen(in);
222  x=0;
223  for (i=0; i<j; i++) {
224    if (in[i]=='~') {
225      if ( (i==(j-1)) ||          /* last character */
226           (in[i+1]=='/') ) {     /* ~/ */
227        /* use my homedir */
228        pw=getpwuid(getuid());
229        if (!pw) {
230          out[x]=in[i];
231        } else {
232          out[x]='\0';
233          strcat(out, pw->pw_dir);
234          x+=strlen(pw->pw_dir);
235        }
236      } else {
237        /* another user homedir */
238        int a, b;
239        b=0;
240        for (a=i+1; i<j; a++) {
241          if (in[a]==' ' || in[a]=='/') {
242            break;
243          } else {
244            user[b]=in[a];
245            i++;
246            b++;
247          }
248        }
249        user[b]='\0';
250        pw=getpwnam(user);
251        if (!pw) {
252          out[x]=in[i];
253        } else {
254          out[x]='\0';
255          strcat(out, pw->pw_dir);
256          x+=strlen(pw->pw_dir);
257        }
258      }
259    } else if (in[i]=='/') {
260      /* check for a double / */
261      if (i<(j-1) && (in[i+1]=='/')) {
262        /* do nothing */
263      } else {
264        out[x]=in[i];
265        x++;
266      }
267    } else {
268      out[x]=in[i];
269      x++;
270    }
271  }
272  out[x]='\0';
273  return(out);
274}
275
276void atokenize_free(char **tok, int nels)
277{
278  int i;
279  for (i=0; i<nels; i++) {
280    owl_free(tok[i]);
281  }
282  owl_free(tok);
283}
284
285
286void owl_parsefree(char **argv, int argc)
287{
288  int i;
289
290  if (!argv) return;
291 
292  for (i=0; i<argc; i++) {
293    if (argv[i]) owl_free(argv[i]);
294  }
295  owl_free(argv);
296}
297
298char **owl_parseline(char *line, int *argc)
299{
300  /* break a command line up into argv, argc.  The caller must free
301     the returned values.  If there is an error argc will be set to
302     -1, argv will be NULL and the caller does not need to free
303     anything */
304
305  char **argv;
306  int i, len, between=1;
307  char *curarg;
308  char quote;
309
310  argv=owl_malloc(sizeof(char *));
311  len=strlen(line);
312  curarg=owl_malloc(len+10);
313  strcpy(curarg, "");
314  quote='\0';
315  *argc=0;
316  for (i=0; i<len+1; i++) {
317    /* find the first real character */
318    if (between) {
319      if (line[i]==' ' || line[i]=='\t' || line[i]=='\0') {
320        continue;
321      } else {
322        between=0;
323        i--;
324        continue;
325      }
326    }
327
328    /* deal with a quote character */
329    if (line[i]=='"' || line[i]=="'"[0]) {
330      /* if this type of quote is open, close it */
331      if (quote==line[i]) {
332        quote='\0';
333        continue;
334      }
335
336      /* if no quoting is open then open with this */
337      if (quote=='\0') {
338        quote=line[i];
339        continue;
340      }
341
342      /* if another type of quote is open then treat this as a literal */
343      curarg[strlen(curarg)+1]='\0';
344      curarg[strlen(curarg)]=line[i];
345      continue;
346    }
347
348    /* if it's not a space or end of command, then use it */
349    if (line[i]!=' ' && line[i]!='\t' && line[i]!='\n' && line[i]!='\0') {
350      curarg[strlen(curarg)+1]='\0';
351      curarg[strlen(curarg)]=line[i];
352      continue;
353    }
354
355    /* otherwise, if we're not in quotes, add the whole argument */
356    if (quote=='\0') {
357      /* add the argument */
358      argv=owl_realloc(argv, sizeof(char *)*((*argc)+1));
359      argv[*argc]=owl_malloc(strlen(curarg)+2);
360      strcpy(argv[*argc], curarg);
361      *argc=*argc+1;
362      strcpy(curarg, "");
363      between=1;
364      continue;
365    }
366
367    /* if it is a space and we're in quotes, then use it */
368    curarg[strlen(curarg)+1]='\0';
369    curarg[strlen(curarg)]=line[i];
370  }
371
372  owl_free(curarg);
373
374  /* check for unbalanced quotes */
375  if (quote!='\0') {
376    owl_parsefree(argv, *argc);
377    *argc=-1;
378    return(NULL);
379  }
380
381  return(argv);
382}
383
384/* caller must free the return */
385char *owl_util_minutes_to_timestr(int in)
386{
387  int days, hours;
388  long run;
389  char *out;
390
391  run=in;
392
393  days=run/1440;
394  run-=days*1440;
395  hours=run/60;
396  run-=hours*60;
397
398  if (days>0) {
399    out=owl_sprintf("%i d %2.2i:%2.2i", days, hours, run);
400  } else {
401    out=owl_sprintf("    %2.2i:%2.2i", hours, run);
402  }
403  return(out);
404}
405
406/* return the index of the last char before a change from the first one */
407int owl_util_find_trans(char *in, int len)
408{
409  int i;
410  for (i=1; i<len; i++) {
411    if (in[i] != in[0]) return(i-1);
412  }
413  return(i);
414}
415
416/* downcase the string 'foo' */
417void downstr(char *foo)
418{
419  int i;
420  for (i=0; foo[i]!='\0'; i++) {
421    foo[i]=tolower(foo[i]);
422  }
423}
424
425/* Caller must free response.
426 * Takes in strings which are space-separated lists of tokens
427 * and returns a single string containing no token more than once.
428 * If prohibit is non-null, no token may start with a character
429 * in prohibit.
430 */
431char *owl_util_uniq(char *A, char *B, char *prohibit)
432{
433 
434  char *cat, **tok;
435  int toklen, i, j, first=1;
436  cat = owl_malloc(strlen(A)+strlen(B)+3);
437  strcpy(cat, A);
438  strcat(cat, " ");
439  strcat(cat, B);
440  tok = atokenize(cat, " ", &toklen);
441  strcpy(cat, "");
442  for (i=0; i<toklen; i++) {
443    int dup=0;
444    for (j=0; j<i; j++) {
445      if (!strcmp(tok[i], tok[j])) dup=1;
446    }
447    if (!dup && (!prohibit || !strchr(prohibit, tok[i][0]))) {
448      if (!first) {
449        strcat(cat, " ");
450      }
451      first=0;
452      strcat(cat, tok[i]);
453    }
454  }
455  atokenize_free(tok, toklen);
456  return(cat);
457}
458
459/* hooks for doing memory allocation et. al. in owl */
460
461void *owl_malloc(size_t size)
462{
463  return(malloc(size));
464}
465
466void owl_free(void *ptr)
467{
468  free(ptr);
469}
470
471char *owl_strdup(const char *s1)
472{
473  return(strdup(s1));
474}
475
476void *owl_realloc(void *ptr, size_t size)
477{
478  return(realloc(ptr, size));
479}
480
481/* allocates memory and returns the string or null.
482 * caller must free the string.
483 * from Linux sprintf man page.
484 */
485char *owl_sprintf(const char *fmt, ...)
486{
487  int n, size = 100;
488  char *p;
489  va_list ap;
490  if ((p = owl_malloc (size)) == NULL) return (NULL);
491  while (1) {
492    /* Try to print in the allocated space. */
493    va_start(ap, fmt);
494    n = vsnprintf (p, size, fmt, ap);
495    va_end(ap);
496    /* If that worked, return the string. */
497    if (n > -1 && n < size)
498      return p;
499    /* Else try again with more space. */
500    if (n > -1)    /* glibc 2.1 */
501      size = n+1; /* precisely what is needed */
502    else           /* glibc 2.0 */
503      size *= 2;  /* twice the old size */
504    if ((p = owl_realloc (p, size)) == NULL)
505      return NULL;
506  }
507}
508
509/* Return the owl color associated with the named color.  Return -1
510 * if the named color is not available
511 */
512int owl_util_string_to_color(char *color)
513{
514  if (!strcasecmp(color, "black")) {
515    return(OWL_COLOR_BLACK);
516  } else if (!strcasecmp(color, "red")) {
517    return(OWL_COLOR_RED);
518  } else if (!strcasecmp(color, "green")) {
519    return(OWL_COLOR_GREEN);
520  } else if (!strcasecmp(color, "yellow")) {
521    return(OWL_COLOR_YELLOW);
522  } else if (!strcasecmp(color, "blue")) {
523    return(OWL_COLOR_BLUE);
524  } else if (!strcasecmp(color, "magenta")) {
525    return(OWL_COLOR_MAGENTA);
526  } else if (!strcasecmp(color, "cyan")) {
527    return(OWL_COLOR_CYAN);
528  } else if (!strcasecmp(color, "white")) {
529    return(OWL_COLOR_WHITE);
530  } else if (!strcasecmp(color, "default")) {
531    return(OWL_COLOR_DEFAULT);
532  }
533  return(-1);
534}
535
536/* Return a string name of the given owl color */
537char *owl_util_color_to_string(int color)
538{
539  if (color==OWL_COLOR_BLACK)   return("black");
540  if (color==OWL_COLOR_RED)     return("red");
541  if (color==OWL_COLOR_GREEN)   return("green");
542  if (color==OWL_COLOR_YELLOW)  return("yellow");
543  if (color==OWL_COLOR_BLUE)    return("blue");
544  if (color==OWL_COLOR_MAGENTA) return("magenta");
545  if (color==OWL_COLOR_CYAN)    return("cyan");
546  if (color==OWL_COLOR_WHITE)   return("white");
547  if (color==OWL_COLOR_DEFAULT) return("default");
548  return("Unknown color");
549}
550
551/* Get the default tty name.  Caller must free the return */
552char *owl_util_get_default_tty()
553{
554  char *out, *tmp;
555
556  if (getenv("DISPLAY")) {
557    out=owl_strdup(getenv("DISPLAY"));
558  } else if ((tmp=ttyname(fileno(stdout)))!=NULL) {
559    out=owl_strdup(tmp);
560    if (!strncmp(out, "/dev/", 5)) {
561      owl_free(out);
562      out=owl_strdup(tmp+5);
563    }
564  } else {
565    out=owl_strdup("unknown");
566  }
567  return(out);
568}
569
570
571/* Animation hack */
572void owl_hack_animate()
573{
574  owl_messagelist *ml;
575  owl_message *m;
576  owl_fmtext *fm;
577  char *text, *ptr;
578  int place;
579
580  /* grab the first message and make sure its id is 0 */
581  ml=owl_global_get_msglist(&g);
582  m=owl_messagelist_get_element(ml, 0);
583  if (!m) return;
584  if (owl_message_get_id(m)!=0) return;
585
586  fm=owl_message_get_fmtext(m);
587  text=owl_fmtext_get_text(fm);
588
589  ptr=strstr(text, "OvO");
590  if (ptr) {
591    place=ptr-text;
592    owl_fmtext_set_char(fm, place, '-');
593    owl_fmtext_set_char(fm, place+2, '-');
594
595    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
596    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
597      owl_popwin_refresh(owl_global_get_popwin(&g));
598      /* TODO: this is a broken kludge */
599      if (owl_global_get_viewwin(&g)) {
600        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
601      }
602    }
603    owl_global_set_needrefresh(&g);
604    return;
605  }
606
607  ptr=strstr(text, "-v-");
608  if (ptr) {
609    place=ptr-text;
610    owl_fmtext_set_char(fm, place, 'O');
611    owl_fmtext_set_char(fm, place+2, 'O');
612
613    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
614    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
615      owl_popwin_refresh(owl_global_get_popwin(&g));
616      /* TODO: this is a broken kludge */
617      if (owl_global_get_viewwin(&g)) {
618        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
619      }
620    }
621    owl_global_set_needrefresh(&g);
622    return;
623  }
624}
625
626/* strip leading and trailing new lines.  Caller must free the
627 * return.
628 */
629char *owl_util_stripnewlines(char *in)
630{
631 
632  char  *tmp, *ptr1, *ptr2, *out;
633
634  ptr1=tmp=owl_strdup(in);
635  while (ptr1[0]=='\n') {
636    ptr1++;
637  }
638  ptr2=ptr1+strlen(ptr1)-1;
639  while (ptr2>ptr1 && ptr2[0]=='\n') {
640    ptr2[0]='\0';
641    ptr2--;
642  }
643
644  out=owl_strdup(ptr1);
645  owl_free(tmp);
646  return(out);
647}
648
649/* Delete the line matching "line" from the named file.  If no such
650 * line is found the file is left intact.  If backup==1 then create a
651 * backupfile containing the original contents.  This is an
652 * inefficient impelementation which reads the entire file into
653 * memory.
654 */
655void owl_util_file_deleteline(char *filename, char *line, int backup)
656{
657  char buff[LINE], *text;
658  char *backupfilename="";
659  FILE *file, *backupfile=NULL;
660  int size, newline;
661
662  /* open the file for reading */
663  file=fopen(filename, "r");
664  if (!file) {
665    owl_function_error("Error opening file %s", filename);
666    return;
667  }
668
669  /* open the backup file for writing */
670  if (backup) {
671    backupfilename=owl_sprintf("%s.backup", filename);
672    backupfile=fopen(backupfilename, "w");
673    if (!backupfile) {
674      owl_function_error("Error opening file %s for writing", backupfilename);
675      owl_free(backupfilename);
676      fclose(file);
677      return;
678    }
679  }
680
681  /* we'll read the entire file into memory, minus the line we don't want and
682   * and at the same time create the backup file if necessary
683   */
684  text=owl_malloc(LINE);
685  strcpy(text, "");
686  size=LINE;
687  while (fgets(buff, LINE, file)!=NULL) {
688    /* strip the newline */
689    newline=0;
690    if (buff[strlen(buff)-1]=='\n') {
691      buff[strlen(buff)-1]='\0';
692      newline=1;
693    }
694   
695    /* if we don't match the line, add to saved text in memory */
696    if (strcasecmp(buff, line)) {
697      size+=LINE;
698      text=owl_realloc(text, size);
699      strcat(text, buff);
700      if (newline) strcat(text, "\n");
701    }
702
703    /* write to backupfile if necessary */
704    if (backup) {
705      fputs(buff, backupfile);
706      if (newline) fputs("\n", backupfile);
707    }
708  }
709  if (backup) fclose(backupfile);
710  fclose(file);
711
712  /* now rewrite the original file from memory */
713  file=fopen(filename, "w");
714  if (!file) {
715    owl_function_error("WARNING: Error opening %s for writing.  Use %s to restore.", filename, backupfilename);
716    owl_function_beep();
717  } else {
718    fputs(text, file);
719    fclose(file);
720  }
721
722  if (backup)
723    owl_free(backupfilename);
724  owl_free(text);
725}
726
727/* add the string 'str' to the list 'list' of strings, only if it
728 * is not already present
729 */
730void owl_util_list_add_unique_string(owl_list *list, char *str)
731{
732  int i, j;
733
734  j=owl_list_get_size(list);
735  for (i=0; i<j; i++) {
736    if (!strcmp(str, owl_list_get_element(list, i))) return;
737  }
738  owl_list_append_element(list, owl_strdup(str));
739}
740
741int owl_util_common_strings_in_lists(owl_list *a, owl_list *b)
742{
743  int i, j, x, y;
744
745  j=owl_list_get_size(a);
746  for (i=0; i<j; i++) {
747    y=owl_list_get_size(b);
748    for (x=0; x<y; x++) {
749      if (!strcmp(owl_list_get_element(a, i), owl_list_get_element(b, x))) return(1);
750    }
751  }
752  return(0);
753}
754
755int owl_util_max(int a, int b)
756{
757  if (a>b) return(a);
758  return(b);
759}
760
761int owl_util_min(int a, int b)
762{
763  if (a<b) return(a);
764  return(b);
765}
766
767/**************************************************************************/
768/************************* REGRESSION TESTS *******************************/
769/**************************************************************************/
770
771#ifdef OWL_INCLUDE_REG_TESTS
772
773#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
774
775int owl_util_regtest(void)
776{
777  int numfailed=0;
778
779  printf("BEGIN testing owl_util\n");
780
781  FAIL_UNLESS("owl_util_substitute 1",
782              !strcmp("foo", owl_text_substitute("foo", "", "Y")));
783  FAIL_UNLESS("owl_text_substitute 2",
784              !strcmp("fYZYZ", owl_text_substitute("foo", "o", "YZ")));
785  FAIL_UNLESS("owl_text_substitute 3",
786              !strcmp("foo", owl_text_substitute("fYZYZ", "YZ", "o")));
787  FAIL_UNLESS("owl_text_substitute 4",
788              !strcmp("/u/foo/meep", owl_text_substitute("~/meep", "~", "/u/foo")));
789
790  FAIL_UNLESS("skiptokens 1", 
791              !strcmp("bar quux", skiptokens("foo bar quux", 1)));
792  FAIL_UNLESS("skiptokens 2", 
793              !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
794
795  FAIL_UNLESS("owl_util_uniq 1", 
796              !strcmp("foo bar x", owl_util_uniq("foo", "bar x", "-")));
797  FAIL_UNLESS("owl_util_uniq 2", 
798              !strcmp("foo bar x", owl_util_uniq("foo", "bar -y x", "-")));
799  FAIL_UNLESS("owl_util_uniq 3", 
800              !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
801
802  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
803  printf("END testing owl_util (%d failures)\n", numfailed);
804  return(numfailed);
805}
806
807#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.