home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xmail / part06 < prev    next >
Encoding:
Text File  |  1993-04-27  |  57.1 KB  |  1,639 lines

  1. Newsgroups: comp.sources.x
  2. From: markham@cadence.com (Jeff Markham)
  3. Subject: v19i031:  xmail - X Window System interface to the mail program, Part06/10
  4. Message-ID: <1993Mar10.202924.11037@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4128d6ffa5af6933a1bdecde395edd9e
  6. Date: Wed, 10 Mar 1993 20:29:24 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: markham@cadence.com (Jeff Markham)
  10. Posting-number: Volume 19, Issue 31
  11. Archive-name: xmail/part06
  12. Environment: X11
  13. Supersedes: xmail: Volume 15, Issue 18-26
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  Makefile.IBMRT environs.c parser.c
  20. # Wrapped by chris@sparky on Wed Mar 10 14:17:48 1993
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 6 (of 10)."'
  24. if test -f 'Makefile.IBMRT' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'Makefile.IBMRT'\"
  26. else
  27.   echo shar: Extracting \"'Makefile.IBMRT'\" \(11852 characters\)
  28.   sed "s/^X//" >'Makefile.IBMRT' <<'END_OF_FILE'
  29. X# Makefile generated by imake - do not edit!
  30. X# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
  31. X#
  32. X# The cpp used on this machine replaces all newlines and multiple tabs and
  33. X# spaces in a macro expansion with a single space.  Imake tries to compensate
  34. X# for this, but is not always successful.
  35. X#
  36. X
  37. X###########################################################################
  38. X# Makefile generated from "Imake.tmpl" and <Imakefile>
  39. X# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
  40. X#
  41. X# Platform-specific parameters may be set in the appropriate .cf
  42. X# configuration files.  Site-wide parameters may be set in the file
  43. X# site.def.  Full rebuilds are recommended if any parameters are changed.
  44. X#
  45. X# If your C preprocessor doesn't define any unique symbols, you'll need
  46. X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
  47. X# "make Makefile", "make Makefiles", or "make World").
  48. X#
  49. X# If you absolutely can't get imake to work, you'll need to set the
  50. X# variables at the top of each Makefile as well as the dependencies at the
  51. X# bottom (makedepend will do this automatically).
  52. X#
  53. X
  54. X###########################################################################
  55. X# platform-specific configuration parameters - edit sun.cf to change
  56. X
  57. X# platform:  $XConsortium: sun.cf,v 1.38 89/12/23 16:10:10 jim Exp $
  58. X# operating system:  SunOS 4.0.3
  59. X
  60. X###########################################################################
  61. X# site-specific configuration parameters - edit site.def to change
  62. X
  63. X# site:  $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $
  64. X
  65. X            SHELL = /bin/sh
  66. X
  67. X              TOP = .
  68. X      CURRENT_DIR = .
  69. X
  70. X               AR = ar cq
  71. X  BOOTSTRAPCFLAGS =
  72. X               CC = cc
  73. X
  74. X         COMPRESS = compress
  75. X              CPP = /lib/cpp $(STD_CPP_DEFINES)
  76. X    PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
  77. X          INSTALL = install
  78. X               LD = ld
  79. X             LINT = lint
  80. X      LINTLIBFLAG = -C
  81. X         LINTOPTS = -axz
  82. X               LN = ln -s
  83. X             MAKE = make
  84. X               MV = mv
  85. X               CP = cp
  86. X           RANLIB = ranlib
  87. X  RANLIBINSTFLAGS =
  88. X               RM = rm -f
  89. X     STD_INCLUDES =
  90. X  STD_CPP_DEFINES = -DSYSV -DAIXV3
  91. X      STD_DEFINES = -DSYSV -DAIXV3
  92. X EXTRA_LOAD_FLAGS = -bnodelcsect
  93. X  EXTRA_LIBRARIES =
  94. X             TAGS = ctags
  95. X
  96. X    SHAREDCODEDEF = -DSHAREDCODE
  97. X         SHLIBDEF = -DSUNSHLIB
  98. X
  99. X    PROTO_DEFINES =
  100. X
  101. X     INSTPGMFLAGS = -s -m 0755
  102. X
  103. X     INSTBINFLAGS = -m 0755
  104. X     INSTUIDFLAGS = -m 4755
  105. X     INSTLIBFLAGS = -m 0664
  106. X     INSTINCFLAGS = -m 0444
  107. X     INSTMANFLAGS = -m 0444
  108. X     INSTDATFLAGS = -m 0444
  109. X    INSTKMEMFLAGS = -m 4755
  110. X
  111. X          DESTDIR =
  112. X
  113. X     TOP_INCLUDES = -I/n/X11/R5/Binaries/include -I$(INCROOT)
  114. X
  115. X      CDEBUGFLAGS = -g
  116. X        CCOPTIONS =
  117. X      COMPATFLAGS =
  118. X
  119. X      ALLINCLUDES = $(STD_INCLUDES) $(TOP_INCLUDES) $(INCLUDES) $(EXTRA_INCLUDES)
  120. X       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
  121. X           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
  122. X        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
  123. X           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
  124. X        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS)
  125. X   LDCOMBINEFLAGS = -X -r
  126. X
  127. X        MACROFILE = sun.cf
  128. X           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
  129. X
  130. X    IMAKE_DEFINES =
  131. X
  132. X         IRULESRC = $(CONFIGDIR)
  133. X        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
  134. X
  135. X     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
  136. X            $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
  137. X            $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
  138. X
  139. X###########################################################################
  140. X# X Window System Build Parameters
  141. X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
  142. X
  143. X###########################################################################
  144. X# X Window System make variables; this need to be coordinated with rules
  145. X# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
  146. X
  147. X          PATHSEP = /
  148. X        USRLIBDIR = $(DESTDIR)/usr/lib
  149. X           BINDIR = $(DESTDIR)/usr/bin/X11
  150. X          INCROOT = $(DESTDIR)/usr/include
  151. X     BUILDINCROOT = $(TOP)
  152. X      BUILDINCDIR = $(BUILDINCROOT)/X11
  153. X      BUILDINCTOP = ..
  154. X           INCDIR = $(INCROOT)/X11
  155. X           ADMDIR = $(DESTDIR)/usr/adm
  156. X           LIBDIR = $(USRLIBDIR)/X11
  157. X        CONFIGDIR = $(LIBDIR)/config
  158. X       LINTLIBDIR = $(USRLIBDIR)/lint
  159. X
  160. X          FONTDIR = $(LIBDIR)/fonts
  161. X         XINITDIR = $(LIBDIR)/xinit
  162. X           XDMDIR = $(LIBDIR)/xdm
  163. X           AWMDIR = $(LIBDIR)/awm
  164. X           TWMDIR = $(LIBDIR)/twm
  165. X           GWMDIR = $(LIBDIR)/gwm
  166. X          MANPATH = $(DESTDIR)/usr/man
  167. X    MANSOURCEPATH = $(MANPATH)/man
  168. X           MANDIR = $(MANSOURCEPATH)n
  169. X        LIBMANDIR = $(MANSOURCEPATH)3
  170. X      XAPPLOADDIR = $(LIBDIR)/app-defaults
  171. X
  172. X        SOXLIBREV = 4.2
  173. X          SOXTREV = 4.0
  174. X         SOXAWREV = 4.0
  175. X        SOOLDXREV = 4.0
  176. X         SOXMUREV = 4.0
  177. X        SOXEXTREV = 4.0
  178. X
  179. X       FONTCFLAGS = -t
  180. X
  181. X     INSTAPPFLAGS = $(INSTDATFLAGS)
  182. X
  183. X            IMAKE = imake
  184. X           DEPEND = makedepend
  185. X              RGB = rgb
  186. X            FONTC = bdftosnf
  187. X        MKFONTDIR = mkfontdir
  188. X        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier.sh
  189. X
  190. X        CONFIGSRC = $(TOP)/config
  191. X        CLIENTSRC = $(TOP)/clients
  192. X          DEMOSRC = $(TOP)/demos
  193. X           LIBSRC = $(TOP)/lib
  194. X          FONTSRC = $(TOP)/fonts
  195. X       INCLUDESRC = $(TOP)/X11
  196. X        SERVERSRC = $(TOP)/server
  197. X          UTILSRC = $(TOP)/util
  198. X        SCRIPTSRC = $(UTILSRC)/scripts
  199. X       EXAMPLESRC = $(TOP)/examples
  200. X       CONTRIBSRC = $(TOP)/../contrib
  201. X           DOCSRC = $(TOP)/doc
  202. X           RGBSRC = $(TOP)/rgb
  203. X        DEPENDSRC = $(UTILSRC)/makedepend
  204. X         IMAKESRC = $(CONFIGSRC)
  205. X         XAUTHSRC = $(LIBSRC)/Xau
  206. X          XLIBSRC = $(LIBSRC)/X
  207. X           XMUSRC = $(LIBSRC)/Xmu
  208. X       TOOLKITSRC = $(LIBSRC)/Xt
  209. X       AWIDGETSRC = $(LIBSRC)/Xaw
  210. X       OLDXLIBSRC = $(LIBSRC)/oldX
  211. X      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
  212. X      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
  213. X     MKFONTDIRSRC = $(FONTSRC)/mkfontdir
  214. X     EXTENSIONSRC = $(TOP)/extensions
  215. X
  216. X  DEPEXTENSIONLIB = $(USRLIBDIR)/libXext.a
  217. X     EXTENSIONLIB =  -lXext
  218. X
  219. X          DEPXLIB = $(DEPEXTENSIONLIB)
  220. X             XLIB = $(EXTENSIONLIB) -lX11
  221. X
  222. X      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
  223. X         XAUTHLIB =  -lXau
  224. X
  225. X        DEPXMULIB =
  226. X           XMULIB = -lXmu
  227. X
  228. X       DEPOLDXLIB =
  229. X          OLDXLIB = -loldX
  230. X
  231. X      DEPXTOOLLIB =
  232. X         XTOOLLIB = -lXt
  233. X
  234. X        DEPXAWLIB =
  235. X           XAWLIB = -lXaw
  236. X
  237. X LINTEXTENSIONLIB = $(USRLIBDIR)/llib-lXext.ln
  238. X         LINTXLIB = $(USRLIBDIR)/llib-lX11.ln
  239. X          LINTXMU = $(USRLIBDIR)/llib-lXmu.ln
  240. X        LINTXTOOL = $(USRLIBDIR)/llib-lXt.ln
  241. X          LINTXAW = $(USRLIBDIR)/llib-lXaw.ln
  242. X
  243. X          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
  244. X
  245. X         DEPLIBS1 = $(DEPLIBS)
  246. X         DEPLIBS2 = $(DEPLIBS)
  247. X         DEPLIBS3 = $(DEPLIBS)
  248. X
  249. X      USRINCDIR = $(DESTDIR)/usr/include
  250. X        TESTSRC = $(TOP)/tests
  251. X    MTOOLKITSRC = $(LIBSRC)/Xt
  252. X     MWIDGETSRC = $(LIBSRC)/Xm
  253. X   MRESOURCESRC = $(LIBSRC)/Mrm
  254. X         UILSRC = $(CLIENTSRC)/uil
  255. X            UIL = $(UILSRC)/uil
  256. X      XMTOOLLIB = $(MTOOLKITSRC)/libXt.a
  257. X          XMLIB = $(MWIDGETSRC)/libXm.a
  258. X   MRESOURCELIB = $(MRESOURCESRC)/libMrm.a
  259. X         UILLIB = $(UILSRC)/libUil.a
  260. X  LINTMRESOURCE = $(MRESOURCESRC)/libMrm.a
  261. XLINTXMWIDGETLIB = $(MWIDGETSRC)/llib-l/Xm.ln
  262. X     LINTXMTOOL = $(MTOOLKITSRC)/llib-lXt.ln
  263. X     LINTUILLIB = $(UILSRC)/llib-lUil.ln
  264. X        SYSLIBS = -lXt -lX11
  265. X    MWM_DEFINES = -DSHAPE -DOPAQUE -DSTRINGS_ALIGNED -D_NO_PROTO -DNO_REGEX
  266. X
  267. X###########################################################################
  268. X# Imake rules for building libraries, programs, scripts, and data files
  269. X# rules:  $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
  270. X
  271. X###########################################################################
  272. X# start of Imakefile
  273. X
  274. X#
  275. X# @(#)Imakefile - for xmail version 1 patchlevel 5
  276. X#
  277. X# Uncomment USE_DIRENT if readdir() uses <dirent.h> instead of <sys/dir.h>
  278. X#
  279. X     USE_DIRENT = -DUSE_DIRENT
  280. X#
  281. X# Uncomment X_FACE and COMPFACE if you have the compface library installed
  282. X# and you want xmail to automatically display the X-Face: header, if found
  283. X# in a message.
  284. X#
  285. X         X_FACE = -DX_FACE
  286. X       COMPFACE = -lcompface
  287. X#
  288. X# Uncomment XPM if you have the Xpm version 3 library and want color icons
  289. X#
  290. X            XPM = -DXPM
  291. X         LIBXPM = -lXpm
  292. X#
  293. X# Uncomment LPT if you require att environment support for pseudo ports.
  294. X#
  295. X#            LPT = -lpt
  296. X#
  297. X# Uncomment REGEXP if your system supplies the regexp.h include file.
  298. X# Otherwise, xmail will use the regex procedures re_comp and re_exec.
  299. X#
  300. X#   REGEXP = -DUSE_REGEXP
  301. X#
  302. X# Define MAILBOX_DIRECTORY if your mail spool is located in other than the
  303. X# default /usr/spool/mail.  (If not specified, the default will be used.)
  304. X#
  305. X#    MAILBOX_DIR = -DMAILBOX_DIRECTORY=\"/usr/spool/mail\"
  306. X#
  307. X# Define DEFAULT_VISUAL if your copy of vi lies in some place other than
  308. X# /usr/ucb.  (If not specified, /usr/ucb/vi will be the default editor.)
  309. X#
  310. X#     DEF_VISUAL = -DDEFAULT_VISUAL=\"/usr/ucb/vi\"
  311. X#
  312. X# Define DEFAULT_MAILER if your mail program is not the standard
  313. X# /usr/ucb/Mail.  CAUTION - Operation is NOT guaranteed with other mailers.
  314. X#
  315. X#     DEF_MAILER = -DDEFAULT_MAILER=\"/usr/ucb/Mail\"
  316. X#
  317. X# Define SIGACTION if your system utilizes the sigaction() call rather
  318. X# than the sigvec() call (true on most SYSV and POSIX compilant systems)
  319. X# You may also need to add the following BSD define (true on SGI systems)
  320. X#
  321. X#         SIGDEF = -D_BSD_SIGNALS
  322. X#
  323. X#         SIGACT = -DSIGACTION
  324. X#
  325. X
  326. X  XMAIL_DEFINES = $(MAILBOX_DIR) $(DEF_VISUAL) $(DEF_MAILER) $(SIGACT) $(SIGDEF)
  327. X        DEFINES = $(USE_DIRENT) $(X_FACE) $(XPM) $(REGEXP) $(XMAIL_DEFINES)
  328. X
  329. X        DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
  330. XLOCAL_LIBRARIES = -L/n/X11/R5/Binaries/lib/ibmrt $(LIBXPM) -L/n/X11/R5/Binaries/lib/ibmrt $(XAWLIB) -L/n/X11/R5/Binaries/lib/ibmrt $(XMULIB) -L/n/X11/R5/Binaries/lib/ibmrt $(XTOOLLIB) -L/n/X11/R5/Binaries/lib/ibmrt $(XLIB) -L/n/X11/R5/Binaries/lib/ibmrt $(COMPFACE) $(LPT)
  331. X
  332. X           SRCS = Mailwatch.c HelpText.c actions.c callMail.c callbacks.c \
  333. X          confirm.c directory.c environs.c handler.c mail.c parser.c \
  334. X          utils.c windows.c xmail.c
  335. X
  336. X           OBJS = Mailwatch.o HelpText.o actions.o callMail.o callbacks.o \
  337. X          confirm.o directory.o environs.o handler.o mail.o parser.o \
  338. X          utils.o windows.o xmail.o
  339. X
  340. X PROGRAM = xmail
  341. X
  342. Xall:: xmail
  343. X
  344. Xxmail: $(OBJS) $(DEPLIBS)
  345. X    $(RM) $@
  346. X    $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
  347. X
  348. Xinstall:: xmail
  349. X    $(INSTALL) -c $(INSTPGMFLAGS)   xmail $(BINDIR)
  350. X
  351. Xinstall.man:: xmail.man
  352. X    $(INSTALL) -c $(INSTMANFLAGS) xmail.man $(MANDIR)/xmail.n
  353. X
  354. Xdepend::
  355. X    $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
  356. X
  357. Xlint:
  358. X    $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
  359. Xlint1:
  360. X    $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
  361. X
  362. Xclean::
  363. X    $(RM) $(PROGRAM)
  364. X
  365. Xinstall:: XMail.ad
  366. X    $(INSTALL) -c $(INSTAPPFLAGS) XMail.ad $(XAPPLOADDIR)/XMail
  367. X
  368. X###########################################################################
  369. X# common rules for all Makefiles - do not edit
  370. X
  371. Xemptyrule::
  372. X
  373. Xclean::
  374. X    $(RM_CMD) \#*
  375. X
  376. XMakefile::
  377. X    -@if [ -f Makefile ]; then \
  378. X    echo "    $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
  379. X    $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
  380. X    else exit 0; fi
  381. X    $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
  382. X
  383. Xtags::
  384. X    $(TAGS) -w *.[ch]
  385. X    $(TAGS) -xw *.[ch] > TAGS
  386. X
  387. X###########################################################################
  388. X# empty rules for directories that do not have SUBDIRS - do not edit
  389. X
  390. Xinstall::
  391. X    @echo "install in $(CURRENT_DIR) done"
  392. X
  393. Xinstall.man::
  394. X    @echo "install.man in $(CURRENT_DIR) done"
  395. X
  396. XMakefiles::
  397. X
  398. Xincludes::
  399. X
  400. X###########################################################################
  401. X# dependencies generated by makedepend
  402. X
  403. END_OF_FILE
  404.   if test 11852 -ne `wc -c <'Makefile.IBMRT'`; then
  405.     echo shar: \"'Makefile.IBMRT'\" unpacked with wrong size!
  406.   fi
  407.   # end of 'Makefile.IBMRT'
  408. fi
  409. if test -f 'environs.c' -a "${1}" != "-c" ; then 
  410.   echo shar: Will not clobber existing file \"'environs.c'\"
  411. else
  412.   echo shar: Extracting \"'environs.c'\" \(18935 characters\)
  413.   sed "s/^X//" >'environs.c' <<'END_OF_FILE'
  414. X/*
  415. X * xmail - X window system interface to the mail program
  416. X *
  417. X * Copyright 1990,1991,1992 by National Semiconductor Corporation
  418. X *
  419. X * Permission to use, copy, modify, and distribute this software and its
  420. X * documentation for any purpose is hereby granted without fee, provided that
  421. X * the above copyright notice appear in all copies and that both that
  422. X * copyright notice and this permission notice appear in supporting
  423. X * documentation, and that the name of National Semiconductor Corporation not
  424. X * be used in advertising or publicity pertaining to distribution of the
  425. X * software without specific, written prior permission.
  426. X *
  427. X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  428. X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  429. X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  430. X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  431. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  432. X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  433. X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  434. X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  435. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  436. X * PERFORMANCE OF THIS SOFTWARE.
  437. X *
  438. X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  439. X *
  440. X */
  441. X#include "global.h"
  442. X
  443. Xextern    char    *mailrcFile();
  444. XString        list = NULL;        /* list of aliases */
  445. Xint        list_length;        /* size of alias list */
  446. X
  447. X
  448. X
  449. Xalias_compare(a1, a2)
  450. XAliasRec **a1, **a2;
  451. X{
  452. X return(strcmp((*a1)->name, (*a2)->name));
  453. X}
  454. X
  455. X
  456. X/*
  457. X** @(#)addtobuf() - add text to recipient or file and folder names buffer
  458. X**            drop any leading backslash from a recipient name
  459. X*/
  460. Xvoid
  461. Xaddtobuf(text, buffer, otherBuffer)
  462. Xchar    *text;
  463. Xchar    *buffer;
  464. Xchar    *otherBuffer;
  465. X{
  466. X int    current_line_length;
  467. X char    *last_line;
  468. X
  469. X
  470. X if (strchr("./+|", *text) != NULL) {
  471. X    if (*otherBuffer)
  472. X       (void) strcat(otherBuffer, ",");
  473. X    (void) strcat(otherBuffer, text);
  474. X   } else {
  475. X    if (*buffer) (void) strcat(buffer, ", ");
  476. X    if (last_line = strrchr(buffer, '\t')) last_line++;
  477. X       else last_line = buffer;
  478. X    current_line_length = strlen(last_line);
  479. X    if (current_line_length && current_line_length + strlen(text) > 71) {
  480. X       (void) strcat(buffer, "\n\t");    /* make it a continuation of header */
  481. X      }
  482. X    (void) strcat(buffer, (*text == '\\') ? &text[1] : text);
  483. X   }
  484. X} /* addtobuf */
  485. X
  486. X
  487. X/*
  488. X** @(#) de_alias() - move (possibly) comma separated aliases into buffers
  489. X*/
  490. Xvoid
  491. Xde_alias(text, buffer, otherBuffer)
  492. Xchar    *text;
  493. Xchar    *buffer;
  494. Xchar    *otherBuffer;
  495. X{
  496. X char    *cp, *next_alias, buf[BUFSIZ];
  497. X
  498. X
  499. X if (strchr(text, ',') == NULL)
  500. X    addtobuf(text, buffer, otherBuffer);
  501. X else {
  502. X    (void) strncpy(buf, text, BUFSIZ);
  503. X    for (next_alias = buf; *next_alias; next_alias = cp) {
  504. X        if (cp = strchr(next_alias, ',')) *cp++ = '\0';
  505. X        else cp = next_alias + strlen(next_alias);
  506. X        addtobuf(next_alias, buffer, otherBuffer);
  507. X       }
  508. X   }
  509. X} /* de_alias */
  510. X
  511. X
  512. X/*
  513. X** @(#)alias() - return alias value(s) from mail, or name if no alias found
  514. X*/
  515. Xchar *
  516. Xalias(name)
  517. Xchar    *name;
  518. X{
  519. X int        i, n, testing_for_compound_address;
  520. X char        tmp[BUFSIZ], buf[BUFSIZ];
  521. X String        ep, s, p, value;
  522. X
  523. X
  524. X tmp[0] = '\0';
  525. X if (name)
  526. X    (void) strncpy(tmp, name, BUFSIZ);
  527. X/*
  528. X** If not already done, extract the mail alias list and build the alias table.
  529. X** Provide support for the possibility of multiple names for an alias with or
  530. X** without comma separations.
  531. X*/
  532. X if (! aliases) {
  533. X    if (mailpid) list = XtNewString(QueryMail("alias"));
  534. X    else  if (! (list = XtNewString(GetMailrc("alias")))) {
  535. X                 list = (String) XtMalloc((unsigned) 2);
  536. X                 list[0] = '\0';
  537. X               }
  538. X/*
  539. X** count up the number of aliases in the list and allocate the list size
  540. X*/
  541. X    ep = &list[strlen(list)];
  542. X    for (i = 1, p = list; p < ep; p++) if (*p == '\n') i++;
  543. X    aliases = (AliasRec **) XtMalloc((unsigned) (i + 1) * sizeof(AliasRec *));
  544. X/*
  545. X** Copy the pointers for the alias names and values into an array, marking
  546. X** the ends of each with a null and separating any multiple values with a
  547. X** comma.  Ensure there is no trailing comma in the value list.
  548. X*/
  549. X    for (n = 0, p = list; n < i && p < ep; n++, p++) {
  550. X        aliases[n] = (AliasRec *) XtMalloc((unsigned) sizeof(AliasRec));
  551. X        for (; *p && (*p == ' ' || *p == '\t'); p++);
  552. X        for (aliases[n]->name = p; *p && *p != ' ' && *p != '\t'; p++);
  553. X        for (*p++ = '\0'; *p && strchr(" \t\"\'", *p); p++);
  554. X        testing_for_compound_address = True;
  555. X        for (aliases[n]->alias = p; *p && *p != '\n'; p++) {
  556. X/*
  557. X** If it contains a chevron, parenthesis, or pipe symbol, then just treat
  558. X** the whole line as one alias entry.
  559. X*/
  560. X            if (*p == '|') {
  561. X               if (s = strchr(p, '\n'))
  562. X                  p = s;
  563. X               else p += strlen(p);
  564. X               break;
  565. X              }
  566. X            if (testing_for_compound_address) {
  567. X               if ((s = strchr(p, '<')) || (s = strchr(p, '('))) {
  568. X                  if (value = strchr(p, '\n')) {    /* could be more than one */
  569. X                     if (s < value) {        /* if its within this alias */
  570. X                        p = value;        /* point to end of this alias */
  571. X                        if (*(p - 1) == '"' ||    /* could be true (no mailpid) */
  572. X                            *(p - 1) == '\'')
  573. X                            *(p - 1) = '\0';
  574. X                        break;
  575. X                       } else {
  576. X                        if (*s == '<' && (s = strchr(p, '(')) && s < value) {
  577. X                           p = value;        /* point to end of this alias */
  578. X                           if (*(p - 1) == '"' || /* possibly not in mail */
  579. X                               *(p - 1) == '\'')
  580. X                               *(p - 1) = '\0';
  581. X                           break;
  582. X                          } else testing_for_compound_address = False;
  583. X                       }
  584. X                    } else {            /* last entry of this record */
  585. X                     p += strlen(p);        /* point to the end of line */
  586. X                     break;
  587. X                    }
  588. X                 } else testing_for_compound_address = False;
  589. X              } /* end - if testing_for_compound_address */
  590. X            if ((*p == ' ' || *p == '\t') && *(p+1) && *(p+1) != '\n' &&
  591. X               *(p-1) != *p && *(p-1) != ',') *p = ',';
  592. X           }
  593. X        for (s = p - 1; strchr(", \t", *s); s--);
  594. X        if (strchr(", \t", *++s)) *s = '\0';
  595. X        if (*p) *p = '\0';
  596. X       }
  597. X    aliases[n] = NULL;
  598. X
  599. X    if (n)
  600. X       qsort((char *)aliases, n, sizeof(char *), alias_compare);
  601. X   } /* end - if no alias list */
  602. X/*
  603. X** In deference to those who didn't install the app-defaults file, accept a
  604. X** newline character as a word separator as well as the comma normally found.
  605. X** If input is made up of more than one word, check each word for aliasing.
  606. X** If it contains a chevron or parenthesis, it is a 'compound' address type.
  607. X** If line length approaches 80 characters, add a newline-tab and continue.
  608. X*/
  609. X if (*(value = tmp)) {
  610. X    buf[0] = '\0';
  611. X    for (p = value; *p;) {        /* 'value' points to current 'word' */
  612. X        for (s = p; *s && strchr(", \t\n", *s) == NULL; s++);
  613. X        if (*s) {
  614. X           /*
  615. X           ** First, check for case of possible compound address.
  616. X           ** Could be a form of either: "(user[ ]name) [<]addr[>]",
  617. X           **                            "<addr> [(]user name[)]",
  618. X           ** or                         "[<]addr[>] (user name)".
  619. X           ** If any of these, skip to end of that address/name.
  620. X           */
  621. X           if (strchr(" \t", *s)) {
  622. X              if (*value == '(') {
  623. X                 s = strchr(value, ')');
  624. X                 if (*s) {        /* if form is '(user) addr', skip to */
  625. X                    for (s++; *s && strchr(" \t", *s); s++); /* start of addr */
  626. X                    for (; *s && ! strchr(", \t\n", *s); s++); /* then to end */
  627. X                   }
  628. X                } else if (*value == '<') {
  629. X                 s = strchr(value, '>');
  630. X                 if (*s) {
  631. X                    /*
  632. X                    ** if form is '<addr> [(]user[)]', skip to end of user str
  633. X                    */
  634. X                    for (s++; *s && strchr(" \t", *s); s++);
  635. X                    for (; *s && ! strchr(",\t\n", *s); s++);
  636. X                   }
  637. X                } else {        /* 'addr (usr)|usr <addr>'? find end */
  638. X                 for (; *s && strchr(" \t", *s); s++);
  639. X                 if (! strchr("(<", *s)) s--;    /* NOT one of these, back up */
  640. X                 else {
  641. X                    if (*s == '<')
  642. X                       s = strchr(s, '>');    /* find end of <address> or */
  643. X                    else
  644. X                       s = strchr(s, ')');    /* find end of (user name) */
  645. X                    if (s && *s) s++;
  646. X                   }
  647. X                }
  648. X             }
  649. X           if (s) *s++ = '\0';
  650. X           p = s;
  651. X          } else p = &value[strlen(value)];
  652. X
  653. X        for (n = 0; aliases[n]; n++) {
  654. X            if (strcmp(value, aliases[n]->name) == 0) {
  655. X               de_alias(aliases[n]->alias, buf, otherBuf);
  656. X               break;
  657. X              }
  658. X           }
  659. X
  660. X        if (! aliases[n])    /* If not an alias, use the name supplied. */
  661. X           de_alias(value, buf, otherBuf);
  662. X
  663. X        for (; *p && strchr(", \t\n", *p); p++);
  664. X        value = p;
  665. X       }
  666. X    value = buf;
  667. X   }
  668. X return ((char *)value);
  669. X} /* alias */
  670. X
  671. X/*
  672. X** @(#)GetMailEnv() - Get environment value from mail or shell
  673. X**                    Accommodate the case of trailing blanks on the item.
  674. X**              Expand environment variables.
  675. X*/
  676. Xchar *
  677. XGetMailEnv(item)
  678. XString    item;
  679. X{
  680. X int    length;
  681. X String    ep, mailenv, s, c, value, getenv();
  682. X char        buf[BUFSIZ];
  683. X
  684. X
  685. X value = NULL;
  686. X (void) strcpy(buf, item);
  687. X for (length = 0; buf[length] && buf[length] != ' '; length++);
  688. X buf[length] = '\0';
  689. X
  690. X if (! mailpid) {
  691. X    if (! (value = GetMailrc(buf))) {
  692. X       if ((s = getenv(buf)) != NULL)
  693. X          value = XtNewString(s);
  694. X      }
  695. X   } else {
  696. X    mailenv = QueryMail("set");
  697. X
  698. X    ep = &mailenv[strlen(mailenv)];
  699. X    for (s = mailenv; s < ep && strncmp(s, buf, length) != 0; s++)
  700. X        for (; s < ep && *s != '\n'; s++);
  701. X
  702. X    if (! *s) {
  703. X       if (s = getenv(buf))
  704. X          value = XtNewString(s);
  705. X      } else {
  706. X       /*
  707. X       ** Try to accomodate Berkeley mail (versus SunOS) whose ``set''
  708. X       ** command returns a sorted list with no equal sign between the
  709. X       ** item and its value.
  710. X       */
  711. X       if (c = strchr(s, '\n')) *c = '\0';
  712. X       c = &s[strlen(buf)];            /* point just past the item */
  713. X       if (*c != '=') {                /* We're NOT running Sunmail */
  714. X          for (;(*c == ' ' || *c == '\t'); c++);
  715. X          if (! *c)
  716. X             value = XtNewString("True");    /* use boolean if no value */
  717. X          else {
  718. X             if (! (ep = strchr(c+1, '"')) && ! (ep = strchr(c+1, "'"[0])))
  719. X                value = XtNewString(c);        /* most things will be okay */
  720. X             else {                /* if value is fully quoted */
  721. X                c++;
  722. X                *ep = '\0';
  723. X                value = XtNewString(c);
  724. X               }
  725. X            }
  726. X         } else {                /* We're are running Sunmail */
  727. X          if (! (c = strchr(s, '"'))) c = strchr(s, "'"[0]);
  728. X          s = c;
  729. X          if (! s)            /* variable is flag only, no value */
  730. X             value = XtNewString("True");    /* use boolean if no value */
  731. X          else {
  732. X             for (c = ++s; *c && *c != *(s - 1); c++);
  733. X             length = c - s;
  734. X             value = (String) XtMalloc((unsigned) length + 1);
  735. X             (void) strncpy(value, s, length);
  736. X             value[length] = '\0';
  737. X        }
  738. X     }
  739. X      }
  740. X   }
  741. X  /*
  742. X   * Expand shell variables in value
  743. X   */
  744. X  if (value) {
  745. X     String v, e, nvalue;
  746. X
  747. X     while (s = strchr(value, '$')) {
  748. X        for (c = s + 1; *c && !strchr(" \t\n$/\"\'", *c); c++);
  749. X        length = c - s - 1;
  750. X        (void) strncpy(buf, s + 1, length);
  751. X        buf[length] = '\0';
  752. X        if (*buf == '{') {            /* if variable is braced... */
  753. X           for (v = buf, e = buf + 1; *e && *e != '}';) *v++ = *e++;
  754. X           *v = '\0';
  755. X          }
  756. X        if (!(e = getenv(buf)))
  757. X       e = "";
  758. X        if (nvalue = (String) XtMalloc((unsigned) strlen(value) - length + strlen(e) + 2)) {
  759. X           for (c = nvalue, v = value; v != s;) *c++ = *v++;
  760. X           for (s = e; *s;) *c++ = *s++;
  761. X           for (v += length + 1; *v;) *c++ = *v++;
  762. X           *c = '\0';
  763. X           XtFree((String) value);
  764. X           value = nvalue;
  765. X          }
  766. X       }
  767. X    }
  768. X return(value);
  769. X} /* GetMailEnv */
  770. X
  771. X
  772. X/*
  773. X** @(#)mailrcFile() - Return a path to environment or default .mailrc file
  774. X*/
  775. Xchar *
  776. XmailrcFile()
  777. X{
  778. X char    *s, *getenv();
  779. X char    buf[BUFSIZ];
  780. X
  781. X if (s = getenv("MAILRC"))
  782. X    (void) strcpy(buf, s);
  783. X else
  784. X    (void) sprintf(buf, "%s/.mailrc", HOME);
  785. X
  786. X return((char *)buf);
  787. X} /* mailrcFile */
  788. X
  789. X
  790. X/*
  791. X** @(#)add_to_list - save buffer of aliases in the global alias list
  792. X*/
  793. Xvoid
  794. Xadd_to_list(s)
  795. XString    s;
  796. X{
  797. X if (! list) {
  798. X    list_length = BUFSIZ;
  799. X    list = (String) XtMalloc((unsigned) list_length);
  800. X    list[0] = '\0';
  801. X   }
  802. X
  803. X for (; *s == ' ' || *s == '\t'; s++);        /* skip leading whitespace */
  804. X if (strlen(list) + strlen(s) + 1 >= list_length) {
  805. X    list_length += BUFSIZ;
  806. X    list = (String) XtRealloc(list, list_length);
  807. X   }
  808. X (void) strcat(list, s);            /* append the entire line */
  809. X} /* end - add_to_list */
  810. X
  811. X
  812. X/*
  813. X** @(#)get_mailrc - item and return it's value
  814. X**                  Handle continuation lines, source of additional files, more
  815. X**                  than one occurance of the item, and aliases/groups.
  816. X*/
  817. Xint
  818. Xget_mailrc(item, value, filename)
  819. Xchar    *item;
  820. Xchar    **value;
  821. Xchar    *filename;
  822. X{
  823. X int    unset, n, status = 0;
  824. X int    negated = strncmp(item, "no", 2) == 0 ? 1 : 0;
  825. X int    size = strlen(item) - 2 * negated;
  826. X int    we_want_aliases = (strcmp(item, "alias") == 0);
  827. X String    c, d, getenv(), s = NULL;
  828. X char    e[1], tmp[BUFSIZ], buf[BUFSIZ];
  829. X FILE    *fp = NULL;
  830. X
  831. X
  832. X if ((fp = fopen(filename, "r")) != NULL) {
  833. X    s = fgets(buf, BUFSIZ, fp);
  834. X    while (s) {
  835. X       if (strncmp(buf, "source", 6) == 0) {
  836. X          bcopy(buf + 7, buf, strlen(buf) - 6);
  837. X          LASTCH(buf) = '\0';            /* drop the newline character */
  838. X          if (buf[0] == '$' || (buf[0] == '~' && buf[1] == '/')) {
  839. X             for (unset = 0, n = 1; buf[n] && buf[n] != '/'; n++)
  840. X                 if (! strchr("{()}", buf[n]))
  841. X                    tmp[unset++] = buf[n];
  842. X             tmp[unset] = '\0';
  843. X             if (tmp[0])
  844. X                d = getenv(tmp);
  845. X             else
  846. X                d = HOME;
  847. X             (void) sprintf(tmp, "%s%s", d, &buf[n]);
  848. X             (void) strcpy(buf, tmp);
  849. X            }
  850. X          if ((status = get_mailrc(item, &s, buf))) {
  851. X             if (we_want_aliases) *value = list;
  852. X             else {
  853. X                XtFree((String) *value);
  854. X                *value = s;
  855. X               }
  856. X            } /* end - if something was found in another source */
  857. X         } else {
  858. X          if (we_want_aliases) {
  859. X             if (strncmp(buf,"alias",5) == 0 || strncmp(buf,"group",5) == 0) {
  860. X                status = 1;        /* we have found at least one alias */
  861. X                add_to_list(&buf[5]);
  862. X                if (buf[strlen(buf) - 2] == '\\') {    /* alias is continued */
  863. X                   list[strlen(list) - 2] = '\0';    /* drop the "\\n" */
  864. X                   while (s = fgets(buf, BUFSIZ, fp)) {
  865. X                         if (strlen(s) > 1 && s[strlen(s) - 2] == '\\') {
  866. X                            (void) strcpy(&buf[strlen(buf) - 2], " "); /* drop "\\n" */
  867. X                            add_to_list(s);        /* add continuations */
  868. X                           } else break;
  869. X                        }
  870. X                   if (s) add_to_list(s);    /* don't forget the last line */
  871. X                  } /* end - if this is a continued alias definition line */
  872. X               } /* end - if we found a match */
  873. X             *value = list;
  874. X            } else {        /* I'm looking for 'set' or 'unset' records */
  875. X             if (! (strncmp(buf, "set", 3) && strncmp(buf, "unset", 5))) {
  876. X                unset = (buf[0] == 'u')? 1:0;    /* find out which one matched */
  877. X                s = &buf[(unset?5:3)];        /* starting just beyond 'set' */
  878. X                while (*s) {            /* could be multiple assigns */
  879. X                   for (; *s && strchr(" \t\\\n", *s); s++);    /* next word */
  880. X                   if (*s) {
  881. X                      if ((strncmp(s, item, size) != 0) && (!unset ||
  882. X                         !negated || strncmp(s, &item[2], size) != 0))
  883. X                         for (;*s&&!strchr(" \t\\\n",*s);s++); /* skip item */
  884. X                      else {
  885. X                         status = 1;        /* we have at least one match */
  886. X                         s = s + size;        /* look for a value to it */
  887. X                         if (*s++ != '=') {    /* variable only, no value */
  888. X                            XtFree((String) *value);
  889. X                            *value = (unset && ! negated)? NULL: XtNewString("True");
  890. X                           } else {
  891. X                            if (*s == '"' || *s == "'"[0])    /* if quoted */
  892. X                               for (c = s + 1; *c && *c != *s; c++);
  893. X                            else
  894. X                               for (c = s--; *c && !strchr(" \t\\\n", *c); c++);
  895. X                            e[0] = *c;        /* save the current character */
  896. X                            *c = '\0';        /* mark the end of the value */
  897. X                            d = c + 1;        /* save point after value */
  898. X                            c = s + 1;        /* point to start of value */
  899. X                            XtFree((String) *value);    /* toss any previous */
  900. X                            *value = XtNewString(c);    /* keep latest value */
  901. X                            s = d--;        /* look for any more matches */
  902. X                            *d = e[0];        /* restore saved character */
  903. X                           } /* end - if boolean variable or valued item */
  904. X                        } /* end - we have a match */
  905. X                     } /* end - if some word(s) still exist on the line */
  906. X                   if (! *s && buf[strlen(buf) - 2] == '\\') /* if continued */
  907. X                      s = fgets(buf, BUFSIZ, fp);    /* then keep looking */
  908. X                  } /* end - while examining this set|unset record */
  909. X               } /* end - if we have a set|unset record */
  910. X            } /* end - looking for alias or set/unset records */
  911. X         } /* end - if not a ``source'' record */
  912. X       s = fgets(buf, BUFSIZ, fp);    /* now read the next line of the file */
  913. X      } /* end - while something to read in the mailrc file */
  914. X    (void) fclose(fp);
  915. X   }
  916. X return(status);
  917. X}
  918. X/* end - get_mailrc */
  919. X
  920. X
  921. X/*
  922. X** @(#)GetMailrc() - Get mail environment variable value from the mailrc file
  923. X**             Added support for source'd files within the .mailrc file
  924. X*/
  925. Xchar *
  926. XGetMailrc(item)
  927. Xchar    *item;
  928. X{
  929. X char    *s = NULL;
  930. X
  931. X (void) get_mailrc(item, &s, mailrcFile());
  932. X
  933. X return((char *)s);
  934. X} /* GetMailrc */
  935. END_OF_FILE
  936.   if test 18935 -ne `wc -c <'environs.c'`; then
  937.     echo shar: \"'environs.c'\" unpacked with wrong size!
  938.   fi
  939.   # end of 'environs.c'
  940. fi
  941. if test -f 'parser.c' -a "${1}" != "-c" ; then 
  942.   echo shar: Will not clobber existing file \"'parser.c'\"
  943. else
  944.   echo shar: Extracting \"'parser.c'\" \(23345 characters\)
  945.   sed "s/^X//" >'parser.c' <<'END_OF_FILE'
  946. X/*
  947. X * xmail - X window system interface to the mail program
  948. X *
  949. X * Copyright 1990,1991,1992 by National Semiconductor Corporation
  950. X *
  951. X * Permission to use, copy, modify, and distribute this software and its
  952. X * documentation for any purpose is hereby granted without fee, provided that
  953. X * the above copyright notice appear in all copies and that both that
  954. X * copyright notice and this permission notice appear in supporting
  955. X * documentation, and that the name of National Semiconductor Corporation not
  956. X * be used in advertising or publicity pertaining to distribution of the
  957. X * software without specific, written prior permission.
  958. X *
  959. X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  960. X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  961. X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  962. X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  963. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  964. X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  965. X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  966. X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  967. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  968. X * PERFORMANCE OF THIS SOFTWARE.
  969. X *
  970. X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  971. X *
  972. X *
  973. X * The following software modules were created and are Copyrighted by
  974. X * National Semiconductor Corporation:
  975. X *
  976. X *  1. regerr:
  977. X *  2. compile_pattern:
  978. X *  3. match: and
  979. X *  4. update_times.
  980. X *
  981. X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  982. X *
  983. X */
  984. X
  985. X#define    PARSER
  986. X
  987. X#include "global.h"
  988. X#include "xmailregexp.h"
  989. X#include <ctype.h>
  990. X#include <utime.h>
  991. X#include "MailwatchP.h"
  992. X
  993. Xextern    void    reset_mailbox();
  994. Xstatic    char    MailPrompt[80];        /* overkill on size, but to be safe */
  995. X
  996. X#if defined(USE_REGEXP)
  997. X#define    INIT        register char *sp=instring; int sed=1;
  998. X#define    GETC()        (*sp++)
  999. X#define    PEEKC()        (*sp)
  1000. X#define    UNGETC(c)    (--sp)
  1001. X#define    RETURN(c)    return
  1002. X#define    ERROR(c)    regerr(c)
  1003. X
  1004. X#include <regexp.h>
  1005. X
  1006. Xint    regexp_indx;
  1007. X
  1008. Xstatic char *regexp_error[] = {
  1009. X          "","","","","","","","","","","",
  1010. X /* 11 */ "Range endpoint too large", "","","","",
  1011. X /* 16 */ "Bad number", "","","","","","","","",
  1012. X /* 25 */ "``\\digit'' out of range", "","","","","","","","","","",
  1013. X /* 36 */ "Illegal or missing delimiter", "","","","",
  1014. X /* 41 */ "No remembered search string",
  1015. X /* 42 */ "\\(\\) imbalance",
  1016. X /* 43 */ "Too many \\(",
  1017. X /* 44 */ "More than 2 numbers given in \\{\\}",
  1018. X /* 45 */ "} expected after \\",
  1019. X /* 46 */ "First number exceeds second in \\{\\}", "", "",
  1020. X /* 49 */ "[] imbalance",
  1021. X /* 50 */ "Regular expression too long",
  1022. X NULL
  1023. X};
  1024. X
  1025. X
  1026. Xregerr(c)
  1027. Xint    c;
  1028. X{
  1029. X (void) fprintf(stderr, "xmail: %s (item %d).\n", regexp_error[c], regexp_indx);
  1030. X exit(0);
  1031. X}
  1032. X
  1033. X
  1034. X/*
  1035. X**  @(#)compile_pattern() - compile regular expression patterns in a table.
  1036. X**  A pattern table is an array of pattern records.  Each pattern record
  1037. X**  consists of a regular expression, and a buffer for the compiled expression.
  1038. X*/
  1039. Xvoid
  1040. Xcompile_pattern(patternTable)
  1041. XPatternRecPtr    patternTable;
  1042. X{
  1043. X String        bp;
  1044. X PatternRecPtr    cp;
  1045. X
  1046. X
  1047. X for (regexp_indx=0, cp=patternTable; cp->pat||cp->buf; regexp_indx++, cp++) {
  1048. X     if (! cp->pat) continue;        /* skip over grouping separations */
  1049. X     bp = (String) XtMalloc((unsigned) BUFSIZ);
  1050. X     (void) compile(cp->pat, bp, &bp[BUFSIZ], '\0');
  1051. X     cp->buf = bp;
  1052. X    }
  1053. X}
  1054. X#endif
  1055. X
  1056. X
  1057. X/*
  1058. X** @(#)match() - string against regular expressions in pattern table.
  1059. X*/
  1060. Xint
  1061. Xmatch(patternTable, string)
  1062. XPatternRecPtr     patternTable;
  1063. Xchar        *string;
  1064. X{
  1065. X PatternRecPtr    cp;
  1066. X char        *bp;
  1067. X int        n, id;
  1068. X
  1069. X
  1070. X if (strcmp(string, "") == 0) return -1;
  1071. X
  1072. X for (id = 0, cp = patternTable; cp->pat || cp->buf; cp++) {
  1073. X     if (! cp->pat) { id++; continue; }
  1074. X
  1075. X#if defined(USE_REGEXP)
  1076. X     if (advance(string, cp->buf))
  1077. X        return (id);
  1078. X#else
  1079. X     if (bp = (char *)re_comp(cp->pat)) {
  1080. X        (void) fprintf(stderr, "xmail: re_comp: %s\n", bp);
  1081. X        return -1;
  1082. X       } else {
  1083. X        if ((n = re_exec(string)) == 1)
  1084. X           return (id);
  1085. X        else if (n < 0) {
  1086. X                (void) fprintf(stderr, "xmail: re_exec: internal error\n");
  1087. X                return -1;
  1088. X               }
  1089. X       }
  1090. X#endif
  1091. X    }
  1092. X return (-1);
  1093. X}
  1094. X
  1095. X
  1096. X/*
  1097. X** @(#)parser_init()- compile command and output pattern tables.
  1098. X*/
  1099. Xvoid
  1100. Xparser_init()
  1101. X{
  1102. X#if defined(USE_REGEXP)
  1103. X (void) compile_pattern(command_pattern);
  1104. X (void) compile_pattern(output_pattern);
  1105. X#else
  1106. X ;
  1107. X#endif
  1108. X}
  1109. X
  1110. X/*
  1111. X** @(#)update_times - update previous folder's timestamps, so SetNewness()
  1112. X**                    will restore no unread message flag for that folder.
  1113. X*/
  1114. Xstatic
  1115. Xupdate_times()
  1116. X{
  1117. X MailwatchWidget mb = (MailwatchWidget) XtNameToWidget(toplevel,"icon.mailbox");
  1118. X char        *p, *q, tmp[BUFSIZ];
  1119. X
  1120. X/*
  1121. X** we need to strip the foldername from the previous title-bar contents
  1122. X*/
  1123. X p = strrchr(lastFolder, '"');
  1124. X q = strchr(lastFolder, '"');
  1125. X if (p && q && p != q) {
  1126. X    *p = '\0';
  1127. X    if (strcmp(++q, mb->mailbox.filename) != 0) { /* not system folder */
  1128. X       if (*q == '+') {            /* the majority of the times */
  1129. X          initfoldir();
  1130. X          (void) sprintf(tmp, "%s%s", foldir, ++q);
  1131. X          q = tmp;
  1132. X         }
  1133. X       (void) utime(q, (struct utimbuf *) 0);
  1134. X      }
  1135. X   }
  1136. X
  1137. X} /* end - update_times */
  1138. X
  1139. X
  1140. X/*
  1141. X** @(#)Reissue_Is_Valid - true/false reissue of Copy/Save to author was valid
  1142. X*/
  1143. Xint
  1144. XReissue_Is_Valid()
  1145. X{
  1146. X int    n;
  1147. X String    p, h, strchr(), strrchr();
  1148. X char    buf[BUFSIZ], tmp[BUFSIZ];
  1149. X
  1150. X
  1151. X if (Command[0] != 'C' && Command[0] != 'S')
  1152. X    return(False);
  1153. X
  1154. X SetCursor(WATCH);
  1155. X if (1 == sscanf(Command, "%*s %d", &n)) {
  1156. X    Command[0] = (Command[0] == 'C' ? 'c' : 's');
  1157. X    LASTCH(Command) = ' ';
  1158. X   } else {
  1159. X n = SelectionNumber(False);
  1160. X    sprintf(buf, "%c %d ", Command[0] == 'C' ? 'c' : 's', n);
  1161. X (void) strcpy(Command, buf);
  1162. X   }
  1163. X
  1164. X (void) sprintf(buf, "f %d", n);
  1165. X p = QueryMail(buf);
  1166. X
  1167. X buf[0] = '\0';
  1168. X if (1 != sscanf(p, "> %*d %s", buf))
  1169. X    (void) sscanf(p, " %*d %s", buf);
  1170. X
  1171. X if (strchr(buf, '<')) {
  1172. X    if (! sscanf(buf, "%*[^<]<%[^>]>", tmp))
  1173. X       (void) sscanf(buf, "<%[^>]>", tmp);
  1174. X    (void) strcpy(buf, tmp);
  1175. X   } else
  1176. X if (strchr(buf, '(')) {
  1177. X    for (h = buf; *h && strchr(" \t", *h); h++);
  1178. X    if (1 != sscanf(h, "%*[^)]) %s", tmp))
  1179. X       (void) sscanf(h, "%s", tmp);
  1180. X    (void) strcpy(buf, tmp);
  1181. X   }
  1182. X if (strlen(buf)) {
  1183. X    if (h = strrchr(buf, '!'))        /* UUCP - host![host!]user[@host]... */
  1184. X       bcopy(h + 1, buf, strlen(h));
  1185. X
  1186. X       if (h = strchr(buf, '@')) {    /* ARPA address - user[%host]@host */
  1187. X          *h = '\0';
  1188. X          if (h = strchr(buf, '%'))
  1189. X             *h = '\0';
  1190. X          if (h = strrchr(buf, ':'))    /* DECNet form - host::user%host@host */
  1191. X             bcopy(h + 1, buf, strlen(h));
  1192. X          if (strchr("'\"", buf[0]))    /* or - ["']user[@host]["']%host@host */
  1193. X             bcopy(buf + 1, buf, strlen(buf));
  1194. X         }
  1195. X   }
  1196. X
  1197. X if (h = GetMailEnv("outfolder")) {
  1198. X    XtFree((String) h);
  1199. X    (void) strcat(Command, "+");
  1200. X   }
  1201. X (void) strcat(Command, buf);
  1202. X (void) strcat(Command, "\n");
  1203. X writeMail(Command);
  1204. X return (True);
  1205. X} /* end - Reissue_Is_Valid */
  1206. X
  1207. X
  1208. X/*
  1209. X** @(#)parse() - command and output and call appropriate handler
  1210. X*/
  1211. Xvoid
  1212. Xparse(msg)
  1213. XString    msg;
  1214. X{
  1215. X static    Boolean    first_time = True;
  1216. X int        j, k, msgnum;
  1217. X String        c, s;
  1218. X char        tmp[128];
  1219. X Widget        button, icon, iw;
  1220. X
  1221. X
  1222. X j = match(command_pattern, Command);
  1223. X switch (j) {
  1224. X    /*
  1225. X    ** If error on startup, mail has terminated connection.  Remove our input
  1226. X    ** handler, close the file from our end, and indicate that no connection
  1227. X    ** exists.  Otherwise, establish conversation requirements and display the
  1228. X    ** current message.  If *Show_Last: resource is NOT False, show latest, if
  1229. X    ** none are newer.  We delay setting the icon event handler until now, to
  1230. X    ** ensure mail startup completed before being interrupted by a map event,
  1231. X    ** for the case where we have been started iconic.
  1232. X    */
  1233. X    case XM_C_START : /*
  1234. X                   ** test to ensure we are not running binmail by mistake
  1235. X                   */
  1236. X           if ((strlen(msg) >= 17) &&
  1237. X              (! strcmp("unknown option N\n", &msg[strlen(msg)-17]))) {
  1238. X              Bell(msg);
  1239. X                      XCloseDisplay(XtDisplay(toplevel));
  1240. X                      (void) fprintf(stderr,
  1241. X      "\007xmail: The specified (or default) mail handler is not supported.\n");
  1242. X                      _exit(0);
  1243. X                      }
  1244. X
  1245. X                    if (XM_O_BELL == match(output_pattern, msg)) {
  1246. X                       if (mailpid) {
  1247. X                          XtRemoveInput(mailInputId);
  1248. X                          (void) close(mail_fd);
  1249. X                          mailpid = 0;
  1250. X                          MailPrompt[0] = '\0';
  1251. X                         }
  1252. X
  1253. X               if (strncmp(msg, "No mail for ", 12) == 0)
  1254. X              Bell("No mail in your system mailbox\n");
  1255. X               else Bell(msg);
  1256. X               (void) UpdateTitleBar("No current folder");
  1257. X               *msg = '\0';
  1258. X                      } else {
  1259. X                       /*
  1260. X                       ** To prevent a race condition (?) when starting the
  1261. X                       ** application iconic, (which would cause this loop to
  1262. X                       ** repeat multiple times), test the value of the mail
  1263. X                       ** environment variable ``screen''.  If its value is
  1264. X                       ** 10,000 then we're done.
  1265. X                       */
  1266. X                       if (c = GetMailEnv("screen")) {
  1267. X                          j = (strcmp("10000", c) != 0) ? True : False;
  1268. X                          XtFree((String) c);
  1269. X                         } else j = True;
  1270. X
  1271. X                       if (j) {            /* if not yet set to 10000... */
  1272. X                          (void) strcpy(tmp, "set screen=10000 toplines=100 ");
  1273. X
  1274. X                          /* default action for xmail is hold (ala mailtool) */
  1275. X
  1276. X                          if (c = GetMailrc("nohold")) XtFree((String) c);
  1277. X                          else (void) strcat(tmp, "hold");
  1278. X
  1279. X                          msg = QueryMail(tmp);
  1280. X
  1281. X                          (void) strcpy(tmp, "unset crt replyall cmd");
  1282. X
  1283. X                          msg = QueryMail(tmp);
  1284. X
  1285. X                  *msg = '\0';
  1286. X
  1287. X                          if (msgnum = file_handler()) {
  1288. X                             (void) sprintf(tmp, "%d", msgnum);
  1289. X                             msg = QueryMail(tmp);
  1290. X                            }
  1291. X                          Bell("");        /* reset any worthy-ness flag */
  1292. X                          Bell(Default_Status_Info);
  1293. X                         } else *msg = '\0';
  1294. X                      }
  1295. X                    if (first_time) {        /* only need to do this once */
  1296. X                       Waiting = FALSE;
  1297. X                       first_time = False;
  1298. X                       icon = XtNameToWidget(toplevel, "icon");
  1299. X                       XtAddEventHandler(icon, StructureNotifyMask, False,
  1300. X                                         icon_handler, NULL);
  1301. X                       if (In_Bogus_Mail_File) {
  1302. X                          (void) sprintf(tmp, "%s+", tmpName);
  1303. X                          (void) unlink(tmp);
  1304. X                  *msg = '\0';        /* ignore 'skipping' message */
  1305. X                         }
  1306. X                      }
  1307. X                break;
  1308. X/*
  1309. X** In response to normal or change folder commands, test output.  If an
  1310. X** error, display message in status window, and ring bell unless command
  1311. X** was save, Save to author, or undelete.  If Save or Copy results in an
  1312. X** error, and the error response begins with 'Unknown', then this is not
  1313. X** Sun mail, and we should try and compensate for these missing functions.
  1314. X** If our current mail message folder is the bogus folder, erase any text
  1315. X** and index and note state.  If we have text of next mail message, tell
  1316. X** index_handler to mark its number, else retrieve the appropriate message
  1317. X** text (which also marks its number).  If *Show_Last: resource is NOT False,
  1318. X** file cmd shows latest, if none new.
  1319. X*/
  1320. X    case XM_C_EXEC  :
  1321. X    case XM_C_FILE  :  j = match(output_pattern, msg);
  1322. X            switch (j) {
  1323. X               case XM_O_BELL:
  1324. X                            if (strchr("SsCcw", Command[0]) != NULL) {
  1325. X                               if (strncmp(msg, "Unknown ", 8) == 0 &&
  1326. X                                          Reissue_Is_Valid()) {
  1327. X                                  *msg = '\0';
  1328. X                                          break;
  1329. X                                         }
  1330. X                               if (isdigit(msg[strlen(msg) - 2]))
  1331. X                                  LASTCH(msg) = '\0';
  1332. X                               else Command[0] = '\0';
  1333. X                              }
  1334. X                    if (strncmp(msg, tmpName, strlen(tmpName)) == 0)
  1335. X                       Bell("No mail in your system mailbox");
  1336. X                    else {
  1337. X                                       Bell(msg);
  1338. X                               *msg = '\0';
  1339. X                                      }
  1340. X/*
  1341. X** Save our current message number, because asking about our 'file' status
  1342. X** will reset mail's idea of the 'current message' count to one, regardless.
  1343. X*/
  1344. X                                    msgnum = SelectionNumber(False);
  1345. X/*
  1346. X** Now ask for 'file' status to determine if we are still caught in our 'bogus'
  1347. X** mailfile, in order to generate a more meaningful title-bar status message.
  1348. X*/
  1349. X                                    msg = QueryMail("file");
  1350. X                                    if (strncmp(&msg[1], tmpName, strlen(tmpName)) == 0) {
  1351. X                               (void) UpdateTitleBar("No current folder");
  1352. X                                       iw = XtNameToWidget(toplevel, "topBox");
  1353. X                                       writeTo(XtNameToWidget(iw, "indexWindow"), " ", REPLACE);
  1354. X                                       writeText(" ");
  1355. X                                      } else {
  1356. X                                       (void) UpdateTitleBar(msg);
  1357. X/*
  1358. X** If not in our bogus mail folder, reset the current message
  1359. X** number in Mail by again pointing at that numbered message.
  1360. X*/
  1361. X                                       (void) sprintf(tmp, "f %d", msgnum);
  1362. X                                       msg = QueryMail(tmp);
  1363. X                                       if (Command[0] != NULL)
  1364. X                                          if (strchr("Ssw", Command[0]))
  1365. X                                             markIndex(">S");
  1366. X                                      }
  1367. X                                    *msg = '\0';
  1368. X                                    break;
  1369. X               case XM_O_EXEC: writeText(msg);
  1370. X                            if (strchr("-np", Command[0]))
  1371. X                               msgnum = index_handler(0, 0);
  1372. X                                    else markIndex("> ");
  1373. X                                    *msg = '\0';
  1374. X                                    break;
  1375. X               case XM_O_FILE: c = strchr(msg, '\n');
  1376. X                            if ((int)(c - msg) < strlen(msg) - 1) {
  1377. X                                       *c = '\0';    /* don't bell this */
  1378. X                       Bell("");    /* clear worthy flag */
  1379. X                       Bell(msg);
  1380. X                              }
  1381. X                                    *msg = '\0';
  1382. X                            msgnum = file_handler();
  1383. X                            update_times();    /* now that we're out */
  1384. X                                    if (msgnum) {
  1385. X                                       (void) sprintf(tmp, "%d", msgnum);
  1386. X                                       msg = QueryMail(tmp);
  1387. X                                      }
  1388. X                            break;
  1389. X                  }
  1390. X                    break;
  1391. X/*
  1392. X** When deleting a message, simply mark that index line with a capital 'D'.
  1393. X** If un-deleting, mark that index line with a blank ' '.  If no current
  1394. X** index, restore it.  If autoprinting, mail will include text of next msg.
  1395. X*/
  1396. X    case XM_C_DELETE : if (XM_O_BELL == match(output_pattern, msg)) {
  1397. X                       Bell(msg);
  1398. X                       *msg = '\0';
  1399. X                      } else {
  1400. X                       writeText(msg);
  1401. X                       msgnum = SelectionNumber(False);
  1402. X                       if (Command[0] == 'd') {
  1403. X                          if (msgnum) {
  1404. X                             markIndex("D");
  1405. X                     msgnum = index_handler(msgnum + 1, 0);
  1406. X                            }
  1407. X                         } else {        /* if we are 'undeleting' */
  1408. X                  c = QueryMail("=");
  1409. X                  (void) sscanf(c, "%d", &msgnum);
  1410. X                  XtFree((String) c);
  1411. X                          iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  1412. X                          if (TextGetLastPos(iw) < (XawTextPosition) 4) {
  1413. X                             c = QueryMail("h");
  1414. X                             writeTo(iw, c, REPLACE);
  1415. X                            }
  1416. X                  msgnum = index_handler(msgnum, 1);
  1417. X                         }
  1418. X                       c = QueryMail("file");    /* resets current msg to 1 */
  1419. X                       (void) UpdateTitleBar(c);
  1420. X
  1421. X                       if (msgnum == 0)        /* if this was the last msg */
  1422. X                          writeText(" ");    /* in folder, erase its text */
  1423. X                       else {
  1424. X                          /*
  1425. X                          ** reset mail's idea of what is the current message
  1426. X                          */
  1427. X                          (void) sprintf(tmp, "f %d", msgnum);
  1428. X                          msg = QueryMail(tmp);
  1429. X                         }
  1430. X                       *msg = '\0';
  1431. X                      }
  1432. X            break;
  1433. X/*
  1434. X** In response to a request to view new mail, first reset the mailbox flag.
  1435. X** If mail came back with an error, complain to the user.  Otherwise, clear
  1436. X** the Newmail command button highlighting. Then display any new mail text.
  1437. X*/
  1438. X    case XM_C_NEWMAIL:
  1439. X            button = XtNameToWidget(toplevel, "topBox.commandPanel.Folder");
  1440. X            UnsetNewmail(button, NULL, NULL);
  1441. X                    if (XM_O_BELL == match(output_pattern, msg)) {
  1442. X                       if (strncmp(msg, "No mail for ", 12) == 0) {
  1443. X                          Bell("No mail in your system mailbox\n");
  1444. X                         } else { Bell(msg); }
  1445. X                       *msg = '\0';
  1446. X                      } else {
  1447. X                       Bell("");        /* reset any worthy-ness flag */
  1448. X                       Bell(Default_Status_Info);
  1449. X               if (*msg) {
  1450. X                  s = msg;
  1451. X                  c = strchr(msg, '\n');
  1452. X                  if ((c - s) + 1 < strlen(msg)) {
  1453. X                             *c = '\0';    /* don't bell this */
  1454. X                 Bell(msg);
  1455. X                            }
  1456. X                         }
  1457. X                       msgnum = file_handler();
  1458. X               update_times();        /* we're out of prev. folder */
  1459. X                       *msg = '\0';
  1460. X                       if (msgnum) {
  1461. X                          (void) sprintf(tmp, "%d", msgnum);
  1462. X                          msg = QueryMail(tmp);
  1463. X                         }
  1464. X                      }
  1465. X            break;
  1466. X
  1467. X           default: j = match(output_pattern, msg);
  1468. X            switch (j) {
  1469. X                       case XM_O_BELL:
  1470. X                            Bell(msg);
  1471. X                            *msg = '\0';
  1472. X                    break;
  1473. X/*
  1474. X** If output is from the print command, display a status message
  1475. X*/
  1476. X               case XM_O_PRINT:
  1477. X                            (void) sscanf(&Command[2], "%d", &j);
  1478. X                            c = strrchr(msg, '/');
  1479. X                            (void) sscanf(c, "/%d", &k);
  1480. X                            (void) sprintf(tmp,
  1481. X                             "Message %d sent to printer -- %d bytes\n", j, k);
  1482. X                            Bell(tmp);
  1483. X                            *msg = '\0';
  1484. X                    break;
  1485. X/*
  1486. X** If we didn't specifically ask for it, and its not an error, just toss it.
  1487. X** Preserve post processing moved here, in case we weren't allowed to do it.
  1488. X*/
  1489. X                       default:
  1490. X                            if (strncmp(Command, "preserve", 8) == 0)
  1491. X                               markIndex("P");
  1492. X                            *msg = '\0';
  1493. X                    break;
  1494. X                      }
  1495. X            break;
  1496. X   }
  1497. X/*
  1498. X** If any text remains, display it in the bottom (text) window.
  1499. X*/
  1500. X if (*msg) {
  1501. X    for (j = strlen(msg)-1; j > 1 && msg[j] == '\n' && msg[j-1] == '\n'; j--);
  1502. X    msg[++j] = '\0';            /* drop all but the last newline */
  1503. X    writeText(msg);
  1504. X    *msg = '\0';
  1505. X   }
  1506. X SetCursor(NORMAL);
  1507. X} /* parse */
  1508. X
  1509. X#define    FILEBUF    8192
  1510. X
  1511. X/*
  1512. X** @(#)QueryMail() - Sends a command and returns corresponding output.
  1513. X** If called by the Xt input procedure readMail, no command is included.
  1514. X** In an attempt to eliminate the occasional segmentation violation in
  1515. X** either malloc or free, we no longer free this buffer each time it is
  1516. X** used.  Instead we simply allow it to grow to the maximum size of a
  1517. X** read ever performed on the mail pipe.
  1518. X*/
  1519. Xchar *
  1520. XQueryMail(cmd)
  1521. Xchar    *cmd;
  1522. X{
  1523. X static int    outputsize = 0;
  1524. X int        j, size, length = 0;
  1525. X static String    output;
  1526. X String        temp;
  1527. X char        s[FILEBUF];
  1528. X
  1529. X
  1530. X if (MailPrompt[0] != '\0') length = strlen(MailPrompt);
  1531. X/*
  1532. X** allocate one block to 'output' to begin with
  1533. X*/
  1534. X if (outputsize <= 0) {
  1535. X    outputsize = FILEBUF;
  1536. X    output = (String) XtMalloc((unsigned) outputsize);
  1537. X   }
  1538. X output[0] = '\0';
  1539. X
  1540. X if (! mailpid)
  1541. X    Bell("No current mail program connection\n");
  1542. X else {
  1543. X    if (*cmd) {                /* allow us to be called by readMail */
  1544. X       if (LASTCH(cmd) != '\n')
  1545. X          (void) sprintf(s, "%s\n", cmd);
  1546. X       else
  1547. X          (void) strcpy(s, cmd);
  1548. X       writeMail(s);
  1549. X      }
  1550. X
  1551. X    for (;;) {
  1552. X        if ((size = read(mail_fd, s, FILEBUF)) < 1) {    /* EOF or an error? */
  1553. X           if (! *output) {        /* For some reason Mail has gone away */
  1554. X              (void) strcpy(output, "No current mail service connection\n");
  1555. X              if (mailpid) {
  1556. X                 XtRemoveInput(mailInputId);
  1557. X                 (void) close(mail_fd);
  1558. X                 mailpid = 0;
  1559. X                 MailPrompt[0] = '\0';
  1560. X                 (void) strcpy(Command, "Start");    /* Focus our errors */
  1561. X                 writeText(" ");    /* erase any current message display */
  1562. X                 writeTo(XtNameToWidget(toplevel, "topBox.indexWindow"), " ", REPLACE);
  1563. X                }
  1564. X             }
  1565. X           break;
  1566. X          }
  1567. X
  1568. X        if (size < FILEBUF)
  1569. X           s[size] = '\0';
  1570. X
  1571. X        if (strlen(output) + size >= outputsize) {
  1572. X           outputsize += FILEBUF;
  1573. X           temp = (String) XtRealloc(output, outputsize);
  1574. X           output = temp;
  1575. X          }
  1576. X        (void) strcat(output, s);
  1577. X
  1578. X        if (strcmp(Command, "Start") == 0) {
  1579. X           /*
  1580. X           ** Check for no message response before we try to catch the prompt.
  1581. X           */
  1582. X           if (XM_O_BELL == match(output_pattern, output))
  1583. X              break;
  1584. X           /*
  1585. X           ** If we have no prompt and are just starting, get the prompt string.
  1586. X           ** This makes the GROSS assumption that we will have gotten it here.
  1587. X           */
  1588. X           if (*output && ! *MailPrompt) {
  1589. X              if ((temp = strrchr(output, '\n')) != NULL)
  1590. X                 (void) strcpy(MailPrompt, temp + 1);
  1591. X              else
  1592. X                 (void) strcpy(MailPrompt, output);
  1593. X              length = strlen(MailPrompt);
  1594. X             }
  1595. X          }
  1596. X
  1597. X        j = strlen(output) - length;
  1598. X        if (j < 0) j = 0;        /* no references before zero */
  1599. X        if (*MailPrompt && strcmp(&output[j], MailPrompt) == 0) {
  1600. X           output[j] = '\0';        /* Drop prompt from end of text */
  1601. X           break;            /* and return from read routine */
  1602. X          }
  1603. X       }
  1604. X
  1605. X    if (*cmd) 
  1606. X       LASTCH(output) = '\0';        /* drop newline for normal queries */
  1607. X   }
  1608. X
  1609. X return(output);
  1610. X} /* QueryMail */
  1611. END_OF_FILE
  1612.   if test 23345 -ne `wc -c <'parser.c'`; then
  1613.     echo shar: \"'parser.c'\" unpacked with wrong size!
  1614.   fi
  1615.   # end of 'parser.c'
  1616. fi
  1617. echo shar: End of archive 6 \(of 10\).
  1618. cp /dev/null ark6isdone
  1619. MISSING=""
  1620. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1621.     if test ! -f ark${I}isdone ; then
  1622.     MISSING="${MISSING} ${I}"
  1623.     fi
  1624. done
  1625. if test "${MISSING}" = "" ; then
  1626.     echo You have unpacked all 10 archives.
  1627.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1628. else
  1629.     echo You still must unpack the following archives:
  1630.     echo "        " ${MISSING}
  1631. fi
  1632. exit 0
  1633. exit 0 # Just in case...
  1634. -- 
  1635.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  1636. \X/  Amiga - The only way to fly!      |
  1637.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  1638.   casual observer..."                  |
  1639.