ftp.nice.ch/pub/next/unix/network/news/slrn0.9.0.0.s.tar.gz#/slrn/src/misc.c

This is misc.c in view mode; [Download] [Up]

/*  Copyright (c) 1995 John E. Davis (davis@space.mit.edu)
 *  All rights reserved.
 */
#include "config.h"
#include "features.h"

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>

#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifndef VMS
#  include <pwd.h>
#  include <sys/types.h>
#  include <sys/stat.h>
#else
#  include <stat.h>
#  include <unixio.h>
#endif

#include <slang.h>
#include "jdmacros.h"

#include "misc.h"
#include "group.h"
#include "slrn.h"
#include "post.h"
#include "server.h"

#if SLRN_HAS_MIME
#include "mime.h"
#endif

#ifdef VMS
/* valid filname chars for unix equiv of vms filename */
#define VALID_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_-/"
#endif


static int Error_Present;
int Slrn_Full_Screen_Update = 1;
int Slrn_User_Wants_Confirmation = 1;

#ifndef VMS
char *Slrn_SendMail_Command;
#endif

char *Slrn_Editor;

void slrn_set_color (int color)
{
#if 0
   if (SLtt_Use_Ansi_Colors == 0)
     {
	if (color >= STATUS_COLOR) SLsmg_reverse_video ();
	else SLsmg_normal_video ();
     }
   else
#endif
     SLsmg_set_color (color);
}

void slrn_redraw (void)
{
   SLsmg_cls ();
   Slrn_Full_Screen_Update = 1;
   
   if ((Slrn_Current_Mode != NULL)
       && (Slrn_Current_Mode->redraw_fun != NULL))
     (*Slrn_Current_Mode->redraw_fun) ();
   
   slrn_smg_refresh ();
}
int Slrn_Message_Present;
void slrn_clear_message (void)
{
   Slrn_Message_Present = Error_Present = 0;
   /* SLang_Error = 0; */
   
   SLKeyBoard_Quit = 0;
   
   if ((Slrn_TT_Initialized & 1) == 0)
     return;
   
   SLsmg_gotorc (SLtt_Screen_Rows - 1, 0);
   SLsmg_erase_eol ();
}

int slrn_message (char *fmt, ...)
{
   int ok;
   va_list ap;
   
   if (Error_Present) return -1;
   if (Slrn_TT_Initialized & 1)
     {
	ok = Slrn_Suspension_Ok;
	if (ok) slrn_set_suspension (0);
	SLsmg_gotorc (SLtt_Screen_Rows - 1, 0);
	slrn_set_color (0);
	va_start(ap, fmt);
	(void) SLsmg_vprintf(fmt, ap);
	SLsmg_erase_eol ();
	Slrn_Message_Present = 1;
	if (ok) slrn_set_suspension (1);
     }
   else
     {
	va_start(ap, fmt);
	(void) vfprintf(stderr, fmt, ap);
	va_end(ap);
	putc ('\n', stderr);
     }
   return 0;
}


extern void slrn_error (char *fmt, ...)
{
   va_list ap;
   
   if ((Slrn_TT_Initialized & 1) == 0)
     {
	va_start(ap, fmt);
	(void) vfprintf(stderr, fmt, ap);
	va_end(ap);
	putc ('\n', stderr);
     }
   else
     {
	int ok;
	if (Error_Present) return;
	
	ok = Slrn_Suspension_Ok;
	if (ok) slrn_set_suspension (0);
	SLtt_beep ();
	slrn_clear_message ();
	
	Error_Present = 1;
	Slrn_Message_Present = 1;
	
	slrn_set_color (ERROR_COLOR);
	va_start(ap, fmt);
	(void) SLsmg_vprintf(fmt, ap);
	va_end(ap);
	slrn_set_color (0);
	SLang_flush_input ();
	if (ok) slrn_set_suspension (1);
     }
   
   if (SLang_Error == 0) SLang_Error = INTRINSIC_ERROR;
}

void slrn_print_percent (int row, int col, int n, int nmax, int width)
{
   SLsmg_erase_eol ();
   SLsmg_gotorc (row, col);
   SLsmg_printf ("-- %d/%d", n, nmax);
   if (n == 1)
     {
#if 1
	SLsmg_write_string ( (n + width > nmax) ? "  (All)" : "  (Top)" );
#else
	SLsmg_printf (" (Top)");
#endif
     }
   else if (n + width > nmax) SLsmg_write_string("  (Bot)");
   else SLsmg_printf("  (%d%%)", ((n + width - 1) * 100) / nmax);
   SLsmg_erase_eol ();
}

