/* Copyright (c) 1996 John E. Davis (davis@space.mit.edu) * All rights reserved. */ #include "config.h" #include #include #include #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifndef VMS # include # include #else # include "vms.h" #endif #include #include "jdmacros.h" #include "util.h" #include "ttymsg.h" /* This function allows NULL as a parameter. This fact _is_ exploited */ char *slrn_skip_whitespace (char *b) /*{{{*/ { register char ch; if (b == NULL) return NULL; while (((ch = *b) == ' ') || (ch == '\t') || (ch == '\n')) b++; return b; } /*}}}*/ /* returns a pointer to the end of the string */ char *slrn_trim_string (char *smin) /*{{{*/ { register char *s, ch; if (smin == NULL) return NULL; s = smin + strlen (smin); while (s > smin) { s--; ch = *s; if ((ch == ' ') || (ch == '\n') || (ch == '\t')) { *s = 0; continue; } s++; break; } return s; } /*}}}*/ char *slrn_strchr (char *s, char ch) /*{{{*/ { register char ch1; while (((ch1 = *s) != 0) && (ch != ch1)) s++; if (ch1 == 0) return NULL; return s; } /*}}}*/ /* Search for characters from list in string str. If found, return a pointer * to the first occurrence. If not found, return NULL. */ char *slrn_strbrk (char *str, char *list) /*{{{*/ { char ch, ch1, *p; while ((ch = *str) != 0) { p = list; while ((ch1 = *p) != 0) { if (ch == ch1) return str; p++; } str++; } return NULL; } /*}}}*/ char *slrn_simple_strtok (char *s, char *chp) /*{{{*/ { static char *s1; char ch = *chp; if (s == NULL) { if (s1 == NULL) return NULL; s = s1; } else s1 = s; while (*s1 && (*s1 != ch)) s1++; if (*s1 == 0) { s1 = NULL; } else *s1++ = 0; return s; } /*}}}*/ /* Note!!! These routines assume a flat address space !! */ int slrn_case_strncmp (unsigned char *a, register unsigned char *b, register unsigned int n) /*{{{*/ { register unsigned char cha, chb, *bmax; register int diff = a - b; bmax = b + n; while (b < bmax) { cha = UPPER_CASE(b[diff]); chb = UPPER_CASE(*b); if (cha != chb) { return (int) cha - (int) chb; } else if (chb == 0) return 0; b++; } return 0; } /*}}}*/ int slrn_case_strcmp (unsigned char *a, register unsigned char *b) /*{{{*/ { register unsigned char cha, chb; register int diff = a - b; while (1) { cha = UPPER_CASE(b[diff]); chb = UPPER_CASE(*b); if (cha != chb) { return (int) cha - (int) chb; } else if (chb == 0) break; b++; } return 0; } /*}}}*/ #if defined(__os2__) || defined(__NT__) void slrn_os2_convert_path (char *path) { char ch; while ((ch = *path) != 0) { if (ch == '/') *path = SLRN_PATH_SLASH_CHAR; path++; } } #endif #ifdef SLRN_USE_OS2_FAT void slrn_os2_make_fat (char *file, char *name, char *ext) { static char drive[3] = " :"; char fsys[5]; strcpy (file, name); if (isalpha(file[0]) && (file[1] == ':')) drive[0] = file[0]; else drive[0] = _getdrive(); if ((0 == _filesys (drive, fsys, sizeof (fsys))) && (0 == stricmp (fsys, "FAT"))) { /* FAT */ _remext (file); /* Remove the extension */ } strcat (file, ext); } #endif static void fixup_path (char *path) /*{{{*/ { #ifndef VMS unsigned int len; len = strlen (path); if (len == 0) return; if (path[len - 1] == SLRN_PATH_SLASH_CHAR) return; path[len] = SLRN_PATH_SLASH_CHAR; path[len + 1] = 0; #endif } /*}}}*/ /* dir and file could be the same in which case this performs a strcat. * If name looks like an absolute path, it will be returned. */ int slrn_dircat (char *dir, char *name, char *file) { unsigned int len = 0; if (name != NULL) { if (slrn_is_absolute_path (name)) { strcpy (file, name); #if defined(__os2__) || defined(__NT__) slrn_os2_convert_path (file); #endif return 0; } len = strlen (name); } if (dir != NULL) len += strlen (dir); len += 2; /* for / and \0 */ if (len > SLRN_MAX_PATH_LEN) { slrn_error ("File name too long."); return -1; } if (dir != NULL) { if (dir != file) strcpy (file, dir); fixup_path (file); } else *file = 0; if (name != NULL) strcat (file, name); #if defined(__os2__) || defined(__NT__) slrn_os2_convert_path (file); #endif return 0; } /*{{{ Memory Allocation Routines */ static char *do_malloc_error (int do_error) { if (do_error) slrn_error ("Memory allocation failure."); return NULL; } char *slrn_safe_strmalloc (char *s) /*{{{*/ { s = SLmake_string (s); if (s == NULL) slrn_exit_error ("Out of memory."); return s; } /*}}}*/ char *slrn_strnmalloc (char *s, unsigned int len, int do_error) { s = SLmake_nstring (s, len); if (s == NULL) return do_malloc_error (do_error); return s; } char *slrn_strmalloc (char *s, int do_error) { if (s == NULL) return NULL; return slrn_strnmalloc (s, strlen (s), do_error); } char *slrn_malloc (unsigned int len, int do_memset, int do_error) { char *s; s = (char *) SLmalloc (len); if (s == NULL) return do_malloc_error (do_error); if (do_memset) memset (s, 0, len); return s; } char *slrn_realloc (char *s, unsigned int len, int do_error) { if (s == NULL) return slrn_malloc (len, 0, do_error); s = SLrealloc (s, len); if (s == NULL) return do_malloc_error (do_error); return s; } char *slrn_safe_malloc (unsigned int len) { char *s; s = slrn_malloc (len, 1, 0); if (s == NULL) slrn_exit_error ("Out of memory"); return s; } void slrn_free (char *s) { if (s != NULL) SLfree (s); } /*}}}*/ char *slrn_fix_regexp (char *pat) /*{{{*/ { static char newpat[256]; char *p, ch; unsigned int len; len = 1; /* For ^ */ p = pat; while (*p != 0) { if ((*p == '.') || (*p == '*')) len++; len++; p++; } len++; /* for $ */ len++; /* for \0 */ if (len > sizeof(newpat)) slrn_exit_error ("Pattern too long for buffer"); p = newpat; *p++ = '^'; while ((ch = *pat++) != 0) { if (ch == '.') *p++ = '\\'; else if (ch == '*') *p++ = '.'; *p++ = ch; } if (*(p - 1) != '$') *p++ = '$'; *p = 0; return newpat; } /*}}}*/ int slrn_is_absolute_path (char *path) { if (path == NULL) return 0; if (*path == SLRN_PATH_SLASH_CHAR) return 1; #if defined(__os2__) || defined(__NT__) if (*path == '/') return 1; if (*path && (path[1] == ':')) return 1; #endif return 0; } /* This is like slrn_dircat except that any dots in name can get mapped to * slashes. It also mallocs space for the resulting file. */ char *slrn_spool_dircat (char *root, char *name, int map_dots) { char *spool_group, *p, ch; unsigned int len; len = strlen (root); spool_group = SLmalloc (strlen (name) + len + 2); if (spool_group == NULL) { slrn_exit_error ("Out of memory."); } strcpy (spool_group, root); p = spool_group + len; if (len && (*(p - 1) != SLRN_PATH_SLASH_CHAR)) *p++ = SLRN_PATH_SLASH_CHAR; strcpy (p, name); if (map_dots) while ((ch = *p) != 0) { if (ch == '.') *p = SLRN_PATH_SLASH_CHAR; p++; } #if defined(__os2__) || defined(__NT__) slrn_os2_convert_path (spool_group); #endif return spool_group; } int slrn_delete_file (char *f) /*{{{*/ { #ifdef VMS return delete(f); #else return unlink(f); #endif } /*}}}*/ int slrn_fclose (FILE *fp) /*{{{*/ { if (0 == fclose (fp)) return 0; slrn_error ("Error closing file. File system full? (errno = %d)", errno); return -1; } /*}}}*/ int slrn_file_exists (char *file) /*{{{*/ { struct stat st; int m; #ifdef _S_IFDIR # ifndef S_IFDIR # define S_IFDIR _S_IFDIR # endif #endif #ifndef S_ISDIR # ifdef S_IFDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # else # define S_ISDIR(m) 0 # endif #endif if (file == NULL) return -1; if (stat(file, &st) < 0) return 0; m = st.st_mode; if (S_ISDIR(m)) return (2); return 1; } /*}}}*/ char *slrn_basename (char *file) { char *f; #ifdef VMS f = slrn_strchr (file, ']'); if (f != NULL) return f + 1; return file; #else while (NULL != (f = slrn_strchr (file, SLRN_PATH_SLASH_CHAR))) file = f + 1; return file; #endif } static int file_eqs (char *a, char *b) { #ifdef REAL_UNIX_SYSTEM struct stat st_a, st_b; #endif if (0 == strcmp (a, b)) return 1; #ifndef REAL_UNIX_SYSTEM return 0; #else if (-1 == stat (a, &st_a)) return 0; if (-1 == stat (b, &st_b)) return 0; return ((st_a.st_ino == st_b.st_ino) && (st_a.st_dev == st_b.st_dev)); #endif } int slrn_copy_file (char *infile, char *outfile) { FILE *in, *out; int ch; int ret; if ((infile == NULL) || (outfile == NULL)) return -1; if (file_eqs (infile, outfile)) return 0; if (NULL == (in = fopen (infile, "rb"))) { slrn_error ("Error opening %s", infile); return -1; } if (NULL == (out = fopen (outfile, "wb"))) { fclose (in); slrn_error ("Error opening %s", outfile); return -1; } ret = 0; while (EOF != (ch = getc (in))) { if (EOF == putc (ch, out)) { slrn_error ("Write Error: %s", outfile); ret = -1; break; } } fclose (in); if (-1 == slrn_fclose (out)) ret = -1; return ret; } int slrn_move_file (char *infile, char *outfile) { if ((infile == NULL) || (outfile == NULL)) return -1; if (file_eqs (infile, outfile)) return 0; (void) slrn_delete_file (outfile); if (-1 == rename (infile, outfile)) { if (-1 == slrn_copy_file (infile, outfile)) return -1; slrn_delete_file (infile); } return 0; }