source: util.c @ 49d67b1

release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 49d67b1 was 946058b, checked in by Karl Ramm <kcr@1ts.org>, 12 years ago
rewrite owl_util_file_deleteline Rewrite owl_util_file_deleteline to be more efficient, use getline, and have no fixed buffers.
  • Property mode set to 100644
File size: 19.0 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6#include <pwd.h>
7
8void sepbar(const char *in)
9{
10  char buff[1024];
11  WINDOW *sepwin;
12  const owl_messagelist *ml;
13  const owl_view *v;
14  int x, y, i;
15  const char *foo, *appendtosepbar;
16
17  sepwin=owl_global_get_curs_sepwin(&g);
18  ml=owl_global_get_msglist(&g);
19  v=owl_global_get_current_view(&g);
20
21  werase(sepwin);
22  wattron(sepwin, A_REVERSE);
23  if (owl_global_is_fancylines(&g)) {
24    whline(sepwin, ACS_HLINE, owl_global_get_cols(&g));
25  } else {
26    whline(sepwin, '-', owl_global_get_cols(&g));
27  }
28
29  if (owl_global_is_sepbar_disable(&g)) {
30    getyx(sepwin, y, x);
31    wmove(sepwin, y, owl_global_get_cols(&g)-1);
32    return;
33  }
34
35  wmove(sepwin, 0, 2); 
36
37  if (owl_messagelist_get_size(ml)==0) {
38    strcpy(buff, " (-/-) ");
39  } else {
40    snprintf(buff, 1024, " (%i/%i/%i) ", owl_global_get_curmsg(&g)+1,
41            owl_view_get_size(v),
42            owl_messagelist_get_size(ml));
43  }
44  waddstr(sepwin, buff);
45
46  foo=owl_view_get_filtname(v);
47  if (strcmp(foo, owl_global_get_view_home(&g))) wattroff(sepwin, A_REVERSE);
48  waddstr(sepwin, " ");
49  waddstr(sepwin, owl_view_get_filtname(v));
50  waddstr(sepwin, " ");
51  if (strcmp(foo, owl_global_get_view_home(&g))) wattron(sepwin, A_REVERSE);
52
53  if (owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
54    getyx(sepwin, y, x);
55    wmove(sepwin, y, x+2);
56    wattron(sepwin, A_BOLD);
57    waddstr(sepwin, " <truncated> ");
58    wattroff(sepwin, A_BOLD);
59  }
60
61  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
62  if ((i != -1) &&
63      (i < owl_view_get_size(v)-1)) {
64    getyx(sepwin, y, x);
65    wmove(sepwin, y, x+2);
66    wattron(sepwin, A_BOLD);
67    waddstr(sepwin, " <more> ");
68    wattroff(sepwin, A_BOLD);
69  }
70
71  if (owl_global_get_rightshift(&g)>0) {
72    getyx(sepwin, y, x);
73    wmove(sepwin, y, x+2);
74    snprintf(buff, 1024, " right: %i ", owl_global_get_rightshift(&g));
75    waddstr(sepwin, buff);
76  }
77
78  if (owl_global_is_zaway(&g) || owl_global_is_aaway(&g)) {
79    getyx(sepwin, y, x);
80    wmove(sepwin, y, x+2);
81    wattron(sepwin, A_BOLD);
82    wattroff(sepwin, A_REVERSE);
83    if (owl_global_is_zaway(&g) && owl_global_is_aaway(&g)) {
84      waddstr(sepwin, " AWAY ");
85    } else if (owl_global_is_zaway(&g)) {
86      waddstr(sepwin, " Z-AWAY ");
87    } else if (owl_global_is_aaway(&g)) {
88      waddstr(sepwin, " A-AWAY ");
89    }
90    wattron(sepwin, A_REVERSE);
91    wattroff(sepwin, A_BOLD);
92  }
93
94  if (owl_global_get_curmsg_vert_offset(&g)) {
95    getyx(sepwin, y, x);
96    wmove(sepwin, y, x+2);
97    wattron(sepwin, A_BOLD);
98    wattroff(sepwin, A_REVERSE);
99    waddstr(sepwin, " SCROLL ");
100    wattron(sepwin, A_REVERSE);
101    wattroff(sepwin, A_BOLD);
102  }
103 
104  if (in) {
105    getyx(sepwin, y, x);
106    wmove(sepwin, y, x+2);
107    waddstr(sepwin, in);
108  }
109
110  appendtosepbar = owl_global_get_appendtosepbar(&g);
111  if (appendtosepbar && *appendtosepbar) {
112    getyx(sepwin, y, x);
113    wmove(sepwin, y, x+2);
114    waddstr(sepwin, " ");
115    waddstr(sepwin, owl_global_get_appendtosepbar(&g));
116    waddstr(sepwin, " ");
117  }
118
119  getyx(sepwin, y, x);
120  wmove(sepwin, y, owl_global_get_cols(&g)-1);
121   
122  wattroff(sepwin, A_BOLD);
123  wattroff(sepwin, A_REVERSE);
124  wnoutrefresh(sepwin);
125}
126
127char **atokenize(const char *buffer, const char *sep, int *i)
128{
129  /* each element of return must be freed by user */
130  char **args;
131  char *workbuff, *foo;
132  int done=0, first=1, count=0;
133
134  workbuff=owl_malloc(strlen(buffer)+1);
135  memcpy(workbuff, buffer, strlen(buffer)+1);
136
137  args=NULL;
138  while (!done) {
139    if (first) {
140      first=0;
141      foo=strtok(workbuff, sep);
142    } else {
143      foo=strtok(NULL, sep);
144    }
145    if (foo==NULL) {
146      done=1;
147    } else {
148      args=owl_realloc(args, sizeof(char *) * (count+1));
149      args[count] = owl_strdup(foo);
150      count++;
151    }
152  }
153  *i=count;
154  owl_free(workbuff);
155  return(args);
156}
157
158const char *skiptokens(const char *buff, int n) {
159  /* skips n tokens and returns where that would be. */
160  char quote = 0;
161  while (*buff && n>0) {
162      while (*buff == ' ') buff++;
163      while (*buff && (quote || *buff != ' ')) {
164        if(quote) {
165          if(*buff == quote) quote = 0;
166        } else if(*buff == '"' || *buff == '\'') {
167          quote = *buff;
168        }
169        buff++;
170      }
171      while (*buff == ' ') buff++;
172      n--;
173  }
174  return buff;
175}
176
177/* Return a "nice" version of the path.  Tilde expansion is done, and
178 * duplicate slashes are removed.  Caller must free the return.
179 */
180char *owl_util_makepath(const char *in)
181{
182  int i, j, x;
183  char *out, user[MAXPATHLEN];
184  struct passwd *pw;
185
186  out=owl_malloc(MAXPATHLEN+1);
187  out[0]='\0';
188  j=strlen(in);
189  x=0;
190  for (i=0; i<j; i++) {
191    if (in[i]=='~') {
192      if ( (i==(j-1)) ||          /* last character */
193           (in[i+1]=='/') ) {     /* ~/ */
194        /* use my homedir */
195        pw=getpwuid(getuid());
196        if (!pw) {
197          out[x]=in[i];
198        } else {
199          out[x]='\0';
200          strcat(out, pw->pw_dir);
201          x+=strlen(pw->pw_dir);
202        }
203      } else {
204        /* another user homedir */
205        int a, b;
206        b=0;
207        for (a=i+1; i<j; a++) {
208          if (in[a]==' ' || in[a]=='/') {
209            break;
210          } else {
211            user[b]=in[a];
212            i++;
213            b++;
214          }
215        }
216        user[b]='\0';
217        pw=getpwnam(user);
218        if (!pw) {
219          out[x]=in[i];
220        } else {
221          out[x]='\0';
222          strcat(out, pw->pw_dir);
223          x+=strlen(pw->pw_dir);
224        }
225      }
226    } else if (in[i]=='/') {
227      /* check for a double / */
228      if (i<(j-1) && (in[i+1]=='/')) {
229        /* do nothing */
230      } else {
231        out[x]=in[i];
232        x++;
233      }
234    } else {
235      out[x]=in[i];
236      x++;
237    }
238  }
239  out[x]='\0';
240  return(out);
241}
242
243void atokenize_free(char **tok, int nels)
244{
245  int i;
246  for (i=0; i<nels; i++) {
247    owl_free(tok[i]);
248  }
249  owl_free(tok);
250}
251
252
253void owl_parsefree(char **argv, int argc)
254{
255  int i;
256
257  if (!argv) return;
258 
259  for (i=0; i<argc; i++) {
260    if (argv[i]) owl_free(argv[i]);
261  }
262  owl_free(argv);
263}
264
265char **owl_parseline(const char *line, int *argc)
266{
267  /* break a command line up into argv, argc.  The caller must free
268     the returned values.  If there is an error argc will be set to
269     -1, argv will be NULL and the caller does not need to free
270     anything */
271
272  char **argv;
273  int i, len, between=1;
274  char *curarg;
275  char quote;
276
277  argv=owl_malloc(sizeof(char *));
278  len=strlen(line);
279  curarg=owl_malloc(len+10);
280  strcpy(curarg, "");
281  quote='\0';
282  *argc=0;
283  for (i=0; i<len+1; i++) {
284    /* find the first real character */
285    if (between) {
286      if (line[i]==' ' || line[i]=='\t' || line[i]=='\0') {
287        continue;
288      } else {
289        between=0;
290        i--;
291        continue;
292      }
293    }
294
295    /* deal with a quote character */
296    if (line[i]=='"' || line[i]=="'"[0]) {
297      /* if this type of quote is open, close it */
298      if (quote==line[i]) {
299        quote='\0';
300        continue;
301      }
302
303      /* if no quoting is open then open with this */
304      if (quote=='\0') {
305        quote=line[i];
306        continue;
307      }
308
309      /* if another type of quote is open then treat this as a literal */
310      curarg[strlen(curarg)+1]='\0';
311      curarg[strlen(curarg)]=line[i];
312      continue;
313    }
314
315    /* if it's not a space or end of command, then use it */
316    if (line[i]!=' ' && line[i]!='\t' && line[i]!='\n' && line[i]!='\0') {
317      curarg[strlen(curarg)+1]='\0';
318      curarg[strlen(curarg)]=line[i];
319      continue;
320    }
321
322    /* otherwise, if we're not in quotes, add the whole argument */
323    if (quote=='\0') {
324      /* add the argument */
325      argv=owl_realloc(argv, sizeof(char *)*((*argc)+1));
326      argv[*argc] = owl_strdup(curarg);
327      *argc=*argc+1;
328      strcpy(curarg, "");
329      between=1;
330      continue;
331    }
332
333    /* if it is a space and we're in quotes, then use it */
334    curarg[strlen(curarg)+1]='\0';
335    curarg[strlen(curarg)]=line[i];
336  }
337
338  owl_free(curarg);
339
340  /* check for unbalanced quotes */
341  if (quote!='\0') {
342    owl_parsefree(argv, *argc);
343    *argc=-1;
344    return(NULL);
345  }
346
347  return(argv);
348}
349
350/* caller must free the return */
351char *owl_util_minutes_to_timestr(int in)
352{
353  int days, hours;
354  long run;
355  char *out;
356
357  run=in;
358
359  days=run/1440;
360  run-=days*1440;
361  hours=run/60;
362  run-=hours*60;
363
364  if (days>0) {
365    out=owl_sprintf("%i d %2.2i:%2.2li", days, hours, run);
366  } else {
367    out=owl_sprintf("    %2.2i:%2.2li", hours, run);
368  }
369  return(out);
370}
371
372/* hooks for doing memory allocation et. al. in owl */
373
374void *owl_malloc(size_t size)
375{
376  return(g_malloc(size));
377}
378
379void owl_free(void *ptr)
380{
381  g_free(ptr);
382}
383
384char *owl_strdup(const char *s1)
385{
386  return(g_strdup(s1));
387}
388
389void *owl_realloc(void *ptr, size_t size)
390{
391  return(g_realloc(ptr, size));
392}
393
394/* allocates memory and returns the string or null.
395 * caller must free the string.
396 */
397char *owl_sprintf(const char *fmt, ...)
398{
399  va_list ap;
400  char *ret = NULL;
401  va_start(ap, fmt);
402  ret = g_strdup_vprintf(fmt, ap);
403  va_end(ap);
404  return ret;
405}
406
407
408/* Return the owl color associated with the named color.  Return -1
409 * if the named color is not available
410 */
411int owl_util_string_to_color(const char *color)
412{
413  int c;
414  if (!strcasecmp(color, "black")) {
415    return(OWL_COLOR_BLACK);
416  } else if (!strcasecmp(color, "red")) {
417    return(OWL_COLOR_RED);
418  } else if (!strcasecmp(color, "green")) {
419    return(OWL_COLOR_GREEN);
420  } else if (!strcasecmp(color, "yellow")) {
421    return(OWL_COLOR_YELLOW);
422  } else if (!strcasecmp(color, "blue")) {
423    return(OWL_COLOR_BLUE);
424  } else if (!strcasecmp(color, "magenta")) {
425    return(OWL_COLOR_MAGENTA);
426  } else if (!strcasecmp(color, "cyan")) {
427    return(OWL_COLOR_CYAN);
428  } else if (!strcasecmp(color, "white")) {
429    return(OWL_COLOR_WHITE);
430  } else if (!strcasecmp(color, "default")) {
431    return(OWL_COLOR_DEFAULT);
432  }
433  c = atoi(color);
434  if (c >= -1 && c < COLORS) {
435    return(c);
436  }
437  return(OWL_COLOR_INVALID);
438}
439
440/* Return a string name of the given owl color */
441const char *owl_util_color_to_string(int color)
442{
443  if (color==OWL_COLOR_BLACK)   return("black");
444  if (color==OWL_COLOR_RED)     return("red");
445  if (color==OWL_COLOR_GREEN)   return("green");
446  if (color==OWL_COLOR_YELLOW)  return("yellow");
447  if (color==OWL_COLOR_BLUE)    return("blue");
448  if (color==OWL_COLOR_MAGENTA) return("magenta");
449  if (color==OWL_COLOR_CYAN)    return("cyan");
450  if (color==OWL_COLOR_WHITE)   return("white");
451  if (color==OWL_COLOR_DEFAULT) return("default");
452  return("Unknown color");
453}
454
455/* Get the default tty name.  Caller must free the return */
456char *owl_util_get_default_tty(void)
457{
458  const char *tmp;
459  char *out;
460
461  if (getenv("DISPLAY")) {
462    out=owl_strdup(getenv("DISPLAY"));
463  } else if ((tmp=ttyname(fileno(stdout)))!=NULL) {
464    out=owl_strdup(tmp);
465    if (!strncmp(out, "/dev/", 5)) {
466      owl_free(out);
467      out=owl_strdup(tmp+5);
468    }
469  } else {
470    out=owl_strdup("unknown");
471  }
472  return(out);
473}
474
475
476/* Animation hack */
477void owl_hack_animate(void)
478{
479  const owl_messagelist *ml;
480  owl_message *m;
481  owl_fmtext *fm;
482  const char *text, *ptr;
483  int place;
484
485  /* grab the first message and make sure its id is 0 */
486  ml=owl_global_get_msglist(&g);
487  m=owl_messagelist_get_element(ml, 0);
488  if (!m) return;
489  if (owl_message_get_id(m)!=0) return;
490
491  fm=owl_message_get_fmtext(m);
492  text=owl_fmtext_get_text(fm);
493
494  ptr=strstr(text, "OvO");
495  if (ptr) {
496    place=ptr-text;
497    owl_fmtext_set_char(fm, place, '-');
498    owl_fmtext_set_char(fm, place+2, '-');
499
500    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
501    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
502      owl_popwin_refresh(owl_global_get_popwin(&g));
503      /* TODO: this is a broken kludge */
504      if (owl_global_get_viewwin(&g)) {
505        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
506      }
507    }
508    owl_global_set_needrefresh(&g);
509    return;
510  }
511
512  ptr=strstr(text, "-v-");
513  if (ptr) {
514    place=ptr-text;
515    owl_fmtext_set_char(fm, place, 'O');
516    owl_fmtext_set_char(fm, place+2, 'O');
517
518    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
519    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
520      owl_popwin_refresh(owl_global_get_popwin(&g));
521      /* TODO: this is a broken kludge */
522      if (owl_global_get_viewwin(&g)) {
523        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
524      }
525    }
526    owl_global_set_needrefresh(&g);
527    return;
528  }
529}
530
531/* strip leading and trailing new lines.  Caller must free the
532 * return.
533 */
534char *owl_util_stripnewlines(const char *in)
535{
536 
537  char  *tmp, *ptr1, *ptr2, *out;
538
539  ptr1=tmp=owl_strdup(in);
540  while (ptr1[0]=='\n') {
541    ptr1++;
542  }
543  ptr2=ptr1+strlen(ptr1)-1;
544  while (ptr2>ptr1 && ptr2[0]=='\n') {
545    ptr2[0]='\0';
546    ptr2--;
547  }
548
549  out=owl_strdup(ptr1);
550  owl_free(tmp);
551  return(out);
552}
553
554/* Delete all lines matching "line" from the named file.  If no such
555 * line is found the file is left intact.  If backup==1 then leave a
556 * backup file containing the original contents.  The match is
557 * case-insensitive.
558 *
559 * Returns the number of lines removed
560 */
561int owl_util_file_deleteline(const char *filename, const char *line, int backup)
562{
563  char *backupfile, *newfile, *buf = NULL;
564  FILE *old, *new;
565  struct stat st;
566  int numremoved = 0;
567
568  if ((old = fopen(filename, "r")) == NULL) {
569    owl_function_error("Cannot open %s (for reading): %s",
570                       filename, strerror(errno));
571    return 0;
572  }
573
574  if (fstat(fileno(old), &st) != 0) {
575    owl_function_error("Cannot stat %s: %s", filename, strerror(errno));
576    return 0;
577  }
578
579  newfile = owl_sprintf("%s.new", filename);
580  if ((new = fopen(newfile, "w")) == NULL) {
581    owl_function_error("Cannot open %s (for writing): %s",
582                       filename, strerror(errno));
583    free(newfile);
584    fclose(old);
585    return 0;
586  }
587
588  if (fchmod(fileno(new), st.st_mode & 0777) != 0) {
589    owl_function_error("Cannot set permissions on %s: %s",
590                       filename, strerror(errno));
591    unlink(newfile);
592    fclose(new);
593    free(newfile);
594    fclose(old);
595    return 0;
596  }
597
598  while (owl_getline_chomp(&buf, old))
599    if (strcasecmp(buf, line) != 0)
600      fprintf(new, "%s\n", buf);
601    else
602      numremoved++;
603
604  fclose(new);
605  fclose(old);
606
607  if (backup) {
608    backupfile = owl_sprintf("%s.backup", filename);
609    unlink(backupfile);
610    if (link(filename, backupfile) != 0) {
611      owl_function_error("Cannot link %s: %s", backupfile, strerror(errno));
612      owl_free(backupfile);
613      unlink(newfile);
614      owl_free(newfile);
615      return 0;
616    }
617    owl_free(backupfile);
618  }
619
620  if (rename(newfile, filename) != 0) {
621    owl_function_error("Cannot move %s to %s: %s",
622                       newfile, filename, strerror(errno));
623    numremoved = 0;
624  }
625
626  unlink(newfile);
627  owl_free(newfile);
628
629  return numremoved;
630}
631
632int owl_util_max(int a, int b)
633{
634  if (a>b) return(a);
635  return(b);
636}
637
638int owl_util_min(int a, int b)
639{
640  if (a<b) return(a);
641  return(b);
642}
643
644/* Return the base class or instance from a zephyr class, by removing
645   leading `un' or trailing `.d'.
646   The caller is responsible for freeing the allocated string.
647*/
648char * owl_util_baseclass(const char * class)
649{
650  char *start, *end;
651
652  while(!strncmp(class, "un", 2)) {
653    class += 2;
654  }
655
656  start = owl_strdup(class);
657  end = start + strlen(start) - 1;
658  while(end > start && *end == 'd' && *(end-1) == '.') {
659    end -= 2;
660  }
661  *(end + 1) = 0;
662
663  return start;
664}
665
666const char * owl_get_datadir(void)
667{
668  const char * datadir = getenv("BARNOWL_DATA_DIR");
669  if(datadir != NULL)
670    return datadir;
671  return DATADIR;
672}
673
674/* Strips format characters from a valid utf-8 string. Returns the
675   empty string if 'in' does not validate. */
676char * owl_strip_format_chars(const char *in)
677{
678  char *r;
679  if (g_utf8_validate(in, -1, NULL)) {
680    const char *s, *p;
681    r = owl_malloc(strlen(in)+1);
682    r[0] = '\0';
683    s = in;
684    p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
685    while(p) {
686      /* If it's a format character, copy up to it, and skip all
687         immediately following format characters. */
688      if (owl_fmtext_is_format_char(g_utf8_get_char(p))) {
689        strncat(r, s, p-s);
690        p = g_utf8_next_char(p);
691        while (owl_fmtext_is_format_char(g_utf8_get_char(p))) {
692          p = g_utf8_next_char(p);
693        }
694        s = p;
695        p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
696      }
697      else {
698        p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
699      }
700    }
701    if (s) strcat(r,s);
702  }
703  else {
704    r = owl_strdup("");
705  }
706  return r;
707}
708
709/* If in is not UTF-8, convert from ISO-8859-1. We may want to allow
710 * the caller to specify an alternative in the future. We also strip
711 * out characters in Unicode Plane 16, as we use that plane internally
712 * for formatting.
713 */
714char * owl_validate_or_convert(const char *in)
715{
716  if (g_utf8_validate(in, -1, NULL)) {
717    return owl_strip_format_chars(in);
718  }
719  else {
720    return g_convert(in, -1,
721                     "UTF-8", "ISO-8859-1",
722                     NULL, NULL, NULL);
723  }
724}
725/*
726 * Validate 'in' as UTF-8, and either return a copy of it, or an empty
727 * string if it is invalid utf-8.
728 */
729char * owl_validate_utf8(const char *in)
730{
731  char *out;
732  if (g_utf8_validate(in, -1, NULL)) {
733    out = owl_strdup(in);
734  } else {
735    out = owl_strdup("");
736  }
737  return out;
738}
739
740/* This is based on _extract() and _isCJ() from perl's Text::WrapI18N */
741int owl_util_can_break_after(gunichar c)
742{
743 
744  if (c == ' ') return 1;
745  if (c >= 0x3000 && c <= 0x312f) {
746    /* CJK punctuations, Hiragana, Katakana, Bopomofo */
747    if (c == 0x300a || c == 0x300c || c == 0x300e ||
748        c == 0x3010 || c == 0x3014 || c == 0x3016 ||
749        c == 0x3018 || c == 0x301a)
750      return 0;
751    return 1;
752  }
753  if (c >= 0x31a0 && c <= 0x31bf) {return 1;}  /* Bopomofo */
754  if (c >= 0x31f0 && c <= 0x31ff) {return 1;}  /* Katakana extension */
755  if (c >= 0x3400 && c <= 0x9fff) {return 1;}  /* Han Ideogram */
756  if (c >= 0xf900 && c <= 0xfaff) {return 1;}  /* Han Ideogram */
757  if (c >= 0x20000 && c <= 0x2ffff) {return 1;}  /* Han Ideogram */
758  return 0;
759}
760
761char *owl_escape_highbit(const char *str)
762{
763  GString *out = g_string_new("");
764  unsigned char c;
765  while((c = (*str++))) {
766    if(c == '\\') {
767      g_string_append(out, "\\\\");
768    } else if(c & 0x80) {
769      g_string_append_printf(out, "\\x%02x", (int)c);
770    } else {
771      g_string_append_c(out, c);
772    }
773  }
774  return g_string_free(out, 0);
775}
776
777/* innards of owl_getline{,_chomp} below */
778static int owl_getline_internal(char **s, FILE *fp, int newline)
779{
780  int size = 0;
781  int target = 0;
782  int count = 0;
783  int c;
784
785  while (1) {
786    c = getc(fp);
787    if ((target + 1) > size) {
788      size += BUFSIZ;
789      *s = owl_realloc(*s, size);
790    }
791    if (c == EOF)
792      break;
793    count++;
794    if (c != '\n' || newline)
795        (*s)[target++] = c;
796    if (c == '\n')
797      break;
798  }
799  (*s)[target] = 0;
800
801  return count;
802}
803
804/* Read a line from fp, allocating memory to hold it, returning the number of
805 * byte read.  *s should either be NULL or a pointer to memory allocated with
806 * owl_malloc; it will be owl_realloc'd as appropriate.  The caller must
807 * eventually free it.  (This is roughly the interface of getline in the gnu
808 * libc).
809 *
810 * The final newline will be included if it's there.
811 */
812int owl_getline(char **s, FILE *fp)
813{
814  return owl_getline_internal(s, fp, 1);
815}
816
817/* As above, but omitting the final newline */
818int owl_getline_chomp(char **s, FILE *fp)
819{
820  return owl_getline_internal(s, fp, 0);
821}
822
823/* Read the rest of the input available in fp into a string. */
824char *owl_slurp(FILE *fp)
825{
826  char *buf = NULL;
827  char *p;
828  int size = 0;
829  int count;
830
831  while (1) {
832    buf = owl_realloc(buf, size + BUFSIZ);
833    p = &buf[size];
834    size += BUFSIZ;
835
836    if ((count = fread(p, 1, BUFSIZ, fp)) < BUFSIZ)
837      break;
838  }
839  p[count] = 0;
840
841  return buf;
842}
Note: See TracBrowser for help on using the repository browser.