static void fixup_path (char *path)
{
   int len;
   
   len = strlen (path);
   if (len == 0) return;
   if (path[len - 1] == '/') return;
   path[len] = '/';
   path[len + 1] = 0;
}

#ifdef VMS
static void vms_fix_name(char *name)
{
   int idx, pos;
   
   pos = strspn(name, VALID_FILENAME_CHARS);
   if (pos == strlen(name))
     return;
   for(idx=pos;idx<strlen(name);idx++)
     if (!(isdigit(name[idx]) || isalpha(name[idx]) || (name[idx] == '$') || (name[idx] == '_') || (name[idx] == '-')
	   || (name[idx] == '/')))
       name[idx] = '-';
}

static char Copystr[256];
static int vms_copyname1 (char *name)
{
   strcpy(Copystr, name);
   return(1);
}

static int vms_copyname2 (char *name, int type)
{
   strcpy(Copystr, name);
   return(1);
}
#endif

void slrn_make_home_filename (char *name, char *file)
{
   char *home;
#ifndef VMS
   if (
#ifdef __os2__
       (*name == '/') || (*name == '\\') || (*(name + 1) == ':') 
       || ((*name == '.') && (*(name + 1) == '/')) 
       || ((*name == '.') && (*(name + 1) == '\\'))
#else
       (*name == '/') || ((*name == '.') && (*(name + 1) == '/'))
#endif
       )
     {
	strcpy (file, name);
	return;
     }
   
   if (NULL == (home = getenv ("SLRNHOME")))
     home = getenv ("HOME");
   
   *file = 0;
   if (home != NULL) strcpy (file, home);
   fixup_path (file);
   strcat (file, name);
   
#else
   char *cp, *cp1;
   static char fname[256];
   char fn[256], fn1[256];
   int rc, idx;
   
   strcpy (fn1, name);
   if (NULL != slrn_strchr (name, ':'))
     {
	strcpy (file, name);
	return;
     }
   
   if (NULL == (home = getenv ("SLRNHOME")))
     home = getenv ("HOME");
   
   *file = 0;
   if (NULL != (cp = slrn_strchr (fn1, '/')))
     {
# ifdef __DECC
	*cp = '\0'; cp++;
	cp1 = decc$translate_vms(home);
	if (cp1 == 0 || (int)cp1 == -1)
	  { /* error translating */ }
	else
	  {
	     strcpy(fname, cp1);
	     strcat(cp1, "/");
 	  }
	strcat (cp1, fn1);
	
	vms_fix_name (cp1);
 	
	rc = decc$to_vms(cp1, vms_copyname2, 0, 2);
 	if (rc > 0)
 	  {
 	     strcpy(fname, Copystr);
 	     rc = mkdir(fname, 0755);
 	  }
	strcat(fname, cp);
# else
	*cp = '\0'; cp++;
	cp1 = shell$translate_vms(home);
	if (cp1 == 0 || (int)cp1 == -1)
	  { /* error translating */ }
	else
 	  {
	     strcpy(fname, cp1);
	     strcat(cp1, "/");
	  }
	strcat (cp1, fn1);
	
	vms_fix_name (cp1);
 	
	rc = shell$to_vms(cp1, vms_copyname2, 0, 2);
	if (rc > 0)
	  {
	     strcpy(fname, Copystr);
	     rc = mkdir(fname, 0755);
	  }
	strcat(fname, cp);
# endif
	strcpy(file,fname);
     }
   else
     {
	if (home != NULL) strcpy(file, home);
	strcat(file, name);
     }
#endif /* VMS */
}

