uulib.c

来自「UUDeview是一个编码解码器」· C语言 代码 · 共 1,274 行 · 第 1/2 页

C
1,274
字号
/* * This file is part of uudeview, the simple and friendly multi-part multi- * file uudecoder  program  (c) 1994-2001 by Frank Pilhofer. The author may * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *//* * This file implements the externally visible functions, as declared * in uudeview.h, and some internal interfacing functions */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef SYSTEM_WINDLL#include <windows.h>#endif#ifdef SYSTEM_OS2#include <os2.h>#endif#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef STDC_HEADERS#include <stdlib.h>#include <stdarg.h>#include <string.h>#else#ifdef HAVE_STDARG_H#include <stdarg.h>#else#ifdef HAVE_VARARGS_H#include <varargs.h>#endif#endif#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif/* to get open() in Windows */#ifdef HAVE_IO_H#include <io.h>#endif#include <uudeview.h>#include <uuint.h>#include <fptools.h>#include <uustring.h>char * uulib_id = "$Id: uulib.c,v 1.28 2003/09/29 23:27:47 fp Exp $";#ifdef SYSTEM_WINDLLBOOL _export WINAPI DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,	       LPVOID lpCmdLine){  /* Don't do anything, so just return true */  return TRUE;}#endif/* * In DOS, we must open the file binary, O_BINARY is defined there */#ifndef O_BINARY#define O_BINARY      0#endif/* for braindead systems */#ifndef SEEK_SET#ifdef L_BEGIN#define SEEK_SET L_BEGIN#else#define SEEK_SET 0#endif#endif/* * Callback functions and their opaque arguments */void   (*uu_MsgCallback)  _ANSI_ARGS_((void *, char *, int))         = NULL;int    (*uu_BusyCallback) _ANSI_ARGS_((void *, uuprogress *))        = NULL;int    (*uu_FileCallback) _ANSI_ARGS_((void *, char *, char *, int)) = NULL;char * (*uu_FNameFilter)  _ANSI_ARGS_((void *, char *))              = NULL;void *uu_MsgCBArg  = NULL;void *uu_BusyCBArg = NULL;void *uu_FileCBArg = NULL;void *uu_FFCBArg   = NULL;/* * Global variables */int uu_fast_scanning = 0;	/* assumes at most 1 part per file          */int uu_bracket_policy = 0;	/* gives part numbers in [] higher priority */int uu_verbose = 1;		/* enables/disables messages&notes          */int uu_desperate = 0;		/* desperate mode                           */int uu_ignreply = 0;		/* ignore replies                           */int uu_debug = 0;		/* debugging mode (print __FILE__/__LINE__) */int uu_errno = 0;		/* the errno that caused this UURET_IOERR   */int uu_dumbness = 0;		/* switch off the program's intelligence    */int uu_overwrite = 1;		/* whether it's ok to overwrite ex. files   */int uu_ignmode = 0;		/* ignore the original file mode            */int uu_handletext = 0;		/* do we want text/plain messages           */int uu_usepreamble = 0;		/* do we want Mime preambles/epilogues      */int uu_tinyb64 = 0;		/* detect short B64 outside of MIME         */int uu_remove_input = 0;        /* remove input files after decoding        */int uu_more_mime = 0;           /* strictly adhere to MIME headers          */headercount hlcount = {  3,			        /* restarting after a MIME body             */  2,                            /* after useful data in freestyle mode      */  1                             /* after useful data and an empty line      */};/* * version string */char uulibversion[256] = VERSION "pl" PATCH;/* * prefix to the files on disk, usually a path name to save files to */char *uusavepath;/* * extension to use when encoding single-part files */char *uuencodeext;/* * areas to malloc */char *uulib_msgstring;char *uugen_inbuffer;char *uugen_fnbuffer;/* * The Global List of Files */uulist *UUGlobalFileList = NULL;/* * time values for BusyCallback. msecs is MILLIsecs here */static long uu_busy_msecs = 0;	/* call callback function each msecs */static long uu_last_secs  = 0;	/* secs  of last call to callback */static long uu_last_usecs = 0;	/* usecs of last call to callback *//* * progress information */uuprogress progress;/* * Linked list of files we want to delete after decoding */typedef struct _itbd {  char *fname;  struct _itbd *NEXT;} itbd;static itbd * ftodel = NULL;/* * for the busy poll */unsigned long uuyctr;/* * Areas to allocate. Instead of using static memory areas, we malloc() * the memory in UUInitialize() and release them in UUCleanUp to prevent * blowing up of the binary size * This is a table with the pointers to allocate and required sizes. * They are guaranteed to be never NULL. */typedef struct {  char **ptr;  size_t size;} allomap;static allomap toallocate[] = {  { &uugen_fnbuffer,    1024 },  /* generic filename buffer */  { &uugen_inbuffer,    1024 },  /* generic input data buffer */  { &uucheck_lastname,   256 },	 /* from uucheck.c */  { &uucheck_tempname,   256 },  { &uuestr_itemp,       256 },  /* from uuencode.c:UUEncodeStream() */  { &uuestr_otemp,      1024 },  { &uulib_msgstring,   1024 },  /* from uulib.c:UUMessage() */  { &uuncdl_fulline,     300 },  /* from uunconc.c:UUDecodeLine() */  { &uuncdp_oline,      1200 },  /* from uunconc.c:UUDecodePart() */  { &uunconc_UUxlat,     256 * sizeof (int) },  /* from uunconc.c:toplevel */  { &uunconc_UUxlen,      64 * sizeof (int) },  { &uunconc_B64xlat,    256 * sizeof (int) },  { &uunconc_XXxlat,     256 * sizeof (int) },  { &uunconc_BHxlat,     256 * sizeof (int) },  { &uunconc_save,     3*300 },  /* from uunconc.c:decoding buffer */  { &uuscan_shlline,    1024 },  /* from uuscan.c:ScanHeaderLine() */  { &uuscan_shlline2,   1024 },  /* from uuscan.c:ScanHeaderLine() */  { &uuscan_pvvalue,     300 },  /* from uuscan.c:ParseValue() */  { &uuscan_phtext,      300 },  /* from uuscan.c:ParseHeader() */  { &uuscan_sdline,      300 },  /* from uuscan.c:ScanData() */  { &uuscan_sdbhds1,     300 },  { &uuscan_sdbhds2,     300 },  { &uuscan_spline,      300 },  /* from uuscan.c:ScanPart() */  { &uuutil_bhwtmp,      300 },  /* from uuutil.c:UUbhwrite() */  { NULL, 0 }};/* * Handle the printing of messages. Works like printf. */#if defined(STDC_HEADERS) || defined(HAVE_STDARG_H)intUUMessage (char *file, int line, int level, char *format, ...)#elseintUUMessage (va_alist)  va_dcl#endif{  char *msgptr;#if defined(STDC_HEADERS) || defined(HAVE_STDARG_H)  va_list ap;  va_start (ap, format);#else  char *file, *format;  int   line, level;  va_list ap;  va_start (ap);  file   = va_arg (ap, char *);  line   = va_arg (ap, int);  level  = va_arg (ap, int);  format = va_arg (ap, char *);#endif  if (uu_debug) {    sprintf (uulib_msgstring, "%s(%d): %s", file, line, msgnames[level]);    msgptr = uulib_msgstring + strlen (uulib_msgstring);  }  else {    sprintf (uulib_msgstring, "%s", msgnames[level]);    msgptr = uulib_msgstring + strlen (uulib_msgstring);  }  if (uu_MsgCallback && (level>UUMSG_NOTE || uu_verbose)) {    vsprintf (msgptr, format, ap);    (*uu_MsgCallback) (uu_MsgCBArg, uulib_msgstring, level);  }  va_end (ap);  return UURET_OK;}/* * Call the Busy Callback from time to time. This function must be * polled from the Busy loops. */intUUBusyPoll (void){#ifdef HAVE_GETTIMEOFDAY  struct timeval tv;  long msecs;  if (uu_BusyCallback) {    (void) gettimeofday (&tv, NULL);    msecs = 1000*(tv.tv_sec-uu_last_secs)+(tv.tv_usec-uu_last_usecs)/1000;    if (uu_last_secs==0 || msecs > uu_busy_msecs) {      uu_last_secs  = tv.tv_sec;      uu_last_usecs = tv.tv_usec;      return (*uu_BusyCallback) (uu_BusyCBArg, &progress);    }  }#else  time_t now;  long msecs;  if (uu_BusyCallback) {    if (uu_busy_msecs <= 0) {      msecs = 1;    }    else {      now   = time(NULL);      msecs = 1000 * (now - uu_last_secs);    }    if (uu_last_secs==0 || msecs > uu_busy_msecs) {      uu_last_secs  = now;      uu_last_usecs = 0;      return (*uu_BusyCallback) (uu_BusyCBArg, &progress);    }  }#endif  return 0;}/* * Initialization function */int UUEXPORTUUInitialize (void){  allomap *aiter;  progress.action     = 0;  progress.curfile[0] = '\0';  ftodel = NULL;  uusavepath  = NULL;  uuencodeext = NULL;  mssdepth = 0;  memset (&localenv, 0, sizeof (headers));  memset (&sstate,   0, sizeof (scanstate));  nofnum    = 0;  mimseqno  = 0;  lastvalid = 0;  lastenc   = 0;  uuyctr    = 0;  /*   * Allocate areas   */  for (aiter=toallocate; aiter->ptr; aiter++)    *(aiter->ptr) = NULL;  for (aiter=toallocate; aiter->ptr; aiter++) {    if ((*(aiter->ptr) = (char *) malloc (aiter->size)) == NULL) {      /*       * oops. we may not print a message here, because we need these       * areas (uulib_msgstring) in UUMessage()       */      for (aiter=toallocate; aiter->ptr; aiter++) {	_FP_free (*(aiter->ptr));      }      return UURET_NOMEM;    }  }  /*   * Must be called after areas have been malloced   */  UUInitConc ();  return UURET_OK;}/* * Set and get Options */int UUEXPORTUUGetOption (int option, int *ivalue, char *cvalue, int clength){  int result;  switch (option) {  case UUOPT_VERSION:    _FP_strncpy (cvalue, uulibversion, clength);    result = 0;    break;  case UUOPT_FAST:    if (ivalue) *ivalue = uu_fast_scanning;    result = uu_fast_scanning;    break;  case UUOPT_DUMBNESS:    if (ivalue) *ivalue = uu_dumbness;    result = uu_dumbness;    break;  case UUOPT_BRACKPOL:    if (ivalue) *ivalue = uu_bracket_policy;    result = uu_bracket_policy;    break;  case UUOPT_VERBOSE:    if (ivalue) *ivalue = uu_verbose;    result = uu_verbose;    break;  case UUOPT_DESPERATE:    if (ivalue) *ivalue = uu_desperate;    result = uu_desperate;    break;  case UUOPT_IGNREPLY:    if (ivalue) *ivalue = uu_ignreply;    result = uu_ignreply;    break;  case UUOPT_DEBUG:    if (ivalue) *ivalue = uu_debug;    result = uu_debug;    break;  case UUOPT_ERRNO:    if (ivalue) *ivalue = uu_errno;    result = uu_errno;    break;  case UUOPT_OVERWRITE:    if (ivalue) *ivalue = uu_overwrite;    result = uu_overwrite;    break;  case UUOPT_SAVEPATH:    _FP_strncpy (cvalue, uusavepath, clength);    result = 0;    break;  case UUOPT_PROGRESS:    if (clength==sizeof(uuprogress)) {      memcpy (cvalue, &progress, sizeof (uuprogress));      result = 0;    }    else      result = -1;    break;  case UUOPT_IGNMODE:    if (ivalue) *ivalue = uu_ignmode;    result = uu_ignmode;    break;  case UUOPT_USETEXT:    if (ivalue) *ivalue = uu_handletext;    result = uu_handletext;    break;  case UUOPT_PREAMB:    if (ivalue) *ivalue = uu_usepreamble;    result = uu_usepreamble;    break;  case UUOPT_TINYB64:    if (ivalue) *ivalue = uu_tinyb64;    result = uu_tinyb64;    break;  case UUOPT_ENCEXT:    _FP_strncpy (cvalue, uuencodeext, clength);    result = 0;    break;  case UUOPT_REMOVE:    if (ivalue) *ivalue = uu_remove_input;    result = uu_remove_input;    break;  case UUOPT_MOREMIME:    if (ivalue) *ivalue = uu_more_mime;    result = uu_more_mime;    break;  default:    return -1;  }  return result;}int UUEXPORTUUSetOption (int option, int ivalue, char *cvalue){  switch (option) {  case UUOPT_FAST:    uu_fast_scanning  = ivalue;    break;  case UUOPT_DUMBNESS:    uu_dumbness       = ivalue;    break;  case UUOPT_BRACKPOL:    uu_bracket_policy = ivalue;    break;  case UUOPT_VERBOSE:    uu_verbose        = ivalue;    break;  case UUOPT_DESPERATE:    uu_desperate      = ivalue;    break;  case UUOPT_IGNREPLY:    uu_ignreply       = ivalue;    break;  case UUOPT_DEBUG:    uu_debug          = ivalue;    break;  case UUOPT_OVERWRITE:    uu_overwrite      = ivalue;    break;  case UUOPT_SAVEPATH:    _FP_free (uusavepath);    uusavepath = _FP_strdup (cvalue);    break;  case UUOPT_IGNMODE:    uu_ignmode = ivalue;    break;  case UUOPT_USETEXT:    uu_handletext = ivalue;    break;  case UUOPT_PREAMB:    uu_usepreamble = ivalue;    break;  case UUOPT_TINYB64:    uu_tinyb64 = ivalue;    break;  case UUOPT_ENCEXT:    _FP_free (uuencodeext);    uuencodeext = _FP_strdup (cvalue);    break;  case UUOPT_REMOVE:    uu_remove_input = ivalue;    break;  case UUOPT_MOREMIME:    uu_more_mime = ivalue;    break;  default:    return UURET_ILLVAL;  }  return UURET_OK;}char * UUEXPORTUUstrerror (int code){  return uuretcodes[code];}/* * Set the various Callback functions */int UUEXPORTUUSetMsgCallback (void *opaque, 		  void (*func) _ANSI_ARGS_((void *, char *, int))){  uu_MsgCallback = func;  uu_MsgCBArg    = opaque;  return UURET_OK;}int UUEXPORTUUSetBusyCallback (void *opaque,		   int (*func) _ANSI_ARGS_((void *, uuprogress *)),		   long msecs){  uu_BusyCallback = func;  uu_BusyCBArg    = opaque;  uu_busy_msecs   = msecs;  return UURET_OK;}int UUEXPORTUUSetFileCallback (void *opaque,		   int (*func) _ANSI_ARGS_((void *, char *, char *, int))){  uu_FileCallback = func;  uu_FileCBArg    = opaque;  return UURET_OK;}int UUEXPORTUUSetFNameFilter (void *opaque,		  char * (*func) _ANSI_ARGS_((void *, char *))){  uu_FNameFilter = func;  uu_FFCBArg     = opaque;  return UURET_OK;}/* * Return a pointer to the nth element of the GlobalFileList * zero-based, returns NULL if item is too large. */uulist * UUEXPORTUUGetFileListItem (int item){  uulist *iter=UUGlobalFileList;  if (item < 0)    return NULL;  while (item && iter) {    iter = iter->NEXT;    item--;  }  return iter;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?