int slrn_make_home_dirname (char *name, char *dir)
{
   /* This needs modified to deal with VMS directory syntax */
#ifndef VMS
   slrn_make_home_filename (name, dir);
#else
   char *home, *cp;
   char fn[256];
   static char fname[256];
   int rc, idx, len;
   
   if (NULL != slrn_strchr (name, ':'))
     {
	strcpy (dir, name);
	return;
     }
   home = getenv ("HOME");
   *dir = 0;
   if (cp = strchr(name,'/'))
     {
#ifdef __DECC
	cp = decc$translate_vms(home);
	if (cp == 0 || (int)cp == -1)
	  { /* error translating */ }
	else
	  {
	     strcpy(fname, cp);
	     strcat(cp, "/");
	  }
	strcat (cp, name);
	vms_fix_name (cp);
	
	rc = decc$to_vms(cp, vms_copyname2, 0, 2);
	if (rc > 0)
	  {
	     strcpy(fname, Copystr);
	     rc = mkdir(fname, 0755);
	  }
#else
	if (shell$from_vms(home, vms_copyname1, 0))
	  {
	     if (Copystr != NULL) strcpy (fn, Copystr);
	     strcat(fn, "/");
	  }
	strcat (fn, name);
	vms_fix_name(fn);
	if (shell$to_vms(fn, vms_copyname1, 0))
	  strcpy(fname, Copystr);
#endif
	strcpy(dir,fname);
     }
   else
     {
	if (home != NULL) 
	 {
	  strcpy(dir, home);
	  len = strlen(dir) - 1;
	  if (dir[len] == ']')
	   {
	    dir[len] = '.';
	    strcat(dir, name);
	    strcat(dir, "]");
	   }
	  else
	    strcat(dir, name);
	 }
	else
	  strcat(dir, name);
     }
#endif /* VMS */
   
   return 0;
}

FILE *slrn_open_tmpfile (char *file, char *mode)
{
   FILE *fp = NULL;
#ifdef _AIX			/* AIX doesn't have mktemp() */
   char *f = tempnam (NULL, "SLRN");
   if (f != NULL)
     {
	strcpy (file, f);
	fp = fopen (f, mode);
	free (f);
     }
#else
   char *dir;

# ifdef __os2__
   dir = getenv ("TMP");
   if (dir == NULL)
# endif
     dir = getenv ("TMPDIR");
   
# ifdef VMS
   if (dir == NULL) dir = "SYS$LOGIN:";
   sprintf (file, "%sSLRN%uXXXXXX", dir, (unsigned int) getpid ());
# else
   if (dir == NULL) dir = "/tmp";
   sprintf (file, "%s/SLRN%uXXXXXX", dir, (unsigned int) getpid ());
# endif
   
   if (NULL != mktemp (file)) fp = fopen (file, mode);
#endif
   return fp;
}


FILE *slrn_open_home_file (char *name, char *mode, char *file, int create_flag)
{
   slrn_make_home_filename (name, file);
   
#ifdef VMS
   if (create_flag)
     {
	FILE *fp = fopen (file, mode, "fop=cif");
	if (fp == NULL) perror ("fopen");
	return fp;
     }
#endif
   return fopen (file, mode);
}


/* invoke the editor */

int slrn_posix_system (char *cmd, int reset)
{
   int init_mode = Slrn_TT_Initialized;
#ifndef VMS
   void (*sint)(int);
   void (*squit)(int);
   int ret;
   
   sint = signal (SIGINT, SIG_IGN);
   squit = signal (SIGQUIT, SIG_IGN);
   if (reset) slrn_reset_display (0);
   ret = system (cmd);
   signal (SIGINT, sint);
# ifdef SIGQUIT
   signal (SIGQUIT, squit);
# endif
#else
   int ret;
   if (reset) slrn_reset_display (0);
   ret = system (cmd);
#endif
   if (reset) slrn_init_display (init_mode, 0);
   return ret;
}

static int create_edit_command (char *edit, char *cmd, char *file, unsigned int line)
{
   int d, s;
   char ch, *p = edit;
   /* Look for %d and %s */
   
   d = s = 0;
   
   while (0 != (ch = *p++))
     {
	if (ch != '%') continue;
	ch = *p;
	if (!d && (ch == 'd'))
	  {
	     *p = 'u';		       /* map %d to %u (unsigned) */
	     if (s == 0) d = 1; else d = 2;
	  }
	else if (!s && (ch == 's'))
	  {
	     if (d == 0) s = 1; else s = 2;
	  }
	else
	  {
	     slrn_error ("Invalid Editor definition.");
	     return 0;
	  }
	p++;
     }
   
   
   /* No %d, %s */
   
   if ((d == 0) && (s == 0))
     {
	sprintf (cmd, "%s %s", edit, file);
     }
   else if (d == 0)
     {
	sprintf (cmd, edit, file);
     }
   else if (s == 0)
     {
	sprintf (cmd, edit, (int) line);
	strcat (edit, " ");
	strcat (edit, file);
     }
   else /* d and s */
     {
	if (d == 1)
	  sprintf (cmd, edit, line, file);
	else sprintf (cmd, edit, file, line);
     }
   return 1;
}


int slrn_edit_file (char *file, unsigned int line)
{
   char buf[512];
   char editbuf[512];
   int ret;
   char *editor = Slrn_Editor;
   
   if ((editor == NULL)
       && (NULL == (editor = getenv("SLRN_EDITOR")))
       && (NULL == (editor = getenv("SLANG_EDITOR")))
       && (NULL == (editor = getenv("EDITOR")))
       && (NULL == (editor = getenv("VISUAL"))))
     {
#ifdef VMS
	editor = "edit";
#else
# ifdef __os2__
	editor = "e";
# else
#  ifdef unix
	editor = "vi";
#  endif
# endif
#endif
     }
   
   strcpy (editbuf, editor);
   if (0 == create_edit_command(editbuf, buf, file, line)) return -1;
   
   ret = slrn_posix_system (buf, 1);
   
   /* Am I the only one who thinks this is a good idea?? */
   if (Slrn_TT_Initialized) while (SLang_input_pending (5))
     {
	SLang_flush_input ();
     }
   
   /* slrn_redraw (); */
   return ret;
}


void slrn_suspend_cmd (void)
{
   slrn_suspend (0);
}

char slrn_get_response (char *valid_chars, char *str, ...)
{
   char ch;
   va_list ap;
   char *v;
   
   /* if (SLang_Error) return -1; */
   
   while (1)
     {
	if (Slrn_TT_Initialized == 0)
	  {
	     char buf[256];
	     va_start(ap, str);
	     (void) vfprintf(stdout, str, ap);
	     va_end(ap);
	     fflush (stdout);
	     *buf = 0;
	     (void) fgets (buf, sizeof(buf), stdin);
	     ch = *buf;
	  }
	else
	  {
	     SLang_flush_input ();
	     slrn_clear_message ();
	     va_start(ap, str);
	     (void) SLsmg_vprintf(str, ap);
	     va_end(ap);
	     slrn_smg_refresh ();
	     
	     ch = SLang_getkey ();
	     slrn_clear_message ();
	     SLang_Error = SLKeyBoard_Quit = 0;
	  }
	
	v = valid_chars;
	while (*v)
	  {
	     if (*v == ch) return ch;
	     v++;
	  }
	
	slrn_error ("Invalid response! Try again.");
	if (Slrn_TT_Initialized & 1)
	  {
	     slrn_smg_refresh ();
	     (void) SLang_input_pending (15);
	  }
     }
}

int slrn_get_yesno (int dflt, char *str, ...)
{
   va_list ap;
   char buf[512];
   char ch, rsp;
   char *fmt;
   
   /* if (SLang_Error) return -1; */
   
   va_start(ap, str);
   (void) vsprintf(buf, str, ap);
   va_end(ap);
   
   if (dflt)
     {
	ch = 'y';
	fmt = "? ([y]/n)";
     }
   else
     {
	ch = 'n';
	fmt = "? (y/[n])";
     }
   
   strcat (buf, fmt);
   rsp = slrn_get_response ("yYnN\r", buf);
   if (rsp == '\r') rsp = ch;
   else rsp |= 0x20;
   
   if (rsp == 'n') return 0;
   return 1;
}

int slrn_get_yesno_cancel (char *str, ...)
{
   va_list ap;
   char buf[512];
   
   if (SLang_Error) return -1;
   
   va_start(ap, str);
   (void) vsprintf(buf, str, ap);
   va_end(ap);
   
   strcat (buf, "? [Y]-es, N-o, C-ancel");
   
   switch (slrn_get_response ("\007yYnNcC\r", buf))
     {
      case '\r':
      case 'Y':
      case 'y':
	return 1;
	
      case 'n':
      case 'N':
	return 0;
	
      default:
	return -1;
     }
}

Slrn_User_Info_Type Slrn_User_Info =
{
   NULL,			       /* realname */
     NULL,			       /* username */
     "",				       /* host */
     NULL,			       /* reply to */
     NULL,			       /* org */
     NULL,			       /* followup_string */
     NULL				       /* signature */
};

#if defined(VMS) && defined(MULTINET)
# include "multinet_root:[multinet.include]netdb.h"
#else
# include <netdb.h>
# ifndef h_errno
     extern int h_errno;
# endif
#endif 


char *slrn_make_startup_string (char *s)
{
   char *ss;
   ss = (char *) SLMALLOC (strlen (s) + 1);
   if (ss == NULL)
     {
	slrn_exit_error ("Out of memory.");
     }
   strcpy (ss, s);
   return ss;
}

char *slrn_skip_whitespace (char *b)
{
   register char ch;
   
   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;
}

int slrn_is_fqdn (char *h)
{
   char *p;
   
   /* Believe it or not, I have come across one system with a '(' character
    * as part of the hostname!!!  I suppose that I should also check for
    * other strange characters as well.  This is an issue since a message
    * id will be composed from the fqdn.  For that reason, such names will
    * be rejected.  Sigh.
    */
   if ((NULL != slrn_strchr (h, '('))
       || (NULL != slrn_strchr (h, '@')))
     return 0;
   
   p = slrn_strchr (h, '.');
   return ((p != NULL) && (p != h));
}


void slrn_get_user_info (void)
{
   struct hostent *host_entry;
   char *name, *host;
#ifndef VMS
   struct passwd *pw;
   
   pw = getpwuid (getuid ());
#endif
   
   /* Fill in what is assumed to be non-NULL by rest of program. */
   Slrn_User_Info.followup_string = slrn_make_startup_string ("In article %m, %r wrote:");
   Slrn_Courtesy_CC_Message = slrn_make_startup_string ("[This message has also been posted.]");
   
   /* Now get default values for rest. */
   
   host = Slrn_User_Info.host;
   
   /* gethostname may not provide the full name so use gethostbyname
    * to get more information.  Why isn't there a simplified interface to
    * get the FQDN!!!!
    */
   host_entry = NULL;
   if (-1 != gethostname (host, MAX_HOST_NAME_LEN))
     host_entry = gethostbyname (host);
#ifdef TRY_AGAIN
   if ((host_entry == NULL) && (h_errno == TRY_AGAIN))
     {
	sleep (2);
	host_entry = gethostbyname (host);
     }
#endif
   
   if ((host_entry == NULL) || (host_entry->h_name == NULL))
     *host = 0;
   else
     {
	if (slrn_is_fqdn ((char *)host_entry->h_name))
	  {
	     Slrn_User_Info.posting_host = slrn_make_startup_string ((char *)host_entry->h_name);
	  }
	else
	  {
	     char **aliases;
	     aliases = host_entry->h_aliases;
	     if (aliases != NULL) while (*aliases != NULL)
	       {
		  if (slrn_is_fqdn (*aliases))
		    {
		       Slrn_User_Info.posting_host = slrn_make_startup_string (*aliases);
		       break;
		    }
		  aliases++;
	       }
	  }
	
	if (Slrn_User_Info.posting_host == NULL)
	  {
	     strcpy (host, (char *) host_entry->h_name);
	  }
	else strcpy (host, Slrn_User_Info.posting_host);
     }
   
#if defined(USE_DOMAIN_NAME) && defined(MY_DOMAIN_NAME)
   if (*host && (0 == slrn_is_fqdn (host)))
     {
	char *my_domain_name;
	unsigned int len;
	
	len = strlen (host);
	my_domain_name = MY_DOMAIN_NAME;
	if (*my_domain_name != '.')
	  {
	     host[len++] = '.';
	  }
	strcpy (host + len, my_domain_name);
     }
#endif
   /* If a value was compiled in, use it. */
#ifdef OUR_HOSTNAME
# ifdef unix
   /* If the value is a file, read the file for the FQDN */
   if (OUR_HOSTNAME[0] == '/')
     {
	FILE *fp;
	
	if (NULL != (fp = fopen(OUR_HOSTNAME, "r")))
	  {
	   char tmphost[MAX_HOST_NAME_LEN];
	     
	     if (fgets(tmphost, MAX_HOST_NAME_LEN , fp) != NULL)
	       {
		  char *p;
		  
		  if ((p = slrn_strchr (tmphost, '\n')) != NULL)
		    *p = '\0';
	       /* If the entry is valid, we're done */
		  if (slrn_is_fqdn(tmphost))
		    strcpy(host, tmphost);
	       }
	     fclose(fp);
	  }
     }
   else
# endif
     if (slrn_is_fqdn (OUR_HOSTNAME)
	 && strlen(OUR_HOSTNAME) < MAX_HOST_NAME_LEN)
       strcpy (host, OUR_HOSTNAME);
#endif

   /* Allow user chance to over ride this.  Until now, host was a pointer
    * to Slrn_User_Info.host.
    */
   if ((NULL != (host = getenv ("HOSTNAME")))
       && slrn_is_fqdn (host))
     {
	strncpy (Slrn_User_Info.host, host, MAX_HOST_NAME_LEN);
	Slrn_User_Info.host[MAX_HOST_NAME_LEN - 1] = 0;
     }
   
   if (
#ifdef VMS
       ((name = getlogin()) == NULL)
#else 
       /* I cannot use getlogin under Unix because some implementations 
	* truncate the username to 8 characters.  Besides, I suspect that
	* it is equivalent to the following line.
	*/
       ((pw == NULL) 
	|| (NULL == (name = pw->pw_name))
	|| (*name == 0))
#endif
       && ((name = getenv("USER")) == NULL)
       && ((name = getenv("LOGNAME")) == NULL))
     name = "";


   Slrn_User_Info.username = slrn_make_startup_string (name);
   
   if ((Slrn_User_Info.replyto = getenv ("REPLYTO")) == NULL)
     Slrn_User_Info.replyto = "";
   Slrn_User_Info.replyto = slrn_make_startup_string (Slrn_User_Info.replyto);
   
#ifdef VMS
   Slrn_User_Info.realname = fix_fullname(get_uaf_fullname());
#else
   if (((Slrn_User_Info.realname = getenv ("NAME")) == NULL)
       && ((pw == NULL) || ((Slrn_User_Info.realname = pw->pw_gecos) == NULL)))
     {
	Slrn_User_Info.realname = "";
     }
#endif
   Slrn_User_Info.realname = slrn_make_startup_string (Slrn_User_Info.realname);
   
   /* truncate at character used to delineate extra gecos fields */
   name = Slrn_User_Info.realname;
   while (*name && (*name != ',')) name++;
   *name = 0;
   
   Slrn_User_Info.org = getenv ("ORGANIZATION");
#ifdef OUR_ORGANIZATION
   if (Slrn_User_Info.org == NULL) Slrn_User_Info.org = OUR_ORGANIZATION;
#endif
   if (Slrn_User_Info.org != NULL)
     {
	/* Check to see if this is an organization file. */
	char orgbuf[512];
	if (*Slrn_User_Info.org == '/')
	  {
	     FILE *fporg;
	     if (NULL != (fporg = fopen (Slrn_User_Info.org, "r")))
	       {
		  if (NULL != fgets (orgbuf, sizeof (orgbuf) - 1, fporg))
		    {
		       unsigned int orglen = strlen (orgbuf);
		       if (orglen && (orgbuf[orglen - 1] == '\n'))
			 orgbuf[orglen - 1] = 0;
		       Slrn_User_Info.org = orgbuf;
		    }
		  slrn_fclose (fporg);
	       }
	  }
	Slrn_User_Info.org = slrn_make_startup_string (Slrn_User_Info.org);
     }
   
   Slrn_User_Info.signature = slrn_make_startup_string (SLRN_SIGNATURE_FILE);
   
#if SLRN_HAS_MIME
   Slrn_Mime_Display_Charset = slrn_make_startup_string ("iso-8859-1");
#endif
   
#ifdef SLRN_SENDMAIL_COMMAND
   Slrn_SendMail_Command = slrn_make_startup_string (SLRN_SENDMAIL_COMMAND);
#endif
}


void update_top_status_line (void)
{
   if (Slrn_Full_Screen_Update == 0) return;
   SLsmg_gotorc (0, 0);
   slrn_set_color (MENU_COLOR);
   SLsmg_printf ("\
slrn %s ** Press '?' for help, 'q' to quit. ** Server: %s",
		 Slrn_Version,
		 Slrn_Server_Obj->sv_name);
   SLsmg_erase_eol ();
   slrn_set_color (0);
}

static void rline_update (unsigned char *buf, int len, int col)
{
   SLsmg_gotorc (SLtt_Screen_Rows - 1, 0);
   SLsmg_write_nchars ((char *) buf, len);
   SLsmg_erase_eol ();
   SLsmg_gotorc (SLtt_Screen_Rows - 1, col);
   slrn_smg_refresh ();
}

SLang_RLine_Info_Type *Slrn_Keymap_RLI;

static SLang_RLine_Info_Type  *init_readline (void)
{
   unsigned char *buf = NULL;
   SLang_RLine_Info_Type *rli;
   
   if ((NULL == (rli = (SLang_RLine_Info_Type *) SLMALLOC (sizeof(SLang_RLine_Info_Type))))
       || (NULL == (buf = (unsigned char *) SLMALLOC (256))))
     {
	if (rli != NULL) SLFREE (rli);
	fprintf(stderr, "malloc error.\n");
	return NULL;
     }
   
   SLMEMSET ((char *) rli, 0, sizeof (SLang_RLine_Info_Type));
   rli->buf = buf;
   rli->buf_len = 255;
   rli->tab = 8;
   rli->dhscroll = 20;
   rli->getkey = SLang_getkey;
   rli->tt_goto_column = NULL;
   rli->update_hook = rline_update;
   
   if (SLang_init_readline (rli) < 0)
     {
	SLFREE (rli);
	SLFREE (buf);
	rli = NULL;
     }
   
   return rli;
}

int slrn_init_readline (void)
{
   if ((Slrn_Keymap_RLI == NULL) 
       && (NULL == (Slrn_Keymap_RLI = init_readline ())))
     return -1;
   return 0;
}   

int slrn_read_input (char *prompt, char *str, int trim_flag)
{
   int i;
   
   Slrn_Keymap_RLI->edit_width = SLtt_Screen_Cols - 1;
   Slrn_Keymap_RLI->prompt = prompt;
   *Slrn_Keymap_RLI->buf = 0;
   if (*str)
     {
	strcpy ((char *) Slrn_Keymap_RLI->buf, str);
	Slrn_Keymap_RLI->point = 0;   /* strlen (str); */
     }
   *str = 0;
   
   slrn_enable_mouse (0);
   i = SLang_read_line (Slrn_Keymap_RLI);
   slrn_enable_mouse (1);
   
   if ((i >= 0) && !SLang_Error && !SLKeyBoard_Quit)
     {
	char *b = (char *) Slrn_Keymap_RLI->buf;
	
	/* SLang_rline_save_line (Slrn_Keymap_RLI); */
	if (trim_flag) 
	  {
	     slrn_trim_string (b);
	     b = slrn_skip_whitespace (b);
	  }
	strcpy (str, b);
	i = strlen (str);
     }
   if (SLKeyBoard_Quit) i = -1;
   SLang_Error = SLKeyBoard_Quit = 0;
   
   /* put cursor at edge of screen to comfort user */
   SLsmg_gotorc (SLtt_Screen_Rows - 1, 0);
   slrn_smg_refresh ();
   return i;
}

int slrn_read_integer (char *prompt, int *dflt, int *np)
{
   char buf[256];
   char str[256];
   int n;
   
   if (dflt != NULL)
     {
	sprintf (buf, "%s (default: %d) ", prompt, *dflt);
     }
   else strcpy (buf, prompt);
   
   *str = 0;
   if (-1 == (n = slrn_read_input (buf, str, 1)))
     {
	slrn_error ("Abort!");
	return -1;
     }
   
   if (1 != sscanf(str, "%d", &n))
     {
	if ((*str == 0) && (dflt != NULL)) n = *dflt;
	else
	  {
	     slrn_error ("Integer expected.");
	     return -1;
	  }
     }
   *np = n;
   return 0;
}

int slrn_mail_file (char *file, int edit, unsigned int editline, char *to, char *subject)
{
   char buf[256];
   
   if (edit)
     {
	if (slrn_edit_file (file, editline) < 0) return -1;
	
	while (1)
	  {
	     char rsp;
	     
	     rsp = slrn_get_response ("yYnNeE", "Mail the message? y/n/e(dit)");
	     rsp |= 0x20;
	     if (rsp == 'n') return -1;
	     if (rsp == 'y') break;
	     if (slrn_edit_file (file, 1) < 0) return -1;
	  }
     }
   slrn_message ("Sending..."); slrn_smg_refresh ();
   
#ifdef VMS
   sprintf(buf, "%s\"%s\"", MAIL_PROTOCOL, to);
   vms_send_mail( buf, subject, file );
#else
   /* What I need to do is to open the file and feed it line by line to the
    * sendmail program.  This way I can strip out blank headers.
    */
   if (Slrn_Use_Mime)
     {
	FILE *fp, *pp;
	int header = 1;
	char line[1024];
	
	fp = fopen (file, "r");
	if (fp == NULL) return (-1);
	
	slrn_mime_scan_file (fp);
	
	pp = slrn_popen (Slrn_SendMail_Command, "w");
	if (pp == NULL)
	  {
	     slrn_fclose (fp);
	     return (-1);
	  }
	
	while (fgets (line, sizeof(line), fp) != NULL)
	  {
	     int len = strlen (line);
	     
	     line[len - 1] = 0;
	     if (header)
	       {
		  if (line[0] == 0)
		    {
		       header = 0;
		       
		       slrn_mime_add_headers (pp);
		       fp = slrn_mime_encode (fp);
		    }
		  slrn_mime_header_encode (line, sizeof(line));
	       }
	     fputs (line, pp);
	     putc('\n', pp);
	  }
	slrn_pclose (pp);
	slrn_fclose (fp);
     }
   else
     {
#ifdef __os2__
	sprintf (buf, "%s -af %s", Slrn_SendMail_Command, file);
#else
	sprintf (buf, "%s < %s", Slrn_SendMail_Command, file);
#endif
	slrn_posix_system (buf, 0);
     }
#endif /* NOT VMS */
   slrn_message ("Sending...done");
   return 0;
}

char *slrn_fix_regexp (char *pat)
{
   static char newpat[256];
   char *p, ch;
   
   p = newpat;
   *p++ = '^';
   while ((ch = *pat++) != 0)
     {
	if (ch == '.')
	  {
	     *p++ = '\\';
	  }
	else if (ch == '*')
	  {
	     *p++ = '.';
	  }
	*p++ = ch;
     }
   *p = 0;
   return newpat;
}


SLRegexp_Type *slrn_compile_regexp_pattern (char *pat)
{
   static unsigned char compiled_pattern_buf [512];
   static SLRegexp_Type re;
   
   re.pat = (unsigned char *) pat;
   re.buf = compiled_pattern_buf;
   re.buf_len = sizeof (compiled_pattern_buf);
   re.case_sensitive = 0;
   
   if (0 != SLang_regexp_compile (&re))
     {
	slrn_error ("Invalid regular expression or expression too long.");
	return NULL;
     }
   
   
   return &re;
}

unsigned char *slrn_regexp_match (SLRegexp_Type *re, char *str)
{
   unsigned int len;
   
   if ((str == NULL)
       || (re->min_length > (len = strlen (str))))
     return NULL;
   
   return SLang_regexp_match ((unsigned char *)str, len, re);
}


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 (stat(file, &st) < 0) return 0;
   m = st.st_mode;
   
   if (S_ISDIR(m)) return (2);
   return 1;
}


void slrn_get_mouse_rc (int *rp, int *cp)
{
   int r, c;
   
   c = (unsigned char) SLang_getkey () - 32;
   r = (unsigned char) SLang_getkey () - 32;
   if (cp != NULL) *cp = c;
   if (rp != NULL) *rp = r;
}

#if SLRN_HAS_PIPING
int slrn_pclose (FILE *fp)
{
   int ret;
   if (fp == NULL) return -1;
   ret = pclose (fp);
   if (ret)
     {
	char buf[256];
	fprintf (stderr, "Command returned non-zero exit status.  Press RETURN.\n");
	fgets (buf, 255, stdin);
     }
   
   slrn_init_display (3, 0);
   return 0;
}

FILE *slrn_popen (char *cmd, char *mode)
{
   FILE *fp;
   
   slrn_reset_display (0);
   fp = popen (cmd, mode);
   
   if (fp == NULL)
     {
	char buf[256];
	fprintf (stderr, "Command %s failed to run.  Press RETURN.\n", cmd);
	fgets (buf, 255, stdin);
	slrn_init_display (3, 0);
     }
   return fp;
}
#endif

int slrn_delete_file (char *f)
{
#ifdef VMS
   return delete(f);
#else
   return unlink(f);
#endif
}


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;
}


int slrn_fclose (FILE *fp)
{
   if (0 == fclose (fp)) return 0;
   slrn_error ("Error closing file.  File system full? (errno = %d)", errno);
   return -1;
}


void slrn_do_key (SLKeyMap_List_Type *map)
{
   SLang_Key_Type *key;
   static SLKeyMap_List_Type *last_map;
   static SLang_Key_Type *last_key;
   
   key = SLang_do_key (map, (int (*)(void)) SLang_getkey);
   if (Slrn_Message_Present || SLang_Error) 
     {
#if SLRN_HAS_SLANG
	if (SLang_Error) SLang_restart (0);
#endif
	slrn_clear_message ();
     }
   SLang_Error = SLKeyBoard_Quit = 0;
   
   if ((key == NULL) || (key->type == 0))
     {
	SLtt_beep ();
	return;
     }
   
   if (key->type == SLKEY_F_INTRINSIC)
     {
	if ((map == last_map) && (key->f.f == (FVOID_STAR) slrn_repeat_last_key))
	  key = last_key;
	
	/* set now to avoid problems with recursive call */
	last_key = key;
	last_map = map;
	
	if (key->type == SLKEY_F_INTRINSIC)
	  {
	     (((void (*)(void))(key->f.f)) ());
	     return;
	  }
     }

   /* Otherwise we have interpreted key. */
#if SLRN_HAS_SLANG
   
   last_key = key;
   last_map = map;

   Slrn_Full_Screen_Update = 1;
   
   if ((*key->f.s == '.')
       || !SLang_execute_function (key->f.s))
     SLang_load_string(key->f.s);
#endif
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.