home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / iso9660 / mail / listserv / listserv.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  1993-06-06  |  1.2 MB  |  37,933 lines

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. #!/bin/sh
  2. touch setup systest; chmod 700 setup systest
  3. #!/bin/sh
  4. # Determine how echo suppresses new-line
  5. echo "a\c" > /tmp/echo
  6. if [ "`grep c /tmp/echo`" = "a\c" ]; then
  7.   n='-n'
  8.   c=''
  9. else
  10.   n=''
  11.   c='\c'
  12. fi
  13. rm /tmp/echo
  14.  
  15. echo
  16. echo \    \    \    UNIX ListServer 6.0
  17. echo \    \    \    -------------------
  18. echo
  19. if [ -d osrc -o -d ohelp -o -d oarchives -o -f oconfig -o -f o.ignored \
  20.      -o -f oowners -o -f ounwanted.hosts -o -f opriv.hosts -o -d outil \
  21.      -o -f owelcome.live ]; then
  22.   echo Old system image found:
  23.   echo
  24.   ls -CFd o[a-w\.]*
  25.   echo
  26.   echo The current system will be moved to files/dirs starting with \'o\'
  27.   echo as shown above and confirmation is required to remove that old image.
  28.   echo $n "Proceed [y]? $c"
  29.   read x
  30.   if [ "$x" = "n" -o "$x" = "N" ]; then
  31.     exit 0
  32.   fi
  33. fi
  34. if [ -d src ]; then
  35.   echo WARNING: Moving src/ to osrc/
  36.   rm -rf osrc
  37.   rmdir osrc > /dev/null 2>&1
  38.   mv src osrc
  39. fi
  40. if [ ! -d src ]; then
  41.   mkdir src
  42. fi
  43. if [ ! -d src/ansi ]; then
  44.   mkdir src/ansi
  45. fi
  46. if [ ! -d src/nonansi ]; then
  47.   mkdir src/nonansi
  48. fi
  49. if [ ! -d gateway ]; then
  50.   mkdir gateway
  51. fi
  52. if [ ! -d doc ]; then
  53.   mkdir doc
  54. fi
  55. if [ -d help ]; then
  56.   echo WARNING: Moving help/ to ohelp/
  57.   rm -rf ohelp
  58.   rmdir ohelp > /dev/null 2>&1
  59.   mv help ohelp
  60. fi
  61. mkdir help
  62. if [ -d util ]; then
  63.   echo WARNING: Moving util/ to outil/
  64.   rm -rf outil
  65.   rmdir outil > /dev/null 2>&1
  66.   mv util outil
  67. fi
  68. mkdir util
  69. if [ -d archives ]; then
  70.   echo WARNING: Moving archives/ to oarchives/
  71.   rm -rf oarchives
  72.   rmdir oarchives > /dev/null 2>&1
  73.   mv archives oarchives
  74. fi
  75. mkdir archives
  76. mkdir archives/listserver
  77. mkdir archives/listserver/example.dat
  78. mkdir archives/pub
  79. mkdir archives/pub/unix
  80. mkdir archives/pub/private
  81. mkdir archives/unix
  82. mkdir archives/iul
  83. if [ -f config ]; then
  84.   echo WARNING: Moving config to oconfig
  85.   mv config oconfig
  86. fi
  87. if [ -f owners ]; then
  88.   echo WARNING: Moving owners to oowners
  89.   mv owners oowners
  90. fi
  91. if [ -f .ignored ]; then
  92.   echo WARNING: Moving .ignored to o.ignored
  93.   mv .ignored o.ignored
  94. fi
  95. if [ -f unwanted.hosts ]; then
  96.   echo WARNING: Moving unwanted.hosts to ounwanted.hosts
  97.   mv unwanted.hosts ounwanted.hosts
  98. fi
  99. if [ -f welcome.live ]; then
  100.   echo WARNING: Moving welcome.live to owelcome.live
  101.   mv welcome.live owelcome.live
  102. fi
  103. echo x - peer
  104. sed 's/^X//' >peer <<'*-*-END-of-peer-*-*'
  105. X#!/bin/sh
  106. X# Shell script to add a peer list to a mailing list. 
  107. X#
  108. X# Usage: peer <LIST_ALIAS> <remote alias> <remote peer email address> 
  109. X#          <remote peer ListServer email address>
  110. X# where:
  111. X# LIST_ALIAS: a local list alias, capitalized, that is to be connected to
  112. X#  the new peer.
  113. X# remote alias: the peer's list alias on the remote machine
  114. X# remote peer email address: full email address of the peer list to be added
  115. X# remote peer ListServer email address: full email address of the server
  116. X#   that handles the remote peer.
  117. X
  118. XPROG=`basename $0`
  119. Xif [ $# -lt 4 ]; then
  120. X  echo Usage: $PROG \<LIST_ALIAS\> \<remote alias\> \
  121. X\<remote $PROG email address\> \<remote $PROG ListServer email address\>
  122. X  exit 1
  123. Xfi
  124. X
  125. XARGS=$PROG\ $*
  126. XDIR=/usr/server/lists/`echo $1 | tr '[a-z]' '[A-Z]'`
  127. XREMOTE_ALIAS=`echo $2 | tr '[A-Z]' '[a-z]'`
  128. XEMAIL=`echo $3 | tr '[A-Z]' '[a-z]'`
  129. XREMOTE_SERVER=`echo $4 | tr '[A-Z]' '[a-z]'`
  130. XREPORT=/usr/server/.report.server
  131. XCONFIG=/usr/server/config
  132. XMODE=NOACK
  133. XFILE=$DIR/.peers
  134. Xshift; shift; shift; shift
  135. X
  136. Xif [ ! -d $DIR ]; then
  137. X  echo $DIR: no such list
  138. X  exit 2
  139. Xfi
  140. Xif [ ! -r $CONFIG ]; then
  141. X  echo Cannot open $CONFIG
  142. X  exit 2
  143. Xfi
  144. Xif [ ! -r $FILE -o ! -w $FILE ]; then
  145. X  echo Cannot open $FILE for read/write
  146. X  exit 2
  147. Xfi
  148. X
  149. Xecho >> $REPORT
  150. Xecho --- NEW MAIL HAS ARRIVED --- >> $REPORT
  151. Xecho $ARGS >> $REPORT
  152. XLOCAL=`grep -i "^list *$REMOTE_ALIAS *$EMAIL" $CONFIG | awk '{ print $2 }'`
  153. Xif [ "$LOCAL" = "" ]; then
  154. X  LOCAL=`grep -i "^server\  *$EMAIL" $CONFIG | awk '{ print $2 }'`
  155. X  txt=server
  156. Xelse
  157. X  txt=list
  158. Xfi
  159. Xif [ "$LOCAL" != "" ]; then
  160. X  echo Cannot add local $txt $LOCAL as $PROG to $FILE >&1 | tee -a $REPORT
  161. Xelse
  162. X  if [ "`grep -i $EMAIL $FILE`" != "" ]; then
  163. X    echo $EMAIL\: Already subscribed as a $PROG in $FILE >&1 | tee -a $REPORT
  164. X  else
  165. X    echo $EMAIL $MODE $REMOTE_ALIAS $REMOTE_SERVER >> $FILE
  166. X  fi
  167. Xfi
  168. Xecho Time/Date: `date` >> $REPORT
  169. Xexit 0
  170. *-*-END-of-peer-*-*
  171. echo x - news
  172. sed 's/^X//' >news <<'*-*-END-of-news-*-*'
  173. X#!/bin/sh
  174. X# Shell script to add a news group to a mailing list.
  175. X#
  176. X# Usage: news <LIST_ALIAS> <news group> <news email address> <news mode>
  177. X#
  178. X# where:
  179. X# LIST_ALIAS: a local list alias, capitalized, that is to be connected to
  180. X#  the news group.
  181. X# news group: the news group name (e.g. alt.sex)
  182. X# news email address: full email address of the news source.
  183. X# news mode: "receive" if the local list will only be receiving articles,
  184. X#  or "send_receive" if the local list will post to the news group as
  185. X#  well.
  186. X
  187. XPROG=`basename $0`
  188. Xif [ $# -lt 4 ]; then
  189. X  echo Usage: $PROG \<LIST_ALIAS\> \<news group\> \<$PROG email address\> \<$PROG mode\>
  190. X  exit 1
  191. Xfi
  192. X
  193. XARGS=$PROG\ $*
  194. XDIR=/usr/server/lists/`echo $1 | tr '[a-z]' '[A-Z]'`
  195. XREPORT=/usr/server/.report.server
  196. XCONFIG=/usr/server/config
  197. XIGNORED=/usr/server/.ignored
  198. XFILE=$DIR/.news
  199. XGROUP=`echo $2 | tr '[A-Z]' '[a-z]'`
  200. XEMAIL=`echo $3 | tr '[A-Z]' '[a-z]'`
  201. Xshift; shift; shift
  202. X
  203. Xif [ ! -d $DIR ]; then
  204. X  echo $DIR: no such list
  205. X  exit 2
  206. Xfi
  207. Xif [ ! -r $CONFIG ]; then
  208. X  echo Cannot open $CONFIG
  209. X  exit 2
  210. Xfi
  211. Xif [ ! -r $FILE -o ! -w $FILE ]; then
  212. X  echo Cannot open $FILE for read/write
  213. X  exit 2
  214. Xfi
  215. Xif [ "$1" = "receive" ]; then
  216. X  MODE=POSTPONE
  217. Xelif [ "$1" = "send_receive" ]; then
  218. X  MODE=NOACK
  219. Xelse
  220. X  echo Token $1 not recognized
  221. X  exit 2
  222. Xfi
  223. X
  224. Xecho >> $REPORT
  225. Xecho --- NEW MAIL HAS ARRIVED --- >> $REPORT
  226. Xecho $ARGS >> $REPORT
  227. XLOCAL=`grep -i "^list *$REMOTE_ALIAS *$EMAIL" $CONFIG | awk '{ print $2 }'`
  228. Xif [ "$LOCAL" = "" ]; then
  229. X  LOCAL=`grep -i "^server\  *$EMAIL" $CONFIG | awk '{ print $2 }'`
  230. X  txt=server
  231. Xelse
  232. X  txt=list
  233. Xfi
  234. Xif [ "$LOCAL" != "" ]; then
  235. X  echo Cannot add local $txt $LOCAL as $PROG to $FILE >&1 | tee -a $REPORT
  236. Xelse
  237. X  if [ "`grep -i $EMAIL $FILE`" != "" ] || [ "`grep -i $GROUP $FILE`" != "" ]
  238. X  then
  239. X    echo $EMAIL\: Already subscribed as a $PROG group in $FILE >&1 | \
  240. X         tee -a $REPORT
  241. X  else
  242. X    echo $EMAIL $MODE $GROUP >> $FILE
  243. X    echo $EMAIL >> $IGNORED
  244. X  fi
  245. Xfi
  246. Xecho Time/Date: `date` >> $REPORT
  247. Xexit 0
  248. *-*-END-of-news-*-*
  249. echo x - doc/catmail.1
  250. sed 's/^X//' >doc/catmail.1 <<'*-*-END-of-doc/catmail.1-*-*'
  251. X.\" UNIX ListServer System
  252. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  253. X.\"
  254. X.TH catmail 1 "UNIX ListServer"
  255. X.SH NAME
  256. X\fBcatmail\fP \- append incoming mail to UNIX ListServer system files
  257. X.SH SYNOPSIS
  258. X\fBcatmail\fP {<\fB-L LIST_ALIAS\fP [\fB-m\fP]> | <\fB-r\fP>} [\fB-f\fP]
  259. X.SH DESCRIPTION
  260. X\fIcatmail\fP is used to redirect incoming mail to the UNIX ListServer system
  261. Xto the appropriate
  262. Xfiles, according to the flags specified. The files affected are
  263. XHOMEDIR/requests (a repository for requests), HOMEDIR/lists/*/mail
  264. X(public messages to be distributed) and HOMEDIR/lists/*/moderated
  265. X(messages to be screened out by a moderator). \fIcatmail\fP reports the
  266. Xuser id and user name that is currently executing it; the setuid bit
  267. Xhas to be set when installed. \fIcatmail\fP first locks the output file
  268. Xbefore appending to it; if the file cannot be locked after 3 minutes, the
  269. Xmail is saved under HOMEDIR/lost+found or HOMEDIR/lists/*/lost+found;
  270. Xboth \fIlist\fP and \fIlistserv\fP
  271. Xlock their mail files while copying them to a safe place.
  272. X.SH OPTIONS
  273. XThe following command line options are recognized:
  274. X.TP
  275. X-L LIST_ALIAS [-m]
  276. XIf the -m flag is not specified, append to
  277. XHOMEDIR/lists/\fILIST_ALIAS\fP/mail; otherwise append to
  278. XHOMEDIR/lists/\fILIST_ALIAS\fP/moderated (see list(1)).
  279. X.TP
  280. X-r
  281. XAppend to HOMEDIR/requests (overrides -L).
  282. X.TP
  283. X-f
  284. XReformat the message in the process: all lines in the message except the first
  285. Xstarting with "From " are converted to ">From ".
  286. X(see also SYSTEM\ SETUP in server(1)).
  287. X.SH SEE\ ALSO
  288. Xlist(1), listserv(1), server(1)
  289. X.SH AUTHOR
  290. X.nf
  291. XAnastasios C. Kotsikonas
  292. XCopyright (c) 1991-93, Anastasios Kotsikonas
  293. XComments to tasos@cs.bu.edu
  294. X.fi
  295. *-*-END-of-doc/catmail.1-*-*
  296. echo x - doc/farch.1
  297. sed 's/^X//' >doc/farch.1 <<'*-*-END-of-doc/farch.1-*-*'
  298. X.\" UNIX ListServer System
  299. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  300. X.\"
  301. X.TH farch 1 "UNIX ListServer"
  302. X.SH NAME
  303. X\fBfarch\fP \- archive files under the UNIX ListServer system
  304. X.SH SYNOPSIS
  305. X\fBfarch\fP {[\fB-n\fP] [\fB-b\fP | \fB-B\fP] [\fB-s\ size\fP] [\fB-d\ dir\fP] [\fB-p\ password\fP] [\fB-D\ description\fP]\ [\fB-t\ file\fP]} | {[\fB-r\fP]} [\fB-a\ archive | path-to-archive\fP] <\fBfiles\fP>
  306. X.SH DESCRIPTION
  307. X\fIfarch\fP is used to archive files under the UNIX ListServer system 
  308. Xor remove files already achived, with support provided for private archives.
  309. XArchives reside under HOMEDIR/archives as subdirectories; the default is
  310. X\fIlistserver\fP,
  311. Xand it is also the master archive. Archives are hierarchically
  312. Xstructured, and each archive has at least two files in its directory:
  313. X.TP
  314. XINDEX
  315. XA list of all subarchives including itself; the format is one line per
  316. Xarchive with the archive's name followed by the archive's full path, followed
  317. Xby an optional password:
  318. X.sp
  319. Xarchive-name full-path-to-archive-directory [password]
  320. X.sp
  321. XThe first entry should be the archive itself;
  322. Xeach first level subarchive is listed next; then each second level
  323. Xsubarchive, starting with the first first-level-archive's subarchives,
  324. Xfollowed by the second first-level-archive's subarchives, etc. No sibling
  325. Xarchives may have the same name, although there is no such restriction
  326. Xfor archives on different levels, or "cousin" archives. The latter archives
  327. Xare distinguished by the relative path needed to access them (see
  328. X\fIserver(1)\fP for more information).
  329. X.TP
  330. XDIR
  331. XA list of files available from that archive; the format is one line
  332. Xper file with the file name followed by the number of parts it may be
  333. Xsplit into, followed by the number of bytes of each of the parts, followed
  334. Xby the full path to the directory these parts can be found, followed
  335. Xby a short descriptive message about the file (optional). The descriptive
  336. Xmessage may span several lines; each line (except the last) should end 
  337. Xwith a '\\':
  338. X.sp
  339. X.nf
  340. Xfile nparts size-of-each-part+ full-path-to-directory [description [\\]]
  341. X[multiple description lines [\\]]*
  342. X.fi
  343. X.sp
  344. XThe number of parts the file is split into may be -1 to indicate that
  345. Xthis is a binary file.
  346. X.PP
  347. X\fIfarch\fP reports on the action taken on each input file: whether it
  348. Xwas split (and how many parts), whether it was uuencoded, whether all files
  349. Xhave been tar'red into a single one, the archive this file was archived under,
  350. Xand the directory the output file(s) (if any) has/have been placed. It
  351. Xalso reports when the input files are tarred.
  352. X.SH OPTIONS
  353. XThe following command line options are recognized:
  354. X.TP
  355. X-n
  356. XDo not split files when archiving them. The default is to split them with
  357. Xeach part not larger than the specified size (see the -s option below).
  358. X.TP
  359. X-b
  360. XInput files are binary; they are uuencoded before archived.
  361. X.TP
  362. X-B
  363. XInput files are binary; they are neither uuencoded nor split.
  364. X.TP
  365. X-s size
  366. XSpecify the maximum \fIsize\fP in kilobytes of each of the subparts 
  367. X(default is 64).
  368. X.TP
  369. X-d dir
  370. XSpecify the \fIdir\fPectory that the output files are to be placed; if
  371. Xleft out, it defaults to the specified archive's directory
  372. X(HOMEDIR/archives/listserver if the archive is left out as well).
  373. XIf the directory (and all of its subdirectories, if any) does not exist,
  374. Xit will be created.
  375. X.TP
  376. X-p password
  377. XWhen a new archive is to be created, and that archive is to be private,
  378. Xspecify the access password.
  379. X.TP
  380. X-D description
  381. XPut \fIdescription\fP (most likely surrounded by single quotes) in the
  382. XDIR file as explanatory comment about the archived file. This option does
  383. Xnot make much sense when archiving more than one file at the same time.
  384. X.TP
  385. X-t file
  386. XInput files are tar'red into \fIfile\fP which is then archived (the -b flag
  387. Xis automatically turned on). Turning on the -B flag will prevent uuencoding
  388. Xof the tar file. Note that whatever the path to \fIfile\fP may
  389. Xbe, it will be moved to the specified directory as specified by the -d flag.
  390. X.TP
  391. X-r
  392. XRemove the specified file(s) from the specified archive (see below), or the
  393. Xdefault one; it has higher priority than all of the options above.
  394. X.TP
  395. X-a archive | path-to-archive
  396. XSpecify the \fIarchive\fP that the input files will be archived under (default
  397. Xis listserver). Archives on different levels of the hierarchy may have the
  398. Xsame name and in this case a \fIpath-to-archive\fP may be specified to
  399. Xdistinguish between them;
  400. X\fIpath-to-archive\fP has the form \fIarchive[/archive[/archive...]]\fP
  401. X(see also server(1)). If any of the archives in the path do not exist,
  402. Xthey will be created with the necessary files.
  403. X.PP
  404. XFile names in the DIR file have to be unique and \fIfarch\fP will not
  405. Xarchive duplicate files.
  406. X.SH ARCHIVING\ A\ FILE
  407. X\fIfarch\fP by default splits the input files if necessary
  408. X(or the tar file, if any),
  409. Xinto files of maximum size as specified. Each part
  410. Xwill contain as many complete lines from the original input file as possible,
  411. Xwithout exceeding the specified size. Binary files (including the tar file)
  412. Xare uuencoded before they are archived unless the -B option is specified,
  413. Xand all archived files are compressed, if possible.
  414. X.SH ADDING\ A\ NEW\ ARCHIVE
  415. X.TP
  416. Xautomatically
  417. XSimply specify the new archive as argument to the -a flag. All necessary DIR
  418. Xand INDEX files as well as all required directories will be created, and
  419. Xall parent archives will be updated.
  420. X.TP
  421. Xby hand
  422. XStep 1
  423. X.sp
  424. XCreate a directory under HOMEDIR/archives or under an existing
  425. Xarchive's directory (beware of the hierarchy structure), naming the
  426. Xdirectory after the archive.
  427. XThe archive's name should be unique among its siblings on that level in the
  428. Xhierarchy (besides, mkdir will not let specify a name that already exists).
  429. X.sp
  430. XStep 2
  431. X.sp
  432. XEdit the master archive's index file (HOMEDIR/archives/listserver/INDEX) and
  433. Xadd the new archive along with its path (and optional password -- see below)
  434. Xat the proper place in the file, making sure you adhere to the
  435. Xrules about hierarchy outined above. The first line of every INDEX
  436. Xfile should be the archive itself. Also edit (add to) every ancestor archive's
  437. XINDEX file, if the new archive is not the default, again making sure you adhere
  438. Xto the same rules.
  439. X.sp
  440. XStep 3
  441. X.sp
  442. XCreate a new INDEX file in the new archive's directory and put an entry
  443. Xfor itself.
  444. X.sp
  445. XStep 4
  446. X.sp
  447. XCreate an empty DIR file in the new archive's directory.
  448. X.SH PRIVATE\ ARCHIVES
  449. XPrivate archives are archives that require a password for obtaining
  450. Xindices and/or files from them. To make an archive private, simply
  451. Xappend a password (case does not matter) after its full path specification
  452. Xin every INDEX file the archive is defined (its own plus all ancestors' --
  453. Xthe same password has to be used in all of these files). Then, that 
  454. Xpassword has
  455. Xto be made known to all users who are to be granted access to this archive.
  456. XNote that all files in the same private archive can be obtained with the
  457. Xsame single password.
  458. X.SH EXAMPLES
  459. XArchive src/data and src/data2 under archive listserver (the default),
  460. Xusing a maximum file size of 1K; the output file(s) will be placed in /tmp/tmp:
  461. X.sp
  462. X.nf
  463. X.in +2
  464. X% farch -s 1 -d /tmp/tmp src/data src/data2
  465. X.fi
  466. X.in -2
  467. X.sp
  468. XArchive /etc/hosts under archive unix (that is listserver/unix) -- the -n
  469. Xflag is used to avoid writing split parts to /etc which is doomed to fail:
  470. X.sp
  471. X.nf
  472. X.in +2
  473. X% farch -n -a unix -d /etc -p private /etc/hosts
  474. X.fi
  475. X.in -2
  476. X.sp
  477. XArchive /etc/password under archive pub/unix (that is listserver/pub/unix):
  478. X.sp
  479. X.nf
  480. X.in +2
  481. X% farch -n -a pub/unix -d /etc /etc/passwd
  482. X.fi
  483. X.in -2
  484. X.sp
  485. XTar and archive all files in /usr/src to the default archive and place the
  486. Xtar file under /tmp/tmp:
  487. X.sp
  488. X.nf
  489. X.in +2
  490. X% farch -t HOMEDIR/source -d /tmp/tmp /usr/src/*.c
  491. X.fi
  492. X.in -2
  493. X.sp
  494. XDescriptive messages about these files are added manually into the archive's
  495. XDIR file. However, the -D option can be used to specify a string as follows:
  496. X.sp
  497. X.nf
  498. X.in +2
  499. X% farch -D 'UNIX ListServer system files' -t ulistserv.tar -n -d /usr/server /usr/server/*
  500. X.SH UPGRADING
  501. XIf you are upgrading from:
  502. X.TP
  503. X5.5
  504. XThe -B, -p, -r and -D options are new; functionality is the same.
  505. X.TP
  506. X5.41 or less
  507. XEvery DIR file should now include the size of each of the parts of every
  508. Xfile, placed between the number of parts and the path name.
  509. X.sp
  510. XThe -a option has been extended to accept paths to archives.
  511. X.SH RESTRICTIONS
  512. X\-
  513. XArchive names and input files must use only lower case characters of the
  514. Xalphabet.
  515. X.SH WARNINGS
  516. X\-
  517. XInput files that are to be tar'red should only include relative path names;
  518. Xotherwise the end user may not be able to extract them.
  519. X.sp
  520. X\-
  521. XThe tar file should not be any of the input files.
  522. X.SH SEE\ ALSO
  523. Xserver(1)
  524. X.SH AUTHOR
  525. X.nf
  526. XAnastasios C. Kotsikonas
  527. XCopyright (c) 1991-93, Anastasios Kotsikonas
  528. XComments to tasos@cs.bu.edu
  529. X.fi
  530. *-*-END-of-doc/farch.1-*-*
  531. echo x - doc/iul.1
  532. sed 's/^X//' >doc/iul.1 <<'*-*-END-of-doc/iul.1-*-*'
  533. X.\" UNIX ListServer System
  534. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  535. X.\"
  536. X.TH iul 1 "IUL 1.0"
  537. X.SH NAME
  538. X\fBiul\fP \- Interactive UNIX ListServer client
  539. X.SH SYNOPSIS
  540. X\fBiul\fP [\fB-v\fP] [\fB-t timeout\fP] [\fB-b buffer-size\fP] \fBhost\fP [\fBport\fP]
  541. X.SH DESCRIPTION
  542. X\fIiul\fP is a client that connects to the specified \fIhost\fP's
  543. XInteractive UNIX ListServer port (372) for a live session -- i.e. for
  544. Xprocessing requests live. Another \fIport\fP
  545. Xmay be specified if necessary. The \fIhost\fP may be a host name, or an 
  546. XIP address.
  547. X.PP
  548. XUpon connection establishment, the protocol attempts to set the user's
  549. Xprivileges during the session by requesting an email address and a password.
  550. XThese are used to determine whether the user is to be granted system,
  551. Xowner, subscriber or casual user privileges. If the user provides
  552. Xhis owner email address and his list's password, he will be granted
  553. Xowner privileges. If he provides an email address that he uses for subscription
  554. Xto a list, along with the password he uses for that list, he will be granted
  555. Xsubscriber privileges. The system provides a brief listing of all valid
  556. Xrequests the user may issue during the session. If no email address is
  557. Xprovided, or no matches are found, the user is restricted to a few
  558. Xrequests.
  559. X.PP
  560. XRequests for remote lists are serviced by attempting to connect
  561. Xto the IUL server(s) (if any) of the system(s) that handle those lists.
  562. X.PP
  563. XThe IUL server recognizes the following special requests:
  564. X.TP
  565. Xquit/exit
  566. XEnd the session.
  567. X.TP
  568. X?/privileges
  569. XGet a brief listing of all valid requests.
  570. X.TP
  571. Xtimeleft
  572. XPrints the remaining time in seconds.
  573. X.TP
  574. X&<new-line>
  575. XInput continues on the next line.
  576. X.TP
  577. Xbinary
  578. XSwitch to binary mode when transferring files.
  579. X.TP
  580. Xascii
  581. XSwitch to ASCII mode when transferring files.
  582. X.TP
  583. X< filename
  584. XInput is taken from the specified file. Each line will be interpreted as
  585. Xa separate request, unless the file is specified in conjunction with a
  586. X\fIput\fP request. If the '<' is to be used literally it
  587. Xmust be escaped with '\\' or enclosed in quotes.
  588. X.TP
  589. X> filename
  590. XRedirect the reply to the request to the specified file. Error messages
  591. X(such as rejections due to invalid requests, etc.) are not redirected.
  592. XWhen a file is downloaded via a \fIget\fP request, this will override the
  593. Xfile name that will be saved under. If the '>' is to be used literally it
  594. Xmust be escaped with '\\', or enclosed in quotes.
  595. X.TP
  596. X>> filename
  597. XSame as above, but the reply is appended to the specified file.
  598. X.TP
  599. X| prog [args]
  600. XThe output of the request is piped to \fIprog\fP; this is similar to a UNIX
  601. Xpipe. \fIprog\fP may be any valid UNIX command, including other pipes, file
  602. Xredirections, etc. Since '<' has higher precedence in this context, you
  603. Xshould escape any '<' characters intended to be used by the pipe, otherwise
  604. Xthe system will assume you are feeding it batched requests. Quotes may also
  605. Xbe used to protect these characters.
  606. X.SH OPTIONS
  607. XThe following options are recognized:
  608. X.TP
  609. X-v
  610. XTurn verbose mode on; the server reply codes are echoed along with
  611. Xpredetermined messages.
  612. X.TP
  613. X-t timeout
  614. XThe default time out for a server response is 180 seconds; to reset
  615. Xuse the -t flag. This timeout should not be confused with the
  616. Xremaining time of a connection.
  617. X.TP
  618. X-b buffer-size
  619. XThe default socket buffer size is 8K; to reset use the -b flag
  620. X(the argument specifies kilobytes).
  621. X
  622. X.SH USER\ PRIVILEGES
  623. XCasual users may only issue help, information, recipients and statistics
  624. Xfor nonprivate lists, lists, index, get, search and release requests.
  625. XSubscriber privileges also include the set, run, unsubscribe and which requests.
  626. XOwners may, in addition, issue all of their administrative requests.
  627. X.PP
  628. XIssue a 'help live' request when you first connect to an IUL server.
  629. X.SH RESTRICTIONS
  630. XThe connection duration is limited to a server-imposed limit.
  631. XAfter that, a connection may be broken by the server as necessary.
  632. XA connection will not be broken during a transfer.
  633. X.SH EXAMPLES
  634. X.nf
  635. Xrequest> put ermis ermis1 subscribers </usr/server/backup/lists/ERMIS/subs >out
  636. X.sp
  637. Xrequest> get listserver example.dat 1 3 >> out
  638. X.sp
  639. Xrequest> get listserver example.dat
  640. X.sp
  641. Xrequest> index iul > IUL
  642. X.sp
  643. Xrequest> < /tmp/batched.requests
  644. X.sp
  645. Xrequest> index | more
  646. X.sp
  647. Xrequest> lists | cut -d ' ' -f1,2 | more
  648. X.sp
  649. Xrequest> search iul "\\>\\> out"
  650. X.sp
  651. X.fi
  652. XIn this last example, we escape '>' to protect it from being interpreted
  653. Xas a regular expression separator, and enclose the whole pattern in quotes
  654. Xto protect the '>>' from being interpreted as the append operator. The same
  655. Xrequest could have been written as:
  656. X.nf
  657. X.sp
  658. Xrequest> search iul \\\\>\\\\> out
  659. X.fi
  660. X.SH FILES
  661. X.TP
  662. Xiul.c, iul.h
  663. XSource code for the client. See iul.c for compile options.
  664. X.TP
  665. Xiulp.h
  666. XDefinition of the Interactive UNIX ListServer Protocol.
  667. X.TP
  668. Xmakefile
  669. Xmakefile to build \fIiul\fP. \fIiul\fP is written with BSD-style signal
  670. Xhandling, therefore on some hosts (like IBM AIX) you will have to link with
  671. XBSD versions of signal(2), socket(3N), and fcntl(2). Platforms that
  672. Xhave the <sys/select.h> and <ulimit.h> header files should compile
  673. Xwith -DHAVE_SELECT_H and/or -DHAVE_ULIMIT_H. SCO ports should compile with
  674. X-Dsco. Always link with libraries that provide DNS support (resolver linked
  675. Xin).
  676. X.SH BUGS
  677. XPlease report any bugs or enhancements to tasos@cs.bu.edu
  678. *-*-END-of-doc/iul.1-*-*
  679. echo x - doc/list.1
  680. sed 's/^X//' >doc/list.1 <<'*-*-END-of-doc/list.1-*-*'
  681. X.\" UNIX ListServer System
  682. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  683. X.\"
  684. X.TH list 1 "UNIX ListServer"
  685. X.SH NAME
  686. X\fBlist\fP \- process a specified UNIX ListServer mailing list
  687. X.SH SYNOPSIS
  688. X\fBlist -L\fP\ <\fBLIST_ALIAS\fP> [\fB-1\fP] [\fB-e\fP] [\fB-s\fP] [\fB-p\fP] [\fB-P\fP] [\fB-m\ #\fP] [\fB-f\fP] [\fB-r\fP] [\fB-M\fP] [\fB-d\fP] [\fB-i\fP <\fBaddress\fP>] [\fB-v\fP] [\fB-D\fP]
  689. X.SH DESCRIPTION:
  690. X\fIlist\fP distributes the message(s) sent to \fIlist_alias@your-domain\fP;
  691. Xthe file ".ignored" in the list's subdirectory is used to filter out any
  692. Xunwanted messages (see below).
  693. X.PP
  694. XMessages from mailer daemons are forwarded to the list's owner and screened
  695. Xlooking for delivery errors (in which case appropriate action is taken --
  696. Xusers are either immediately removed from the list, or after a series of
  697. Xdelivery errors within a certain time frame -- entries removed from the
  698. Xsystem's files are placed into HOMEDIR/lists/*/removed.users and
  699. XHOMEDIR/lists/*/removed.alias files),
  700. Xwhereas messages
  701. Xfrom non-subscribers are returned to the original senders (the -f flag
  702. Xoverrides this). Messages whose first line looks like a ListServer request
  703. Xare bounced back to the sender.
  704. X.PP
  705. XMessages from news groups are distributed only to local
  706. Xsubscribers and peer lists. Messages from peers are distributed to local
  707. Xsubscribers and possibly posted to news groups. Finally, messages from
  708. Xlocal subscribers are either distributed locally, copies are sent to all peers,
  709. Xand are possibly posted to news groups, or are forwarded to the list's
  710. Xowner for screening if the list is moderated.
  711. X.PP
  712. XAll distributed messages 
  713. X(i.e. legitimate messages from subscribers, peers and news groups -- not
  714. Xrejected, ignored or error messages)
  715. Xare automatically archived in HOMEDIR/lists/*/archive. In contrast,
  716. Xthe files HOMEDIR/lists/*/mbox contain all messages sent to these
  717. Xlists (including, error, rejected and ignored messages).
  718. X.PP
  719. XEmail from one or more subscribers may be selectively distributed to an
  720. Xalternate list of recipients, by way of restricted mail (see below),
  721. Xin which case mail will not be distributed to the regular subscribers.
  722. X.PP
  723. XWhen the system is for some reason aborted while making a delivery, a
  724. Xbuilt-in mechanism allows it to resume from the point it left off.
  725. X.SH OPTIONS
  726. XThe following command line options are recognized:
  727. X.TP
  728. X-L LIST_ALIAS
  729. XProcess any messages sent to this \fILIST_ALIAS\fP -- \fILIST_ALIAS\fP should
  730. Xbe in capital letters.
  731. X.TP
  732. X-1
  733. XExecute only once; process the mailing list and return control to
  734. X\fIserverd\fP(1); any new messages that may have arrived in the meantime will
  735. Xbe processed at a later time. Without this option, \fIlist\fP will be
  736. Xlistening for messages for the specified list for ever. \fIserverd\fP(1)
  737. Xuses this option by default when spawning \fIlist\fP.
  738. X.TP
  739. X-e
  740. XEcho reports to the screen; it has no effect if the system has been compiled
  741. Xwith -DSYSLOG.
  742. X.TP
  743. X-s
  744. XBy default, only subscribers can send messages to a list. This option
  745. Xturns off subscription checking.
  746. X.TP
  747. X-p
  748. XBy default, replies to messages posted to news groups go to the list; 
  749. Xthis option forces replies to be forwarded to the original author.
  750. X.TP
  751. X-P
  752. XBy default, replies to messages sent to subscribers and peers go to the
  753. Xlist; this option forces replies to be forwarded to the original author.
  754. X.TP
  755. X-m number
  756. XNormally, each outgoing message has one recipient. This flag switches to
  757. Xmulti-recipient outgoing messages and specifies the \fInumber\fP of recipients
  758. Xto be included in these messages.
  759. X.TP
  760. X-f
  761. XForward any messages from non-subscribers to the list's owner. By default,
  762. Xthey are returned to the sender.
  763. X.TP
  764. X-r
  765. XRestricted mail: \fIlist\fP will look at the ".restricted" file (see
  766. Xbelow) to get the name of the alternate recipients file. If the sender
  767. Xis listed in that ".restricted" file, his messages will be distributed
  768. Xto users listed in the alternate recipients file.
  769. X.TP
  770. X-M
  771. XThe list is moderated;
  772. Xall incoming messages not from the owner(s) are forwarded to the
  773. Xlist's primary owner for review and editing. The owner then sends back the
  774. Xones that are approved for posting (for an alternate scheme see the
  775. XMODERATED\ LISTS section below).
  776. X.TP
  777. X-d
  778. XForce a digest to be distributed. This flag is internally used by
  779. X\fIserverd\fP(1) when digest time has been reached for this list.
  780. X.TP
  781. X-i address
  782. XSend a partial digest to \fIaddress\fP (what has accumulated so far).
  783. XThis flag is internally used by
  784. X\fIlistserv\fP(1) when the user identified by \fIaddress\fP changes his
  785. X\fImail\fP mode from \fIdigest\fP to something else. Note that when 
  786. Xthe time arrives for the current digest to be distributed, this
  787. Xuser will get duplicate messages.
  788. X.TP
  789. X-v
  790. XPrint version information.
  791. X.TP
  792. X-D
  793. XTurns debugging on. When the \fIsystem\fP mailmethod is used (see server(1)), a
  794. Xcopy of the last SMTP transaction can be found in the files
  795. XHOMEDIR/sent and HOMEDIR/received.
  796. X.SH ADDING\ A\ NEW\ LIST
  797. XTo add a new list, first shut the system down by executing \fIstart\fP(1):
  798. X.sp
  799. X.in +2
  800. X\fI% start -k\fP
  801. X.in -2
  802. X.sp
  803. XThen edit the \fIconfig\fP file and add a line defining the
  804. Xnew list -- you may wish to add a comment and/or disable a few requests also.
  805. XA new alias has to be set up in /etc/aliases, /usr/lib/aliases
  806. Xor /usr/ucblib/aliases of the following form:
  807. X.nf
  808. X.sp
  809. Xlist_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f"
  810. X.sp
  811. X.fi
  812. XNote that \fIlist_alias\fP is all lower case and \fILIST_ALIAS\fP is all
  813. Xupper case. In this case \fIcatmail\fP(1) appends incoming mail to the list's
  814. Xmail file (HOMEDIR/lists/LIST_ALIAS/mail).
  815. XAlso keep in mind the case of reformatting messages as described in
  816. X\fIcatmail\fP(1).
  817. X.PP
  818. XFinally, restart the system. At this point, the file ".ignored" in the
  819. XHOMEDIR/lists/LIST_ALIAS directory may be edited to add more
  820. Xunwanted senders. You should also edit the files ".welcome" and ".info"
  821. Xin the list's subdirectory; the former is included in the return message
  822. Xfor a new subscription request for that list, and the latter
  823. Xis included in the return message for an \fIinformation\fP request for that
  824. Xlist (see \fIlistserv\fP(1)). These files may be simple text files, or shell
  825. Xscripts (see the HELP section in server(1)).
  826. X.SH ADDING\ A\ PEER\ LIST
  827. XPeer lists are mailing lists that happen to be subscribers to one
  828. Xor more of your own mailing lists; they handle local distribution of
  829. Xmessages just like you do at your own site. Peer lists can be mutual
  830. Xsubscribers, so that a message originating in a peer list gets distributed
  831. Xover there locally, and a copy is sent to the other for local distribution,
  832. Xand vice versa. An automatic mechanism is provided for avoiding loops.
  833. XA peer list can be added to
  834. Xa local mailing list by using the script \fIpeer\fP:
  835. X.sp
  836. Xpeer\ <LIST_ALIAS>\ <remote\ alias>\ <peer\ address>\ <remote\ ListServer\ address>
  837. X.sp
  838. Xwhere \fILIST_ALIAS\fP is a local list alias in capital letters, 
  839. X\fIremote\ alias\fP is the peer's alias on the remote machine,
  840. X\fIpeer\ address\fP is taken
  841. Xfrom the first line of the header of a test message sent to your host
  842. Xby the peer 
  843. X(the first line may be something like: "From peer@other-domain" -- see also
  844. Xthe discussion about aliases below), and
  845. X\fIremote\ ListServer\ address\fP is the full email address of the
  846. Xremote request-handler.
  847. X.PP
  848. XHere is an example for
  849. Xestablishing connection between two peer lists a@domain1 and b@domain2:
  850. XThe \fImanager\fP at domain1 issues the following command:
  851. X.sp
  852. X.nf
  853. Xpeer a b b@domain2 listserver@hdomain2
  854. X.fi
  855. X.sp
  856. XThe \fImanager\fP at domain2 issues the following command:
  857. X.sp
  858. X.nf
  859. Xpeer b a a@domain1 listserver@domain1
  860. X.fi
  861. X.sp
  862. XOnce these two commands are issued the connection is automatically
  863. Xset up.
  864. XPeer lists should make sure that only one of them posts
  865. Xto the same news group(s), and that only one of them receives articles
  866. Xfrom the same news group(s)/gateway(s).
  867. XLists handled by the same server cannot be mutual
  868. Xpeers. Finally, peer lists should not be regular subscribers (the
  869. X\fIpeer\fP script places them in a file called ".peers").
  870. X.SH NEWS\ GROUPS\ AND\ GATEWAYS
  871. XA mailing list may be linked with one or more news groups (or gateways) 
  872. Xfrom which
  873. Xit may receive messages for local distribution, and/or send messages to
  874. Xthe newsgroup(s) for posting \-\- in this case only messages from
  875. Xregular subscribers and peers are sent for posting, i.e. no news messages
  876. Xwill be posted to any news groups (or gateways). 
  877. XA news group or gateway is linked using the script \fInews\fP:
  878. X.sp
  879. X.ce
  880. Xnews\ <LIST_ALIAS>\ <news\ group>\ <email\ address>\ <mode>
  881. X.sp
  882. Xwhere \fILIST_ALIAS\fP is a local list alias (in capital letters) 
  883. Xthat is being linked to the news group, \fInews\ group\fP is the name
  884. Xof the news group (used only when posting) e.g. misc.test,
  885. X\fIemail\ address\fP is the address of the backbone or moderator of 
  886. Xthe news group, or the gateway, and it is taken
  887. Xfrom the first line of the header of a test message sent to your host
  888. Xby the group (the first line may be something like: 
  889. X"From gateway@foo ..." -- see also the discussion about aliases below);
  890. X\fImode\fP is one of the following:
  891. X.TP
  892. Xreceive
  893. XThe list will only be receiving messages from this news group and never
  894. Xpost to it. This allows access to the group (or gateway)
  895. Xto send articles to the list.
  896. X.TP
  897. Xsend_receive
  898. XThe list may be receiving messages from this news group, and it will post
  899. Xto it any messages from regular subscribers and peer lists (messages from
  900. Xnews groups are never posted to other news groups). This also
  901. Xallows access to the group (or gateway) to send articles to the list.
  902. X.PP
  903. XOf course, the news group's
  904. Xcaretaker has to be notified of the list's address so that articles will indeed
  905. Xbe sent to it. Finally, news groups should not be regular subscribers (the
  906. X\fInews\fP script places them in a file called ".news"). 
  907. X.PP
  908. XIf the config option \fIpost_mail\fP is used,
  909. Xthe system will use \fIinews\fP for posting, and it assumes that the
  910. Xpath to it is /usr/lib/news/inews, so make sure that \fIinews\fP resides there,
  911. Xor a link exists to it. In this case, the group's name is used for posting
  912. X(e.g. misc.test). If instead \fIgate_mail\fP is defined, messages will
  913. Xbe sent via email to news gateways (using the \fIemail\ address\fP)
  914. X-- the \fInews\ group\fP name has no significance in this case.
  915. X.SH MODERATED\ LISTS
  916. XThe system supports two schemes for moderating lists. The first scheme uses
  917. Xthe -M flag to \fIlist\fP(1), and in this case messages not from the
  918. Xlist's owner(s) are forwarded to the list's primary owner for review;
  919. Xthe owner then sends back the approved (and possibly edited) ones.
  920. X.PP
  921. XThe second scheme uses the -m flag to \fIcatmail\fP(1). In this case, the
  922. Xlist's alias is changed slightly in the aliases file:
  923. X.nf
  924. X.sp
  925. Xlist_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f -m"
  926. X.sp
  927. X.fi
  928. X\fIlist\fP(1) distributes messages from a file called \fImail\fP; by having
  929. Xincoming messages redirected to the file \fImoderated\fP (the effect of the
  930. X-m flag to \fIcatmail\fP(1)), the list's owner may \fIapprove\fP or
  931. X\fIdiscard\fP any number of these messages (see \fIlistserv\fP(1)).
  932. XWhenever a new
  933. Xmail message arrives for a moderated list, a copy is sent to the list's
  934. Xowner with instructions for approving or discarding it. These instructions
  935. Xinclude a unique tag number for identifying that message. When a message
  936. Xis approved, it is transferred to the \fImail\fP file for later delivery,
  937. Xand when discarded, it is simply removed from the
  938. X\fImoderated\fP file. This scheme cuts down on mail traffic.
  939. X.SH RESTRICTED\ MAIL
  940. XWhen the -r flag is used with \fIlist\fP(1), for every message received its
  941. Xsender is checked against a list of "restricted" email addresses, in the
  942. Xfile ".restricted" in the list's directory -- a
  943. Xsubset of the ".subscribers" file. If a match is found, mail is
  944. Xforwarded to the people listed in the file following this email
  945. Xaddress. If no match is found, the message is distributed to the
  946. Xregular subscribers. Note that the alternate recipients file should
  947. Xbe in the same format as the ".subscribers".
  948. X.SH .SUBSCRIBERS
  949. XThe format is as follows:
  950. X.PP
  951. XOne entry per line; each entry is the full email address of the subscriber
  952. Xas it appears in the "From " field, followed by the word "ACK" (in which
  953. Xcase his/her message will be sent back to him/her as an acknowledgement),
  954. X"NOACK" (the opposite), "POSTPONE" (no mail will be sent until the
  955. Xuser changes mode again),
  956. Xor "DIGEST" (digests are periodically sent), followed by a string that
  957. Xplays the role of the user's password, followed by either "YES" or "NO"
  958. Xwhich are the values of the conceal attribute, followed by the subscriber's
  959. Xname. See also \fIlistserv\fP(1).
  960. X.SH .RESTRICTED
  961. XThe format is as follows:
  962. X.PP
  963. XOne entry per line; each entry is the full email address of the
  964. Xsubscriber, followed by a file name where email addresses of recipients
  965. Xare listed (just like in the ".subscribers" file). Example:
  966. X.sp
  967. X.ce
  968. Xjdoe@foo.bar.com  HOMEDIR/lists/LIST_ALIAS/.recipients
  969. X.sp
  970. XIf the recipient file given is the word "NONE", then no one will receive
  971. Xany messages.
  972. X.SH .ALIASES
  973. XIt is possible that a subscriber's/peer's/news group's/gateway's email
  974. Xmay arrive using a different path than registered, which may raise
  975. Xsubscription issues. To work around this,
  976. Xeach list provides a ".aliases" file in its subdirectory, which may contain
  977. Xalternate email addresses to be used when checking for subscription. The
  978. Xformat is one line per alias with the following information:
  979. X.sp
  980. X.ce
  981. Xalias-address address-as-subscribed
  982. X.sp
  983. XPlease note that only the subscribed address is used for sending out
  984. Xemail (see next section about regular expressions).
  985. X.PP
  986. XThe aliased address may be a regular expression with egrep(1) style syntax,
  987. Xin which case
  988. Xthe following characters have special meanings: '~', if leading the
  989. Xregular expression it reverses its meaning; '|' and '&' separate multiple
  990. Xregular expressions (logical OR and AND); '<' '>' group regular expressions
  991. X(we preserve the meaning of the parentheses from ed(1), and remove the
  992. Xmeaning of < and > from ed(1) since in the ListServer context they are either
  993. Xthe default, or inappropriate).
  994. XThese can be used literally by escaping them
  995. Xwith '\\'. In addition, the following characters should be defined
  996. Xin matched pairs: (), <>, [], "". For example:
  997. X.sp
  998. X.ce
  999. Xjdoe@.*\\.bar\\.com jdoe@foo.bar.com
  1000. X.sp
  1001. Xwill enable this user to send messages from any machine in his local
  1002. Xnetwork and receive replies at foo.bar.com -- keep in mind that a '.'
  1003. Xmatches exactly one character, and '.*' matches zero or more characters.
  1004. XIn a more complicated example:
  1005. X.sp
  1006. X.ce
  1007. X~jdoe@cc.*|jdoe@....*\\.bar\\.com jdoe@foo.bar.com
  1008. X.sp
  1009. Xwill match if jdoe sends a message from a machine whose name does not start
  1010. Xwith 'cc', or from a machine whose name has at least 3 characters.
  1011. X.PP
  1012. XIf certain parts of the regular expression are parenthesized, then the
  1013. Xstrings that matched the subexpressions can be used in
  1014. Xthe 'address-as-subscribed' to form new return addresses; these matched
  1015. Xstrings are accessed by \fI\\n\fP where \fIn\fP is a digit between 1 and
  1016. X9. For example, if the sender is:
  1017. X.sp
  1018. X.ce
  1019. XGATE!HOP!USER@UUCP.SOME.COM
  1020. X.sp
  1021. Xand the entry in the ".aliases" file reads:
  1022. X.sp
  1023. X.ce
  1024. X[^!@]*!([^!@.]*)!([^!@]*)@.*    \\2@\\1.UUCP
  1025. X.sp
  1026. Xthen what will be returned as 'address-as-subscribed' is:
  1027. X.sp
  1028. X.ce
  1029. XUSER@HOP.UUCP
  1030. X.sp
  1031. XThis way you can map addresses coming in via various gateways to steady ones
  1032. X(\\2 refers to the second set of parentheses, and \\1 to the first).
  1033. XManagers may edit HOMEDIR/src/regex.c to test regular expression
  1034. Xbehavior, introduce ls(1) style meanings to the * and ? wild characters,
  1035. Xundefine ed(1) special characters, and enforce strict egrep(1) syntax (remove
  1036. Xthe meanings of ~ & < and >).
  1037. X.PP
  1038. XRegular expressions should be used with caution for obvious reasons.
  1039. X.PP
  1040. XIf someone is experiencing subscription
  1041. Xproblems, you may wish to add their alternate email address(es) in this
  1042. Xfile. This includes regular subscribers, news groups, peers and gateways.
  1043. XIf the sender is also a restricted subscriber, do not forget to put
  1044. Xanother entry in ".restricted" with the new alternate address. Any
  1045. Xnumber of aliases may be defined for each individual address.
  1046. X.PP
  1047. XIn addition, a ".aliases" file is also provided for Listserver
  1048. Xrequests and is under HOMEDIR. The same syntax is used, but each
  1049. Xentry has a slightly different meaning:
  1050. X.sp
  1051. X.ce
  1052. Xaddress-as-arrived address-used-for-reply
  1053. X.sp
  1054. XIn this case, \fIaddress-used-for-reply\fP will be used to reply to all
  1055. Xrequests sent in by \fIaddress-as-arrived\fP. A user may have any
  1056. Xnumber of aliases, but only the first one matching
  1057. X\fIaddress-as-arrived\fP will be used. Like before, the first argument may
  1058. Xbe a regular expression and the second may use the matches in the first.
  1059. X.sp
  1060. XFor each new list, the system puts the following default alias in its
  1061. X".aliases" file:
  1062. X.sp
  1063. X.ce
  1064. X^@.*:(.*)@(.*) \\1@\\2
  1065. X.sp
  1066. XThis removes source routing.
  1067. X.SH .IGNORED
  1068. XAs described before, the system's home directory as well as every list's
  1069. Xsubdirectory contains a ".ignored" file which is used to filter out messages
  1070. Xsent by certain users. The default file contains entries for server,
  1071. Xbin, and sys; you may wish to add an entry for every list alias that is
  1072. Xdefined on your system. A list's ".ignored" file also contains an
  1073. Xentry of its alias and full email address, as well as the server account's
  1074. Xfull email address.
  1075. X.PP
  1076. XEntries in this file may also be regular expressions as explained in the
  1077. Xprevious section. For example, to restrict requests (and postings)
  1078. Xto .com and .edu domain addresses, one may add:
  1079. X.sp
  1080. X.ce
  1081. X~<.*\\.com|.*\\.edu>
  1082. X.sp
  1083. XNotice, it is incorrect to list them as follows:
  1084. X.sp
  1085. X.ce
  1086. X~.*\\.com
  1087. X.ce
  1088. X~.*\\.edu
  1089. X.sp
  1090. Xas anything not from the .com domain matches the first regular expression,
  1091. Xand therefore will be ignored.
  1092. XTo refuse access to certain user names and certain sites one may include:
  1093. X.sp
  1094. X.ce
  1095. X \.*\\.bar\\.com|jdoe@.*
  1096. X.sp
  1097. XThe system's manager should use extra caution when adding regular expressions
  1098. Xto the system's ".ignored" file, because a simple '.*' prohibits anyone from
  1099. Xusing its services.
  1100. X.SH SEE\ ALSO
  1101. Xcatmail(1), listserv(1), server(1), serverd(1), start(1)
  1102. X.SH AUTHOR
  1103. X.nf
  1104. XAnastasios C. Kotsikonas
  1105. XCopyright (c) 1991-93, Anastasios Kotsikonas
  1106. XComments to tasos@cs.bu.edu
  1107. X.fi
  1108. *-*-END-of-doc/list.1-*-*
  1109. echo x - doc/listserv.1
  1110. sed 's/^X//' >doc/listserv.1 <<'*-*-END-of-doc/listserv.1-*-*'
  1111. X.\" UNIX ListServer System
  1112. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  1113. X.\"
  1114. X.TH listserv 1 "UNIX ListServer"
  1115. X.SH NAME
  1116. X\fBlistserv\fP \- process requests sent to the UNIX ListServer request handler
  1117. X.SH SYNOPSIS
  1118. X\fBlistserv\fP [\fB-1\fP] [\fB-e\fP] [\fB-i\fP] [\fB-n\fP] {[\fB-a\fP\ <\fBLIST_ALIAS\fP>]}* {[\fB-r\fP\ <\fBreq\fP>]}* {[\fB-d\fP\ <\fBreq\fP>]}* {[\fB-b\fP\ <\fBreq\fP>]}* [\fB-B\fP] [\fB-D\fP]
  1119. X.SH DESCRIPTION
  1120. X\fIlistserv\fP processes user requests sent to \fIlistserver@your-domain\fP,
  1121. Xforwards requests about known remote lists, and processes list-owner
  1122. Xadministrative requests (see also the LIST\ OWNERS section below).
  1123. XEach request should appear in a separate line with any possible arguments.
  1124. XThe file
  1125. X".ignored" is used in the system's home directory to filter out unwanted
  1126. Xsenders. If the system is not instructed to ignore invalid requests
  1127. X(see the CONFIG section in server(1)), the sender is notified of the first
  1128. Xinvalid request; all subsequent requests are ignored.
  1129. XFor each successfully completed request,
  1130. Xa confirmation is sent back to the sender.
  1131. X.PP
  1132. X\fIlistserv\fP stops reading
  1133. Xrequests when it encounters the string "--" in a line by itself, which
  1134. Xon most systems signifies the start of the .signature message, or at the
  1135. Xfirst occurence of a thankful request. \fIlistserv\fP reads the \fIconfig\fP
  1136. Xfile (see server(1)).
  1137. X.PP
  1138. XSubscriptions may be
  1139. Xmanager-approved (private lists), files and archive indices may be password
  1140. Xprotected (private archives), and requests may be placed in a batch queue.
  1141. XA single request may span multiple lines if each part ends with
  1142. X\fI&\\n\fP.
  1143. X.SH USER\ REQUESTS
  1144. XThe following user requests are recognized (requests may be abbreviated):
  1145. X.TP
  1146. X\fIhelp\fP\ [topic]
  1147. XSend a help message on all valid requests or the selected topic (possibly
  1148. Xa request) only.
  1149. X.TP
  1150. X\fIset\fP\ list\ [option arg(s)]
  1151. XWithout the optional arguments, return the current values for all options
  1152. Xset for \fIlist\fP; otherwise, 
  1153. Xset subscriber preferences for \fIlist\fP.
  1154. X.sp
  1155. X\fIoption\fP can be:
  1156. X.in +2
  1157. X.sp
  1158. X\fImail\fP: set mail preferences.
  1159. X.sp
  1160. X.in +2
  1161. X\fIarg\fP has to be one of the following:
  1162. X.sp
  1163. X.in +2
  1164. X\fIack\fP: send a copy of the current message to the original sender.
  1165. X.sp
  1166. X\fInoack\fP: do not send a copy of the current message to the original sender.
  1167. XThis is the default for newly subscribed users.
  1168. X.sp
  1169. X\fIpostpone\fP: do not send any messages to the particular subscriber until
  1170. Xhe changes status again.
  1171. X.sp
  1172. X\fIdigest\fP: do not send individual messages to the particular
  1173. Xsubscriber. Instead, store messages in a digest and send it when the
  1174. Xdigest exceeds a specified number of lines, or when a specified amount
  1175. Xof time has passed since the last digest was sent.
  1176. X.sp
  1177. XIf the mail mode is changed from \fIdigest\fP to anything else,
  1178. Xall messages currently stored for the next digest will be sent to the
  1179. Xsubscriber at once, in digest format.
  1180. X.in -2
  1181. X.in -2
  1182. X.sp
  1183. X\fIpassword\fP: change the password (used to establish
  1184. Xsubscriber privileges when connecting to ListServer for a "live" session and
  1185. Xfor the option below).
  1186. X.sp
  1187. X.in +2
  1188. X\fIargs\fP must be: old-password new-password.
  1189. X.in -2
  1190. X.sp
  1191. X\fIaddress\fP: set the address the user is subscribed with (if allowed for this
  1192. Xlist).
  1193. X.sp
  1194. X.in +2
  1195. X\fIargs\fP must be: current-password new-address.
  1196. X.sp
  1197. X.in -2
  1198. X\fIconceal\fP: set the user's visibility.
  1199. X.sp
  1200. X.in +2
  1201. X\fIarg\fP must be one of the following:
  1202. X.sp
  1203. X.in +2
  1204. X\fIyes\fP: the user is not listed in \fIrecipients\fP and \fIstatistics\fP
  1205. Xrequests.
  1206. X.sp
  1207. X\fIno\fP: the user's email address and name are made public.
  1208. X.in -2
  1209. X.in -2
  1210. X.in -2
  1211. X.TP
  1212. X\fIsubscribe\fP\ list\ full_name
  1213. XSubscribe the sender to \fIlist\fP (note, his email address is used for
  1214. Xsubscription, not his \fIfull_name\fP). A password is assigned by the
  1215. Xsystem at that time and is included in the reply message to the new
  1216. Xsubscriber. The password is to be used when connecting to the interactive
  1217. Xpart of the system for identification purposes, and for changing the
  1218. Xsubscription address if allowed for this list.
  1219. X.TP
  1220. X\fIwhich\fP
  1221. XGet a list of local mailing lists to which the sender has subscribed.
  1222. X.TP
  1223. X\fIunsubscribe\fP\ list
  1224. XRemove the sender from the specified \fIlist\fP.
  1225. X.TP
  1226. X\fIsignoff\fP\ list
  1227. XAlias of the unsubscribe request.
  1228. X.TP
  1229. X\fIrecipients\fP\ list
  1230. XGet a list of all subscribers of \fIlist\fP. The request is also forwarded
  1231. Xto all peer lists, and the servers handling them will respond accordingly.
  1232. XThe user is notified when this request is being forwarded. If a list
  1233. Xis private, only members may issue this request.
  1234. X.TP
  1235. X\fIreview\fP\ list
  1236. XAlias of the recipients request.
  1237. X.TP
  1238. X\fIinformation\fP\ list
  1239. XGet information about a particular \fIlist\fP.
  1240. X.TP
  1241. X\fIstatistics\fP\ list\ {[subscriber\ email\ address(es)]\ |\ [-all]}
  1242. XObtain a count of messages sent per subscriber to the specified \fIlist\fP,
  1243. Xor by those subscribers given as argument only (wild characters are
  1244. Xsupported). If \fI-all\fP is specified, then statistics are compiled for all
  1245. Xusers (currently subscribed or not) who have posted to the list in the past.
  1246. XThe request is also forwarded to all peer lists and the
  1247. Xservers handling them will respond accordingly.
  1248. XThe user is notified when this request is being forwarded.
  1249. XIf a list is private, only members may issue this request.
  1250. X.TP
  1251. X\fIrun\fP\ list\ [password\ cmd\ [args]]
  1252. XWithout the optional arguments, just list all commands that may be executed
  1253. Xby subscribers of this \fIlist\fP. Otherwise, run \fIcmd\fP with the
  1254. Xoptional \fIargs\fP, if the correct \fIpassword\fP is provided. The reply
  1255. Xwill contain the output from stdout and/or stderr.
  1256. X.TP
  1257. X\fIlists\fP
  1258. XObtain a list of mailing list addresses that are serviced by this system,
  1259. Xwith a small description of their purpose. If remote lists (see below)
  1260. Xare also defined, their addresses and descriptive messages will also be
  1261. Xincluded.
  1262. X.TP
  1263. X\fIindex\fP\ [archive\ |\ path-to-archive]\ [/password]\ [-all]
  1264. XObtain an index of files in the specified \fIarchive\fP (or the master archive
  1265. Xif none specified) and all of its subarchives if the the \fI-all\fP
  1266. Xoption is specified. Certain archives may be
  1267. Xprivate, and these require a \fI/password\fP to be able to obtain their
  1268. Xindices. Archives on different places in the hierarchy may have the same
  1269. Xnames and they can be distinguished by specifying paths to them; 
  1270. X\fIpath-to-archive\fP has the form \fIarchive[/archive[/archive...]]\fP.
  1271. X\fIindex\fP requests always report the paths to the archives they list.
  1272. X.TP
  1273. X\fIget\fP\ <archive\ |\ path-to-archive>\ file\ [/password]\ [parts]
  1274. XGet the specified \fIfile\fP from the \fIarchive\fP given. The file 
  1275. Xmay have been
  1276. Xsplit into smaller parts due to its size, in which case each part will
  1277. Xbe sent in a different email message. If only certain \fIparts\fP are desired,
  1278. Xthey may be given as arguments (numbers, separated by spaces -- ranges
  1279. Xare not recognized). Certain archives may be private, in which case their
  1280. X\fI/password\fP has to be provided in order to get the desired files.
  1281. XArchives on different places in the hierarchy may have the same
  1282. Xnames and they can be distinguished by specifying paths to them;
  1283. X\fIpath-to-archive\fP has the form \fIarchive[/archive[/archive...]]\fP.
  1284. XIf the file is pure binary, it will be uuencoded first.
  1285. X.TP
  1286. X\fIsearch\fP\ <archive\ |\ path-to-archive>\ [/password]\ [-all]\ <pattern>
  1287. XSearch all files in the specified archive (and all of its subarchives if
  1288. X\fI-all\fP) and return lines that match the \fIpattern\fP.
  1289. XThe pattern can be an extended regular expression with egrep(1)-style syntax,
  1290. Xwith support for the following additional operators: '~', if leading the
  1291. Xregular expression it reverses its meaning; '|' and '&' separate multiple
  1292. Xregular expressions (logical OR and AND); '<' '>' group regular expressions
  1293. X(we preserve the meaning of the parentheses from ed(1), and remove the
  1294. Xmeaning of < and > from ed(1) since in the ListServer context they are either
  1295. Xthe default, or inappropriate).
  1296. XThese can be used literally by escaping them
  1297. Xwith '\\'. In addition, the following characters should be defined
  1298. Xin matched pairs: (), <>, []. \fIpattern\fP may be enclosed in single
  1299. Xor double quotes. Pattern matching is case insensitive.
  1300. X.TP
  1301. X\fIfax\fP\ <fax-no>\ <archive\ |\ path-to-archive>\ file\ [/password]\ [parts]
  1302. XSame as the \fIget\fP request except that the files are faxed to the
  1303. Xspecified number.
  1304. X.TP
  1305. X\fIrelease\fP
  1306. XGet information about the current release of this server system.
  1307. X.TP
  1308. X\fIexecute\fP\ password\ #command\ [arguments]
  1309. XIntended for the system's \fImanager\fP, this will execute the UNIX \fIcommand\fP
  1310. Xwith the optional \fIarguments\fP and send the output (if any) from stdout
  1311. Xand/or stderr to the sender. See the sample \fIconfig\fP file for
  1312. X\fIpassword\fP definition.
  1313. X.PP
  1314. XFor a list of the list administration requests that may be issued by list
  1315. Xowners, see the LIST\ OWNERS section below.
  1316. X.SH OPTIONS
  1317. XThe following command line options are recognized:
  1318. X.TP
  1319. X-1
  1320. XExecute only once; process any requests and return control to
  1321. X\fIserverd\fP(1); any new messages that may have arrived in the meantime will
  1322. Xbe processed at a later time. Without this option, \fIlistserv\fP will be
  1323. Xlistening for requests for ever. \fIserverd\fP(1)
  1324. Xuses this option by default when spawning \fIlisterv\fP.
  1325. X.TP
  1326. X-e
  1327. XEcho reports to the screen; it has no effect if the system has been compiled
  1328. Xwith -DSYSLOG.
  1329. X.TP
  1330. X-i
  1331. XGo to interactive mode -- messages by \fIlistserv\fP are not mailed out
  1332. Xbut instead \fIserverd\fP(1) reads them during its interactive session. Do not
  1333. Xuse this option in the \fIconfig\fP file (see server(1)).
  1334. X.TP
  1335. X-n
  1336. XBy default, peer servers are notified upon \fIstatistics\fP and
  1337. X\fIrecipients\fP requests. The system uses a protocol for avoiding
  1338. Xloops as described in \fIserver(1)\fP.
  1339. XIf you detect loops with other servers, you should use this option to
  1340. Xturn off notification of peer servers.
  1341. X.TP
  1342. X-a LIST_ALIAS
  1343. XUsually, subscriptions are automatic. This option turns off automatic
  1344. Xsubscription to the specified list (\fILIST_ALIAS\fP should be in capital
  1345. Xletters), and makes this list private (members only may issue \fIrecipients\fP
  1346. Xand \fIstatistics\fP requests). The sender is notified of this effect,
  1347. Xand a message is sent
  1348. Xto the list's owner requesting his/her approval, with instructions for
  1349. Xplacing the subscription. Notice that the specified list has to be defined
  1350. Xbeforehand via a \fIlist\fP directive in the \fIconfig\fP file. This
  1351. Xoption may be repeated any number of times.
  1352. X.TP
  1353. X-c LIST_ALIAS
  1354. XConceal \fILIST_ALIAS\fP from \fIlists\fP requests.
  1355. X.TP
  1356. X-r request
  1357. XPlace a restriction on the specified server \fIrequest\fP as outlined above.
  1358. XIf the number of users on the system at the time the request is about
  1359. Xto be processed is above the limit
  1360. Xgiven in the \fIconfig\fP file (using the \fIrestriction\fP directive),
  1361. Xthe request is rejected \-\- meant for requests that may take a 
  1362. Xconsiderable amount
  1363. Xof resources such as the \fIstatistics\fP request \-\- this option may
  1364. Xbe repeated any number of times. List administration requests are not
  1365. Xsubject to these restrictions (see later on).
  1366. X.TP
  1367. X-d request
  1368. XDisable \fIrequest\fP, i.e. make it totally unknown to the server \-\- this
  1369. Xsupersedes any \fIdisable\fP directives for this request in the \fIconfig\fP
  1370. Xfile, i.e. this request will not be recognized for any list (see
  1371. X\fIserver(1)\fP).
  1372. XHowever, help is still available for that request. List administration
  1373. Xrequests are also subject to these restrictions (see later on). This
  1374. Xoption may be repeated any number of times.
  1375. X.TP
  1376. X-b request
  1377. XAll such \fIrequest\fPs will be batch-processed if they arrive between
  1378. Xthe hours specified in the \fIconfig\fP file.
  1379. XThis option may be repeated any number of times.
  1380. X.TP
  1381. X-B
  1382. XProcess the batch queue. This is done automatically by \fIserverd\fP(1) after
  1383. Xmidnight every day, or when the system is restarted, so no further action
  1384. Xneeds to be taken. Caution:
  1385. Xdo not place this option in the definition of \fIserver\fP in the
  1386. X\fIconfig\fP file. If you do so, only the batch queue
  1387. Xwill be processed (no new requests will be processed, ever).
  1388. XThe batch queue is processed once a day only, unless the system
  1389. Xis restarted repeatedly.
  1390. X.TP
  1391. X-D
  1392. XTurns debugging on. When the \fIsystem\fP mailmethod is used, a
  1393. Xcopy of the last SMTP transaction can be found in the files
  1394. XHOMEDIR/sent and HOMEDIR/received.
  1395. X.SH PEER\ SERVERS
  1396. XThe system supports the notion of remote lists. A ListServer may know of
  1397. Xremote lists served by remote servers. Yet users may send requests about
  1398. Xthese remote lists to this server, which will in turn forward
  1399. Xthem to the remote servers. The user is notified when a list is not local
  1400. Xand his/her request is about to be forwarded.
  1401. XA \fIlists\fP request will tell the user which remote lists are known 
  1402. Xto this server.
  1403. X.PP
  1404. XRemote lists should be made known
  1405. Xto this server only if they are served by a server of version 5.31 or higher.
  1406. XThis restriction is posed because of incompatible requests
  1407. Xacross various list server systems; for example, the meaning of an 
  1408. X\fIinformation\fP request is different on a BITNET Listserv. See the
  1409. Xdiscussion about the \fIconfig\fP file for setting up remote lists.
  1410. X.PP
  1411. XIn addition, \fIrecipients\fP and \fIstatistics\fP requests are
  1412. Xforwarded to the servers handling peer lists (the -n flag to \fIlistserv\fP
  1413. Xturns this feature off).
  1414. X.SH LIST\ OWNERS
  1415. XList owners are individuals responsible for list administration via
  1416. Xmail requests. Thus, list owners may be remotely located. Each list
  1417. Xhas to have at least one list owner. These owners may be different than
  1418. Xthe system's \fImanager\fP, and have special privileges: they may issue
  1419. Xrequests on users' behalf (add a user, remove a user, etc.) overriding
  1420. Xsystem restrictions set on regular users (these include disabled commands
  1421. Xas described above),
  1422. Xobtain reports about the lists they administer,
  1423. Xappend to the ".aliases" and ".ignored" files, change the welcoming
  1424. X(".welcome") and informative (".info") messages, as well as other system
  1425. Xfiles such as the aliases file (".aliases"), the ".ignored" file, the
  1426. Xsubscribers file (".subscribers"), the news file (".news") and the
  1427. Xpeers file (".peers"). In addition, they may moderate their lists and they
  1428. Xreceive various error messages pertaining to their lists.
  1429. XAll administrative requests are author authenticated and
  1430. Xpassword protected. Whenever a message cannot be author authenticated,
  1431. Xthe list's owner and \fImanager\fP are notified.
  1432. X.PP
  1433. XOn the other hand, list owners may not add restricted users; this
  1434. Xservice can be provided by contacting the system's \fImanager\fP.
  1435. X.PP
  1436. XList owners may also receive copies of user requests and/or error
  1437. Xmessages such as invalid postings, syntax errors on requests, etc.
  1438. XThese options are described in the following sections.
  1439. X.TP
  1440. XDefining list owners
  1441. XOnce a new mailing list is defined in the \fIconfig\fP file, the list's
  1442. Xowner address and access password are provided to the \fIlist\fP directive.
  1443. XOf course, this password should be made known to the owner; it
  1444. Xwill be needed for all administrative requests. Next, the owner's
  1445. Xaddress has to be registered in HOMEDIR/owners; the \fImanager\fP
  1446. Xsimply edits this file adding the owner's address along with the
  1447. Xlist's name (alias) he is assigned to, followed by any
  1448. Xpreferences (see below).
  1449. XMultiple owners for a list may be defined by adding their addresses to
  1450. Xthis file, and providing them with the list's password. However, only
  1451. Xthe primary owner's address (as defined by the \fIlist\fP directive) will
  1452. Xbe used as reference in correspondence and for system-error notifications,
  1453. Xand only the primary owner will be forwarded messages from his moderated list
  1454. Xfor approval.
  1455. XThe \fImanager\fP should also add his address (login name) to this file.
  1456. X.TP
  1457. XOwner preferences
  1458. XThe primary owner may wish to be copied on certain replies to user
  1459. Xrequests (such as subscribe), on error conditions (rejected
  1460. Xpostings, invalid requests, etc.), or on all cases. These preferences
  1461. Xare listed in the \fIowners\fP file on the line his address and list are
  1462. Xdefined. Valid preferences are:
  1463. X.sp
  1464. X.in +2
  1465. XCCSET: copy on \fIset\fP requests.
  1466. X.sp
  1467. XCCSUBSCRIBE: copy on \fIsubscribe\fP requests.
  1468. X.sp
  1469. XCCUNSUBSCRIBE: copy on \fIunsubscribe\fP requests.
  1470. X.sp
  1471. XCCRECIPIENTS: copy on \fIrecipients\fP requests.
  1472. X.sp
  1473. XCCINFORMATION: copy on \fIinformation\fP requests.
  1474. X.sp
  1475. XCCSTATISTICS: copy on \fIstatistics\fP requests.
  1476. X.sp
  1477. XCCRUN: copy on \fIrun\fP requests.
  1478. X.sp
  1479. XCCPRIVATE: copy on requests rejected because they are open only to
  1480. Xthe list's members.
  1481. X.sp
  1482. XCCERRORS: copy on various error conditions.
  1483. X.sp
  1484. XCCALL: all of the above.
  1485. X.in -2
  1486. X.sp
  1487. XOwner preferences are optional.
  1488. X.PP
  1489. XThe \fImanager\fP may define preferences
  1490. Xfor himself as well by using the keyword \fIserver\fP in place of a
  1491. Xlist alias. However, such preferences make sense only in the following
  1492. Xcases:
  1493. X.sp
  1494. X.in +2
  1495. XCCGET: copy on \fIget\fP requests.
  1496. X.sp
  1497. XCCINDEX: copy on \fIindex\fP requests.
  1498. X.sp
  1499. XCCLISTS: copy on \fIlists\fP requests.
  1500. X.sp
  1501. XCCRELEASE: copy on \fIrelease\fP requests.
  1502. X.sp
  1503. XCCHELP: copy on \fIhelp\fP requests.
  1504. X.sp
  1505. XCCERRORS: copy on various error conditions.
  1506. X.sp
  1507. XCCALL: all of the above.
  1508. X.in -2
  1509. X.sp
  1510. XManager preferences are optional.
  1511. X.TP
  1512. XOwner privileges
  1513. XWhenever an owner issues a user request on a user's behalf (see below),
  1514. Xall restrictions, including disabled commands, do not apply. All other
  1515. Xadministrative requests are subject to restrictions set by the \fImanager\fP.
  1516. XAll requests (user and administrative) are subject to batch-processing.
  1517. X.TP
  1518. XAdministrative requests
  1519. XThe following requests may be issued by a list's owner:
  1520. X.TP
  1521. X\fIsystem\fP\ list password\ user-address\ #user-request
  1522. XThis request overrides all system restrictions and executes
  1523. X\fIuser-request\fP on behalf of \fIuser-address\fP; this
  1524. Xaddress has to appear as listed in the ".subscribers" file, where applicable.
  1525. XThe most frequent use of the \fIsystem\fP request is to subscribe a user
  1526. Xto a private list. For example:
  1527. X.sp
  1528. X.in +2
  1529. Xsystem herc herc1 john@foo #subscribe herc Some Name
  1530. X.in -2
  1531. X.sp
  1532. XIf a \fIuser-request\fP refers to a list, this list has to be
  1533. X\fIlist\fP, so that a list's owner may not have privileges over another
  1534. Xlist's affairs. Note that all replies about \fIuser-request\fP are
  1535. Xforwarded to \fIuser-address\fP, not the owner; therefore, care has to
  1536. Xbe taken to avoid syntax errors. The \fIsystem\fP request is not subject
  1537. Xto restrictions, disabled requests, and private list subscription
  1538. Xverification (it is still subject to private list review as outlined 
  1539. Xabove, and batching). To remove a member from his list, the owner may issue the
  1540. Xfollowing request:
  1541. X.sp
  1542. X.in +2
  1543. Xsystem herc herc1 john@foo #unsubscribe herc
  1544. X.in -2
  1545. X.sp
  1546. XTo bypass restrictions and review his list, the owner may issue the
  1547. Xfollowing:
  1548. X.sp
  1549. X.in +2
  1550. Xsystem venus venus1 his-address #review venus
  1551. X.in -2
  1552. X.sp
  1553. XIn general, \fIuser-request\fP may be any of the recognized user requests
  1554. Xdescribed under \fIlistserv\fP. The pound sign is mandatory.
  1555. XThere is no help available to users for this request for security reasons.
  1556. X.TP
  1557. X\fIapprove\fP\ list\ password\ tag
  1558. XWhenever a new message arrives for a moderated list a copy is sent to the
  1559. Xlist's owner soliciting his approval -- proper instructions for approving
  1560. Xor discarding a message are included. This request
  1561. Xapproves the message identified by the \fItag\fP number for posting to
  1562. X\fIlist\fP. The tag number is
  1563. Xprovided to the list's owner by \fIlistserv\fP and is unique.
  1564. X.TP
  1565. X\fIdiscard\fP\ list\ password\ tag
  1566. XIn contrast to the above request, this discards the message identified
  1567. Xby \fItag\fP. Messages that are not approved or discarded remain in the
  1568. Xlist's \fImoderated\fP file (see \fIlist(1)\fP).
  1569. X.TP
  1570. X\fIreports\fP\ list\ password
  1571. XObtain all reports pertinent to \fIlist\fP; this will send two mail messages:
  1572. Xone with the current report (HOMEDIR/lists/ALIAS/.report.list), and
  1573. Xone with the previously archived ones (HOMEDIR/lists/ALIAS/.rep.list.acc);
  1574. Xsee the REPORTS section below. Once the ".rep.list.acc" file is sent,
  1575. Xit is shrunk in size, therefore the owner should make sure he keeps the
  1576. Xcopy he receives.
  1577. X.sp
  1578. XThis request has no effect if the system is using syslog(3) to generate
  1579. Xreports.
  1580. X.TP
  1581. X\fIedit\fP\ list\ password\ file
  1582. XObtain the specified \fIfile\fP for editing; candidate files are:
  1583. X.sp
  1584. X.in +2
  1585. X\fIaliases\fP: obtain the list's aliases file.
  1586. X.sp
  1587. X\fIignored\fP: obtain the list's list of unwelcome addresses.
  1588. X.sp
  1589. X\fIinfo\fP: obtain the list's informative message.
  1590. X.sp
  1591. X\fIsubscribers\fP: obtain the list's subscribers list.
  1592. X.sp
  1593. X\fIwelcome\fP: obtain the list's welcoming message.
  1594. X.sp
  1595. X\fInews\fP: obtain the list's list of newsgroup connections.
  1596. X.sp
  1597. X\fIpeers\fP: obtain the list's peers.
  1598. X.in -2
  1599. X.TP
  1600. X\fIput\fP\ list\ password\ keyword\ [args]
  1601. XThis enables the list's owner to append to the ".aliases" and ".ignored" files,
  1602. Xand replace his list's ".welcome", ".info", ".aliases", ".ignored",
  1603. X".subscribers", ".news" and ".peers" files, depending
  1604. Xon the \fIkeyword\fP. Valid \fIkeyword\fPs are:
  1605. X.in +2
  1606. X.sp
  1607. X\fIalias\fP: Add a user address alias to the list's and system's ".aliases"
  1608. Xfiles (see .ALIASES below). This requires the new address and the address
  1609. Xused for subscription as arguments:
  1610. X.sp
  1611. Xput <list> <password> alias <new-alias> <address-as-subscribed>
  1612. X.sp
  1613. XFor example:
  1614. X.sp
  1615. X.in +2
  1616. Xput venus venus1 alias foo!john john@foo
  1617. X.in -2
  1618. X.sp
  1619. X\fIignore\fP: Add a user address to the list's ".ignore" file only. Of
  1620. Xcourse this address has to be provided as argument:
  1621. X.sp
  1622. Xput <list> <password> ignore <address-as-subscribed-or-aliased>
  1623. X.sp
  1624. XFor example:
  1625. X.sp
  1626. X.in +2
  1627. X.nf
  1628. Xput ermis ermis1 ignore jack@foo
  1629. Xput ermis ermis1 ignore foo!jack
  1630. X.fi
  1631. X.in -2
  1632. X.sp
  1633. X.nf
  1634. X\fIwelcome\fP,
  1635. X\fIinfo\fP,
  1636. X\fIaliases\fP,
  1637. X\fIignored\fP,
  1638. X\fIsubscribers\fP,
  1639. X\fInews\fP,
  1640. X.fi
  1641. X\fIpeers\fP: Create a new system file.
  1642. X.sp
  1643. XFor example:
  1644. X.sp
  1645. X.in +2
  1646. X.nf
  1647. Xput <list> <password> subscribers
  1648. Xtasos ACK PASSWORD NO Tasos Kotsikonas
  1649. Xjohn NOACK PASS1 NO John Doe
  1650. X.fi
  1651. X.in -2
  1652. X.sp
  1653. XNo arguments are needed. The text that is to
  1654. Xgo to the corresponding file starts at the line following this request
  1655. Xand spans till the end of the mail message. Thus, no more requests can
  1656. Xbe made in the same mail message -- they are treated as regular text;
  1657. Xsignature lines also signify the end of text, provided they start with
  1658. X"--" in a single line.
  1659. X.in -2
  1660. X.sp
  1661. XA confirmation is sent to the owner once a \fIput\fP request is successfully
  1662. Xprocessed.
  1663. X.SH OWNERS
  1664. XThe format of the \fIowners\fP file is as follows:
  1665. X.sp
  1666. XOne entry per line; each entry is the full email address of a list's
  1667. Xowner, followed by the list alias he owns, followed by any optional
  1668. Xpreferences. If the keyword \fIserver\fP is specified in place of the
  1669. Xlist alias, then preferences are defined for the \fImanager\fP.
  1670. X.SH SEE\ ALSO
  1671. Xcatmail(1), farch(1), list(1), queue(1), server(1), serverd(1), start(1)
  1672. X.SH AUTHOR
  1673. X.nf
  1674. XAnastasios C. Kotsikonas
  1675. XCopyright (c) 1991-93, Anastasios Kotsikonas
  1676. XComments to tasos@cs.bu.edu
  1677. X.fi
  1678. *-*-END-of-doc/listserv.1-*-*
  1679. echo x - doc/queue.1
  1680. sed 's/^X//' >doc/queue.1 <<'*-*-END-of-doc/queue.1-*-*'
  1681. X.\" UNIX ListServer System
  1682. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  1683. X.\"
  1684. X.TH queue 1 "UNIX ListServer"
  1685. X.SH NAME
  1686. X\fBqueued\fP \- UNIX ListServer mail queue daemon
  1687. X.SH SYNOPSIS
  1688. X\fBqueued\fP <\fBfrequency\fP>
  1689. X.SH NAME
  1690. X\fBpqueue\fP \- process the specified mail queue files
  1691. X.SH SYNOPSIS
  1692. X\fBpqueue\fP [\fB-e\fP] [\fB-D\fP] <\fBfiles\fP>
  1693. X.SH OVERVIEW
  1694. XThis part of the UNIX ListServer system can be employed only when using the
  1695. X\fIsystem\fP mailmethod (see \fIserver\fP(1)).
  1696. XMessages and replies to requests not
  1697. Xdelivered due to network problems are queued by the system in the
  1698. Xdirectory HOMEDIR/mqueue. This part of the system attempts periodic
  1699. Xredelivery of these files. If problems still persist, files (messages)
  1700. Xthat cannot be delivered are requeued.
  1701. X.SH DESCRIPTION:\ queued
  1702. XThis is the daemon that looks for files in the mail queue. It uses
  1703. X\fIpqueue\fP for redelivery. The queue is checked every \fIfrequency\fP
  1704. Xseconds. Whenever an error occurs with \fIpqueue\fP, \fIqueued\fP sends
  1705. Xa mail message to \fImanager\fP (as defined in the \fIconfig\fP file)
  1706. Xand aborts.
  1707. X.PP
  1708. X\fIqueued\fP is not spawned by \fIstart\fP(1) in order to reduce the number of
  1709. Xprocesses running, since the probability of messages being queued is
  1710. Xvery low. Instead, it should be started manually whenever there are
  1711. Xfiles in the mail queue directory.
  1712. X.SH DESCRIPTION:\ pqueue
  1713. XThe \fIfiles\fP given as arguments are redelivered. If any of these
  1714. Xcannot be redelivered, they are requeued and will be processed in the next
  1715. Xrun. \fIpqueue\fP reports to the file HOMEDIR/.report.pqueue
  1716. X.PP
  1717. XThe following command line options are recognized:
  1718. X.TP
  1719. X-e
  1720. XEcho reports to the screen; it has no effect if the system has been compiled
  1721. Xwith -DSYSLOG.
  1722. X.TP
  1723. X-D
  1724. XTurns debugging on; a copy of the last SMTP transaction can be found in 
  1725. Xthe files HOMEDIR/sent and HOMEDIR/received. Warning: these files
  1726. Xare also used by \fIlist\fP(1) and \fIlistserv\fP(1) when they have their
  1727. Xdebug mode on, so use caution.
  1728. X.SH NOTE
  1729. XThis mail queueing system should not be confused with the one implemented
  1730. Xby sendmail(1).
  1731. X.SH SEE\ ALSO
  1732. Xserver(1)
  1733. X.SH AUTHOR
  1734. X.nf
  1735. XAnastasios C. Kotsikonas
  1736. XCopyright (c) 1991-93, Anastasios Kotsikonas
  1737. XComments to tasos@cs.bu.edu
  1738. X.fi
  1739. *-*-END-of-doc/queue.1-*-*
  1740. echo x - doc/server.1
  1741. sed 's/^X//' >doc/server.1 <<'*-*-END-of-doc/server.1-*-*'
  1742. X.\" UNIX ListServer System
  1743. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  1744. X.\"
  1745. X.TH server 1 "UNIX ListServer"
  1746. X.SH NAME
  1747. XUNIX ListServer version 6.0
  1748. X.SH OVERVIEW
  1749. XThis is a system that implements various mailing lists with one
  1750. Xlist server. It is automated, and obliterates the need for user intervention
  1751. Xand maintenance of multiple aliases of the form "list, list-owner,
  1752. Xlist-request", etc. There is support provided for public and private 
  1753. Xhierarchical archives,
  1754. Xmoderated and non-moderated lists, peer lists, peer servers, private
  1755. Xlists, address aliasing, news connections and gateways, mail queueing,
  1756. Xdigests, list ownership, owner preferences, crash recovery, batch
  1757. Xprocessing, configurable headers, regular expressions, archive searching,
  1758. Xand live user connections via TCP/IP.
  1759. X.SH OBTAINING\ INFORMATION
  1760. X.TP
  1761. Xmailing lists, aliases, news groups, peer lists
  1762. XSee list(1).
  1763. X.TP
  1764. Xuser requests, list owners, peer servers, remote lists
  1765. XSee listserv(1).
  1766. X.TP
  1767. Xdistributing incoming mail
  1768. XSee catmail(1).
  1769. X.TP
  1770. Xarchiving files
  1771. XSee farch(1).
  1772. X.TP
  1773. Xarchiving of lists' messages
  1774. XSee below.
  1775. X.TP
  1776. Xprocessing the mail queue
  1777. XSee queue(1).
  1778. X.TP
  1779. Xoptions for the system's daemon
  1780. XSee serverd(1).
  1781. X.TP
  1782. Xstarting and stopping the system
  1783. XSee start(1).
  1784. X.TP
  1785. Xlive connections
  1786. XSee iul(1) and serverd(1).
  1787. X.SH SYSTEM\ SETUP
  1788. XThe UNIX ListServer system is installed under the HOMEDIR directory as defined
  1789. Xin src/Makefile; HOMEDIR points to the top level directory of the installation;
  1790. Xa \fIserver\fP user account has to be setup. The system should be installed and
  1791. Xset up using this account, and always be started from this account as well
  1792. X(see \fIstart\fP(1)).
  1793. XThen, the following alias
  1794. Xhas to be defined in /etc/aliases, /usr/lib/aliases  or /usr/ucblib/aliases
  1795. X(depending
  1796. Xon your system) for listserver (where users send their requests):
  1797. X.sp
  1798. X.in +2
  1799. Xlistserver: "|HOMEDIR/catmail -r -f"
  1800. X.in -2
  1801. X.sp
  1802. XKeep in mind, that the recommended alias before version 6.0 was "listserv",
  1803. Xso you may wish to use that for compatibility purposes.
  1804. X.PP
  1805. XVarious mailing lists are set up in a similar fashion; see \fIlist\fP(1).
  1806. X.PP
  1807. XIt is important to keep in mind that mailers should convert any text lines 
  1808. X(not header lines) of incoming messages starting with "From ", to ">From ".
  1809. XThis is automatically done by the -f flag to \fIcatmail\fP(1).
  1810. X.PP
  1811. XThe \fIcatmail\fP(1) utility is used to append incoming mail to the appropriate
  1812. Xfiles. When properly set up, it has the setuid bit turned on. Since
  1813. Xexecute permission is granted to everybody, it is possible for anyone
  1814. Xto append to these files; however, each time \fIcatmail\fP(1) is run, it
  1815. Xreports the user id and user name whom access was granted to.
  1816. X.PP
  1817. XIf the system is to go interactive (see \fIserverd\fP(1)), you have to add
  1818. Xthe following line in your /etc/services file:
  1819. X.sp
  1820. X.ce
  1821. Xulistserv   372/tcp
  1822. X.sp
  1823. XSee also src/Makefile.
  1824. X.PP
  1825. XHow the system operates is defined in the \fIconfig\fP file (see below).
  1826. XOnce the system is loaded, you will have to run the script \fIsetup\fP;
  1827. Xthis will ensure that all necessary files and directories are present, and
  1828. Xhave the right permissions. Before starting the
  1829. Xsystem, you may wish to edit the ".ignored" file in HOMEDIR (see \fIlist\fP(1)).
  1830. XAt this point, you may also wish to alter the help files in HOMEDIR/help;
  1831. Xeach file in that directory corresponds to one of the recognized requests.
  1832. XHelp files may be simple text files, or shell scripts starting with "#!"
  1833. Xin the first line, followed by the shell to execute.
  1834. X.PP
  1835. XFile protections are a major issue and the requirements may vary from system
  1836. Xto system. The problems usually arise from inadequate write permissions while
  1837. Xappending mail to the various mail files. The system uses the environment
  1838. Xvariable ULISTSERVER_UMASK in the same way as umask(1) is used when updating
  1839. Xfiles. If not set, the default is 066. A value of 026 should be acceptable in
  1840. Xmost cases. This variable should be set in both .cshrc and .profile.
  1841. X.PP
  1842. XFinally, experiment with the various mail methods described below, until
  1843. Xyou get the proper "From " line in the beginning of the outgoing message;
  1844. Xfor instance, when \fIlistserv\fP(1) is replying to a request, you should see
  1845. Xsomething like "From listserver@your-domain" as the first line of the header;
  1846. Xor when
  1847. Xthe list abc is distributing messages, this line should look like
  1848. X"From abc@your-domain". If you cannot get it to work, i.e. you get something
  1849. Xlike "From server@your-domain" then the server system may have
  1850. Xto run with superuser privileges. In this case, the server userid should
  1851. Xbe the same as root's. Also consult the PORT\ SPECIFIC section below,
  1852. Xfor suggested mailmethods. You will not have any of these problems
  1853. Xif you use the \fIsystem\fP mailmethod (see below).
  1854. X.PP
  1855. XIf this part of the setup is not done properly, peer lists will not
  1856. Xwork at all and users may not be able to reply to the list. As a final
  1857. Xnote, if \fItelnet\fP does not seem to be sending any mail, it is a
  1858. Xbug with the telnet implementation on your system: telnet
  1859. Xcannot have its input redirected or piped, and should be reported to your
  1860. Xvendor.
  1861. X.PP
  1862. XThe last step for a complete set up is to define your system in the
  1863. X\fIconfig\fP file.
  1864. X.SH CONFIG
  1865. XThe server system is defined in the \fIconfig\fP file; an example
  1866. Xfile is provided with the system. This file is used by \fIstart\fP(1),
  1867. X\fIserverd\fP(1), \fIlist\fP(1) and \fIlistserv\fP(1), and is not a shell
  1868. Xscript.
  1869. X.PP
  1870. XThe following keywords (directives) are recognized and is advisable that each
  1871. Xone of them starts at column 1; directives may span multiple lines if each
  1872. Xline is terminated by &\\n:
  1873. X.TP
  1874. X\fIorganization\fP name
  1875. XThis defines your organization when posting to news and upon connection
  1876. Xestablishment of a live session. \fIname\fP may
  1877. Xinclude blanks.
  1878. X.TP
  1879. X\fIserver\ listserver\fP@your-domain\ command-line-options
  1880. XThis defines the list server; the first argument is the full email address
  1881. Xof the server (e.g. listserver@foo.edu) followed by any command line
  1882. Xoptions to be used when \fIserverd\fP spawns \fIlistserv\fP
  1883. X(see \fIserverd\fP(1), \fIlistserv\fP(1)).
  1884. X.TP
  1885. X\fIlist\fP\ list_alias\ email-addr\ owner-addr\ password\ cmd-line-opt
  1886. XThis defines a mailing list; the first argument is the list's alias
  1887. Xin /etc/aliases, /usr/lib/aliases  or /usr/ucblib/aliases (see \fIlist\fP(1)),
  1888. Xfollowed by its full email
  1889. Xaddress, followed by its owner's full email address, followed by the
  1890. Xlist's password for maintenance, followed by any command line options
  1891. Xto be used when \fIserverd\fP(1) spawns \fIlist\fP(1).
  1892. X.TP
  1893. X\fIheader\fP\ list\ {\ [Header-Line:]\ ...\ }
  1894. XIt specifies precious header lines from the original sender's message
  1895. Xthat are to be preserved during distribution. The \fIlist\fP has to be
  1896. Xdefined before, and precious header lines are specified within the
  1897. Xenclosing \fI{\fP and \fI}\fP, possibly spanning multiple lines.
  1898. X.TP
  1899. X\fIdefault\fP\ list\ {\ [option = value]\ ...\ }
  1900. XDetermine various default values for \fIlist\fP for new and current subscribers;
  1901. Xthe list has to be defined before. Pairs of options and values may be repeated
  1902. Xany number of times, and may span multiple lines; if certain options are
  1903. Xmissing, then system defaults are used. Valid \fIoption\fPs are:
  1904. X.sp
  1905. X.in +2
  1906. X\fIaddress\fP: turn user-settable subscription addresses on or off. Valid values
  1907. Xare:
  1908. X.sp
  1909. X.in +2
  1910. X\fIfixed\fP: users are not allowed to change the address they are subscribed
  1911. Xwith via the \fIset <list> address\fP request (see \fIlistserv\fP(1)).
  1912. XThis is the system default as well.
  1913. X.sp
  1914. X\fIvariable\fP: opposite of the above.
  1915. X.in -2
  1916. X.sp
  1917. X\fImail\fP: select the default mail mode for new subscribers. Valid values are:
  1918. X.sp
  1919. X.in +2
  1920. X\fIack\fP: see \fIset\fP in \fIlistserv\fP(1).
  1921. X.sp
  1922. X\fInoack\fP: see \fIset\fP in \fIlistserv\fP(1); this is the system default.
  1923. X.sp
  1924. X\fIpostpone\fP: see \fIset\fP in \fIlistserv\fP(1) (a rather useless setting indeed).
  1925. X.sp
  1926. X\fIdigest\fP: see \fIset\fP in \fIlistserv\fP(1).
  1927. X.in -2
  1928. X.sp
  1929. X\fIpassword\fP: define a single password for new users; if missing, the system
  1930. Xassigns a random password. Any string that contains no white spaces may be
  1931. Xused.
  1932. X.sp
  1933. X\fIconceal\fP: determine the default visibility of new users; see \fIset\fP
  1934. Xin \fIlistserv\fP(1). Valid options are:
  1935. X.sp
  1936. X.in +2
  1937. X\fIyes\fP: hidden from \fIrecipients\fP and \fIstatistics\fP requests.
  1938. X.sp
  1939. X\fIno\fP: this is the system default.
  1940. X.in -2
  1941. X.in -2
  1942. X.TP
  1943. X\fIceiling\fP\ list\ max_messages
  1944. XRestrict the number of messages processed daily for \fIlist\fP to
  1945. X\fImax_messages\fP; this includes posted and rejected messages.
  1946. X.TP
  1947. X\fIremote\fP\ alias\ email-addr\ listserver-addr\ [host\ [port]]\ #Comment
  1948. XThis makes a remote list known to the server. A remote list is another
  1949. Xmailing list served by another server, and your server is now capable
  1950. Xof forwarding to the proper remote list server any requests sent about
  1951. Xthis remote list to your server. \fIalias\fP is the name by which the remote
  1952. Xlist is known by, \fIemail-addr\fP is the full email address of the
  1953. Xremote list, \fIlistserver-addr\fP is the full email address of the
  1954. Xremote list server, and \fI#Comment\fP
  1955. Xwill be used upon a \fIlists\fP request made to this server (the pound
  1956. Xsign is mandatory). \fIhost\fP is either the DNS name or IP address
  1957. Xof the remote server, used to connect to that server when a live request
  1958. Xrefers to that list; the \fIport\fP should be specified if not the default
  1959. X(372) (see \fIserverd\fP(1)).
  1960. X.sp
  1961. XRemote lists may have the same \fIalias\fP and they should not be confused
  1962. Xwith peer lists. However, each remote list should be defined only once.
  1963. XSee the discussion about PEER\ SERVERS (\fIlistserv\fP(1)) for further information.
  1964. X.TP
  1965. X\fIfax\fP fax-program options
  1966. XDefine the fax program to use for \fIfax\fP requests (if any) and any
  1967. Xcommand line options the program may use. The program should also be capable
  1968. Xof accepting the file to fax from its standard input; otherwise a script
  1969. Xwill have to be used instead which will in turn use the fax program
  1970. Xappropriately. If this directive is left or commented out, then \fIfax\fP
  1971. Xrequests are automatically turned of.
  1972. X.sp
  1973. XThe actual faxing program is called as follows:
  1974. X.sp
  1975. X.ce
  1976. X\fIfax-program\fP \fIoptions\fP fax-number < file
  1977. X.sp
  1978. XThis request may not be issued from a live session, since fax programs work
  1979. Xon email messages and extract the sender's address for reference when sending
  1980. Xthe cover page of the fax.
  1981. X.TP
  1982. X\fIunix_cmd\fP\ list_alias\ password\ name\ \'unix-command\ [args]\'\ #Comment
  1983. XAllow a \fIlist_alias\fP's subscribers only to execute the above
  1984. X\fIunix-command\fP aliased to \fIname\fP. The \fIpassword\fP is made known
  1985. Xto users who are to be given this privilege. The oprional \fIargs\fP may be
  1986. Xliteral arguments to the command as well as the special sequences \fI$n\fP,
  1987. Xwhere \fIn\fP is a digit from 1 to 9, or *; their meaning is that of the Bourne
  1988. Xshell, and they will be substituted by the user's actual arguments. For
  1989. Xexample:
  1990. X.sp
  1991. X.ce
  1992. Xunix_cmd ermis pass1 swap \'/bin/echo $2 $1\' #Syntax: swap <arg1> <arg2>
  1993. X.sp
  1994. Xwill swap the user's first and second arguments. The user would submit a
  1995. Xrequest that could look like this:
  1996. X.sp
  1997. X.ce
  1998. Xrun ermis pass1 swap arg1 arg2
  1999. X.sp
  2000. XNo security checks are made except to ensure that the arguments contain no `, |,
  2001. X:, < and >, so the \fImanager\fP is encouraged to review
  2002. Xand verify the proper functioning of \fIunix-command\fP. The \fIComment\fP
  2003. Xis used when users issue \'run <list>\' query requests.
  2004. X.TP
  2005. X\fIserverd\fP\ command-line-options
  2006. XThis defines the command line options that \fIstart\fP(1) is to use
  2007. Xwhen spawning \fIserverd\fP(1).
  2008. X.TP
  2009. X\fIrestriction\fP\ nusers
  2010. XIf a restriction is placed on a ListServer request (via a -r command line
  2011. Xoption to \fIlistserv\fP(1)), this directive defines the threshold number of users,
  2012. Xabove which the restriction will take effect.
  2013. X.TP
  2014. X\fIdisable\fP\ list_alias request
  2015. XThe specified server \fIrequest\fP is disabled for the specified list, and
  2016. Xall such requests for this list are rejected, except when issued by privileged
  2017. Xusers (list owners). The \fIlist_alias\fP has to
  2018. Xbe defined (via a \fIlist\fP directive) before any requests can
  2019. Xbe disabled.
  2020. X.TP
  2021. X\fImanager\fP\ full-email-address
  2022. XThis defines the recipient of all system error messages, and the system's
  2023. Xadministrator and caretaker; \fIfull-email-address\fP
  2024. Xcan be any valid user name that can be reached via email by your system.
  2025. XThe \fImanager\fP is usually the person responsible for the server
  2026. Xaccount.
  2027. X.TP
  2028. X\fIcomment server\fP\ #Actual comment
  2029. X.TP
  2030. X\fIcomment\fP\ list_alias\ #Actual comment
  2031. XA 'X-Comment:' line is included in every outgoing list/server message, and the
  2032. Xtext following the pound sign will be copied every time; note that the pound
  2033. Xsign is mandatory for the definition but will not be part of the actual string.
  2034. XA list's comment is also used for the \fIlists\fP request to
  2035. Xspecify the purpose of the particular mailing list. No 'X-Comment:' line
  2036. Xis included if this directive is not defined for the particular list and/or
  2037. Xserver.
  2038. X.TP
  2039. X\fIdigest\fP\ list_alias\ lines\ hours
  2040. XIf any subscriber to the list requests digests, a digest will be sent when
  2041. Xits length exceeds \fIlines\fP, or when \fIhours\fP have passed
  2042. Xwithout a digest being sent. Digests for a list are collected only if at
  2043. Xleast one of its subscribers has set his mail mode to \fIdigest\fP.
  2044. X.TP
  2045. X\fIarchive\fP\ list_alias\ dir\ filename\ [archive]\ [password]\ [digest]
  2046. XRequest that all public messages are automatically archived; \fIlist_alias\fP
  2047. Xis the list's name, \fIdir\fP is the directory that the archived
  2048. Xfiles will be located (a full path has to be specified, and the directory
  2049. Xhas to be writable by the server uid), \fIarchive\fP is the archive's name
  2050. Xand is a relative path under the default archive (listserver) or "-" for the
  2051. Xdefault, \fIpassword\fP is an optional password ("-" if none) to be used
  2052. Xif the archive is meant to be private, and the optional
  2053. Xkeyword \fIdigest\fP will force only digests to be archived; \fIfilename\fP
  2054. Xspecifies the format of the archived files, and may contain any lower case
  2055. Xcharacters and numbers, as well as the following special sequences:
  2056. X.in +2
  2057. X.sp
  2058. X%m: Numeric month (01 - 12)
  2059. X.sp
  2060. X%d: Numeric day of the month (01 - 31)
  2061. X.sp
  2062. X%y: Year (00 - 99)
  2063. X.sp
  2064. X%j: Julian date (001 - 366)
  2065. X.sp
  2066. X%h: Month name (Jan - Dec)
  2067. X.sp
  2068. X%a: Contents of the Archive-Name: header line, if present; cannot be used if
  2069. Xarchiving digests. The Archive-Name: header line has to be manually inserted
  2070. Xby the sender of the message; it may show up in the body of the message as
  2071. Xwell.
  2072. X.sp
  2073. X%#: Digest number; can only be used if archiving digests.
  2074. X.sp
  2075. X%1: First word of the first non-blank line of the message.
  2076. X.sp
  2077. X%v: Volume number, if the message contains a 'Volume # Number #' line before
  2078. Xthe actual message.
  2079. X.sp
  2080. X%n: Issue number, if the message contains a 'Volume # Number #' line before the
  2081. Xactual message.
  2082. X.sp
  2083. X%%: The character %
  2084. X.in -2
  2085. X.sp
  2086. XFor example, to archive messages daily:
  2087. X.sp
  2088. X.ce
  2089. Xarchive ermis HOMEDIR/archives/lists/ermis %y%m%d listserver/lists/ermis
  2090. X.sp
  2091. Xor to archive only files sent to the list:
  2092. X.sp
  2093. X.ce
  2094. Xarchive venus /ftp/lists/venus vol-%v.num-%n listserver/lists/venus johny-be-good
  2095. X.sp
  2096. Xand in this case the sender that wants a file to be archived would precede
  2097. Xit with a line similar to:
  2098. X.sp
  2099. X.nf
  2100. XVolume 10 Number 5
  2101. X.fi
  2102. X.sp
  2103. Xfollowed by the actual file.
  2104. X.sp
  2105. XWhen a new archive file is created, the Subject: line is used as the short
  2106. Xdescriptive message for the archive.
  2107. X.TP
  2108. X\fIfrequency\fP\ seconds
  2109. XHow often should \fIserverd\fP(1) check for new mail. When \fIseconds\fP is
  2110. Xset to zero, \fIserverd\fP does not sleep.
  2111. X.TP
  2112. X\fIbatch\fP\ start\ stop
  2113. XSpecify the hours (in military time) when requests are to be batched.
  2114. XThe defaults are 8 and 20. \fIstart\fP and \fIstop\fP should be within
  2115. Xthe same day (e.g. 8 am and 1 am the following day are not valid).
  2116. X.TP
  2117. X\fIlimit\fP\ keyword\ arguments
  2118. XUsed to set certain limits in the system; \fIkeyword\fP can be:
  2119. X.in +2
  2120. X.sp
  2121. X\fImessage\fP: limit the size of distributed messages to a certain
  2122. Xnumber of bytes, which is the \fIargument\fP following this keyword.
  2123. XA notification is sent back to the sender when this limit is exceeded,
  2124. Xincluding the first few lines of his/her original message for reference.
  2125. X.in -2
  2126. X.sp
  2127. X.in +2
  2128. X\fIfiles\fP: limit the size of archive files that can be sent out to a certain
  2129. Xnumber of bytes, which is the \fIargument\fP following this keyword.
  2130. XWhen this limit is reached, the file is automatically split into subparts.
  2131. X.TP
  2132. X\fIprecedence\fP\ string
  2133. XThe header of each outgoing message contains a Precedence: line; \fIstring\fP
  2134. Xcan be:
  2135. X.in +2
  2136. X.sp
  2137. Xbulk, junk, first-class, none: primarily used for vacation programs.
  2138. X.in -2
  2139. X.TP
  2140. X\fIoption\fP\ keyword
  2141. XThis defines a series of system-dependent options; \fIkeyword\fP can be:
  2142. X.in +2
  2143. X.sp
  2144. X\fIsysv_ps\fP: the system will assume a System V version of ps(1).
  2145. X.sp
  2146. X\fIbsd_ps\fP: the system will assume a BSD version of ps(1).
  2147. X.sp
  2148. X\fIbsd_mail\fP: define it if BSD (UCB) mail is available on your system; if this
  2149. Xis the case, make sure that /usr/ucb/mail is the path (or a link) to it; also
  2150. Xsee src/Makefile.
  2151. XThis is used to notify the \fImanager\fP of any error conditions.
  2152. X.sp
  2153. X\fIbad_telnet\fP: if the mail method used (see below) is \fItelnet\fP and 
  2154. Xthe system seems to send out only one message and then go to sleep, use
  2155. Xthis option.
  2156. X.sp
  2157. X\fIpost_mail\fP: this will force the system to post messages to news
  2158. Xgroups (using \fIinews\fP), using the groups' names (e.g. misc.test). Make
  2159. Xsure that \fIinews\fP resides in /usr/lib/news, or 
  2160. X/usr/lib/news/inews is a link to it (also see src/Makefile).
  2161. X.sp
  2162. X\fIgate_mail\fP: this will force the system to gate messages to news, using
  2163. Xthe gateways' email addresses.
  2164. X.sp
  2165. X\fIignore_invalid_requests\fP: ignore all unrecognized user requests and
  2166. Xprocess valid ones only; by default, the system aborts processing requests
  2167. Xupon the first invalid one, in which case a reply is sent to the user and
  2168. Xall subsequent requests are flushed.
  2169. X.sp
  2170. X\fIrelaxed_syntax\fP: by default, the system complains when a request is
  2171. Xgiven more arguments than expected. This turns such checking off.
  2172. X.in -2
  2173. X.TP
  2174. X\fImailmethod\fP\ method\ [arguments]
  2175. XEvery outgoing
  2176. Xmessage should begin with a line of the form:
  2177. X.in +2
  2178. X.sp
  2179. XFrom listserver@your-domain
  2180. X.sp
  2181. Xor
  2182. X.sp
  2183. XFrom list_alias@your-domain
  2184. X.sp
  2185. X.in -2
  2186. Xwhich depends on the mail \fImethod\fP used:
  2187. X.in +2
  2188. X.sp
  2189. X\fIsystem\fP: the recommended method; it provides a unified approach to
  2190. Xsending mail and it has been ported and tested on lots of systems (see
  2191. Xthe section PORT\ SPECIFIC below).
  2192. XIn addition, since a full set of the SMTP protocol is implemented,
  2193. X\fImanager\fP and list owners will be notified of invalid addresses and
  2194. Xvarious system problems.
  2195. XMoreover, mail will be queued when it cannot be delivered, in the
  2196. Xdirectory HOMEDIR/mqueue; see \fIqueue(1)\fP for more information
  2197. Xon how to process the mail queue.
  2198. X.sp
  2199. XThis method requires host TCP/IP and internet support; consult the
  2200. Xsrc/README file for more information.
  2201. X.sp
  2202. X\fItelnet\fP: to be used only when \fIsystem\fP is inappropriate and telnet(1)
  2203. Xis available on your host.
  2204. X.sp
  2205. X\fIenv_var\fP: usually followed by \fILOGNAME /bin/rmail\fP,
  2206. Xor \fILOGNAME /usr/lib/sendmail -ba\fP (-ba is mandatory) -- to be 
  2207. Xused only when the previous methods are inappropriate.
  2208. X.in -2
  2209. X.SH MAIL\ LOOPS
  2210. XThe system uses the following protocol for avoiding mail loops between
  2211. Xa list and news connections: In the header of the outgoing message an
  2212. X"Originator: " field is added. For each list plus listserver, a log of
  2213. Xthe most recent (500) Message-Id's is kept.
  2214. XWhenever a message is received, the
  2215. XOriginator, Reply-To and Message-Id fields are extracted and looked up in
  2216. Xthe ".ignored" and ".message.ids"
  2217. Xfiles in the list's subdirectory. Gateways that feed back to the list
  2218. Xshould preserve at least the Reply-To and Message-Id fields. The Originator
  2219. Xand Message-Id fields are preserved by this system. A new Reply-To is
  2220. Xtacked on when redistributing mail locally from a peer or a news feed.
  2221. X.PP
  2222. XTo avoid mail loops when forwarding ListServer requests to peers, the system
  2223. Xlooks up the Message-Id field in the ".message.ids" file in 
  2224. XHOMEDIR.
  2225. XIf this field is not preserved by the peer ListServer, it is suggested that you
  2226. Xturn off request forwarding when connecting with peers served by such
  2227. Xsystems, until a unified approach is taken. The Message-Id field is preserved
  2228. Xby this ListServer. This system is also using a special Subject field,
  2229. Xtotally proprietary and non-standard, in order to avoid unnecessary
  2230. Xforwarding of requests, thus cutting down on email traffic.
  2231. X.SH CRASH\ RECOVERY
  2232. XIt is possible that a message delivery was interrupted by a user
  2233. X(\fIstart -k\fP), or by the system (crash/reboot). A built-in mechanism
  2234. Xguarrantees to pick up delivery again from where it left off, if the
  2235. Xsystem is restarted using \fIstart\fP(1). Both \fIstart\fP(1) and \fIlist\fP(1)
  2236. Xreport to the effect that mail delivery was interrupted and will
  2237. Xresume. On the other hand, processing of interrupted requests will not
  2238. Xresume and all unprocessed requests will be lost.
  2239. X.SH COMMUNICATING
  2240. XUsers send requests to \fIlistserver@your-domain\fP and public messages to the
  2241. Xvarious \fIlist_alias@your-domain\fP.
  2242. X.SH ARCHIVES
  2243. XThe server has an archiving capability of files. Archives may be public
  2244. Xso that anyone can get files from them, or private so that only privileged
  2245. Xusers may obtain files from them. There is a master archive
  2246. Xin HOMEDIR/archives/listserver where all subarchives are defined. The archives
  2247. Xkeep lists of files that are available to users via a \fIget\fP request, and
  2248. Xindex of subarchives that are available to users via an \fIindex\fP
  2249. Xrequest.
  2250. X.PP
  2251. XAs outlined in \fIlist\fP(1), each list's public messages are
  2252. Xautomatically saved under the list's subdirectory in the file \fIarchive\fP.
  2253. XThis file may periodically be placed in the system's archives by hand (if not
  2254. Xarchiving automatically via the \fIarchive\fP directive), or may point to
  2255. X/dev/null. The archived files may not necessarily reside in
  2256. Xthe archive directories, as long
  2257. Xas the archives know where they are located. See the man page for
  2258. X\fIfarch(1)\fP for more information.
  2259. X.PP
  2260. XAlternatively, messages may be automatically archived via the \fIarchive\fP
  2261. Xdirective in the \fIconfig\fP file.
  2262. X.SH HELP
  2263. XThe system comes configured with default help topics the recognized
  2264. Xrequests. More topics may be added by editing the file
  2265. XHOMEDIR/help/TOPICS, adding the topic(s) and the file(s) where the
  2266. Xactual text exists.
  2267. X.PP
  2268. XHelp files may be simple text files or shell scripts, in which case they
  2269. Xhave to start with "#!" in the first line and be followed by the path
  2270. Xto the shell to be used; for example: #!/bin/sh
  2271. X.SH SYSTEM\ MAINTENANCE
  2272. XAs mentioned below, all programs report to certain files. The system's
  2273. Xmanager should periodically check the files HOMEDIR/.report.server
  2274. Xand the various HOMEDIR/lists/*/.report.list for any problems.
  2275. XAll messages sent are saved under HOMEDIR/mbox and 
  2276. XHOMEDIR/lists/*/mbox and they should be cleaned up periodically.
  2277. XFor debugging purposes, various warnings are written to 
  2278. XHOMEDIR/.warning; this file, as well as HOMEDIR/.report.catmail
  2279. Xare shrunk every time \fIstart\fP(1) is run.
  2280. X.PP
  2281. XFor whenever the necessity arises to administer the system remotely, the
  2282. Xfollowing scheme may be used to start or kill the system, process the mail
  2283. Xqueue, force an application to execute immediately, etc: a mail message
  2284. Xis sent to an alias whose sole role is to fire up an application; the
  2285. Xapplication has to have been setuid before.
  2286. X.PP
  2287. XFor instance, to start the
  2288. Xsystem remotely, you may set up an alias such as:
  2289. X.sp
  2290. X.nf
  2291. X.in +2
  2292. Xstart-server: "|HOMEDIR/start -cr > /dev/null"
  2293. X.in -2
  2294. X.fi
  2295. X.sp
  2296. XTo kill the system, you may define another alias:
  2297. X.sp
  2298. X.nf
  2299. X.in +2
  2300. Xkill-server: "|HOMEDIR/start -crk > /dev/null"
  2301. X.in -2
  2302. X.fi
  2303. X.sp
  2304. XTo force requests to get processed now:
  2305. X.sp
  2306. X.nf
  2307. X.in +2
  2308. Xrun-listserver: "|HOMEDIR/listserv -1 > /dev/null"
  2309. X.in -2
  2310. X.fi
  2311. X.sp
  2312. XTo start the queue daemon:
  2313. X.sp
  2314. X.nf
  2315. X.in +2
  2316. Xproc-queue: "|HOMEDIR/queued 60 & > /dev/null"
  2317. X.in -2
  2318. X.fi
  2319. X.sp
  2320. XThese aliases should be hard to guess for obvious reasons. The actual
  2321. Xmessage sent to such an alias is discarded.
  2322. X.SH EXIT\ CODES
  2323. XAll applications except tlock use the following exit codes for communication:
  2324. X.sp
  2325. X.TP
  2326. X0
  2327. X- OK, normal exit
  2328. X.TP
  2329. X1
  2330. X- Could not open or lock file
  2331. X.TP
  2332. X2
  2333. X- SIGINT signal (normal termination)
  2334. X.TP
  2335. X3
  2336. X- Command line option error
  2337. X.TP
  2338. X4
  2339. X- Syntax error in file
  2340. X.TP
  2341. X5
  2342. X- Could not spawn (restart failed)
  2343. X.TP
  2344. X6
  2345. X- Shutdown request
  2346. X.TP
  2347. X7
  2348. X- Restart request
  2349. X.TP
  2350. X8
  2351. X- Received system signal (anything but SIGINT will bring the system down)
  2352. X.TP
  2353. X9
  2354. X- Too many multiple recipients
  2355. X.TP
  2356. X10
  2357. X- Could not deliver mail (unexpected reply during the SMTP transaction)
  2358. X.TP
  2359. X11
  2360. X- malloc() failed
  2361. X.TP
  2362. X12
  2363. X- Cannot fork()
  2364. X.TP
  2365. X13
  2366. X- Socket connection problem
  2367. X.TP
  2368. X14
  2369. X- Semaphore error
  2370. X.TP
  2371. X15
  2372. X- Cannot setuid()/setgid()
  2373. X.TP
  2374. X16
  2375. X- Internal error or system call failure
  2376. X.fi
  2377. X.PP
  2378. Xtlock exits with:
  2379. X.TP
  2380. X-1
  2381. X- File locking not functional
  2382. X.TP
  2383. X0
  2384. X- No files locked
  2385. X.TP
  2386. X1
  2387. X- Cannot open config
  2388. X.TP
  2389. X2 & up
  2390. X- Number of files locked + 1
  2391. X.SH REPORTS
  2392. XThe system provides two ways of reporting progress: via syslog(3) when available
  2393. X(by compiling with -DSYSLOG=facility) with priority LOG_INFO and facility as
  2394. Xspecified, or through its own report files (when not using syslog(3)); these
  2395. Xare:
  2396. X.TP
  2397. XHOMEDIR/.report.catmail
  2398. XMessages from \fIcatmail\fP(1) every time new messages are appended to the
  2399. Xvarious mail files.
  2400. X.TP
  2401. XHOMEDIR/.report.daemon
  2402. XMessages from \fIserverd\fP(1) every time new mail has arrived.
  2403. X.TP
  2404. XHOMEDIR/.report.list
  2405. XError messages from \fIlist\fP(1) when attempting to process public messages.
  2406. X.TP
  2407. XHOMEDIR/.report.pqueue
  2408. XMessages from \fIpqueue\fP (see \fIqueue\fP(1)).
  2409. X.TP
  2410. XHOMEDIR/.report.server
  2411. XMessages from \fIlistserv\fP(1) every time new requests are processed.
  2412. X.TP
  2413. XHOMEDIR/.report.start
  2414. XGenerated by \fIstart\fP(1) every time the system is started.
  2415. X.TP
  2416. XHOMEDIR/lists/LIST_ALIAS/.report.list
  2417. XMessages from \fIlist\fP(1) when processing public messages.
  2418. X.TP
  2419. XHOMEDIR/.*.acc
  2420. XAccumulated reports since the system was first installed.
  2421. X.TP
  2422. XHOMEDIR/lists/*/.*.acc
  2423. XAccumulated reports for each mailing list.
  2424. X.PP
  2425. XEvery report includes a time stamp; every list and server report also
  2426. Xincludes the actual sender of the message, and every server report
  2427. Xincludes all requests made by the sender.
  2428. X.PP
  2429. XWhenever a program dies abnormally (and BSD mail is present) a message
  2430. Xis sent to \fImanager\fP (as defined in \fIconfig\fP). 
  2431. XThe message is usually sent by \fIserverd\fP(1) which
  2432. Xthen exits. The daemon dies with a different message according to the exit
  2433. Xstatus of the child; the various error conditions that may occur are:
  2434. X.TP
  2435. XCould not open file
  2436. XHOMEDIR is not a valid path; file was accidentally deleted;
  2437. Xinsufficient access privileges. Run \fIsetup\fP and \fIstart\fP.
  2438. X.TP
  2439. XCould not lock file
  2440. XHOMEDIR is not a valid path; file was accidentally deleted;
  2441. Xinsufficient access privileges; another program is using the lock
  2442. Xfile. Run \fItlock\fP, and if necessary, \fIulock\fP; then \fIstart\fP.
  2443. X\fItlock\fP checks for locked files, and \fIulock\fP removes all lock
  2444. Xfiles.
  2445. X.TP
  2446. XCommand line option error
  2447. XCheck the \fIconfig\fP file and restart.
  2448. X.TP
  2449. XSyntax error in file
  2450. XCheck \fIconfig\fP, all reports, .subscribers, .peers and .news files.
  2451. X.TP
  2452. XCould not spawn
  2453. XNo more processes.
  2454. X.TP
  2455. XReceived system signal
  2456. XSIGQUIT, SIGTERM, SIGBUS, SIGSEGV, SIGILL.
  2457. X.SH FILES
  2458. X.TP
  2459. XHOMEDIR/.aliases
  2460. XAliases of email addresses of users having trouble getting replies to requests.
  2461. X.TP
  2462. XHOMEDIR/.awk
  2463. Xawk program for formatting the \fIstatistics\fP request.
  2464. X.TP
  2465. XHOMEDIR/.grep
  2466. Xscript used for counting the number of messages sent by a subscriber.
  2467. X.TP
  2468. XHOMEDIR/.ignored
  2469. XList of unwanted senders.
  2470. X.TP
  2471. XHOMEDIR/.lock.list
  2472. XLock file for \fIlist\fP(1).
  2473. X.TP
  2474. XHOMEDIR/.lock.pqueue
  2475. XLock file for \fIpqueue\fP (see \fIqueue\fP(1)).
  2476. X.TP
  2477. XHOMEDIR/.lock.server
  2478. XLock file for \fIlistserv\fP(1).
  2479. X.TP
  2480. XHOMEDIR/.lock.serverd
  2481. XLock file for \fIserverd\fP(1).
  2482. X.TP
  2483. XHOMEDIR/.message.ids
  2484. XA database of recent message id's used to detect mail loops.
  2485. X.TP
  2486. XHOMEDIR/.queue.id
  2487. XNext id to be assigned to next undeliverable message placed in the mqueue/
  2488. Xdirectory.
  2489. X.TP
  2490. XHOMEDIR/.reply.listser
  2491. XThe reply code given to \fIserverd\fP(1) during a live session.
  2492. X.TP
  2493. XHOMEDIR/.rep.server.acc
  2494. XArchived \fIlistserv\fP(1) reports.
  2495. X.TP
  2496. XHOMEDIR/.rep.serverd.acc
  2497. XArchived \fIserverd\fP(1) reports.
  2498. X.TP
  2499. XHOMEDIR/.rep.start.acc
  2500. XArchived \fIstart\fP(1) reports.
  2501. X.TP
  2502. XHOMEDIR/.report.catmail
  2503. XCurrent \fIcatmail\fP(1) report.
  2504. X.TP
  2505. XHOMEDIR/.report.daemon
  2506. XCurrent \fIserverd\fP(1) report.
  2507. X.TP
  2508. XHOMEDIR/.report.list
  2509. XError messages from \fIlist\fP(1).
  2510. X.TP
  2511. XHOMEDIR/.report.server
  2512. XCurrent \fIlistserv\fP(1) report.
  2513. X.TP
  2514. XHOMEDIR/.report.start
  2515. XLast \fIstart\fP(1) action (system started or shut down).
  2516. X.TP
  2517. XHOMEDIR/.stats
  2518. XScript used for the \fIstatistics\fP request.
  2519. X.TP
  2520. XHOMEDIR/.tag.id
  2521. XNext id to be assigned to next moderated message.
  2522. X.TP
  2523. XHOMEDIR/.warning
  2524. XLog of system calls' exit statuses.
  2525. X.TP
  2526. XHOMEDIR/batch
  2527. XBatched user requests.
  2528. X.TP
  2529. XHOMEDIR/catmail
  2530. XIncoming message redirection application.
  2531. X.TP
  2532. XHOMEDIR/config
  2533. XThe configuration file.
  2534. X.TP
  2535. XHOMEDIR/farch
  2536. XFile archiving utility.
  2537. X.TP
  2538. XHOMEDIR/iul
  2539. XInteractive UNIX ListServer client; to be used to connect to the
  2540. Xinteractive part of the system.
  2541. X.TP
  2542. XHOMEDIR/list
  2543. XThe mailing list program.
  2544. X.TP
  2545. XHOMEDIR/listserv
  2546. XThe system's request server.
  2547. X.TP
  2548. XHOMEDIR/lost+found
  2549. XRequests that could not be appended to HOMEDIR/requests.
  2550. X.TP
  2551. XHOMEDIR/mbox
  2552. XAn archive of all requests sent to date to ListServer.
  2553. X.TP
  2554. XHOMEDIR/news
  2555. XScript used to add a news group to a list.
  2556. X.TP
  2557. XHOMEDIR/owners
  2558. XList of list owners' addresses used for authentication of list maintenance
  2559. Xrequests.
  2560. X.TP
  2561. XHOMEDIR/peer
  2562. XScript used to add a peer list.
  2563. X.TP
  2564. XHOMEDIR/pqueue
  2565. XThe mail queue processing program (see \fIqueue(1)\fP).
  2566. X.TP
  2567. XHOMEDIR/priv.hosts
  2568. XList of hosts that may connect to the interactive part of the system.
  2569. X.TP
  2570. XHOMEDIR/queued
  2571. XThe mail queue processing daemon (see \fIqueue(1)\fP).
  2572. X.TP
  2573. XHOMEDIR/received
  2574. XFile containing the messages received from sendmail during the
  2575. Xlast message distribution -- the \fIsystem\fP mailmethod has to be
  2576. Xin use.
  2577. X.TP
  2578. XHOMEDIR/requests
  2579. XNewly arrived user requests.
  2580. X.TP
  2581. XHOMEDIR/requests.live
  2582. XRepository for requests coming in from live connections.
  2583. X.TP
  2584. XHOMEDIR/sent
  2585. XFile containing the messages sent to sendmail during the
  2586. Xlast message distribution -- the \fIsystem\fP mailmethod has to be
  2587. Xin use.
  2588. X.TP
  2589. XHOMEDIR/serverd
  2590. XThe system's daemon.
  2591. X.TP
  2592. XHOMEDIR/setup
  2593. XSystem setup script.
  2594. X.TP
  2595. XHOMEDIR/start
  2596. XThe system's housekeeping program.
  2597. X.TP
  2598. XHOMEDIR/tlock
  2599. XChecks for any locked files.
  2600. X.TP
  2601. XHOMEDIR/ulock
  2602. XScript to remove all lock files.
  2603. X.TP
  2604. XHOMEDIR/unwanted.hosts
  2605. XList of hosts that may not connect to the interactive part of the system.
  2606. X.TP
  2607. XHOMEDIR/welcome.live
  2608. XWelcoming message upon live connection establishment.
  2609. X.TP
  2610. XHOMEDIR/archives/listserver/DIR
  2611. XDirectory of all files available from the master archive (listserver).
  2612. X.TP
  2613. XHOMEDIR/archives/listserver/INDEX
  2614. XThe master archive index.
  2615. X.TP
  2616. XHOMEDIR/doc/catmail.1
  2617. XMan page source for \fIcatmail\fP(1).
  2618. X.TP
  2619. XHOMEDIR/doc/catmail.nr
  2620. XFormatted man page for \fIcatmail\fP(1).
  2621. X.TP
  2622. XHOMEDIR/doc/farch.1
  2623. XMan page source for the \fIfarch\fP(1) utility.
  2624. X.TP
  2625. XHOMEDIR/doc/farch.nr
  2626. XFormatted man page for the \fIfarch\fP(1) utility.
  2627. X.TP
  2628. XHOMEDIR/doc/iul.1
  2629. XMan page source for the \fIiul\fP(1) utility.
  2630. X.TP
  2631. XHOMEDIR/doc/iul.nr
  2632. XFormatted man page for \fIiul\fP(1).
  2633. X.TP
  2634. XHOMEDIR/doc/list.1
  2635. XMan page source for \fIlist\fP(1).
  2636. X.TP
  2637. XHOMEDIR/doc/list.nr
  2638. XFormatted man page for \fIlist\fP(1).
  2639. X.TP
  2640. XHOMEDIR/doc/listserv.1
  2641. XMan page source for \fIlistserv\fP(1).
  2642. X.TP
  2643. XHOMEDIR/doc/listserv.nr
  2644. XFormatted man page for \fIlistserv\fP(1).
  2645. X.TP
  2646. XHOMEDIR/doc/queue.1
  2647. XMan page source for \fIpqueue\fP and \fIqueued\fP(1).
  2648. X.TP
  2649. XHOMEDIR/doc/queue.nr
  2650. XFormatted man page for \fIpqueue\fP and \fIqueued\fP(1).
  2651. X.TP
  2652. XHOMEDIR/doc/server.1
  2653. XSource of the system's main man page.
  2654. X.TP
  2655. XHOMEDIR/doc/server.nr
  2656. XFormatted main man page.
  2657. X.TP
  2658. XHOMEDIR/doc/serverd.1
  2659. XMan page source for \fIserverd\fP(1).
  2660. X.TP
  2661. XHOMEDIR/doc/serverd.nr
  2662. XFormatted man page for \fIserverd\fP(1).
  2663. X.TP
  2664. XHOMEDIR/doc/start.1
  2665. XMan page source for \fIstart\fP(1).
  2666. X.TP
  2667. XHOMEDIR/doc/start.nr
  2668. XFormatted man page for \fIstart\fP(1).
  2669. X.TP
  2670. XHOMEDIR/help/*
  2671. XGeneral and topic-specific help files available upon a \fIhelp\fP
  2672. Xrequest. The TOPICS is a special file where topics are defined.
  2673. X.TP
  2674. XHOMEDIR/lists/LIST_ALIAS/.aliases
  2675. XAliases of email addresses of subscribers.
  2676. X.TP
  2677. XHOMEDIR/lists/LIST_ALIAS/.digest.toc
  2678. XAll the subject lines from the digest. It will be
  2679. Xwritten at the head of the digest when it is sent.
  2680. X.TP
  2681. XHOMEDIR/lists/LIST_ALIAS/.digest.msg
  2682. XAll the messages of the digest, separated by dashed lines.
  2683. X.TP
  2684. XHOMEDIR/lists/LIST_ALIAS/.digest.time
  2685. XThe time that the last digest was sent, represented as the value
  2686. Xreturned by time(2). It is used to calculate when it is time to send
  2687. Xout the next digest.
  2688. X.TP
  2689. XHOMEDIR/lists/LIST_ALIAS/.headers
  2690. XAn archive of who sent each message; used upon a \fIstatistics\fP
  2691. Xrequest.
  2692. X.TP
  2693. XHOMEDIR/lists/LIST_ALIAS/.ignored
  2694. XA list of unwanted senders.
  2695. X.TP
  2696. XHOMEDIR/lists/LIST_ALIAS/.info
  2697. XText sent upon an \fIinformation\fP request.
  2698. X.TP
  2699. XHOMEDIR/lists/LIST_ALIAS/.limits
  2700. XUsed by \fIserverd\fP(1) when placing various limits for the list.
  2701. X.TP
  2702. XHOMEDIR/lists/LIST_ALIAS/.message.ids
  2703. XA database of recent message id's used to detect mail loops.
  2704. X.TP
  2705. XHOMEDIR/lists/LIST_ALIAS/.news
  2706. XA list of all news groups connected to this list.
  2707. X.TP
  2708. XHOMEDIR/lists/LIST_ALIAS/.peers
  2709. XA list of all peer lists for this mailing list,
  2710. Xalong with the email addresses of their servers.
  2711. X.TP
  2712. XHOMEDIR/lists/LIST_ALIAS/.rep.list.acc
  2713. XArchived reports from \fIlist\fP(1).
  2714. X.TP
  2715. XHOMEDIR/lists/LIST_ALIAS/.report.list
  2716. XCurrent report from \fIlist\fP(1).
  2717. X.TP
  2718. XHOMEDIR/lists/LIST_ALIAS/.restricted
  2719. XList of subscribers with alternate recipient files.
  2720. X.TP
  2721. XHOMEDIR/lists/LIST_ALIAS/.subscribers
  2722. XA list of all subscribers along with preferences and settings.
  2723. X.TP
  2724. XHOMEDIR/lists/LIST_ALIAS/.un.digest
  2725. XWhen a digest is constructed, it will be stored in this file until it
  2726. Xhas been sent to all digest subscribers.
  2727. X.TP
  2728. XHOMEDIR/lists/LIST_ALIAS/.welcome
  2729. XText sent on a \fIsubscribe\fP request.
  2730. X.TP
  2731. XHOMEDIR/lists/LIST_ALIAS/archive
  2732. XArchive of all distributed messages since the file was last created.
  2733. X.TP
  2734. XHOMEDIR/lists/LIST_ALIAS/lost+found
  2735. XMail that could not be appended to the 'mail' or 'moderated' files
  2736. X(see next entries and \fIcatmail\fP(1)).
  2737. X.TP
  2738. XHOMEDIR/lists/LIST_ALIAS/mail
  2739. XNewly arrived public messages to be distributed.
  2740. X.TP
  2741. XHOMEDIR/lists/LIST_ALIAS/mbox
  2742. XAn archive of all messages sent to date.
  2743. X.TP
  2744. XHOMEDIR/lists/LIST_ALIAS/moderated
  2745. XNewly arrived public messages that need to be edited before
  2746. Xdistributed.
  2747. X.TP
  2748. XHOMEDIR/lists/LIST_ALIAS/removed.users
  2749. XEntries from the .subscribers file for users who have been automatically
  2750. Xremoved from the list.
  2751. X.TP
  2752. XHOMEDIR/lists/LIST_ALIAS/removed.alias
  2753. XEntries from the .aliases file for users who have been automatically
  2754. Xremoved from the list.
  2755. X.TP
  2756. XHOMEDIR/mqueue/*
  2757. XQueued messages for later delivery.
  2758. X.SH UPGRADING
  2759. XWhen upgrading, it is not necessary to remove your current system.
  2760. XOld key directories and files will be moved elsewhere. Always run the
  2761. X\fIsetup\fP script. In addition, if you are upgrading from:
  2762. X.TP
  2763. X5.5
  2764. XThe system may now go interactive with the -i flag to \fIserverd\fP(1).
  2765. X.sp
  2766. X\fIremote\fP lists may now specify host names or Internet addresses and ports if
  2767. Xthey are served by interactive UNIX ListServers.
  2768. X.sp
  2769. XThe ULISTSERVER_UMASK environment variable is now used.
  2770. X.sp
  2771. XThe IUL (\fIiul(1)\fP) client is available to connect to interactive UNIX
  2772. XListServers.
  2773. X.sp
  2774. XThe \fIhelp\ live\fP request explains how to connect to interactive UNIX
  2775. XListServers.
  2776. X.sp
  2777. XThe \fIprecedence\fP directive has been added to the \fIconfig\fP file.
  2778. X.sp
  2779. XPrecious header lines are preserved for each list via the \fIheader\fP
  2780. Xdirective.
  2781. X.sp
  2782. XRegular expressions are implemented for the ".aliases" and ".ignored" files.
  2783. X.sp
  2784. XLists may now automaticlly archive distributed messages via the
  2785. X\fIarchive\fP directive.
  2786. X.sp
  2787. XThe manager may allow subscribers of a list to execute UNIX commands via the
  2788. X\fIunix_cmd\fP directive. Users submit a \fIrun\fP request in this case
  2789. X(CCRUN is added as a preference).
  2790. X.sp
  2791. X\fIfarch\fP now creates new archives and takes care of updating and creating
  2792. XDIR and INDEX files as well as directories, and may archive true binary files
  2793. X(does not uuencode them) if requested (-B flag); the -p option was introduced
  2794. Xto accept a password for a new private archive, the -D option to specify
  2795. Xa short description of the files, and the -r option to remove files from
  2796. Xarchives.
  2797. X.sp
  2798. XCommands in the \fIconfig\fP file may span multiple lines if each line is
  2799. Xterminated by &\\n.
  2800. X.sp
  2801. XThe system intercepts requests sent to lists.
  2802. X.sp
  2803. XThe \fIconceal\fP user attribute has been introduced to the subscribers files.
  2804. X.sp
  2805. XThe \fIdefault\fP directive has been introduced to the \fIconfig\fP file to
  2806. Xset default values for new subscribers.
  2807. X.sp
  2808. XUsers may change the address they are subscribed with, if the owner allows this.
  2809. X.sp
  2810. XThe util/ directory has been introduced for general utilities.
  2811. X.sp
  2812. XHelp files may now be shell scripts; same for all lists' ".welcome" and
  2813. X".info" files.
  2814. X.sp
  2815. Xsyslog(3) is now supported for progress reporting by compiling with
  2816. X-DSYSLOG=facility.
  2817. X.sp
  2818. XArchive files may be split on the way out if they exceed the \fIlimit\fP
  2819. Xspecified in the \fIconfig\fP file.
  2820. X.sp
  2821. XLists may restrict the number of messages processed per day with the
  2822. X\fIceiling\fP directive.
  2823. X.sp
  2824. XThe new request \fIfax\fP with its synonymous directive have been introduced.
  2825. X.sp
  2826. XConcealed lists are supported via the -c option to \fIlistserv\fP(1).
  2827. X.sp
  2828. XError messages from mailer daemons are scanned and automatic action is taken
  2829. Xif compiling with -DERROR_MAIL_ANALYSIS=level (1=conservative, 9=full).
  2830. X.sp
  2831. XArchives may now be searched with the \fIsearch\fP request.
  2832. X.sp
  2833. XRun the upgrade_to_6.0 script.
  2834. X.TP
  2835. X5.41
  2836. XModerated lists are now owner controlled, rather than manager controlled.
  2837. X.sp
  2838. XManager preferences have now been introduced.
  2839. X.sp
  2840. XSee the UPGRADING section in farch(1).
  2841. X.sp
  2842. XFollow the upgrade instructions for 5.5
  2843. X.TP
  2844. X5.4
  2845. X\fIcatmail\fP(1) has been implemented, therefore the various aliases
  2846. Xin the aliases file have to be redefined (as explained above) to
  2847. Xtake advantage.
  2848. X.sp
  2849. XOwner preferences have been introduced in the \fIowners\fP file.
  2850. X.sp
  2851. XFollow the upgrade instructions for 5.41
  2852. X.TP
  2853. X5.31
  2854. XThe \fIlist\fP directive in the \fIconfig\fP file now takes two extra
  2855. Xarguments: the list owner's address, and the list's access password.
  2856. X.sp
  2857. X\fIqueued\fP now takes only one argument, a frequency count.
  2858. X.sp
  2859. XThe system supports 10 lists by default (see LIMITATIONS below);
  2860. Xif you are currently using the maximum supported number of lists, consult
  2861. Xthe HOMEDIR/src/defs.h file.
  2862. X.sp
  2863. XThe layout and structure of INDEX files has been extended; see
  2864. X\fIfarch(1)\fP for more information.
  2865. X.sp
  2866. XFollow the upgrade instructions for 5.4
  2867. X.TP
  2868. X5.3
  2869. XThe \fIlist\fP directive in the \fIconfig\fP file now takes two extra
  2870. Xarguments: the list owner's address, and the list's access password.
  2871. X.sp
  2872. XThe system supports 10 lists by default (see LIMITATIONS below);
  2873. Xif you are currently using the maximum supported number of lists, consult
  2874. Xthe HOMEDIR/src/defs.h file.
  2875. X.sp
  2876. XThe layout and structure of INDEX files has been extended; see
  2877. X\fIfarch(1)\fP for more information.
  2878. X.sp
  2879. XFollow the upgrade instructions for 5.4
  2880. X.TP
  2881. X5.2\*
  2882. XUse the \fIsystem\fP mailmethod.
  2883. X.sp
  2884. XFor every list you need to edit HOMEDIR/lists/LIST_ALIAS/.ignored
  2885. Xand add one more entry: the full email address of the server account.
  2886. X.sp
  2887. XFollow the upgrade instructions for 5.3
  2888. X.TP
  2889. X5.0, 5.1\*
  2890. XFor every list you need to edit
  2891. XHOMEDIR/lists/LIST_ALIAS/.ignored and add
  2892. Xtwo entries: the actual list alias, and the full email address
  2893. Xof this list.
  2894. X.sp
  2895. X\fIneverack\fP is not a valid mail mode anymore. Change every
  2896. Xoccurrence in ".subscribers" to NOACK, for every list.
  2897. X.sp
  2898. XAny peer lists and/or news groups appearing in ".subscribers"
  2899. Xshould be removed; use the \fIpeer\fP and \fInews\fP scripts
  2900. Xto put them back.
  2901. X.sp
  2902. X\fIserverd\fP, \fIlist\fP and \fIlistserv\fP no longer report to the
  2903. Xstdout by default -- use the -e command line option.
  2904. X.sp
  2905. XFollow the upgrade instructions for 5.2
  2906. X.SH PORT\ SPECIFIC
  2907. XFor various compilation options, consult the src/Makefile.
  2908. XStarting with version 5.3, a universal mailmethod was introduced: \fIsystem\fP;
  2909. XIt should be used in every system that has TCP/IP installed,
  2910. Xas it has been verified to work on
  2911. Xmany systems below -- consult the src/README file.
  2912. X.TP
  2913. XIBM Risc
  2914. XYou should use \fIsysv_ps\fP as an option in the \fIconfig\fP file,
  2915. Xand compile with xlc -D_ALL_SOURCE -qnoro. You have to use \fIsystem\fP
  2916. Xas the mailmethod.  Messages distributed to local
  2917. Xsubscribers on the system may see their messages arrive "From root...",
  2918. Xbut all other subscribers in the outside world will see "From listserver@..."
  2919. Xand/or "From list@..." which is the correct header. If you use
  2920. X\fIenv_var\ LOGNAME\ /bin/rmail\fP instead, the behavior will be reversed.
  2921. X\fItelnet\fP may not be used as a mailmethod. Compile with -DHAVE_SELECT_H,
  2922. X-DHAVE_ULIMIT_H and -DHAVE_SETJMP_H, and link with -lbsd.
  2923. XIn defs.h the system is defined as having an SVR3 flavor.
  2924. X.TP
  2925. XSGI
  2926. XYou have to use the \fIsystem\fP mailmethod.
  2927. XAll Irix versions to date seem to have a serious problem with telnet (it
  2928. Xcorrupts file descriptors). Use the \fIsysv_ps\fP option.
  2929. XIn the Makefile, define the symbol CC to be 'cc -ansi' or 'cc -D__STDC__',
  2930. Xand compile with -DHAVE_SETJMP_H and -D_POSIX_SOURCE.
  2931. XIn defs.h the system is defined as having an SVR3 flavor.
  2932. X.TP
  2933. XSUN
  2934. X\fIsystem\fP and \fItelnet\fP work fine as mailmethods.
  2935. XUse the \fIbsd_ps\fP option. The server user id should not be the same
  2936. Xas root's.
  2937. XIf you use the native cc compiler you will need to convert to K&R C
  2938. X(by using the unproto system -- consult the src/Makefile);
  2939. Xotherwise /usr/lang/acc -w (ANSI C) can be used. Compile with -DHAVE_SETJMP_H.
  2940. XIn defs.h the system is defined as having a BSD flavor. On Solaris,
  2941. Xcompile with -Dsvr4. If using the live part of the system and your host
  2942. Xis a YP/NIS client you should put the new service in the master's services
  2943. Xmap, or if on the master, remake the map. Older versions of SUNOS have
  2944. Xproblems with their include files, and in this case you have to comment out
  2945. Xthe line:
  2946. X.sp
  2947. X#include <netdb.h>
  2948. X.sp
  2949. Xin src/*.c
  2950. X.TP
  2951. XDECstations
  2952. XYou have to use \fIsystem\fP as the mailmethod; if you use
  2953. X\fItelnet\fP instead, you may have to use the \fIbad_telnet\fP
  2954. Xoption; \fIbsd_ps\fP should be used. Ultrix 3.0 has lots of system bugs
  2955. Xand you may experience strange behavior; the file locking mechanism
  2956. Xover NFS appears to be non-standard and is disabled by default; upgrade to 4.2A
  2957. Xis recommended.
  2958. XAn ANSI C compiler should be used. If you are using the unproto system,
  2959. Xuse the -nocpp flag to cc when compiling. Compile with -DHAVE_SETJMP_H.
  2960. XIn defs.h the system is defined as having a BSD flavor. All Bourne shell scripts
  2961. Xmay need to be altered to invoke /bin/sh5, before they are used.
  2962. X.TP
  2963. XConvex
  2964. XIt is suggested that you use the \fIstds\fP script (available via anonymous ftp
  2965. Xfrom cs.bu.edu) and the non-ANSI compiler; \fIstds\fP should be used as follows:
  2966. X.sp
  2967. Xstds src/nonansi/*.h src/*.c
  2968. X.sp
  2969. XThis should be done after redefining the HOMEDIR entry in src/Makefile and
  2970. Xrunning setup to make all the necessary changes. Compiling under
  2971. XANSI standards (-std flag) is not recommended, since system
  2972. Xinclude files are not ANSI-C compliant. The system cannot go interactive
  2973. Xsince the system does not support semaphores. \fIsystem\fP works fine as
  2974. Xa mailmethod. \fIpaste(1)\fP is missing and \fIstatistics\fP requests will
  2975. Xlook erroneous.
  2976. X.TP
  2977. XStardent GS series
  2978. X\fIsystem\fP and \fItelnet\fP work fine as mailmethods.
  2979. XUse the \fIsysv_ps\fP option. The unproto system has to be used (consult
  2980. Xthe src/Makefile) if not using an ANSI C compiler. The system cannot
  2981. Xgo interactive due to a system() bug. In defs.h the system
  2982. Xis defined as having an SVR3 flavor.
  2983. X.TP
  2984. XStardent/KPC Titan series
  2985. X\fIsystem\fP and \fIenv_var\ LOGNAME\ /bin/rmail\fP work fine as mailmethods.
  2986. XUse the \fIsysv_ps\fP option. The system cannot go interactive due to the
  2987. Xabsence of waitpid(), and compiling and linking with -43 (to use wait3())
  2988. Xhangs \fIserverd(1)\fP and the other applications.
  2989. XIn defs.h the system is defined as having an SVR3 flavor.
  2990. X.TP
  2991. XNeXT
  2992. X\fItelnet\fP, \fIsendmail\fP, \fIsystem\fP (if TCP/IP is installed and SMTP is
  2993. Xused) work fine as mailmethods; however, 'mailmethod sendmail
  2994. X/usr/lib/sendmail -ba' has been characterized as a "DISASTER in terms of
  2995. Xhogging the cpu." Compile with
  2996. X-D__NeXT__ if your compiler does not define this symbol (under version 3.0
  2997. Xof the OS this symbol is automatically defined -- 3.0 is the only supported
  2998. Xenvironment). Compile with -I/usr/include/bsd and -I/usr/include/bsd/sys.
  2999. XFile locking is turned off because of an OS bug.
  3000. XIn defs.h the system is defined as having a BSD flavor. The system
  3001. Xcannot go interactive due to lack of semaphore support.
  3002. X.TP
  3003. XHP-UX
  3004. XCompile with -Aa, -D_HPUX_SOURCE, -DHAVE_ULIMIT_H, -DHAVE_SETJMP_H.
  3005. X\fIsystem\fP is the mailmethod to use.
  3006. XIn defs.h the system is defined as having a BSD flavor.
  3007. X.TP
  3008. XSCO
  3009. XCompile with -Dsco and possibly with -I/usr/include/netinet.
  3010. XYou may wish to link with a
  3011. Xspecial libbsd.a which can be obtained from /pub/sco-ports/libbsd on
  3012. Xdribble.c-mols.siu.edu (131.230.93.2). You need to link with -lsocket.
  3013. XIn defs.h the system is defined as having an SVR3 flavor. The port was done
  3014. Xunder SCO version 3.2.4. The interactive part seems to hang for no apparent
  3015. Xreason.
  3016. X.TP
  3017. XApollo
  3018. XUse the \fIsystem\fP mailmethod. Do not compile with -A ansi, or if you do
  3019. Xalso compile with -Dapollo. The OS that the port was performed under was
  3020. XSR10.4 and version 6.8 of cc. The server id's path should include
  3021. X/sys5.3/usr/bin so that 'paste' may be found. In defs.h the system is defined
  3022. Xas having a BSD flavor. The system cannot go interactive due to lack of
  3023. Xsemaphore support.
  3024. X.TP
  3025. XXenix
  3026. XCompile with -Dxenix; grep(1) is buggy and is suggested that another version
  3027. Xis used. In defs.h the system is defined as having an SVR3 flavor.
  3028. X.TP
  3029. XSequent
  3030. XCompile with gcc -fwritable-strings and -Dsequent if the compiler does not
  3031. Xdefine this symbol. In defs.h
  3032. Xthe system is given a BSD flavor. If under Dynix/PTX, compile with -Dsvr3
  3033. X(PTX is a a System V R3.2 implementation; V2.0.3 includes an ANSI C compiler).
  3034. X.TP
  3035. XData General
  3036. XCompile using gcc -fwritable-strings; in defs.h the system is given an SVR4
  3037. Xflavor and is advisable not to give it a BSD one; keep in mind that
  3038. Xsignals frequently get lost.
  3039. X.TP
  3040. Xi860
  3041. XThis is a standard SVR4.2 UNIX; \fIsystem\fP works fine as mailmethod. All
  3042. Xfeatures are functional.
  3043. X.TP
  3044. Xi386
  3045. XThis is a BSD environment; the system cannot go interactive due
  3046. Xto lack of semaphore support, and file locking is turned off. \fIsystem\fP
  3047. Xworks fine as mailmethod. Compile with the -fwritable-strings flag.
  3048. X.TP
  3049. XOSF
  3050. XThis is a standard SVR3 UNIX; \fIsystem\fP works fine as mailmethod. All
  3051. Xfeatures are functional. Compile with the -std1 flag. Do not compile with
  3052. X-DHAVE_SELECT_H because of missing system header files.
  3053. X.TP
  3054. XOther
  3055. XFirst, attempt compiling with -Dunknown_port.
  3056. X.SH LIMITATIONS
  3057. X\-
  3058. XUp to 10 mailing lists can be supported (configurable in
  3059. Xsrc/defs.h and src/Makefile).
  3060. X.sp
  3061. X\-
  3062. XThe system assumes a length of 32 bits or higher for long integers.
  3063. X.sp
  3064. X\-
  3065. XA list alias may not be called "server".
  3066. X.SH COMPILER
  3067. X.TP
  3068. Xgcc
  3069. XIf you are using gcc to compile, use the -fwritable-strings flag. Versions
  3070. Xprior to 2.2.1 may cause problems.
  3071. X.SH MAILER
  3072. X.TP
  3073. XZmailer
  3074. XIf you are using the Zmailer to send mail, or any other mailer (like Smail)
  3075. Xthat requires a 'HELO hostname' to start the SMTP transaction,
  3076. Xcompile with -DZMAILER (also see src/README and src/Makefile).
  3077. X.SH REQUIREMENTS
  3078. XThe $path for the server account should include all necessary paths to
  3079. Xcut(1), paste(1), awk(1), grep(1), uptime(1) and telnet(1).
  3080. XIn addition, uptime(1) should report the number of users and the system
  3081. Xload; otherwise \fIserverd\fP(1) cannot be run with the -l option, and
  3082. X\fIlistserv\fP(1) cannot be run with the -r option. The output from uptime
  3083. Xshould look like:
  3084. X.nf
  3085. X.sp
  3086. X12:45pm up 5 days, 16 mins, 4 users, load average: 0.00, ...
  3087. X.sp
  3088. X.fi
  3089. XAlso, make sure that when posting, /usr/lib/news/\fIinews\fP exists either
  3090. Xas itself or as a link to wherever \fIinews\fP resides (also see src/Makefile).
  3091. X.sp
  3092. XFinally, grep(1) should support the -i (case insensitive matching) and
  3093. X-v (print all lines that do not match the expression) flags.
  3094. X.SH BUGS
  3095. X.TP
  3096. Xuptime
  3097. XWhen user and load restrictions are enforced, the system assumes
  3098. Xthat uptime outputs a line similar to the one shown above, 
  3099. Xin which the number of
  3100. Xusers is the third column (columns are separated by commas) and
  3101. Xthe load average is the fourth column. The problem is that on a system
  3102. Xthat has been up for less than one day, uptime will report the number
  3103. Xof users in the second column, and the load average in the third
  3104. Xcolumn. In this case, such restrictions should not be enforced.
  3105. X.TP
  3106. Xblanks
  3107. XAlthough the system handles email addresses with blanks in them fairly
  3108. Xwell, \fIstatistics\fP, \fIrecipients\fP and \fIset\ list\fP (status
  3109. Xquery) requests will show erroneous results for these users.
  3110. X.TP
  3111. Xspecial characters
  3112. XThe system does not accept addresses that contain single quotes, back-quotes
  3113. Xor wild characters.
  3114. X.TP
  3115. Xmessages exceeding limits not caught
  3116. XWhen all subscribers of a list have set their mail mode to \fIdigest\fP,
  3117. Xmessages are not subject to size limitations.
  3118. X.TP
  3119. Xno \fIstatistics\fP request for NeXT 2.1 hosts
  3120. XDue to the absense of \fIcut(1)\fP the \fI.stats\fP script has to be
  3121. Xmodified to replace the use of \fIcut(1)\fP with \fIawk(1)\fP.
  3122. X.TP
  3123. X\fIserverd\fP(1) dies with 'no tty' error message
  3124. XIn the \fIconfig\fP file use the -e flag in the \fIlist\fP, \fIserver\fP and
  3125. X\fIserverd\fP definitions followed by '> /dev/null 2>&1'. For example:
  3126. X.sp
  3127. X.ce
  3128. Xserverd -i 600 -e > /dev/null 2>&1
  3129. X.TP
  3130. Xincorrect auto-splitting of files on the way out
  3131. XWhen splitting files that exceed the specified limit, the system precalculates
  3132. Xthe number of parts it will send and puts this number in the Subject: line.
  3133. XHowever, since each part may actually be less than that limit (each part
  3134. Xextends to the nearest newline without exceeding the limit) it is possible to
  3135. Xsend more parts than predicted, if the total number of bytes backtracked (for
  3136. Xall parts) is an integer multiple of the limit; in this case the number of
  3137. Xextra parts will be this integer multiple. The probability of this happening
  3138. Xincreases as the limit is decreased.
  3139. X.SH SEE\ ALSO
  3140. Xcatmail(1), farch(1), iul(1), list(1), listserv(1), queue(1), serverd(1),
  3141. Xstart(1)
  3142. X.SH AUTHOR
  3143. X.nf
  3144. XAnastasios C. Kotsikonas
  3145. XCopyright (c) 1991-93, Anastasios Kotsikonas
  3146. XComments to tasos@cs.bu.edu
  3147. X.fi
  3148. *-*-END-of-doc/server.1-*-*
  3149. echo x - doc/serverd.1
  3150. sed 's/^X//' >doc/serverd.1 <<'*-*-END-of-doc/serverd.1-*-*'
  3151. X.\" UNIX ListServer System
  3152. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  3153. X.\"
  3154. X.TH serverd 1 "UNIX ListServer"
  3155. X.SH NAME
  3156. X\fBserverd\fP \- UNIX ListServer system daemon
  3157. X.SH SYNOPSIS
  3158. X\fBserverd\fP [\fB-1\fP] [\fB-e\fP] [\fB-l load\fP] [\fB-i duration\fP]
  3159. X.SH DESCRIPTION:
  3160. X\fIserverd\fP silently looks for any new messages for the request
  3161. Xserver and for any of the supported mailing lists, checks whether
  3162. Xthe time has arrived for processing the batch queue, whether
  3163. Xdigest time has been reached for the various lists, and whether any
  3164. Xlive TCP/IP connections are requested. It then spawns
  3165. X\fIlistserv\fP(1) and/or \fIlist\fP(1) as necessary, and sleeps until the
  3166. Xmessage(s) is (are) processed. \fIserverd\fP reads the \fIconfig\fP file
  3167. X(see \fIserver\fP(1)).
  3168. X.SH OPTIONS
  3169. XThe following command line options are recognized:
  3170. X.TP
  3171. X-1
  3172. XExecute only once -- to be used with cron(1).
  3173. X.TP
  3174. X-e
  3175. XEcho reports to the screen; it has no effect if the system has been compiled
  3176. Xwith -DSYSLOG.
  3177. X.TP
  3178. X-l load
  3179. XEnforce load restrictions; \fIserverd\fP will postpone spawning if the
  3180. Xsystem load is above the limit specified.
  3181. X.TP
  3182. X-i duration
  3183. XA child process is also spawned which listens for live TCP/IP connections
  3184. Xat port 372 (this is referred to as the Listsener process, and its parent as
  3185. Xthe Master); for each such connection a child process is created to
  3186. Xprocess the live requests (see the INTERACTIVE\ LISTSERVER section below). The
  3187. Xmaximum \fIduration\fP time is given in seconds.
  3188. X.SH INTERACTIVE\ LISTSERVER
  3189. XProvided that the host supports the TCP/IP protocol, the system provides
  3190. Xa mechanism for processing live requests by specifying the -i flag to
  3191. X\fIserverd\fP. Any user may use \fItelnet(1)\fP to connect to a host
  3192. Xthat runs this system at port number 372, issue requests as he would
  3193. Xby email, and receive responses immediately. However, the proper way
  3194. Xto connect to the server is by using \fIiul(1)\fP which lets the user download
  3195. Xfiles through \fIget\fP requests, and provides other amenities as well.
  3196. X.PP
  3197. XWhat requests are allowed
  3198. Xdepends on the privileges assigned upon login: the user is asked for
  3199. Xan email address (default is no email address); then a password should be
  3200. Xprovided. If the user needs manager privileges, he has to provide both the
  3201. Xmanager's email address and the system's password as they appear in the
  3202. X\fIconfig\fP file. If he wishes owner privileges, he has to provide both
  3203. Xhis email address as it appears in the \fIowners\fP file and his list's
  3204. Xpassword as it appears in the \fIconfig\fP file. To gain subscriber privileges
  3205. Xhe has to provide his email address as subscribed to the list where privileges
  3206. Xare to be granted to, as well as the password \fIset\fP for that list.
  3207. X.PP
  3208. XA mismatch or no email address reduces privileges to a minimum. These
  3209. Xare restricted to \fIhelp\fP, \fIinformation\fP, \fIrecipients\fP and
  3210. X\fIstatistics\fP for nonprivate lists, \fIlists\fP, \fIindex\fP, \fIget\fP,
  3211. X\fIrun\fP and \fIrelease\fP requests. Subscriber privileges extend
  3212. Xthese to \fIset\fP, \fIrun\fP, \fIunsubscribe\fP and \fIwhich\fP requests.
  3213. XOwners are granted permission to also issue \fIsystem\fP, \fIreports\fP,
  3214. X\fIedit\fP, \fIput\fP, \fIapprove\fP and \fIdiscard\fP requests in
  3215. Xaddition to the ones above. Finally, the \fImanager\fP may issue any
  3216. Xrequest except \fIexecute\fP.
  3217. X.PP
  3218. XRequests for remote lists are serviced by attempting to connect to the
  3219. Xremote servers serving these lists.
  3220. X.PP
  3221. XThe system may restrict connections to certain hosts, and/or reject connections
  3222. Xfrom certain hosts. First, the system looks for the file \fIpriv.hosts\fP
  3223. Xwhich lists hostnames and/or IP addresses that are allowed access; only
  3224. Xhosts listed in this file are granted acces. For example, to allow access to
  3225. Xhosts on one's local network only, one could do:
  3226. X.sp
  3227. X.ce
  3228. Xln -s /etc/hosts HOMEDIR/priv.hosts
  3229. X.sp
  3230. XNext, the file \fIunwanted.hosts\fP is looked up, and connections from hosts
  3231. Xlisted in it are rejected. Regular expressions may be used in both files.
  3232. X.sp
  3233. XThe duration of each connection is limited to the number of seconds
  3234. Xgiven as argument to the -i flag. A maximum of 5 simultaneous connections
  3235. Xcan be accepted at any time. All requests are serialized and the server may
  3236. Xbe kept busy if it has not finished sending data to a socket (for example,
  3237. Xwhen a user pipes the output he receives to more(1) and the amount of data 
  3238. Xto be sent is more than the the socket's buffer).
  3239. X.PP
  3240. XTo set up your system to accept such connections, the following line has to
  3241. Xbe inserted into your host's /etc/services file:
  3242. X.sp
  3243. X.ce
  3244. Xulistserv   372/tcp
  3245. X.sp
  3246. XThis port is privileged, therefore \fIserverd\fP has to be started with
  3247. Xroot privileges (the \fIsetup\fP script takes care of this). If you do not
  3248. Xhave root access you may choose any other port number above 1024, and in
  3249. Xthis case \fIserverd\fP will give a warning every time it starts, which
  3250. Xcan be ignored.
  3251. X.PP
  3252. XConsult the src/README file for qualification tests for your system to go
  3253. Xinteractive and the Makefile for compilation options; also see the
  3254. XPORT\ SPECIFIC section in \fIserver\fP(1). Lastly, the file HOMEDIR/welcome.live
  3255. Xis copied upon log in, and it may be modified.
  3256. X.PP
  3257. XIf your setup uses a name server you may wish to link with libraries that
  3258. Xprovide DNS support.
  3259. X.SH SEE\ ALSO
  3260. Xiul(1), list(1), listserv(1), queue(1), server(1)
  3261. X.SH AUTHOR
  3262. X.nf
  3263. XAnastasios C. Kotsikonas
  3264. XCopyright (c) 1991-93, Anastasios Kotsikonas
  3265. XComments to tasos@cs.bu.edu
  3266. X.fi
  3267. *-*-END-of-doc/serverd.1-*-*
  3268. echo x - doc/start.1
  3269. sed 's/^X//' >doc/start.1 <<'*-*-END-of-doc/start.1-*-*'
  3270. X.\" UNIX ListServer System
  3271. X.\" Copyright (c) 1991-93, Anastasios Kotsikonas
  3272. X.\"
  3273. X.TH start 1 "UNIX ListServer"
  3274. X.SH NAME
  3275. X\fBstart\fP \- start/stop the UNIX ListServer system
  3276. X.SH SYNOPSIS
  3277. X\fBstart\fP [\fB-c\fP] [\fB-r\fP] [\fB-k\fP]
  3278. X.SH DESCRIPTION
  3279. X\fIstart\fP is used to start or stop the UNIX ListServer system.
  3280. XWhen starting the system, any
  3281. Xprevious server processes still running are killed, all necessary
  3282. Xlock files are created, any previous reports are archived into files with
  3283. Xextension \fI.acc\fP, new files and directories are created for any
  3284. Xnew mailing lists, and \fIserverd\fP(1) is spawned. \fIstart\fP reads the
  3285. X\fIconfig\fP file (see server(1)), and should always be run from the server
  3286. Xaccount (also see \fIserver\fP(1)).
  3287. X.SH OPTIONS
  3288. XThe following command line options are recognized:
  3289. X.TP
  3290. X-c
  3291. XSuppress confirmation when killing processes or when creating new
  3292. Xmailing directories and files.
  3293. X.TP
  3294. X-k
  3295. XJust kill any old server system processes and exit.
  3296. X.TP
  3297. X-r
  3298. XRestrict reporting to stdout.
  3299. X.SH SEE\ ALSO
  3300. Xserver(1), serverd(1)
  3301. X.SH AUTHOR
  3302. X.nf
  3303. XAnastasios C. Kotsikonas
  3304. XCopyright (c) 1991-93, Anastasios Kotsikonas
  3305. XComments to tasos@cs.bu.edu
  3306. X.fi
  3307. *-*-END-of-doc/start.1-*-*
  3308. echo x - doc/catmail.nr
  3309. sed 's/^X//' >doc/catmail.nr <<'*-*-END-of-doc/catmail.nr-*-*'
  3310. X
  3311. X
  3312. X
  3313. Xcatmail(1)               USER COMMANDS                 catmail(1)
  3314. X
  3315. X
  3316. X
  3317. XNNNNAAAAMMMMEEEE
  3318. X     ccccaaaattttmmmmaaaaiiiillll - append incoming mail  to  UNIX  ListServer  system
  3319. X     files
  3320. X
  3321. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  3322. X     ccccaaaattttmmmmaaaaiiiillll {<----LLLL LLLLIIIISSSSTTTT____AAAALLLLIIIIAAAASSSS [----mmmm]> | <----rrrr>} [----ffff]
  3323. X
  3324. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  3325. X     _c_a_t_m_a_i_l is used to redirect incoming mail to the UNIX  List-
  3326. X     Server  system  to  the  appropriate files, according to the
  3327. X     flags specified. The files affected are HOMEDIR/requests  (a
  3328. X     repository  for requests), HOMEDIR/lists/*/mail (public mes-
  3329. X     sages to be distributed) and HOMEDIR/lists/*/moderated (mes-
  3330. X     sages  to  be  screened out by a moderator). _c_a_t_m_a_i_l reports
  3331. X     the user id and user name that is  currently  executing  it;
  3332. X     the  setuid  bit has to be set when installed. _c_a_t_m_a_i_l first
  3333. X     locks the output file before appending to it;  if  the  file
  3334. X     cannot  be  locked  after 3 minutes, the mail is saved under
  3335. X     HOMEDIR/lost+found or HOMEDIR/lists/*/lost+found; both  _l_i_s_t
  3336. X     and  _l_i_s_t_s_e_r_v  lock their mail files while copying them to a
  3337. X     safe place.
  3338. X
  3339. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  3340. X     The following command line options are recognized:
  3341. X
  3342. X     -L LIST_ALIAS [-m]
  3343. X          If  the  -m  flag   is   not   specified,   append   to
  3344. X          HOMEDIR/lists/_L_I_S_T__A_L_I_A_S/mail;   otherwise   append  to
  3345. X          HOMEDIR/lists/_L_I_S_T__A_L_I_A_S/moderated (see list(1)).
  3346. X
  3347. X     -r   Append to HOMEDIR/requests (overrides -L).
  3348. X
  3349. X     -f   Reformat the message in the process: all lines  in  the
  3350. X          message except the first starting with "From " are con-
  3351. X          verted  to  ">From  ".   (see  also   SYSTEM SETUP   in
  3352. X          server(1)).
  3353. X
  3354. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  3355. X     list(1), listserv(1), server(1)
  3356. X
  3357. XAAAAUUUUTTTTHHHHOOOORRRR
  3358. X     Anastasios C. Kotsikonas
  3359. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  3360. X     Comments to tasos@cs.bu.edu
  3361. X
  3362. X
  3363. X
  3364. X
  3365. X
  3366. X
  3367. X
  3368. X
  3369. X
  3370. X
  3371. X
  3372. XAnastasios Kotsikonas                                               1
  3373. X
  3374. X
  3375. X
  3376. *-*-END-of-doc/catmail.nr-*-*
  3377. echo x - doc/farch.nr
  3378. sed 's/^X//' >doc/farch.nr <<'*-*-END-of-doc/farch.nr-*-*'
  3379. X
  3380. X
  3381. X
  3382. Xfarch(1)                 USER COMMANDS                   farch(1)
  3383. X
  3384. X
  3385. X
  3386. XNNNNAAAAMMMMEEEE
  3387. X     ffffaaaarrrrcccchhhh - archive files under the UNIX ListServer system
  3388. X
  3389. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  3390. X     ffffaaaarrrrcccchhhh {[----nnnn] [----bbbb | ----BBBB] [----ssss ssssiiiizzzzeeee]  [----dddd ddddiiiirrrr]  [----pppp ppppaaaasssssssswwwwoooorrrrdddd]  [----
  3391. X     DDDD ddddeeeessssccccrrrriiiippppttttiiiioooonnnn] [----tttt ffffiiiilllleeee]}  |  {[----rrrr]}  [----aaaa aaaarrrrcccchhhhiiiivvvveeee |||| ppppaaaatttthhhh----ttttoooo----
  3392. X     aaaarrrrcccchhhhiiiivvvveeee] <ffffiiiilllleeeessss>
  3393. X
  3394. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  3395. X     _f_a_r_c_h is used to archive files  under  the  UNIX  ListServer
  3396. X     system  or  remove  files already achived, with support pro-
  3397. X     vided  for  private   archives.    Archives   reside   under
  3398. X     HOMEDIR/archives  as  subdirectories;  the  default is _l_i_s_t_-
  3399. X     _s_e_r_v_e_r, and it is also  the  master  archive.  Archives  are
  3400. X     hierarchically structured, and each archive has at least two
  3401. X     files in its directory:
  3402. X
  3403. X     INDEX
  3404. X          A list of all subarchives including itself; the  format
  3405. X          is  one  line  per archive with the archive's name fol-
  3406. X          lowed by  the  archive's  full  path,  followed  by  an
  3407. X          optional password:
  3408. X
  3409. X          archive-name full-path-to-archive-directory [password]
  3410. X
  3411. X          The first entry should  be  the  archive  itself;  each
  3412. X          first level subarchive is listed next; then each second
  3413. X          level subarchive, starting with the first  first-level-
  3414. X          archive's  subarchives,  followed  by the second first-
  3415. X          level-archive's subarchives, etc. No  sibling  archives
  3416. X          may  have the same name, although there is no such res-
  3417. X          triction for archives on different levels, or  "cousin"
  3418. X          archives.  The latter archives are distinguished by the
  3419. X          relative path needed to access them (see _s_e_r_v_e_r(_1)  for
  3420. X          more information).
  3421. X
  3422. X     DIR  A list of files available from that archive; the format
  3423. X          is one line per file with the file name followed by the
  3424. X          number of parts it may be split into, followed  by  the
  3425. X          number  of  bytes of each of the parts, followed by the
  3426. X          full path to the directory these parts  can  be  found,
  3427. X          followed  by a short descriptive message about the file
  3428. X          (optional). The descriptive message  may  span  several
  3429. X          lines;  each  line  (except the last) should end with a
  3430. X          '\':
  3431. X
  3432. X          file nparts size-of-each-part+ full-path-to-directory [description [\]]
  3433. X          [multiple description lines [\]]*
  3434. X
  3435. X          The number of parts the file is split into may be -1 to
  3436. X          indicate that this is a binary file.
  3437. X
  3438. X
  3439. X
  3440. X
  3441. XAnastasios Kotsikonas                                               1
  3442. X
  3443. X
  3444. X
  3445. X
  3446. X
  3447. X
  3448. Xfarch(1)                 USER COMMANDS                   farch(1)
  3449. X
  3450. X
  3451. X
  3452. X     _f_a_r_c_h reports on  the  action  taken  on  each  input  file:
  3453. X     whether  it  was  split (and how many parts), whether it was
  3454. X     uuencoded, whether all files have been tar'red into a single
  3455. X     one,  the  archive  this  file  was  archived under, and the
  3456. X     directory the output file(s) (if any) has/have been  placed.
  3457. X     It also reports when the input files are tarred.
  3458. X
  3459. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  3460. X     The following command line options are recognized:
  3461. X
  3462. X     -n   Do not split files when archiving them. The default  is
  3463. X          to split them with each part not larger than the speci-
  3464. X          fied size (see the -s option below).
  3465. X
  3466. X     -b   Input files  are  binary;  they  are  uuencoded  before
  3467. X          archived.
  3468. X
  3469. X     -B   Input files are binary; they are neither uuencoded  nor
  3470. X          split.
  3471. X
  3472. X     -s size
  3473. X          Specify the maximum _s_i_z_e in kilobytes of  each  of  the
  3474. X          subparts (default is 64).
  3475. X
  3476. X     -d dir
  3477. X          Specify the _d_i_rectory that the output files are  to  be
  3478. X          placed;  if  left  out,  it  defaults  to the specified
  3479. X          archive's directory (HOMEDIR/archives/listserver if the
  3480. X          archive  is  left  out as well).  If the directory (and
  3481. X          all of its subdirectories, if any) does not  exist,  it
  3482. X          will be created.
  3483. X
  3484. X     -p password
  3485. X          When a new archive is to be created, and  that  archive
  3486. X          is to be private, specify the access password.
  3487. X
  3488. X     -D description
  3489. X          Put  _d_e_s_c_r_i_p_t_i_o_n  (most  likely  surrounded  by  single
  3490. X          quotes)  in  the  DIR file as explanatory comment about
  3491. X          the archived file. This option does not make much sense
  3492. X          when archiving more than one file at the same time.
  3493. X
  3494. X     -t file
  3495. X          Input  files  are  tar'red  into  _f_i_l_e  which  is  then
  3496. X          archived  (the  -b  flag  is  automatically turned on).
  3497. X          Turning on the -B flag will prevent uuencoding  of  the
  3498. X          tar  file.  Note that whatever the path to _f_i_l_e may be,
  3499. X          it will be moved to the specified directory  as  speci-
  3500. X          fied by the -d flag.
  3501. X
  3502. X     -r   Remove the specified file(s) from the specified archive
  3503. X          (see below), or the default one; it has higher priority
  3504. X
  3505. X
  3506. X
  3507. XAnastasios Kotsikonas                                               2
  3508. X
  3509. X
  3510. X
  3511. X
  3512. X
  3513. X
  3514. Xfarch(1)                 USER COMMANDS                   farch(1)
  3515. X
  3516. X
  3517. X
  3518. X          than all of the options above.
  3519. X
  3520. X     -a archive | path-to-archive
  3521. X          Specify the  _a_r_c_h_i_v_e  that  the  input  files  will  be
  3522. X          archived  under  (default  is  listserver). Archives on
  3523. X          different levels of the hierarchy  may  have  the  same
  3524. X          name  and  in this case a _p_a_t_h-_t_o-_a_r_c_h_i_v_e may be speci-
  3525. X          fied to distinguish between them;  _p_a_t_h-_t_o-_a_r_c_h_i_v_e  has
  3526. X          the   form  _a_r_c_h_i_v_e[/_a_r_c_h_i_v_e[/_a_r_c_h_i_v_e...]]   (see  also
  3527. X          server(1)). If any of the archives in the path  do  not
  3528. X          exist, they will be created with the necessary files.
  3529. X
  3530. X     File names in the DIR file have to be unique and _f_a_r_c_h  will
  3531. X     not archive duplicate files.
  3532. X
  3533. XAAAARRRRCCCCHHHHIIIIVVVVIIIINNNNGGGG AAAA FFFFIIIILLLLEEEE
  3534. X     _f_a_r_c_h by default splits the input files if necessary (or the
  3535. X     tar  file, if any), into files of maximum size as specified.
  3536. X     Each part will contain as many complete lines from the  ori-
  3537. X     ginal  input  file as possible, without exceeding the speci-
  3538. X     fied size. Binary files (including the tar file)  are  uuen-
  3539. X     coded  before  they  are  archived  unless  the -B option is
  3540. X     specified, and all archived files are compressed, if  possi-
  3541. X     ble.
  3542. X
  3543. XAAAADDDDDDDDIIIINNNNGGGG AAAA NNNNEEEEWWWW AAAARRRRCCCCHHHHIIIIVVVVEEEE
  3544. X     automatically
  3545. X          Simply specify the new archive as argument  to  the  -a
  3546. X          flag.  All necessary DIR and INDEX files as well as all
  3547. X          required directories will be created,  and  all  parent
  3548. X          archives will be updated.
  3549. X
  3550. X     by hand
  3551. X          Step 1
  3552. X
  3553. X          Create a directory under HOMEDIR/archives or  under  an
  3554. X          existing  archive's  directory (beware of the hierarchy
  3555. X          structure), naming the  directory  after  the  archive.
  3556. X          The  archive's name should be unique among its siblings
  3557. X          on that level in the hierarchy (besides, mkdir will not
  3558. X          let specify a name that already exists).
  3559. X
  3560. X          Step 2
  3561. X
  3562. X          Edit    the     master     archive's     index     file
  3563. X          (HOMEDIR/archives/listserver/INDEX)  and  add  the  new
  3564. X          archive along with its path (and optional  password  --
  3565. X          see below) at the proper place in the file, making sure
  3566. X          you adhere to the rules about hierarchy outined  above.
  3567. X          The  first  line  of  every  INDEX  file  should be the
  3568. X          archive itself.  Also  edit  (add  to)  every  ancestor
  3569. X          archive's  INDEX  file,  if  the new archive is not the
  3570. X
  3571. X
  3572. X
  3573. XAnastasios Kotsikonas                                               3
  3574. X
  3575. X
  3576. X
  3577. X
  3578. X
  3579. X
  3580. Xfarch(1)                 USER COMMANDS                   farch(1)
  3581. X
  3582. X
  3583. X
  3584. X          default, again making  sure  you  adhere  to  the  same
  3585. X          rules.
  3586. X
  3587. X          Step 3
  3588. X
  3589. X          Create a new INDEX file in the new archive's  directory
  3590. X          and put an entry for itself.
  3591. X
  3592. X          Step 4
  3593. X
  3594. X          Create an empty DIR file in the  new  archive's  direc-
  3595. X          tory.
  3596. X
  3597. XPPPPRRRRIIIIVVVVAAAATTTTEEEE AAAARRRRCCCCHHHHIIIIVVVVEEEESSSS
  3598. X     Private archives are archives that require  a  password  for
  3599. X     obtaining indices and/or files from them. To make an archive
  3600. X     private, simply append a password  (case  does  not  matter)
  3601. X     after  its  full  path specification in every INDEX file the
  3602. X     archive is defined (its own plus all ancestors' -- the  same
  3603. X     password  has  to be used in all of these files). Then, that
  3604. X     password has to be made known to all users  who  are  to  be
  3605. X     granted  access to this archive.  Note that all files in the
  3606. X     same private archive can be obtained with  the  same  single
  3607. X     password.
  3608. X
  3609. XEEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
  3610. X     Archive src/data and src/data2 under archive listserver (the
  3611. X     default),  using  a  maximum  file  size  of  1K; the output
  3612. X     file(s) will be placed in /tmp/tmp:
  3613. X
  3614. X       % farch -s 1 -d /tmp/tmp src/data src/data2
  3615. X
  3616. X     Archive   /etc/hosts   under   archive   unix    (that    is
  3617. X     listserver/unix)  --  the  -n  flag is used to avoid writing
  3618. X     split parts to /etc which is doomed to fail:
  3619. X
  3620. X       % farch -n -a unix -d /etc -p private /etc/hosts
  3621. X
  3622. X     Archive  /etc/password  under  archive  pub/unix  (that   is
  3623. X     listserver/pub/unix):
  3624. X
  3625. X       % farch -n -a pub/unix -d /etc /etc/passwd
  3626. X
  3627. X     Tar and archive all files in /usr/src to the default archive
  3628. X     and place the tar file under /tmp/tmp:
  3629. X
  3630. X       % farch -t HOMEDIR/source -d /tmp/tmp /usr/src/*.c
  3631. X
  3632. X     Descriptive messages about these files  are  added  manually
  3633. X     into  the  archive's DIR file. However, the -D option can be
  3634. X     used to specify a string as follows:
  3635. X
  3636. X
  3637. X
  3638. X
  3639. XAnastasios Kotsikonas                                               4
  3640. X
  3641. X
  3642. X
  3643. X
  3644. X
  3645. X
  3646. Xfarch(1)                 USER COMMANDS                   farch(1)
  3647. X
  3648. X
  3649. X
  3650. X       % farch -D 'UNIX ListServer system files' -t ulistserv.tar -n -d /usr/server /usr/server/*
  3651. X
  3652. XUUUUPPPPGGGGRRRRAAAADDDDIIIINNNNGGGG
  3653. X     If you are upgrading from:
  3654. X
  3655. X     5.5  The -B, -p, -r and -D options are new; functionality is
  3656. X          the same.
  3657. X
  3658. X     5.41 or less
  3659. X          Every DIR file should now include the size of  each  of
  3660. X          the  parts  of every file, placed between the number of
  3661. X          parts and the path name.
  3662. X
  3663. X          The -a option has been  extended  to  accept  paths  to
  3664. X          archives.
  3665. X
  3666. XRRRREEEESSSSTTTTRRRRIIIICCCCTTTTIIIIOOOONNNNSSSS
  3667. X     - Archive names and input files must  use  only  lower  case
  3668. X     characters of the alphabet.
  3669. X
  3670. XWWWWAAAARRRRNNNNIIIINNNNGGGGSSSS
  3671. X     - Input files that are to be  tar'red  should  only  include
  3672. X     relative  path names; otherwise the end user may not be able
  3673. X     to extract them.
  3674. X
  3675. X     - The tar file should not be any of the input files.
  3676. X
  3677. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  3678. X     server(1)
  3679. X
  3680. XAAAAUUUUTTTTHHHHOOOORRRR
  3681. X     Anastasios C. Kotsikonas
  3682. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  3683. X     Comments to tasos@cs.bu.edu
  3684. X
  3685. X
  3686. X
  3687. X
  3688. X
  3689. X
  3690. X
  3691. X
  3692. X
  3693. X
  3694. X
  3695. X
  3696. X
  3697. X
  3698. X
  3699. X
  3700. X
  3701. X
  3702. X
  3703. X
  3704. X
  3705. XAnastasios Kotsikonas                                               5
  3706. X
  3707. X
  3708. X
  3709. *-*-END-of-doc/farch.nr-*-*
  3710. echo x - doc/iul.nr
  3711. sed 's/^X//' >doc/iul.nr <<'*-*-END-of-doc/iul.nr-*-*'
  3712. X
  3713. X
  3714. X
  3715. Xiul(1)                   USER COMMANDS                     iul(1)
  3716. X
  3717. X
  3718. X
  3719. XNNNNAAAAMMMMEEEE
  3720. X     iiiiuuuullll - Interactive UNIX ListServer client
  3721. X
  3722. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  3723. X     iiiiuuuullll [----vvvv] [----tttt ttttiiiimmmmeeeeoooouuuutttt] [----bbbb bbbbuuuuffffffffeeeerrrr----ssssiiiizzzzeeee] hhhhoooosssstttt [ppppoooorrrrtttt]
  3724. X
  3725. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  3726. X     _i_u_l is a  client  that  connects  to  the  specified  _h_o_s_t's
  3727. X     Interactive UNIX ListServer port (372) for a live session --
  3728. X     i.e. for processing  requests  live.  Another  _p_o_r_t  may  be
  3729. X     specified  if  necessary. The _h_o_s_t may be a host name, or an
  3730. X     IP address.
  3731. X
  3732. X     Upon connection establishment, the protocol attempts to  set
  3733. X     the  user's  privileges  during the session by requesting an
  3734. X     email address and a password.  These are used  to  determine
  3735. X     whether  the user is to be granted system, owner, subscriber
  3736. X     or casual user privileges. If the user  provides  his  owner
  3737. X     email  address  and  his list's password, he will be granted
  3738. X     owner privileges. If he provides an email  address  that  he
  3739. X     uses  for subscription to a list, along with the password he
  3740. X     uses  for  that  list,  he  will   be   granted   subscriber
  3741. X     privileges. The system provides a brief listing of all valid
  3742. X     requests the user may issue during the session. If no  email
  3743. X     address  is  provided,  or no matches are found, the user is
  3744. X     restricted to a few requests.
  3745. X
  3746. X     Requests for remote lists are serviced by attempting to con-
  3747. X     nect  to  the  IUL  server(s) (if any) of the system(s) that
  3748. X     handle those lists.
  3749. X
  3750. X     The IUL server recognizes the following special requests:
  3751. X
  3752. X     quit/exit
  3753. X          End the session.
  3754. X
  3755. X     ?/privileges
  3756. X          Get a brief listing of all valid requests.
  3757. X
  3758. X     timeleft
  3759. X          Prints the remaining time in seconds.
  3760. X
  3761. X     &<new-line>
  3762. X          Input continues on the next line.
  3763. X
  3764. X     binary
  3765. X          Switch to binary mode when transferring files.
  3766. X
  3767. X     ascii
  3768. X          Switch to ASCII mode when transferring files.
  3769. X
  3770. X     < filename
  3771. X
  3772. X
  3773. X
  3774. XAnastasios Kotsikonas                                               1
  3775. X
  3776. X
  3777. X
  3778. X
  3779. X
  3780. X
  3781. Xiul(1)                   USER COMMANDS                     iul(1)
  3782. X
  3783. X
  3784. X
  3785. X          Input is taken from the specified file. Each line  will
  3786. X          be  interpreted  as a separate request, unless the file
  3787. X          is specified in conjunction with a _p_u_t request. If  the
  3788. X          '<' is to be used literally it must be escaped with '\'
  3789. X          or enclosed in quotes.
  3790. X
  3791. X     > filename
  3792. X          Redirect the reply to  the  request  to  the  specified
  3793. X          file. Error messages (such as rejections due to invalid
  3794. X          requests, etc.) are not redirected.   When  a  file  is
  3795. X          downloaded  via  a  _g_e_t request, this will override the
  3796. X          file name that will be saved under. If the '>' is to be
  3797. X          used literally it must be escaped with '\', or enclosed
  3798. X          in quotes.
  3799. X
  3800. X     >> filename
  3801. X          Same as above, but the reply is appended to the  speci-
  3802. X          fied file.
  3803. X
  3804. X     | prog [args]
  3805. X          The output of the request is piped  to  _p_r_o_g;  this  is
  3806. X          similar to a UNIX pipe. _p_r_o_g may be any valid UNIX com-
  3807. X          mand, including other pipes,  file  redirections,  etc.
  3808. X          Since  '<'  has  higher precedence in this context, you
  3809. X          should escape any '<' characters intended to be used by
  3810. X          the  pipe,  otherwise  the  system  will assume you are
  3811. X          feeding it batched requests. Quotes may also be used to
  3812. X          protect these characters.
  3813. X
  3814. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  3815. X     The following options are recognized:
  3816. X
  3817. X     -v   Turn verbose mode on; the server reply codes are echoed
  3818. X          along with predetermined messages.
  3819. X
  3820. X     -t timeout
  3821. X          The default time out  for  a  server  response  is  180
  3822. X          seconds;  to reset use the -t flag. This timeout should
  3823. X          not be confused with the remaining time  of  a  connec-
  3824. X          tion.
  3825. X
  3826. X     -b buffer-size
  3827. X          The default socket buffer size is 8K; to reset use  the
  3828. X          -b flag (the argument specifies kilobytes).
  3829. X
  3830. X
  3831. XUUUUSSSSEEEERRRR PPPPRRRRIIIIVVVVIIIILLLLEEEEGGGGEEEESSSS
  3832. X     Casual users may only issue  help,  information,  recipients
  3833. X     and  statistics  for  nonprivate  lists,  lists, index, get,
  3834. X     search and release  requests.   Subscriber  privileges  also
  3835. X     include  the set, run, unsubscribe and which requests.  Own-
  3836. X     ers may, in addition,  issue  all  of  their  administrative
  3837. X
  3838. X
  3839. X
  3840. XAnastasios Kotsikonas                                               2
  3841. X
  3842. X
  3843. X
  3844. X
  3845. X
  3846. X
  3847. Xiul(1)                   USER COMMANDS                     iul(1)
  3848. X
  3849. X
  3850. X
  3851. X     requests.
  3852. X
  3853. X     Issue a 'help live' request when you first connect to an IUL
  3854. X     server.
  3855. X
  3856. XRRRREEEESSSSTTTTRRRRIIIICCCCTTTTIIIIOOOONNNNSSSS
  3857. X     The connection  duration  is  limited  to  a  server-imposed
  3858. X     limit.  After that, a connection may be broken by the server
  3859. X     as necessary.  A connection will  not  be  broken  during  a
  3860. X     transfer.
  3861. X
  3862. XEEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
  3863. X     request> put ermis ermis1 subscribers </usr/server/backup/lists/ERMIS/subs >out
  3864. X
  3865. X     request> get listserver example.dat 1 3 >> out
  3866. X
  3867. X     request> get listserver example.dat
  3868. X
  3869. X     request> index iul > IUL
  3870. X
  3871. X     request> < /tmp/batched.requests
  3872. X
  3873. X     request> index | more
  3874. X
  3875. X     request> lists | cut -d ' ' -f1,2 | more
  3876. X
  3877. X     request> search iul "\>\> out"
  3878. X
  3879. X     In this last example, we escape '>' to protect it from being
  3880. X     interpreted  as  a regular expression separator, and enclose
  3881. X     the whole pattern in quotes to protect the '>>'  from  being
  3882. X     interpreted  as  the append operator. The same request could
  3883. X     have been written as:
  3884. X
  3885. X     request> search iul \\>\\> out
  3886. X
  3887. XFFFFIIIILLLLEEEESSSS
  3888. X     iul.c, iul.h
  3889. X          Source code for  the  client.  See  iul.c  for  compile
  3890. X          options.
  3891. X
  3892. X     iulp.h
  3893. X          Definition of the Interactive UNIX ListServer Protocol.
  3894. X
  3895. X     makefile
  3896. X          makefile to build _i_u_l. _i_u_l is  written  with  BSD-style
  3897. X          signal handling, therefore on some hosts (like IBM AIX)
  3898. X          you will have to link with BSD versions  of  signal(2),
  3899. X          socket(3N),  and  fcntl(2).  Platforms  that  have  the
  3900. X          <sys/select.h> and <ulimit.h> header files should  com-
  3901. X          pile  with  -DHAVE_SELECT_H and/or -DHAVE_ULIMIT_H. SCO
  3902. X          ports should  compile  with  -Dsco.  Always  link  with
  3903. X
  3904. X
  3905. X
  3906. XAnastasios Kotsikonas                                               3
  3907. X
  3908. X
  3909. X
  3910. X
  3911. X
  3912. X
  3913. Xiul(1)                   USER COMMANDS                     iul(1)
  3914. X
  3915. X
  3916. X
  3917. X          libraries  that  provide  DNS  support (resolver linked
  3918. X          in).
  3919. X
  3920. XBBBBUUUUGGGGSSSS
  3921. X     Please report any bugs or enhancements to tasos@cs.bu.edu
  3922. X
  3923. X
  3924. X
  3925. X
  3926. X
  3927. X
  3928. X
  3929. X
  3930. X
  3931. X
  3932. X
  3933. X
  3934. X
  3935. X
  3936. X
  3937. X
  3938. X
  3939. X
  3940. X
  3941. X
  3942. X
  3943. X
  3944. X
  3945. X
  3946. X
  3947. X
  3948. X
  3949. X
  3950. X
  3951. X
  3952. X
  3953. X
  3954. X
  3955. X
  3956. X
  3957. X
  3958. X
  3959. X
  3960. X
  3961. X
  3962. X
  3963. X
  3964. X
  3965. X
  3966. X
  3967. X
  3968. X
  3969. X
  3970. X
  3971. X
  3972. XAnastasios Kotsikonas                                               4
  3973. X
  3974. X
  3975. X
  3976. *-*-END-of-doc/iul.nr-*-*
  3977. echo x - doc/list.nr
  3978. sed 's/^X//' >doc/list.nr <<'*-*-END-of-doc/list.nr-*-*'
  3979. X
  3980. X
  3981. X
  3982. Xlist(1)                  USER COMMANDS                    list(1)
  3983. X
  3984. X
  3985. X
  3986. XNNNNAAAAMMMMEEEE
  3987. X     lllliiiisssstttt - process a specified UNIX ListServer mailing list
  3988. X
  3989. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  3990. X     lllliiiisssstttt ----LLLL <LLLLIIIISSSSTTTT____AAAALLLLIIIIAAAASSSS> [----1111] [----eeee] [----ssss] [----pppp]  [----PPPP]  [----mmmm ####]  [----ffff]
  3991. X     [----rrrr] [----MMMM] [----dddd] [----iiii <aaaaddddddddrrrreeeessssssss>] [----vvvv] [----DDDD]
  3992. X
  3993. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN::::
  3994. X     _l_i_s_t distributes the  message(s)  sent  to  _l_i_s_t__a_l_i_a_s@_y_o_u_r-
  3995. X     _d_o_m_a_i_n;  the  file  ".ignored" in the list's subdirectory is
  3996. X     used to filter out any unwanted messages (see below).
  3997. X
  3998. X     Messages from mailer daemons are  forwarded  to  the  list's
  3999. X     owner  and  screened  looking  for delivery errors (in which
  4000. X     case appropriate action is taken -- users are either immedi-
  4001. X     ately  removed  from the list, or after a series of delivery
  4002. X     errors within a certain time frame -- entries  removed  from
  4003. X     the       system's      files      are      placed      into
  4004. X     HOMEDIR/lists/*/removed.users                            and
  4005. X     HOMEDIR/lists/*/removed.alias  files), whereas messages from
  4006. X     non-subscribers are returned to the original senders (the -f
  4007. X     flag overrides this). Messages whose first line looks like a
  4008. X     ListServer request are bounced back to the sender.
  4009. X
  4010. X     Messages from news groups are distributed only to local sub-
  4011. X     scribers and peer lists. Messages from peers are distributed
  4012. X     to local subscribers and possibly  posted  to  news  groups.
  4013. X     Finally,  messages from local subscribers are either distri-
  4014. X     buted locally, copies are sent to all peers, and are  possi-
  4015. X     bly  posted  to  news groups, or are forwarded to the list's
  4016. X     owner for screening if the list is moderated.
  4017. X
  4018. X     All distributed messages (i.e. legitimate messages from sub-
  4019. X     scribers,  peers and news groups -- not rejected, ignored or
  4020. X     error    messages)    are    automatically    archived    in
  4021. X     HOMEDIR/lists/*/archive.     In    contrast,    the    files
  4022. X     HOMEDIR/lists/*/mbox contain  all  messages  sent  to  these
  4023. X     lists (including, error, rejected and ignored messages).
  4024. X
  4025. X     Email from one or more subscribers may be  selectively  dis-
  4026. X     tributed  to an alternate list of recipients, by way of res-
  4027. X     tricted mail (see below), in which case  mail  will  not  be
  4028. X     distributed to the regular subscribers.
  4029. X
  4030. X     When the system is for some reason aborted  while  making  a
  4031. X     delivery,  a built-in mechanism allows it to resume from the
  4032. X     point it left off.
  4033. X
  4034. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  4035. X     The following command line options are recognized:
  4036. X
  4037. X     -L LIST_ALIAS
  4038. X
  4039. X
  4040. X
  4041. XAnastasios Kotsikonas                                               1
  4042. X
  4043. X
  4044. X
  4045. X
  4046. X
  4047. X
  4048. Xlist(1)                  USER COMMANDS                    list(1)
  4049. X
  4050. X
  4051. X
  4052. X          Process  any  messages  sent  to  this  _L_I_S_T__A_L_I_A_S   --
  4053. X          _L_I_S_T__A_L_I_A_S should be in capital letters.
  4054. X
  4055. X     -1   Execute only once; process the mailing list and  return
  4056. X          control  to  _s_e_r_v_e_r_d(1); any new messages that may have
  4057. X          arrived in the meantime will be processed  at  a  later
  4058. X          time.  Without  this option, _l_i_s_t will be listening for
  4059. X          messages for the specified list  for  ever.  _s_e_r_v_e_r_d(1)
  4060. X          uses this option by default when spawning _l_i_s_t.
  4061. X
  4062. X     -e   Echo reports to the screen; it has  no  effect  if  the
  4063. X          system has been compiled with -DSYSLOG.
  4064. X
  4065. X     -s   By default, only subscribers can  send  messages  to  a
  4066. X          list. This option turns off subscription checking.
  4067. X
  4068. X     -p   By default, replies to messages posted to  news  groups
  4069. X          go  to  the list; this option forces replies to be for-
  4070. X          warded to the original author.
  4071. X
  4072. X     -P   By default, replies to messages sent to subscribers and
  4073. X          peers  go to the list; this option forces replies to be
  4074. X          forwarded to the original author.
  4075. X
  4076. X     -m number
  4077. X          Normally, each outgoing message has one recipient. This
  4078. X          flag  switches to multi-recipient outgoing messages and
  4079. X          specifies the _n_u_m_b_e_r of recipients to  be  included  in
  4080. X          these messages.
  4081. X
  4082. X     -f   Forward any messages from non-subscribers to the list's
  4083. X          owner. By default, they are returned to the sender.
  4084. X
  4085. X     -r   Restricted mail: _l_i_s_t will look  at  the  ".restricted"
  4086. X          file (see below) to get the name of the alternate reci-
  4087. X          pients file. If the sender is  listed  in  that  ".res-
  4088. X          tricted"  file,  his  messages  will  be distributed to
  4089. X          users listed in the alternate recipients file.
  4090. X
  4091. X     -M   The list is moderated; all incoming messages  not  from
  4092. X          the  owner(s) are forwarded to the list's primary owner
  4093. X          for review and editing. The owner then sends  back  the
  4094. X          ones  that  are  approved for posting (for an alternate
  4095. X          scheme see the MODERATED LISTS section below).
  4096. X
  4097. X     -d   Force a digest to be distributed. This flag  is  inter-
  4098. X          nally  used  by  _s_e_r_v_e_r_d(1)  when  digest time has been
  4099. X          reached for this list.
  4100. X
  4101. X     -i address
  4102. X          Send a partial digest to _a_d_d_r_e_s_s (what has  accumulated
  4103. X          so  far).   This flag is internally used by _l_i_s_t_s_e_r_v(1)
  4104. X
  4105. X
  4106. X
  4107. XAnastasios Kotsikonas                                               2
  4108. X
  4109. X
  4110. X
  4111. X
  4112. X
  4113. X
  4114. Xlist(1)                  USER COMMANDS                    list(1)
  4115. X
  4116. X
  4117. X
  4118. X          when the user identified by _a_d_d_r_e_s_s  changes  his  _m_a_i_l
  4119. X          mode  from _d_i_g_e_s_t to something else. Note that when the
  4120. X          time arrives for the current digest to be  distributed,
  4121. X          this user will get duplicate messages.
  4122. X
  4123. X     -v   Print version information.
  4124. X
  4125. X     -D   Turns debugging on. When the _s_y_s_t_e_m mailmethod is  used
  4126. X          (see  server(1)),  a  copy of the last SMTP transaction
  4127. X          can  be   found   in   the   files   HOMEDIR/sent   and
  4128. X          HOMEDIR/received.
  4129. X
  4130. XAAAADDDDDDDDIIIINNNNGGGG AAAA NNNNEEEEWWWW LLLLIIIISSSSTTTT
  4131. X     To add a new list, first shut the system down  by  executing
  4132. X     _s_t_a_r_t(1):
  4133. X
  4134. X       % _s_t_a_r_t -_k
  4135. X
  4136. X     Then edit the _c_o_n_f_i_g file and add a line  defining  the  new
  4137. X     list  --  you may wish to add a comment and/or disable a few
  4138. X     requests  also.   A  new  alias  has  to  be   set   up   in
  4139. X     /etc/aliases, /usr/lib/aliases or /usr/ucblib/aliases of the
  4140. X     following form:
  4141. X
  4142. X     list_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f"
  4143. X
  4144. X     Note that _l_i_s_t__a_l_i_a_s is all lower case and _L_I_S_T__A_L_I_A_S is all
  4145. X     upper case. In this case _c_a_t_m_a_i_l(1) appends incoming mail to
  4146. X     the list's mail file (HOMEDIR/lists/LIST_ALIAS/mail).   Also
  4147. X     keep  in mind the case of reformatting messages as described
  4148. X     in _c_a_t_m_a_i_l(1).
  4149. X
  4150. X     Finally,  restart  the  system.  At  this  point,  the  file
  4151. X     ".ignored"  in the HOMEDIR/lists/LIST_ALIAS directory may be
  4152. X     edited to add more unwanted senders. You  should  also  edit
  4153. X     the files ".welcome" and ".info" in the list's subdirectory;
  4154. X     the former is included in the return message for a new  sub-
  4155. X     scription  request for that list, and the latter is included
  4156. X     in the return message for an _i_n_f_o_r_m_a_t_i_o_n  request  for  that
  4157. X     list  (see  _l_i_s_t_s_e_r_v(1)).  These  files  may  be simple text
  4158. X     files, or shell scripts (see the HELP section in server(1)).
  4159. X
  4160. XAAAADDDDDDDDIIIINNNNGGGG AAAA PPPPEEEEEEEERRRR LLLLIIIISSSSTTTT
  4161. X     Peer lists are mailing lists that happen to  be  subscribers
  4162. X     to  one or more of your own mailing lists; they handle local
  4163. X     distribution of messages just like you do at your own  site.
  4164. X     Peer lists can be mutual subscribers, so that a message ori-
  4165. X     ginating in a peer list gets distributed over there locally,
  4166. X     and  a copy is sent to the other for local distribution, and
  4167. X     vice versa. An automatic mechanism is provided for  avoiding
  4168. X     loops.   A peer list can be added to a local mailing list by
  4169. X     using the script _p_e_e_r:
  4170. X
  4171. X
  4172. X
  4173. XAnastasios Kotsikonas                                               3
  4174. X
  4175. X
  4176. X
  4177. X
  4178. X
  4179. X
  4180. Xlist(1)                  USER COMMANDS                    list(1)
  4181. X
  4182. X
  4183. X
  4184. X     peer <LIST_ALIAS> <remote alias> <peer address> <remote ListServer address>
  4185. X
  4186. X     where  _L_I_S_T__A_L_I_A_S  is a local list alias in capital letters,
  4187. X     _r_e_m_o_t_e _a_l_i_a_s is the peer's  alias  on  the  remote  machine,
  4188. X     _p_e_e_r _a_d_d_r_e_s_s is taken from the first line of the header of a
  4189. X     test message sent to your host by the peer (the  first  line
  4190. X     may  be something like: "From peer@other-domain" -- see also
  4191. X     the     discussion     about     aliases     below),     and
  4192. X     _r_e_m_o_t_e _L_i_s_t_S_e_r_v_e_r _a_d_d_r_e_s_s  is  the full email address of the
  4193. X     remote request-handler.
  4194. X
  4195. X     Here is an example for establishing connection  between  two
  4196. X     peer  lists a@domain1 and b@domain2:  The _m_a_n_a_g_e_r at domain1
  4197. X     issues the following command:
  4198. X
  4199. X     peer a b b@domain2 listserver@hdomain2
  4200. X
  4201. X     The _m_a_n_a_g_e_r at domain2 issues the following command:
  4202. X
  4203. X     peer b a a@domain1 listserver@domain1
  4204. X
  4205. X     Once  these  two  commands  are  issued  the  connection  is
  4206. X     automatically set up.  Peer lists should make sure that only
  4207. X     one of them posts to the same news group(s), and  that  only
  4208. X     one   of   them   receives   articles  from  the  same  news
  4209. X     group(s)/gateway(s).  Lists handled by the same server  can-
  4210. X     not be mutual peers. Finally, peer lists should not be regu-
  4211. X     lar subscribers (the _p_e_e_r  script  places  them  in  a  file
  4212. X     called ".peers").
  4213. X
  4214. XNNNNEEEEWWWWSSSS GGGGRRRROOOOUUUUPPPPSSSS AAAANNNNDDDD GGGGAAAATTTTEEEEWWWWAAAAYYYYSSSS
  4215. X     A mailing list may be linked with one or  more  news  groups
  4216. X     (or  gateways)  from which it may receive messages for local
  4217. X     distribution, and/or send messages to the  newsgroup(s)  for
  4218. X     posting  --  in  this  case  only messages from regular sub-
  4219. X     scribers and peers are sent for posting, i.e. no  news  mes-
  4220. X     sages  will  be  posted  to any news groups (or gateways). A
  4221. X     news group or gateway is linked using the script _n_e_w_s:
  4222. X
  4223. X        news <LIST_ALIAS> <news group> <email address> <mode>
  4224. X
  4225. X     where _L_I_S_T__A_L_I_A_S is a local list alias (in capital  letters)
  4226. X     that  is  being  linked to the news group, _n_e_w_s _g_r_o_u_p is the
  4227. X     name of  the  news  group  (used  only  when  posting)  e.g.
  4228. X     misc.test,  _e_m_a_i_l _a_d_d_r_e_s_s  is the address of the backbone or
  4229. X     moderator of the news group, or the gateway, and it is taken
  4230. X     from  the first line of the header of a test message sent to
  4231. X     your host by the group (the  first  line  may  be  something
  4232. X     like:  "From  gateway@foo  ..."  --  see also the discussion
  4233. X     about aliases below); _m_o_d_e is one of the following:
  4234. X
  4235. X     receive
  4236. X
  4237. X
  4238. X
  4239. XAnastasios Kotsikonas                                               4
  4240. X
  4241. X
  4242. X
  4243. X
  4244. X
  4245. X
  4246. Xlist(1)                  USER COMMANDS                    list(1)
  4247. X
  4248. X
  4249. X
  4250. X          The list will only be receiving messages from this news
  4251. X          group  and  never post to it. This allows access to the
  4252. X          group (or gateway) to send articles to the list.
  4253. X
  4254. X     send_receive
  4255. X          The list may  be  receiving  messages  from  this  news
  4256. X          group, and it will post to it any messages from regular
  4257. X          subscribers and peer lists (messages from  news  groups
  4258. X          are  never  posted  to  other  news  groups). This also
  4259. X          allows access to the group (or gateway) to  send  arti-
  4260. X          cles to the list.
  4261. X
  4262. X     Of course, the news group's caretaker has to be notified  of
  4263. X     the  list's  address so that articles will indeed be sent to
  4264. X     it. Finally, news groups should not be  regular  subscribers
  4265. X     (the _n_e_w_s script places them in a file called ".news").
  4266. X
  4267. X     If the config option _p_o_s_t__m_a_i_l is used, the system will  use
  4268. X     _i_n_e_w_s  for  posting,  and  it assumes that the path to it is
  4269. X     /usr/lib/news/inews, so make sure that _i_n_e_w_s resides  there,
  4270. X     or  a  link  exists to it. In this case, the group's name is
  4271. X     used for posting (e.g. misc.test). If instead  _g_a_t_e__m_a_i_l  is
  4272. X     defined,  messages  will  be sent via email to news gateways
  4273. X     (using the _e_m_a_i_l _a_d_d_r_e_s_s) -- the _n_e_w_s _g_r_o_u_p name has no sig-
  4274. X     nificance in this case.
  4275. X
  4276. XMMMMOOOODDDDEEEERRRRAAAATTTTEEEEDDDD LLLLIIIISSSSTTTTSSSS
  4277. X     The system supports two schemes for  moderating  lists.  The
  4278. X     first  scheme  uses the -M flag to _l_i_s_t(1), and in this case
  4279. X     messages not from the list's owner(s) are forwarded  to  the
  4280. X     list's  primary  owner for review; the owner then sends back
  4281. X     the approved (and possibly edited) ones.
  4282. X
  4283. X     The second scheme uses the -m flag to  _c_a_t_m_a_i_l(1).  In  this
  4284. X     case,  the  list's  alias is changed slightly in the aliases
  4285. X     file:
  4286. X
  4287. X     list_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f -m"
  4288. X
  4289. X     _l_i_s_t(1) distributes messages from a  file  called  _m_a_i_l;  by
  4290. X     having  incoming  messages  redirected to the file _m_o_d_e_r_a_t_e_d
  4291. X     (the effect of the -m flag to _c_a_t_m_a_i_l(1)), the list's  owner
  4292. X     may  _a_p_p_r_o_v_e  or  _d_i_s_c_a_r_d  any number of these messages (see
  4293. X     _l_i_s_t_s_e_r_v(1)).  Whenever a new mail  message  arrives  for  a
  4294. X     moderated  list,  a  copy  is  sent to the list's owner with
  4295. X     instructions for approving or discarding it. These  instruc-
  4296. X     tions  include a unique tag number for identifying that mes-
  4297. X     sage. When a message is approved, it is transferred  to  the
  4298. X     _m_a_i_l file for later delivery, and when discarded, it is sim-
  4299. X     ply removed from the _m_o_d_e_r_a_t_e_d file. This scheme  cuts  down
  4300. X     on mail traffic.
  4301. X
  4302. X
  4303. X
  4304. X
  4305. XAnastasios Kotsikonas                                               5
  4306. X
  4307. X
  4308. X
  4309. X
  4310. X
  4311. X
  4312. Xlist(1)                  USER COMMANDS                    list(1)
  4313. X
  4314. X
  4315. X
  4316. XRRRREEEESSSSTTTTRRRRIIIICCCCTTTTEEEEDDDD MMMMAAAAIIIILLLL
  4317. X     When the -r flag is used with  _l_i_s_t(1),  for  every  message
  4318. X     received  its  sender  is  checked  against  a list of "res-
  4319. X     tricted" email addresses, in the file ".restricted"  in  the
  4320. X     list's  directory -- a subset of the ".subscribers" file. If
  4321. X     a match is found, mail is forwarded to the people listed  in
  4322. X     the file following this email address. If no match is found,
  4323. X     the message is distributed to the regular subscribers.  Note
  4324. X     that  the  alternate  recipients  file should be in the same
  4325. X     format as the ".subscribers".
  4326. X
  4327. X....SSSSUUUUBBBBSSSSCCCCRRRRIIIIBBBBEEEERRRRSSSS
  4328. X     The format is as follows:
  4329. X
  4330. X     One entry per line; each entry is the full email address  of
  4331. X     the  subscriber as it appears in the "From " field, followed
  4332. X     by the word "ACK" (in which case  his/her  message  will  be
  4333. X     sent  back  to  him/her as an acknowledgement), "NOACK" (the
  4334. X     opposite), "POSTPONE" (no mail will be sent until  the  user
  4335. X     changes  mode  again), or "DIGEST" (digests are periodically
  4336. X     sent), followed by a string  that  plays  the  role  of  the
  4337. X     user's  password, followed by either "YES" or "NO" which are
  4338. X     the  values  of  the  conceal  attribute,  followed  by  the
  4339. X     subscriber's name. See also _l_i_s_t_s_e_r_v(1).
  4340. X
  4341. X....RRRREEEESSSSTTTTRRRRIIIICCCCTTTTEEEEDDDD
  4342. X     The format is as follows:
  4343. X
  4344. X     One entry per line; each entry is the full email address  of
  4345. X     the   subscriber,  followed  by  a  file  name  where  email
  4346. X     addresses of recipients are listed (just like in the  ".sub-
  4347. X     scribers" file). Example:
  4348. X
  4349. X        jdoe@foo.bar.com  HOMEDIR/lists/LIST_ALIAS/.recipients
  4350. X
  4351. X     If the recipient file given is the word "NONE", then no  one
  4352. X     will receive any messages.
  4353. X
  4354. X....AAAALLLLIIIIAAAASSSSEEEESSSS
  4355. X     It   is    possible    that    a    subscriber's/peer's/news
  4356. X     group's/gateway's  email  may  arrive using a different path
  4357. X     than registered, which may  raise  subscription  issues.  To
  4358. X     work  around  this,  each list provides a ".aliases" file in
  4359. X     its  subdirectory,  which  may   contain   alternate   email
  4360. X     addresses  to  be  used  when checking for subscription. The
  4361. X     format is one line per alias with the following information:
  4362. X
  4363. X                 alias-address address-as-subscribed
  4364. X
  4365. X     Please note that only the subscribed  address  is  used  for
  4366. X     sending  out  email  (see next section about regular expres-
  4367. X     sions).
  4368. X
  4369. X
  4370. X
  4371. XAnastasios Kotsikonas                                               6
  4372. X
  4373. X
  4374. X
  4375. X
  4376. X
  4377. X
  4378. Xlist(1)                  USER COMMANDS                    list(1)
  4379. X
  4380. X
  4381. X
  4382. X     The  aliased  address  may  be  a  regular  expression  with
  4383. X     egrep(1)  style  syntax, in which case the following charac-
  4384. X     ters have special meanings:  '~',  if  leading  the  regular
  4385. X     expression  it  reverses  its  meaning; '|' and '&' separate
  4386. X     multiple regular expressions (logical OR and AND);  '<'  '>'
  4387. X     group  regular  expressions  (we preserve the meaning of the
  4388. X     parentheses from ed(1), and remove the meaning of  <  and  >
  4389. X     from  ed(1)  since in the ListServer context they are either
  4390. X     the default, or inappropriate).  These can be used literally
  4391. X     by  escaping them with '\'. In addition, the following char-
  4392. X     acters should be defined in matched pairs: (), <>,  [],  "".
  4393. X     For example:
  4394. X
  4395. X                  jdoe@.*\.bar\.com jdoe@foo.bar.com
  4396. X
  4397. X     will enable this user to send messages from any  machine  in
  4398. X     his local network and receive replies at foo.bar.com -- keep
  4399. X     in mind that a '.'  matches exactly one character, and  '.*'
  4400. X     matches  zero  or  more  characters.   In a more complicated
  4401. X     example:
  4402. X
  4403. X           ~jdoe@cc.*|jdoe@....*\.bar\.com jdoe@foo.bar.com
  4404. X
  4405. X     will match if jdoe sends a message from a machine whose name
  4406. X     does  not  start with 'cc', or from a machine whose name has
  4407. X     at least 3 characters.
  4408. X
  4409. X     If   certain   parts   of   the   regular   expression   are
  4410. X     parenthesized,  then the strings that matched the subexpres-
  4411. X     sions can be used in the 'address-as-subscribed' to form new
  4412. X     return  addresses;  these matched strings are accessed by \_n
  4413. X     where _n is a digit between 1 and  9.  For  example,  if  the
  4414. X     sender is:
  4415. X
  4416. X                     GATE!HOP!USER@UUCP.SOME.COM
  4417. X
  4418. X     and the entry in the ".aliases" file reads:
  4419. X
  4420. X               [^!@]*!([^!@.]*)!([^!@]*)@.*  \2@\1.UUCP
  4421. X
  4422. X     then what will be returned as 'address-as-subscribed' is:
  4423. X
  4424. X                            USER@HOP.UUCP
  4425. X
  4426. X     This way you can map addresses coming in via  various  gate-
  4427. X     ways  to  steady  ones  (\2  refers  to  the  second  set of
  4428. X     parentheses, and  \1  to  the  first).   Managers  may  edit
  4429. X     HOMEDIR/src/regex.c  to  test  regular  expression behavior,
  4430. X     introduce ls(1) style meanings to the * and ?  wild  charac-
  4431. X     ters,  undefine ed(1) special characters, and enforce strict
  4432. X     egrep(1) syntax (remove the meanings of ~ & < and >).
  4433. X
  4434. X
  4435. X
  4436. X
  4437. XAnastasios Kotsikonas                                               7
  4438. X
  4439. X
  4440. X
  4441. X
  4442. X
  4443. X
  4444. Xlist(1)                  USER COMMANDS                    list(1)
  4445. X
  4446. X
  4447. X
  4448. X     Regular expressions should be used with caution for  obvious
  4449. X     reasons.
  4450. X
  4451. X     If someone is experiencing subscription  problems,  you  may
  4452. X     wish  to add their alternate email address(es) in this file.
  4453. X     This includes regular subscribers, news  groups,  peers  and
  4454. X     gateways.  If the sender is also a restricted subscriber, do
  4455. X     not forget to put another entry in  ".restricted"  with  the
  4456. X     new  alternate address. Any number of aliases may be defined
  4457. X     for each individual address.
  4458. X
  4459. X     In addition, a ".aliases" file is also  provided  for  List-
  4460. X     server  requests  and  is  under HOMEDIR. The same syntax is
  4461. X     used, but each entry has a slightly different meaning:
  4462. X
  4463. X              address-as-arrived address-used-for-reply
  4464. X
  4465. X     In this case, _a_d_d_r_e_s_s-_u_s_e_d-_f_o_r-_r_e_p_l_y will be used  to  reply
  4466. X     to  all  requests  sent in by _a_d_d_r_e_s_s-_a_s-_a_r_r_i_v_e_d. A user may
  4467. X     have any number of aliases, but only the first one  matching
  4468. X     _a_d_d_r_e_s_s-_a_s-_a_r_r_i_v_e_d  will  be  used.  Like  before, the first
  4469. X     argument may be a regular expression and the second may  use
  4470. X     the matches in the first.
  4471. X
  4472. X     For each new list, the system  puts  the  following  default
  4473. X     alias in its ".aliases" file:
  4474. X
  4475. X                         ^@.*:(.*)@(.*) \1@\2
  4476. X
  4477. X     This removes source routing.
  4478. X
  4479. X....IIIIGGGGNNNNOOOORRRREEEEDDDD
  4480. X     As described before, the system's home directory as well  as
  4481. X     every  list's  subdirectory contains a ".ignored" file which
  4482. X     is used to filter out messages sent by  certain  users.  The
  4483. X     default  file contains entries for server, bin, and sys; you
  4484. X     may wish to add an  entry  for  every  list  alias  that  is
  4485. X     defined  on  your system. A list's ".ignored" file also con-
  4486. X     tains an entry of its alias and full email address, as  well
  4487. X     as the server account's full email address.
  4488. X
  4489. X     Entries in this file may  also  be  regular  expressions  as
  4490. X     explained  in the previous section. For example, to restrict
  4491. X     requests (and postings) to .com and .edu  domain  addresses,
  4492. X     one may add:
  4493. X
  4494. X                          ~<.*\.com|.*\.edu>
  4495. X
  4496. X     Notice, it is incorrect to list them as follows:
  4497. X
  4498. X                               ~.*\.com
  4499. X                               ~.*\.edu
  4500. X
  4501. X
  4502. X
  4503. XAnastasios Kotsikonas                                               8
  4504. X
  4505. X
  4506. X
  4507. X
  4508. X
  4509. X
  4510. Xlist(1)                  USER COMMANDS                    list(1)
  4511. X
  4512. X
  4513. X
  4514. X     as anything not from the .com domain matches the first regu-
  4515. X     lar  expression,  and  therefore will be ignored.  To refuse
  4516. X     access to certain user  names  and  certain  sites  one  may
  4517. X     include:
  4518. X
  4519. X                         .*\.bar\.com|jdoe@.*
  4520. X
  4521. X     The system's manager should use extra  caution  when  adding
  4522. X     regular expressions to the system's ".ignored" file, because
  4523. X     a simple '.*' prohibits anyone from using its services.
  4524. X
  4525. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  4526. X     catmail(1), listserv(1), server(1), serverd(1), start(1)
  4527. X
  4528. XAAAAUUUUTTTTHHHHOOOORRRR
  4529. X     Anastasios C. Kotsikonas
  4530. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  4531. X     Comments to tasos@cs.bu.edu
  4532. X
  4533. X
  4534. X
  4535. X
  4536. X
  4537. X
  4538. X
  4539. X
  4540. X
  4541. X
  4542. X
  4543. X
  4544. X
  4545. X
  4546. X
  4547. X
  4548. X
  4549. X
  4550. X
  4551. X
  4552. X
  4553. X
  4554. X
  4555. X
  4556. X
  4557. X
  4558. X
  4559. X
  4560. X
  4561. X
  4562. X
  4563. X
  4564. X
  4565. X
  4566. X
  4567. X
  4568. X
  4569. XAnastasios Kotsikonas                                               9
  4570. X
  4571. X
  4572. X
  4573. *-*-END-of-doc/list.nr-*-*
  4574. echo x - doc/listserv.nr
  4575. sed 's/^X//' >doc/listserv.nr <<'*-*-END-of-doc/listserv.nr-*-*'
  4576. X
  4577. X
  4578. X
  4579. Xlistserv(1)              USER COMMANDS                listserv(1)
  4580. X
  4581. X
  4582. X
  4583. XNNNNAAAAMMMMEEEE
  4584. X     lllliiiissssttttsssseeeerrrrvvvv - process requests  sent  to  the  UNIX  ListServer
  4585. X     request handler
  4586. X
  4587. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  4588. X     lllliiiissssttttsssseeeerrrrvvvv  [----1111]  [----eeee]  [----iiii]  [----nnnn]  {[----aaaa <LLLLIIIISSSSTTTT____AAAALLLLIIIIAAAASSSS>]}*   {[----
  4589. X     rrrr <rrrreeeeqqqq>]}* {[----dddd <rrrreeeeqqqq>]}* {[----bbbb <rrrreeeeqqqq>]}* [----BBBB] [----DDDD]
  4590. X
  4591. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  4592. X     _l_i_s_t_s_e_r_v processes user requests  sent  to  _l_i_s_t_s_e_r_v_e_r@_y_o_u_r-
  4593. X     _d_o_m_a_i_n,  forwards  requests  about  known  remote lists, and
  4594. X     processes list-owner administrative requests (see  also  the
  4595. X     LIST OWNERS section below).  Each request should appear in a
  4596. X     separate  line  with  any  possible  arguments.   The   file
  4597. X     ".ignored"  is used in the system's home directory to filter
  4598. X     out unwanted senders. If the system  is  not  instructed  to
  4599. X     ignore   invalid   requests   (see  the  CONFIG  section  in
  4600. X     server(1)), the sender is  notified  of  the  first  invalid
  4601. X     request; all subsequent requests are ignored.  For each suc-
  4602. X     cessfully completed request, a confirmation is sent back  to
  4603. X     the sender.
  4604. X
  4605. X     _l_i_s_t_s_e_r_v stops  reading  requests  when  it  encounters  the
  4606. X     string  "--" in a line by itself, which on most systems sig-
  4607. X     nifies the start of the .signature message, or at the  first
  4608. X     occurence  of  a thankful request. _l_i_s_t_s_e_r_v reads the _c_o_n_f_i_g
  4609. X     file (see server(1)).
  4610. X
  4611. X     Subscriptions may be manager-approved (private lists), files
  4612. X     and  archive  indices  may  be  password  protected (private
  4613. X     archives), and requests may be placed in a batch  queue.   A
  4614. X     single  request  may  span  multiple lines if each part ends
  4615. X     with &\_n.
  4616. X
  4617. XUUUUSSSSEEEERRRR RRRREEEEQQQQUUUUEEEESSSSTTTTSSSS
  4618. X     The following user requests are recognized (requests may  be
  4619. X     abbreviated):
  4620. X
  4621. X     _h_e_l_p [topic]
  4622. X          Send a help  message  on  all  valid  requests  or  the
  4623. X          selected topic (possibly a request) only.
  4624. X
  4625. X     _s_e_t list [option arg(s)]
  4626. X          Without the  optional  arguments,  return  the  current
  4627. X          values  for  all  options  set for _l_i_s_t; otherwise, set
  4628. X          subscriber preferences for _l_i_s_t.
  4629. X
  4630. X          _o_p_t_i_o_n can be:
  4631. X
  4632. X            _m_a_i_l: set mail preferences.
  4633. X
  4634. X              _a_r_g has to be one of the following:
  4635. X
  4636. X
  4637. X
  4638. XAnastasios Kotsikonas                                               1
  4639. X
  4640. X
  4641. X
  4642. X
  4643. X
  4644. X
  4645. Xlistserv(1)              USER COMMANDS                listserv(1)
  4646. X
  4647. X
  4648. X
  4649. X                _a_c_k: send a copy of the current  message  to  the
  4650. X                original sender.
  4651. X
  4652. X                _n_o_a_c_k: do not send a copy of the current  message
  4653. X                to  the original sender.  This is the default for
  4654. X                newly subscribed users.
  4655. X
  4656. X                _p_o_s_t_p_o_n_e: do not send any messages to the partic-
  4657. X                ular subscriber until he changes status again.
  4658. X
  4659. X                _d_i_g_e_s_t: do not send individual  messages  to  the
  4660. X                particular subscriber. Instead, store messages in
  4661. X                a digest and send it when the  digest  exceeds  a
  4662. X                specified  number  of  lines, or when a specified
  4663. X                amount of time has passed since the  last  digest
  4664. X                was sent.
  4665. X
  4666. X                If the mail mode is changed from _d_i_g_e_s_t  to  any-
  4667. X                thing else, all messages currently stored for the
  4668. X                next digest will be sent  to  the  subscriber  at
  4669. X                once, in digest format.
  4670. X
  4671. X            _p_a_s_s_w_o_r_d: change the password (used to establish sub-
  4672. X            scriber  privileges when connecting to ListServer for
  4673. X            a "live" session and for the option below).
  4674. X
  4675. X              _a_r_g_s must be: old-password new-password.
  4676. X
  4677. X            _a_d_d_r_e_s_s: set the address the user is subscribed  with
  4678. X            (if allowed for this list).
  4679. X
  4680. X              _a_r_g_s must be: current-password new-address.
  4681. X
  4682. X            _c_o_n_c_e_a_l: set the user's visibility.
  4683. X
  4684. X              _a_r_g must be one of the following:
  4685. X
  4686. X                _y_e_s: the user is not  listed  in  _r_e_c_i_p_i_e_n_t_s  and
  4687. X                _s_t_a_t_i_s_t_i_c_s requests.
  4688. X
  4689. X                _n_o: the user's email address and  name  are  made
  4690. X                public.
  4691. X
  4692. X     _s_u_b_s_c_r_i_b_e list full_name
  4693. X          Subscribe the sender to _l_i_s_t (note, his  email  address
  4694. X          is  used  for subscription, not his _f_u_l_l__n_a_m_e). A pass-
  4695. X          word is assigned by the system  at  that  time  and  is
  4696. X          included  in  the  reply message to the new subscriber.
  4697. X          The password is to  be  used  when  connecting  to  the
  4698. X          interactive  part of the system for identification pur-
  4699. X          poses, and for changing  the  subscription  address  if
  4700. X          allowed for this list.
  4701. X
  4702. X
  4703. X
  4704. XAnastasios Kotsikonas                                               2
  4705. X
  4706. X
  4707. X
  4708. X
  4709. X
  4710. X
  4711. Xlistserv(1)              USER COMMANDS                listserv(1)
  4712. X
  4713. X
  4714. X
  4715. X     _w_h_i_c_h
  4716. X          Get a list of local mailing lists to which  the  sender
  4717. X          has subscribed.
  4718. X
  4719. X     _u_n_s_u_b_s_c_r_i_b_e list
  4720. X          Remove the sender from the specified _l_i_s_t.
  4721. X
  4722. X     _s_i_g_n_o_f_f list
  4723. X          Alias of the unsubscribe request.
  4724. X
  4725. X     _r_e_c_i_p_i_e_n_t_s list
  4726. X          Get a list of all subscribers of _l_i_s_t. The  request  is
  4727. X          also  forwarded to all peer lists, and the servers han-
  4728. X          dling them will respond accordingly.  The user is noti-
  4729. X          fied when this request is being forwarded. If a list is
  4730. X          private, only members may issue this request.
  4731. X
  4732. X     _r_e_v_i_e_w list
  4733. X          Alias of the recipients request.
  4734. X
  4735. X     _i_n_f_o_r_m_a_t_i_o_n list
  4736. X          Get information about a particular _l_i_s_t.
  4737. X
  4738. X     _s_t_a_t_i_s_t_i_c_s list {[subscriber email address(es)] | [-all]}
  4739. X          Obtain a count of messages sent per subscriber  to  the
  4740. X          specified  _l_i_s_t, or by those subscribers given as argu-
  4741. X          ment only (wild characters are supported). If  -_a_l_l  is
  4742. X          specified,  then  statistics are compiled for all users
  4743. X          (currently subscribed or not) who have  posted  to  the
  4744. X          list in the past.  The request is also forwarded to all
  4745. X          peer lists and the servers handling them  will  respond
  4746. X          accordingly.  The user is notified when this request is
  4747. X          being forwarded.  If a list is  private,  only  members
  4748. X          may issue this request.
  4749. X
  4750. X     _r_u_n list [password cmd [args]]
  4751. X          Without the optional arguments, just list all  commands
  4752. X          that  may be executed by subscribers of this _l_i_s_t. Oth-
  4753. X          erwise, run _c_m_d with the optional _a_r_g_s, if the  correct
  4754. X          _p_a_s_s_w_o_r_d is provided. The reply will contain the output
  4755. X          from stdout and/or stderr.
  4756. X
  4757. X     _l_i_s_t_s
  4758. X          Obtain a list of mailing list addresses that  are  ser-
  4759. X          viced by this system, with a small description of their
  4760. X          purpose. If remote lists (see below) are also  defined,
  4761. X          their  addresses  and descriptive messages will also be
  4762. X          included.
  4763. X
  4764. X     _i_n_d_e_x [archive | path-to-archive] [/password] [-all]
  4765. X          Obtain an index of files in the specified  _a_r_c_h_i_v_e  (or
  4766. X          the  master  archive  if none specified) and all of its
  4767. X
  4768. X
  4769. X
  4770. XAnastasios Kotsikonas                                               3
  4771. X
  4772. X
  4773. X
  4774. X
  4775. X
  4776. X
  4777. Xlistserv(1)              USER COMMANDS                listserv(1)
  4778. X
  4779. X
  4780. X
  4781. X          subarchives if the the -_a_l_l option is  specified.  Cer-
  4782. X          tain  archives  may  be  private,  and  these require a
  4783. X          /_p_a_s_s_w_o_r_d to be able to obtain their indices.  Archives
  4784. X          on  different places in the hierarchy may have the same
  4785. X          names and they can be distinguished by specifying paths
  4786. X          to     them;     _p_a_t_h-_t_o-_a_r_c_h_i_v_e     has    the    form
  4787. X          _a_r_c_h_i_v_e[/_a_r_c_h_i_v_e[/_a_r_c_h_i_v_e...]].  _i_n_d_e_x requests  always
  4788. X          report the paths to the archives they list.
  4789. X
  4790. X     _g_e_t <archive | path-to-archive> file [/password] [parts]
  4791. X          Get the specified _f_i_l_e from the _a_r_c_h_i_v_e given. The file
  4792. X          may have been split into smaller parts due to its size,
  4793. X          in which case each part will be  sent  in  a  different
  4794. X          email  message. If only certain _p_a_r_t_s are desired, they
  4795. X          may be given as arguments (numbers, separated by spaces
  4796. X          --  ranges are not recognized). Certain archives may be
  4797. X          private, in which case their /_p_a_s_s_w_o_r_d has to  be  pro-
  4798. X          vided  in  order to get the desired files.  Archives on
  4799. X          different places in the hierarchy  may  have  the  same
  4800. X          names and they can be distinguished by specifying paths
  4801. X          to    them;    _p_a_t_h-_t_o-_a_r_c_h_i_v_e     has     the     form
  4802. X          _a_r_c_h_i_v_e[/_a_r_c_h_i_v_e[/_a_r_c_h_i_v_e...]].   If  the  file is pure
  4803. X          binary, it will be uuencoded first.
  4804. X
  4805. X     _s_e_a_r_c_h <archive | path-to-archive> [/password] [-all]  <pat-
  4806. X          tern>
  4807. X          Search all files in the specified archive (and  all  of
  4808. X          its  subarchives  if  -_a_l_l) and return lines that match
  4809. X          the _p_a_t_t_e_r_n.  The pattern can be  an  extended  regular
  4810. X          expression with egrep(1)-style syntax, with support for
  4811. X          the following additional operators: '~', if leading the
  4812. X          regular expression it reverses its meaning; '|' and '&'
  4813. X          separate multiple regular expressions (logical  OR  and
  4814. X          AND);  '<'  '>'  group regular expressions (we preserve
  4815. X          the meaning of the parentheses from ed(1),  and  remove
  4816. X          the  meaning  of  < and > from ed(1) since in the List-
  4817. X          Server context they are either the  default,  or  inap-
  4818. X          propriate).   These  can  be used literally by escaping
  4819. X          them with '\'. In addition,  the  following  characters
  4820. X          should be defined in matched pairs: (), <>, []. _p_a_t_t_e_r_n
  4821. X          may be enclosed in single  or  double  quotes.  Pattern
  4822. X          matching is case insensitive.
  4823. X
  4824. X     _f_a_x <fax-no> <archive |  path-to-archive>  file  [/password]
  4825. X          [parts]
  4826. X          Same as the _g_e_t request except that the files are faxed
  4827. X          to the specified number.
  4828. X
  4829. X     _r_e_l_e_a_s_e
  4830. X          Get information  about  the  current  release  of  this
  4831. X          server system.
  4832. X
  4833. X
  4834. X
  4835. X
  4836. XAnastasios Kotsikonas                                               4
  4837. X
  4838. X
  4839. X
  4840. X
  4841. X
  4842. X
  4843. Xlistserv(1)              USER COMMANDS                listserv(1)
  4844. X
  4845. X
  4846. X
  4847. X     _e_x_e_c_u_t_e password #command [arguments]
  4848. X          Intended for the system's _m_a_n_a_g_e_r,  this  will  execute
  4849. X          the  UNIX  _c_o_m_m_a_n_d with the optional _a_r_g_u_m_e_n_t_s and send
  4850. X          the output (if any) from stdout and/or  stderr  to  the
  4851. X          sender. See the sample _c_o_n_f_i_g file for _p_a_s_s_w_o_r_d defini-
  4852. X          tion.
  4853. X
  4854. X     For a list of the list administration requests that  may  be
  4855. X     issued by list owners, see the LIST OWNERS section below.
  4856. X
  4857. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  4858. X     The following command line options are recognized:
  4859. X
  4860. X     -1   Execute only once; process any requests and return con-
  4861. X          trol  to  _s_e_r_v_e_r_d(1);  any  new  messages that may have
  4862. X          arrived in the meantime will be processed  at  a  later
  4863. X          time.  Without  this option, _l_i_s_t_s_e_r_v will be listening
  4864. X          for requests for ever. _s_e_r_v_e_r_d(1) uses this  option  by
  4865. X          default when spawning _l_i_s_t_e_r_v.
  4866. X
  4867. X     -e   Echo reports to the screen; it has  no  effect  if  the
  4868. X          system has been compiled with -DSYSLOG.
  4869. X
  4870. X     -i   Go to interactive mode -- messages by _l_i_s_t_s_e_r_v are  not
  4871. X          mailed out but instead _s_e_r_v_e_r_d(1) reads them during its
  4872. X          interactive session. Do not use this option in the _c_o_n_-
  4873. X          _f_i_g file (see server(1)).
  4874. X
  4875. X     -n   By default, peer servers are notified  upon  _s_t_a_t_i_s_t_i_c_s
  4876. X          and _r_e_c_i_p_i_e_n_t_s requests. The system uses a protocol for
  4877. X          avoiding loops  as  described  in  _s_e_r_v_e_r(_1).   If  you
  4878. X          detect  loops  with  other servers, you should use this
  4879. X          option to turn off notification of peer servers.
  4880. X
  4881. X     -a LIST_ALIAS
  4882. X          Usually, subscriptions are automatic. This option turns
  4883. X          off   automatic  subscription  to  the  specified  list
  4884. X          (_L_I_S_T__A_L_I_A_S should be in capital  letters),  and  makes
  4885. X          this  list  private  (members only may issue _r_e_c_i_p_i_e_n_t_s
  4886. X          and _s_t_a_t_i_s_t_i_c_s requests). The  sender  is  notified  of
  4887. X          this  effect, and a message is sent to the list's owner
  4888. X          requesting  his/her  approval,  with  instructions  for
  4889. X          placing  the  subscription.  Notice  that the specified
  4890. X          list has to be defined beforehand via a _l_i_s_t  directive
  4891. X          in  the  _c_o_n_f_i_g  file.  This option may be repeated any
  4892. X          number of times.
  4893. X
  4894. X     -c LIST_ALIAS
  4895. X          Conceal _L_I_S_T__A_L_I_A_S from _l_i_s_t_s requests.
  4896. X
  4897. X     -r request
  4898. X          Place a restriction on the specified server _r_e_q_u_e_s_t  as
  4899. X
  4900. X
  4901. X
  4902. XAnastasios Kotsikonas                                               5
  4903. X
  4904. X
  4905. X
  4906. X
  4907. X
  4908. X
  4909. Xlistserv(1)              USER COMMANDS                listserv(1)
  4910. X
  4911. X
  4912. X
  4913. X          outlined  above.   If the number of users on the system
  4914. X          at the time the request is about  to  be  processed  is
  4915. X          above  the  limit  given  in the _c_o_n_f_i_g file (using the
  4916. X          _r_e_s_t_r_i_c_t_i_o_n directive),  the  request  is  rejected  --
  4917. X          meant  for requests that may take a considerable amount
  4918. X          of resources such as the  _s_t_a_t_i_s_t_i_c_s  request  --  this
  4919. X          option  may  be  repeated  any  number  of  times. List
  4920. X          administration requests are not subject to  these  res-
  4921. X          trictions (see later on).
  4922. X
  4923. X     -d request
  4924. X          Disable _r_e_q_u_e_s_t, i.e. make it totally  unknown  to  the
  4925. X          server  --  this  supersedes any _d_i_s_a_b_l_e directives for
  4926. X          this request in the _c_o_n_f_i_g file, i.e. this request will
  4927. X          not  be  recognized for any list (see _s_e_r_v_e_r(_1)).  How-
  4928. X          ever, help is still available for  that  request.  List
  4929. X          administration  requests are also subject to these res-
  4930. X          trictions (see later on). This option may  be  repeated
  4931. X          any number of times.
  4932. X
  4933. X     -b request
  4934. X          All such  _r_e_q_u_e_s_ts  will  be  batch-processed  if  they
  4935. X          arrive  between the hours specified in the _c_o_n_f_i_g file.
  4936. X          This option may be repeated any number of times.
  4937. X
  4938. X     -B   Process the batch queue. This is done automatically  by
  4939. X          _s_e_r_v_e_r_d(1) after midnight every day, or when the system
  4940. X          is restarted, so no further action needs to  be  taken.
  4941. X          Caution:  do not place this option in the definition of
  4942. X          _s_e_r_v_e_r in the _c_o_n_f_i_g file. If you do so, only the batch
  4943. X          queue  will  be processed (no new requests will be pro-
  4944. X          cessed, ever).  The batch queue is processed once a day
  4945. X          only, unless the system is restarted repeatedly.
  4946. X
  4947. X     -D   Turns debugging on. When the _s_y_s_t_e_m mailmethod is used,
  4948. X          a copy of the last SMTP transaction can be found in the
  4949. X          files HOMEDIR/sent and HOMEDIR/received.
  4950. X
  4951. XPPPPEEEEEEEERRRR SSSSEEEERRRRVVVVEEEERRRRSSSS
  4952. X     The system supports the notion of remote lists. A ListServer
  4953. X     may know of remote lists served by remote servers. Yet users
  4954. X     may send requests about these remote lists to  this  server,
  4955. X     which  will  in turn forward them to the remote servers. The
  4956. X     user is notified when  a  list  is  not  local  and  his/her
  4957. X     request is about to be forwarded.  A _l_i_s_t_s request will tell
  4958. X     the user which remote lists are known to this server.
  4959. X
  4960. X     Remote lists should be made known to  this  server  only  if
  4961. X     they are served by a server of version 5.31 or higher.  This
  4962. X     restriction is posed because of incompatible requests across
  4963. X     various  list server systems; for example, the meaning of an
  4964. X     _i_n_f_o_r_m_a_t_i_o_n request is different on a BITNET  Listserv.  See
  4965. X
  4966. X
  4967. X
  4968. XAnastasios Kotsikonas                                               6
  4969. X
  4970. X
  4971. X
  4972. X
  4973. X
  4974. X
  4975. Xlistserv(1)              USER COMMANDS                listserv(1)
  4976. X
  4977. X
  4978. X
  4979. X     the  discussion  about the _c_o_n_f_i_g file for setting up remote
  4980. X     lists.
  4981. X
  4982. X     In addition, _r_e_c_i_p_i_e_n_t_s and  _s_t_a_t_i_s_t_i_c_s  requests  are  for-
  4983. X     warded  to  the  servers handling peer lists (the -n flag to
  4984. X     _l_i_s_t_s_e_r_v turns this feature off).
  4985. X
  4986. XLLLLIIIISSSSTTTT OOOOWWWWNNNNEEEERRRRSSSS
  4987. X     List owners are individuals responsible for list administra-
  4988. X     tion  via  mail  requests. Thus, list owners may be remotely
  4989. X     located. Each list has to have  at  least  one  list  owner.
  4990. X     These owners may be different than the system's _m_a_n_a_g_e_r, and
  4991. X     have special privileges: they may issue requests  on  users'
  4992. X     behalf  (add  a user, remove a user, etc.) overriding system
  4993. X     restrictions set on regular users  (these  include  disabled
  4994. X     commands as described above), obtain reports about the lists
  4995. X     they administer, append to  the  ".aliases"  and  ".ignored"
  4996. X     files,  change  the  welcoming  (".welcome") and informative
  4997. X     (".info") messages, as well as other system  files  such  as
  4998. X     the aliases file (".aliases"), the ".ignored" file, the sub-
  4999. X     scribers file (".subscribers"), the news file (".news")  and
  5000. X     the  peers  file  (".peers"). In addition, they may moderate
  5001. X     their lists and they receive various error messages pertain-
  5002. X     ing  to their lists.  All administrative requests are author
  5003. X     authenticated and password  protected.  Whenever  a  message
  5004. X     cannot be author authenticated, the list's owner and _m_a_n_a_g_e_r
  5005. X     are notified.
  5006. X
  5007. X     On the other hand, list owners may not add restricted users;
  5008. X     this  service  can  be  provided  by contacting the system's
  5009. X     _m_a_n_a_g_e_r.
  5010. X
  5011. X     List owners may also receive copies of user requests  and/or
  5012. X     error  messages  such  as invalid postings, syntax errors on
  5013. X     requests, etc.  These options are described in the following
  5014. X     sections.
  5015. X
  5016. X     Defining list owners
  5017. X          Once a new mailing list is defined in the _c_o_n_f_i_g  file,
  5018. X          the  list's  owner address and access password are pro-
  5019. X          vided to the _l_i_s_t directive.  Of course, this  password
  5020. X          should  be  made  known to the owner; it will be needed
  5021. X          for all  administrative  requests.  Next,  the  owner's
  5022. X          address  has  to  be  registered in HOMEDIR/owners; the
  5023. X          _m_a_n_a_g_e_r simply  edits  this  file  adding  the  owner's
  5024. X          address  along  with  the  list's  name  (alias)  he is
  5025. X          assigned to, followed by any preferences  (see  below).
  5026. X          Multiple  owners  for  a  list may be defined by adding
  5027. X          their addresses to this file, and providing  them  with
  5028. X          the  list's password. However, only the primary owner's
  5029. X          address (as defined by the _l_i_s_t directive) will be used
  5030. X          as  reference  in  correspondence  and for system-error
  5031. X
  5032. X
  5033. X
  5034. XAnastasios Kotsikonas                                               7
  5035. X
  5036. X
  5037. X
  5038. X
  5039. X
  5040. X
  5041. Xlistserv(1)              USER COMMANDS                listserv(1)
  5042. X
  5043. X
  5044. X
  5045. X          notifications, and only the primary owner will be  for-
  5046. X          warded  messages  from his moderated list for approval.
  5047. X          The _m_a_n_a_g_e_r should also add his address (login name) to
  5048. X          this file.
  5049. X
  5050. X     Owner preferences
  5051. X          The primary owner may wish  to  be  copied  on  certain
  5052. X          replies  to user requests (such as subscribe), on error
  5053. X          conditions (rejected postings, invalid requests, etc.),
  5054. X          or  on  all  cases. These preferences are listed in the
  5055. X          _o_w_n_e_r_s file on  the  line  his  address  and  list  are
  5056. X          defined. Valid preferences are:
  5057. X
  5058. X            CCSET: copy on _s_e_t requests.
  5059. X
  5060. X            CCSUBSCRIBE: copy on _s_u_b_s_c_r_i_b_e requests.
  5061. X
  5062. X            CCUNSUBSCRIBE: copy on _u_n_s_u_b_s_c_r_i_b_e requests.
  5063. X
  5064. X            CCRECIPIENTS: copy on _r_e_c_i_p_i_e_n_t_s requests.
  5065. X
  5066. X            CCINFORMATION: copy on _i_n_f_o_r_m_a_t_i_o_n requests.
  5067. X
  5068. X            CCSTATISTICS: copy on _s_t_a_t_i_s_t_i_c_s requests.
  5069. X
  5070. X            CCRUN: copy on _r_u_n requests.
  5071. X
  5072. X            CCPRIVATE: copy on requests rejected because they are
  5073. X            open only to the list's members.
  5074. X
  5075. X            CCERRORS: copy on various error conditions.
  5076. X
  5077. X            CCALL: all of the above.
  5078. X
  5079. X          Owner preferences are optional.
  5080. X
  5081. X     The _m_a_n_a_g_e_r may define preferences for himself  as  well  by
  5082. X     using  the keyword _s_e_r_v_e_r in place of a list alias. However,
  5083. X     such preferences make sense only in the following cases:
  5084. X
  5085. X       CCGET: copy on _g_e_t requests.
  5086. X
  5087. X       CCINDEX: copy on _i_n_d_e_x requests.
  5088. X
  5089. X       CCLISTS: copy on _l_i_s_t_s requests.
  5090. X
  5091. X       CCRELEASE: copy on _r_e_l_e_a_s_e requests.
  5092. X
  5093. X       CCHELP: copy on _h_e_l_p requests.
  5094. X
  5095. X       CCERRORS: copy on various error conditions.
  5096. X
  5097. X
  5098. X
  5099. X
  5100. XAnastasios Kotsikonas                                               8
  5101. X
  5102. X
  5103. X
  5104. X
  5105. X
  5106. X
  5107. Xlistserv(1)              USER COMMANDS                listserv(1)
  5108. X
  5109. X
  5110. X
  5111. X       CCALL: all of the above.
  5112. X
  5113. X     Manager preferences are optional.
  5114. X
  5115. X     Owner privileges
  5116. X          Whenever an owner issues a user  request  on  a  user's
  5117. X          behalf  (see  below),  all restrictions, including dis-
  5118. X          abled commands, do not apply. All other  administrative
  5119. X          requests   are  subject  to  restrictions  set  by  the
  5120. X          _m_a_n_a_g_e_r.  All requests (user  and  administrative)  are
  5121. X          subject to batch-processing.
  5122. X
  5123. X     Administrative requests
  5124. X          The following requests may be issued by a list's owner:
  5125. X
  5126. X     _s_y_s_t_e_m list password user-address #user-request
  5127. X          This request overrides all system restrictions and exe-
  5128. X          cutes  _u_s_e_r-_r_e_q_u_e_s_t  on  behalf  of  _u_s_e_r-_a_d_d_r_e_s_s; this
  5129. X          address has to appear as listed in  the  ".subscribers"
  5130. X          file,  where  applicable.  The most frequent use of the
  5131. X          _s_y_s_t_e_m request is to subscribe  a  user  to  a  private
  5132. X          list. For example:
  5133. X
  5134. X            system herc herc1 john@foo #subscribe herc Some Name
  5135. X
  5136. X          If a _u_s_e_r-_r_e_q_u_e_s_t refers to a list, this list has to be
  5137. X          _l_i_s_t,  so  that  a list's owner may not have privileges
  5138. X          over another list's  affairs.  Note  that  all  replies
  5139. X          about  _u_s_e_r-_r_e_q_u_e_s_t  are forwarded to _u_s_e_r-_a_d_d_r_e_s_s, not
  5140. X          the owner; therefore, care has to  be  taken  to  avoid
  5141. X          syntax  errors.  The  _s_y_s_t_e_m  request is not subject to
  5142. X          restrictions, disabled requests, and private list  sub-
  5143. X          scription  verification (it is still subject to private
  5144. X          list review as outlined above, and batching). To remove
  5145. X          a member from his list, the owner may issue the follow-
  5146. X          ing request:
  5147. X
  5148. X            system herc herc1 john@foo #unsubscribe herc
  5149. X
  5150. X          To bypass restrictions and review his list,  the  owner
  5151. X          may issue the following:
  5152. X
  5153. X            system venus venus1 his-address #review venus
  5154. X
  5155. X          In general, _u_s_e_r-_r_e_q_u_e_s_t may be any of  the  recognized
  5156. X          user  requests described under _l_i_s_t_s_e_r_v. The pound sign
  5157. X          is mandatory.  There is no help available to users  for
  5158. X          this request for security reasons.
  5159. X
  5160. X     _a_p_p_r_o_v_e list password tag
  5161. X          Whenever a new message arrives for a moderated  list  a
  5162. X          copy  is  sent  to  the  list's  owner  soliciting  his
  5163. X
  5164. X
  5165. X
  5166. XAnastasios Kotsikonas                                               9
  5167. X
  5168. X
  5169. X
  5170. X
  5171. X
  5172. X
  5173. Xlistserv(1)              USER COMMANDS                listserv(1)
  5174. X
  5175. X
  5176. X
  5177. X          approval -- proper instructions for approving  or  dis-
  5178. X          carding  a  message are included. This request approves
  5179. X          the message identified by the _t_a_g number for posting to
  5180. X          _l_i_s_t. The tag number is provided to the list's owner by
  5181. X          _l_i_s_t_s_e_r_v and is unique.
  5182. X
  5183. X     _d_i_s_c_a_r_d list password tag
  5184. X          In contrast to the above  request,  this  discards  the
  5185. X          message  identified  by  _t_a_g.  Messages  that  are  not
  5186. X          approved or discarded remain in  the  list's  _m_o_d_e_r_a_t_e_d
  5187. X          file (see _l_i_s_t(_1)).
  5188. X
  5189. X     _r_e_p_o_r_t_s list password
  5190. X          Obtain all reports pertinent to _l_i_s_t;  this  will  send
  5191. X          two   mail  messages:   one  with  the  current  report
  5192. X          (HOMEDIR/lists/ALIAS/.report.list), and  one  with  the
  5193. X          previously                 archived                ones
  5194. X          (HOMEDIR/lists/ALIAS/.rep.list.acc);  see  the  REPORTS
  5195. X          section  below.  Once the ".rep.list.acc" file is sent,
  5196. X          it is shrunk in size, therefore the owner  should  make
  5197. X          sure he keeps the copy he receives.
  5198. X
  5199. X          This request has no effect if the system is using  sys-
  5200. X          log(3) to generate reports.
  5201. X
  5202. X     _e_d_i_t list password file
  5203. X          Obtain the specified _f_i_l_e for editing; candidate  files
  5204. X          are:
  5205. X
  5206. X            _a_l_i_a_s_e_s: obtain the list's aliases file.
  5207. X
  5208. X            _i_g_n_o_r_e_d:  obtain  the  list's   list   of   unwelcome
  5209. X            addresses.
  5210. X
  5211. X            _i_n_f_o: obtain the list's informative message.
  5212. X
  5213. X            _s_u_b_s_c_r_i_b_e_r_s: obtain the list's subscribers list.
  5214. X
  5215. X            _w_e_l_c_o_m_e: obtain the list's welcoming message.
  5216. X
  5217. X            _n_e_w_s: obtain the list's  list  of  newsgroup  connec-
  5218. X            tions.
  5219. X
  5220. X            _p_e_e_r_s: obtain the list's peers.
  5221. X
  5222. X     _p_u_t list password keyword [args]
  5223. X          This  enables  the  list's  owner  to  append  to   the
  5224. X          ".aliases" and ".ignored" files, and replace his list's
  5225. X          ".welcome",  ".info",  ".aliases",  ".ignored",  ".sub-
  5226. X          scribers", ".news" and ".peers" files, depending on the
  5227. X          _k_e_y_w_o_r_d. Valid _k_e_y_w_o_r_ds are:
  5228. X
  5229. X
  5230. X
  5231. X
  5232. XAnastasios Kotsikonas                                              10
  5233. X
  5234. X
  5235. X
  5236. X
  5237. X
  5238. X
  5239. Xlistserv(1)              USER COMMANDS                listserv(1)
  5240. X
  5241. X
  5242. X
  5243. X            _a_l_i_a_s: Add a user address alias  to  the  list's  and
  5244. X            system's  ".aliases" files (see .ALIASES below). This
  5245. X            requires the new address and  the  address  used  for
  5246. X            subscription as arguments:
  5247. X
  5248. X            put <list> <password> alias <new-alias>  <address-as-
  5249. X            subscribed>
  5250. X
  5251. X            For example:
  5252. X
  5253. X              put venus venus1 alias foo!john john@foo
  5254. X
  5255. X            _i_g_n_o_r_e: Add a user address to  the  list's  ".ignore"
  5256. X            file  only. Of course this address has to be provided
  5257. X            as argument:
  5258. X
  5259. X            put <list> <password> ignore  <address-as-subscribed-
  5260. X            or-aliased>
  5261. X
  5262. X            For example:
  5263. X
  5264. X              put ermis ermis1 ignore jack@foo
  5265. X              put ermis ermis1 ignore foo!jack
  5266. X
  5267. X            _w_e_l_c_o_m_e,
  5268. X            _i_n_f_o,
  5269. X            _a_l_i_a_s_e_s,
  5270. X            _i_g_n_o_r_e_d,
  5271. X            _s_u_b_s_c_r_i_b_e_r_s,
  5272. X            _n_e_w_s,
  5273. X            _p_e_e_r_s: Create a new system file.
  5274. X
  5275. X            For example:
  5276. X
  5277. X              put <list> <password> subscribers
  5278. X              tasos ACK PASSWORD NO Tasos Kotsikonas
  5279. X              john NOACK PASS1 NO John Doe
  5280. X
  5281. X            No arguments are needed. The text that is  to  go  to
  5282. X            the  corresponding  file starts at the line following
  5283. X            this request and spans till the end of the mail  mes-
  5284. X            sage.  Thus, no more requests can be made in the same
  5285. X            mail message -- they are  treated  as  regular  text;
  5286. X            signature  lines  also  signify the end of text, pro-
  5287. X            vided they start with "--" in a single line.
  5288. X
  5289. X          A confirmation is sent to the owner once a _p_u_t  request
  5290. X          is successfully processed.
  5291. X
  5292. XOOOOWWWWNNNNEEEERRRRSSSS
  5293. X     The format of the _o_w_n_e_r_s file is as follows:
  5294. X
  5295. X
  5296. X
  5297. X
  5298. XAnastasios Kotsikonas                                              11
  5299. X
  5300. X
  5301. X
  5302. X
  5303. X
  5304. X
  5305. Xlistserv(1)              USER COMMANDS                listserv(1)
  5306. X
  5307. X
  5308. X
  5309. X     One entry per line; each entry is the full email address  of
  5310. X     a list's owner, followed by the list alias he owns, followed
  5311. X     by any optional preferences. If the keyword _s_e_r_v_e_r is speci-
  5312. X     fied  in  place  of  the  list  alias,  then preferences are
  5313. X     defined for the _m_a_n_a_g_e_r.
  5314. X
  5315. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  5316. X     catmail(1), farch(1),  list(1),  queue(1),  server(1),  ser-
  5317. X     verd(1), start(1)
  5318. X
  5319. XAAAAUUUUTTTTHHHHOOOORRRR
  5320. X     Anastasios C. Kotsikonas
  5321. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  5322. X     Comments to tasos@cs.bu.edu
  5323. X
  5324. X
  5325. X
  5326. X
  5327. X
  5328. X
  5329. X
  5330. X
  5331. X
  5332. X
  5333. X
  5334. X
  5335. X
  5336. X
  5337. X
  5338. X
  5339. X
  5340. X
  5341. X
  5342. X
  5343. X
  5344. X
  5345. X
  5346. X
  5347. X
  5348. X
  5349. X
  5350. X
  5351. X
  5352. X
  5353. X
  5354. X
  5355. X
  5356. X
  5357. X
  5358. X
  5359. X
  5360. X
  5361. X
  5362. X
  5363. X
  5364. XAnastasios Kotsikonas                                              12
  5365. X
  5366. X
  5367. X
  5368. *-*-END-of-doc/listserv.nr-*-*
  5369. echo x - doc/queue.nr
  5370. sed 's/^X//' >doc/queue.nr <<'*-*-END-of-doc/queue.nr-*-*'
  5371. X
  5372. X
  5373. X
  5374. Xqueue(1)                 USER COMMANDS                   queue(1)
  5375. X
  5376. X
  5377. X
  5378. XNNNNAAAAMMMMEEEE
  5379. X     qqqquuuueeeeuuuueeeedddd - UNIX ListServer mail queue daemon
  5380. X
  5381. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  5382. X     qqqquuuueeeeuuuueeeedddd <ffffrrrreeeeqqqquuuueeeennnnccccyyyy>
  5383. X
  5384. XNNNNAAAAMMMMEEEE
  5385. X     ppppqqqquuuueeeeuuuueeee - process the specified mail queue files
  5386. X
  5387. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  5388. X     ppppqqqquuuueeeeuuuueeee [----eeee] [----DDDD] <ffffiiiilllleeeessss>
  5389. X
  5390. XOOOOVVVVEEEERRRRVVVVIIIIEEEEWWWW
  5391. X     This part of the UNIX ListServer system can be employed only
  5392. X     when  using the _s_y_s_t_e_m mailmethod (see _s_e_r_v_e_r(1)).  Messages
  5393. X     and replies to requests not delivered due to  network  prob-
  5394. X     lems   are   queued   by   the   system   in  the  directory
  5395. X     HOMEDIR/mqueue. This part of the  system  attempts  periodic
  5396. X     redelivery  of these files. If problems still persist, files
  5397. X     (messages) that cannot be delivered are requeued.
  5398. X
  5399. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN:::: qqqquuuueeeeuuuueeeedddd
  5400. X     This is the daemon that looks for files in the  mail  queue.
  5401. X     It  uses  _p_q_u_e_u_e  for redelivery. The queue is checked every
  5402. X     _f_r_e_q_u_e_n_c_y seconds. Whenever an  error  occurs  with  _p_q_u_e_u_e,
  5403. X     _q_u_e_u_e_d  sends  a  mail message to _m_a_n_a_g_e_r (as defined in the
  5404. X     _c_o_n_f_i_g file) and aborts.
  5405. X
  5406. X     _q_u_e_u_e_d is not spawned by _s_t_a_r_t(1) in  order  to  reduce  the
  5407. X     number  of  processes running, since the probability of mes-
  5408. X     sages being queued  is  very  low.  Instead,  it  should  be
  5409. X     started  manually whenever there are files in the mail queue
  5410. X     directory.
  5411. X
  5412. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN:::: ppppqqqquuuueeeeuuuueeee
  5413. X     The _f_i_l_e_s given as arguments  are  redelivered.  If  any  of
  5414. X     these  cannot  be redelivered, they are requeued and will be
  5415. X     processed in the  next  run.  _p_q_u_e_u_e  reports  to  the  file
  5416. X     HOMEDIR/.report.pqueue
  5417. X
  5418. X     The following command line options are recognized:
  5419. X
  5420. X     -e   Echo reports to the screen; it has  no  effect  if  the
  5421. X          system has been compiled with -DSYSLOG.
  5422. X
  5423. X     -D   Turns debugging on; a copy of the last SMTP transaction
  5424. X          can   be   found   in   the   files   HOMEDIR/sent  and
  5425. X          HOMEDIR/received. Warning: these files are also used by
  5426. X          _l_i_s_t(1) and _l_i_s_t_s_e_r_v(1) when they have their debug mode
  5427. X          on, so use caution.
  5428. X
  5429. X
  5430. X
  5431. X
  5432. X
  5433. XAnastasios Kotsikonas                                               1
  5434. X
  5435. X
  5436. X
  5437. X
  5438. X
  5439. X
  5440. Xqueue(1)                 USER COMMANDS                   queue(1)
  5441. X
  5442. X
  5443. X
  5444. XNNNNOOOOTTTTEEEE
  5445. X     This mail queueing system should not be  confused  with  the
  5446. X     one implemented by sendmail(1).
  5447. X
  5448. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  5449. X     server(1)
  5450. X
  5451. XAAAAUUUUTTTTHHHHOOOORRRR
  5452. X     Anastasios C. Kotsikonas
  5453. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  5454. X     Comments to tasos@cs.bu.edu
  5455. X
  5456. X
  5457. X
  5458. X
  5459. X
  5460. X
  5461. X
  5462. X
  5463. X
  5464. X
  5465. X
  5466. X
  5467. X
  5468. X
  5469. X
  5470. X
  5471. X
  5472. X
  5473. X
  5474. X
  5475. X
  5476. X
  5477. X
  5478. X
  5479. X
  5480. X
  5481. X
  5482. X
  5483. X
  5484. X
  5485. X
  5486. X
  5487. X
  5488. X
  5489. X
  5490. X
  5491. X
  5492. X
  5493. X
  5494. X
  5495. X
  5496. X
  5497. X
  5498. X
  5499. XAnastasios Kotsikonas                                               2
  5500. X
  5501. X
  5502. X
  5503. *-*-END-of-doc/queue.nr-*-*
  5504. echo x - doc/server.nr
  5505. sed 's/^X//' >doc/server.nr <<'*-*-END-of-doc/server.nr-*-*'
  5506. X
  5507. X
  5508. X
  5509. Xserver(1)                USER COMMANDS                  server(1)
  5510. X
  5511. X
  5512. X
  5513. XNNNNAAAAMMMMEEEE
  5514. X     UNIX ListServer version 6.0
  5515. X
  5516. XOOOOVVVVEEEERRRRVVVVIIIIEEEEWWWW
  5517. X     This is a system that implements various mailing lists  with
  5518. X     one  list  server. It is automated, and obliterates the need
  5519. X     for user intervention and maintenance of multiple aliases of
  5520. X     the  form  "list,  list-owner,  list-request", etc. There is
  5521. X     support  provided  for  public  and   private   hierarchical
  5522. X     archives,  moderated  and  non-moderated  lists, peer lists,
  5523. X     peer servers, private lists, address aliasing, news  connec-
  5524. X     tions  and gateways, mail queueing, digests, list ownership,
  5525. X     owner preferences, crash recovery, batch processing,  confi-
  5526. X     gurable headers, regular expressions, archive searching, and
  5527. X     live user connections via TCP/IP.
  5528. X
  5529. XOOOOBBBBTTTTAAAAIIIINNNNIIIINNNNGGGG IIIINNNNFFFFOOOORRRRMMMMAAAATTTTIIIIOOOONNNN
  5530. X     mailing lists, aliases, news groups, peer lists
  5531. X          See list(1).
  5532. X
  5533. X     user requests, list owners, peer servers, remote lists
  5534. X          See listserv(1).
  5535. X
  5536. X     distributing incoming mail
  5537. X          See catmail(1).
  5538. X
  5539. X     archiving files
  5540. X          See farch(1).
  5541. X
  5542. X     archiving of lists' messages
  5543. X          See below.
  5544. X
  5545. X     processing the mail queue
  5546. X          See queue(1).
  5547. X
  5548. X     options for the system's daemon
  5549. X          See serverd(1).
  5550. X
  5551. X     starting and stopping the system
  5552. X          See start(1).
  5553. X
  5554. X     live connections
  5555. X          See iul(1) and serverd(1).
  5556. X
  5557. XSSSSYYYYSSSSTTTTEEEEMMMM SSSSEEEETTTTUUUUPPPP
  5558. X     The UNIX ListServer system is installed  under  the  HOMEDIR
  5559. X     directory  as defined in src/Makefile; HOMEDIR points to the
  5560. X     top level directory  of  the  installation;  a  _s_e_r_v_e_r  user
  5561. X     account  has to be setup. The system should be installed and
  5562. X     set up using this account, and always be started  from  this
  5563. X     account  as  well (see _s_t_a_r_t(1)).  Then, the following alias
  5564. X     has to be  defined  in  /etc/aliases,  /usr/lib/aliases   or
  5565. X
  5566. X
  5567. X
  5568. XAnastasios Kotsikonas                                               1
  5569. X
  5570. X
  5571. X
  5572. X
  5573. X
  5574. X
  5575. Xserver(1)                USER COMMANDS                  server(1)
  5576. X
  5577. X
  5578. X
  5579. X     /usr/ucblib/aliases  (depending  on  your  system) for list-
  5580. X     server (where users send their requests):
  5581. X
  5582. X       listserver: "|HOMEDIR/catmail -r -f"
  5583. X
  5584. X     Keep in mind, that the recommended alias before version  6.0
  5585. X     was  "listserv", so you may wish to use that for compatibil-
  5586. X     ity purposes.
  5587. X
  5588. X     Various mailing lists are set up in a similar  fashion;  see
  5589. X     _l_i_s_t(1).
  5590. X
  5591. X     It is important to keep in mind that mailers should  convert
  5592. X     any  text  lines  (not  header  lines)  of incoming messages
  5593. X     starting with "From ", to ">From ".  This  is  automatically
  5594. X     done by the -f flag to _c_a_t_m_a_i_l(1).
  5595. X
  5596. X     The _c_a_t_m_a_i_l(1) utility is used to append  incoming  mail  to
  5597. X     the  appropriate  files.  When  properly  set up, it has the
  5598. X     setuid bit turned on. Since execute permission is granted to
  5599. X     everybody,  it  is  possible  for  anyone to append to these
  5600. X     files; however, each time _c_a_t_m_a_i_l(1) is run, it reports  the
  5601. X     user id and user name whom access was granted to.
  5602. X
  5603. X     If the system is to go  interactive  (see  _s_e_r_v_e_r_d(1)),  you
  5604. X     have to add the following line in your /etc/services file:
  5605. X
  5606. X                         ulistserv   372/tcp
  5607. X
  5608. X     See also src/Makefile.
  5609. X
  5610. X     How the system operates is defined in the _c_o_n_f_i_g  file  (see
  5611. X     below).  Once the system is loaded, you will have to run the
  5612. X     script _s_e_t_u_p; this will ensure that all necessary files  and
  5613. X     directories  are  present,  and  have the right permissions.
  5614. X     Before starting  the  system,  you  may  wish  to  edit  the
  5615. X     ".ignored"  file  in  HOMEDIR (see _l_i_s_t(1)).  At this point,
  5616. X     you may also wish to alter the help files  in  HOMEDIR/help;
  5617. X     each file in that directory corresponds to one of the recog-
  5618. X     nized requests.  Help files may be  simple  text  files,  or
  5619. X     shell  scripts  starting  with "#!"  in the first line, fol-
  5620. X     lowed by the shell to execute.
  5621. X
  5622. X     File protections are a major issue and the requirements  may
  5623. X     vary  from system to system. The problems usually arise from
  5624. X     inadequate write permissions while  appending  mail  to  the
  5625. X     various mail files. The system uses the environment variable
  5626. X     ULISTSERVER_UMASK in the same way as umask(1) is  used  when
  5627. X     updating  files.  If not set, the default is 066. A value of
  5628. X     026 should be acceptable in most cases. This variable should
  5629. X     be set in both .cshrc and .profile.
  5630. X
  5631. X
  5632. X
  5633. X
  5634. XAnastasios Kotsikonas                                               2
  5635. X
  5636. X
  5637. X
  5638. X
  5639. X
  5640. X
  5641. Xserver(1)                USER COMMANDS                  server(1)
  5642. X
  5643. X
  5644. X
  5645. X     Finally, experiment with the various mail methods  described
  5646. X     below,  until  you get the proper "From " line in the begin-
  5647. X     ning of the outgoing message; for instance, when _l_i_s_t_s_e_r_v(1)
  5648. X     is  replying  to  a  request,  you should see something like
  5649. X     "From listserver@your-domain"  as  the  first  line  of  the
  5650. X     header;  or when the list abc is distributing messages, this
  5651. X     line should look like "From abc@your-domain". If you  cannot
  5652. X     get   it   to  work,  i.e.  you  get  something  like  "From
  5653. X     server@your-domain" then the server system may have  to  run
  5654. X     with  superuser  privileges. In this case, the server userid
  5655. X     should be the same as root's. Also consult the PORT SPECIFIC
  5656. X     section  below, for suggested mailmethods. You will not have
  5657. X     any of these problems if you use the _s_y_s_t_e_m mailmethod  (see
  5658. X     below).
  5659. X
  5660. X     If this part of the setup is not done properly,  peer  lists
  5661. X     will  not  work at all and users may not be able to reply to
  5662. X     the list. As a final note, if _t_e_l_n_e_t does  not  seem  to  be
  5663. X     sending any mail, it is a bug with the telnet implementation
  5664. X     on your system: telnet cannot have its input  redirected  or
  5665. X     piped, and should be reported to your vendor.
  5666. X
  5667. X     The last step for a complete set up is to define your system
  5668. X     in the _c_o_n_f_i_g file.
  5669. X
  5670. XCCCCOOOONNNNFFFFIIIIGGGG
  5671. X     The server system is defined in the _c_o_n_f_i_g file; an  example
  5672. X     file  is  provided  with  the  system.  This file is used by
  5673. X     _s_t_a_r_t(1), _s_e_r_v_e_r_d(1), _l_i_s_t(1) and _l_i_s_t_s_e_r_v(1), and is not  a
  5674. X     shell script.
  5675. X
  5676. X     The following keywords (directives) are  recognized  and  is
  5677. X     advisable  that  each one of them starts at column 1; direc-
  5678. X     tives may span multiple lines if each line is terminated  by
  5679. X     &\n:
  5680. X
  5681. X     _o_r_g_a_n_i_z_a_t_i_o_n name
  5682. X          This defines your organization when posting to news and
  5683. X          upon  connection  establishment of a live session. _n_a_m_e
  5684. X          may include blanks.
  5685. X
  5686. X     _s_e_r_v_e_r _l_i_s_t_s_e_r_v_e_r@your-domain command-line-options
  5687. X          This defines the list server; the first argument is the
  5688. X          full    email    address    of    the    server   (e.g.
  5689. X          listserver@foo.edu)  followed  by  any   command   line
  5690. X          options  to  be  used when _s_e_r_v_e_r_d spawns _l_i_s_t_s_e_r_v (see
  5691. X          _s_e_r_v_e_r_d(1), _l_i_s_t_s_e_r_v(1)).
  5692. X
  5693. X     _l_i_s_t list_alias email-addr owner-addr password cmd-line-opt
  5694. X          This defines a mailing list; the first argument is  the
  5695. X          list's  alias  in  /etc/aliases,  /usr/lib/aliases   or
  5696. X          /usr/ucblib/aliases (see _l_i_s_t(1)), followed by its full
  5697. X
  5698. X
  5699. X
  5700. XAnastasios Kotsikonas                                               3
  5701. X
  5702. X
  5703. X
  5704. X
  5705. X
  5706. X
  5707. Xserver(1)                USER COMMANDS                  server(1)
  5708. X
  5709. X
  5710. X
  5711. X          email  address,  followed  by  its  owner's  full email
  5712. X          address, followed by the list's  password  for  mainte-
  5713. X          nance,  followed by any command line options to be used
  5714. X          when _s_e_r_v_e_r_d(1) spawns _l_i_s_t(1).
  5715. X
  5716. X     _h_e_a_d_e_r list { [Header-Line:] ... }
  5717. X          It specifies precious header lines  from  the  original
  5718. X          sender's  message  that are to be preserved during dis-
  5719. X          tribution. The _l_i_s_t has to be defined before, and  pre-
  5720. X          cious header lines are specified within the enclosing {
  5721. X          and }, possibly spanning multiple lines.
  5722. X
  5723. X     _d_e_f_a_u_l_t list { [option = value] ... }
  5724. X          Determine various default values for _l_i_s_t for  new  and
  5725. X          current subscribers; the list has to be defined before.
  5726. X          Pairs of options and values may be repeated any  number
  5727. X          of  times,  and  may  span  multiple  lines; if certain
  5728. X          options are missing, then  system  defaults  are  used.
  5729. X          Valid _o_p_t_i_o_ns are:
  5730. X
  5731. X            _a_d_d_r_e_s_s: turn user-settable subscription addresses on
  5732. X            or off. Valid values are:
  5733. X
  5734. X              _f_i_x_e_d: users are not allowed to change the  address
  5735. X              they are subscribed with via the _s_e_t <_l_i_s_t> _a_d_d_r_e_s_s
  5736. X              request (see  _l_i_s_t_s_e_r_v(1)).   This  is  the  system
  5737. X              default as well.
  5738. X
  5739. X              _v_a_r_i_a_b_l_e: opposite of the above.
  5740. X
  5741. X            _m_a_i_l: select the  default  mail  mode  for  new  sub-
  5742. X            scribers. Valid values are:
  5743. X
  5744. X              _a_c_k: see _s_e_t in _l_i_s_t_s_e_r_v(1).
  5745. X
  5746. X              _n_o_a_c_k: see _s_e_t in _l_i_s_t_s_e_r_v(1); this is  the  system
  5747. X              default.
  5748. X
  5749. X              _p_o_s_t_p_o_n_e: see _s_e_t in _l_i_s_t_s_e_r_v(1) (a rather  useless
  5750. X              setting indeed).
  5751. X
  5752. X              _d_i_g_e_s_t: see _s_e_t in _l_i_s_t_s_e_r_v(1).
  5753. X
  5754. X            _p_a_s_s_w_o_r_d: define a single password for new users;  if
  5755. X            missing,  the  system  assigns a random password. Any
  5756. X            string that contains no white spaces may be used.
  5757. X
  5758. X            _c_o_n_c_e_a_l: determine  the  default  visibility  of  new
  5759. X            users; see _s_e_t in _l_i_s_t_s_e_r_v(1). Valid options are:
  5760. X
  5761. X              _y_e_s:  hidden   from   _r_e_c_i_p_i_e_n_t_s   and   _s_t_a_t_i_s_t_i_c_s
  5762. X              requests.
  5763. X
  5764. X
  5765. X
  5766. XAnastasios Kotsikonas                                               4
  5767. X
  5768. X
  5769. X
  5770. X
  5771. X
  5772. X
  5773. Xserver(1)                USER COMMANDS                  server(1)
  5774. X
  5775. X
  5776. X
  5777. X              _n_o: this is the system default.
  5778. X
  5779. X     _c_e_i_l_i_n_g list max_messages
  5780. X          Restrict the number of  messages  processed  daily  for
  5781. X          _l_i_s_t to _m_a_x__m_e_s_s_a_g_e_s; this includes posted and rejected
  5782. X          messages.
  5783. X
  5784. X     _r_e_m_o_t_e alias email-addr listserver-addr [host [port]]  #Com-
  5785. X          ment
  5786. X          This makes a remote list known to the server. A  remote
  5787. X          list  is another mailing list served by another server,
  5788. X          and your server is now capable  of  forwarding  to  the
  5789. X          proper  remote list server any requests sent about this
  5790. X          remote list to your server. _a_l_i_a_s is the name by  which
  5791. X          the  remote  list  is  known by, _e_m_a_i_l-_a_d_d_r is the full
  5792. X          email address of the remote  list,  _l_i_s_t_s_e_r_v_e_r-_a_d_d_r  is
  5793. X          the  full  email address of the remote list server, and
  5794. X          #_C_o_m_m_e_n_t will be used upon a _l_i_s_t_s request made to this
  5795. X          server  (the  pound  sign is mandatory). _h_o_s_t is either
  5796. X          the DNS name or IP address of the remote  server,  used
  5797. X          to connect to that server when a live request refers to
  5798. X          that list; the _p_o_r_t should  be  specified  if  not  the
  5799. X          default (372) (see _s_e_r_v_e_r_d(1)).
  5800. X
  5801. X          Remote lists may have the same _a_l_i_a_s  and  they  should
  5802. X          not  be  confused with peer lists. However, each remote
  5803. X          list should be defined only once.  See  the  discussion
  5804. X          about  PEER SERVERS  (_l_i_s_t_s_e_r_v(1)) for further informa-
  5805. X          tion.
  5806. X
  5807. X     _f_a_x fax-program options
  5808. X          Define the fax program to use for _f_a_x requests (if any)
  5809. X          and  any  command line options the program may use. The
  5810. X          program should also be capable of accepting the file to
  5811. X          fax  from  its  standard input; otherwise a script will
  5812. X          have to be used instead which will in turn use the  fax
  5813. X          program  appropriately.  If  this  directive is left or
  5814. X          commented out,  then  _f_a_x  requests  are  automatically
  5815. X          turned of.
  5816. X
  5817. X          The actual faxing program is called as follows:
  5818. X
  5819. X                   _f_a_x-_p_r_o_g_r_a_m _o_p_t_i_o_n_s fax-number < file
  5820. X
  5821. X          This request may not be issued  from  a  live  session,
  5822. X          since  fax  programs work on email messages and extract
  5823. X          the sender's address for  reference  when  sending  the
  5824. X          cover page of the fax.
  5825. X
  5826. X     _u_n_i_x__c_m_d  list_alias  password  name  'unix-command  [args]'
  5827. X          #Comment
  5828. X          Allow a _l_i_s_t__a_l_i_a_s's subscribers only  to  execute  the
  5829. X
  5830. X
  5831. X
  5832. XAnastasios Kotsikonas                                               5
  5833. X
  5834. X
  5835. X
  5836. X
  5837. X
  5838. X
  5839. Xserver(1)                USER COMMANDS                  server(1)
  5840. X
  5841. X
  5842. X
  5843. X          above  _u_n_i_x-_c_o_m_m_a_n_d  aliased  to  _n_a_m_e. The _p_a_s_s_w_o_r_d is
  5844. X          made known to users who are to be given this privilege.
  5845. X          The  oprional _a_r_g_s may be literal arguments to the com-
  5846. X          mand as well as the special sequences $_n, where _n is  a
  5847. X          digit  from  1 to 9, or *; their meaning is that of the
  5848. X          Bourne shell, and  they  will  be  substituted  by  the
  5849. X          user's actual arguments. For example:
  5850. X
  5851. X          unix_cmd ermis pass1 swap '/bin/echo $2 $1' #Syntax: swap <arg1> <arg2>
  5852. X
  5853. X          will swap the user's first and  second  arguments.  The
  5854. X          user would submit a request that could look like this:
  5855. X
  5856. X                      run ermis pass1 swap arg1 arg2
  5857. X
  5858. X          No security checks are made except to ensure  that  the
  5859. X          arguments  contain  no `, |, :, < and >, so the _m_a_n_a_g_e_r
  5860. X          is encouraged to review and verify the proper function-
  5861. X          ing  of  _u_n_i_x-_c_o_m_m_a_n_d.  The  _C_o_m_m_e_n_t is used when users
  5862. X          issue 'run <list>' query requests.
  5863. X
  5864. X     _s_e_r_v_e_r_d command-line-options
  5865. X          This defines the command line options that _s_t_a_r_t(1)  is
  5866. X          to use when spawning _s_e_r_v_e_r_d(1).
  5867. X
  5868. X     _r_e_s_t_r_i_c_t_i_o_n nusers
  5869. X          If a restriction is placed on a ListServer request (via
  5870. X          a  -r  command line option to _l_i_s_t_s_e_r_v(1)), this direc-
  5871. X          tive defines the threshold number of users, above which
  5872. X          the restriction will take effect.
  5873. X
  5874. X     _d_i_s_a_b_l_e list_alias request
  5875. X          The specified server _r_e_q_u_e_s_t is disabled for the speci-
  5876. X          fied  list,  and  all  such  requests for this list are
  5877. X          rejected, except when issued by privileged users  (list
  5878. X          owners).  The  _l_i_s_t__a_l_i_a_s has to be defined (via a _l_i_s_t
  5879. X          directive) before any requests can be disabled.
  5880. X
  5881. X     _m_a_n_a_g_e_r full-email-address
  5882. X          This defines the recipient of  all  system  error  mes-
  5883. X          sages,  and  the  system's administrator and caretaker;
  5884. X          _f_u_l_l-_e_m_a_i_l-_a_d_d_r_e_s_s can be any valid user name that  can
  5885. X          be  reached  via  email by your system.  The _m_a_n_a_g_e_r is
  5886. X          usually the person responsible for the server account.
  5887. X
  5888. X     _c_o_m_m_e_n_t _s_e_r_v_e_r #Actual comment
  5889. X
  5890. X     _c_o_m_m_e_n_t list_alias #Actual comment
  5891. X          A 'X-Comment:'  line  is  included  in  every  outgoing
  5892. X          list/server  message,  and the text following the pound
  5893. X          sign will be copied every time;  note  that  the  pound
  5894. X          sign  is  mandatory  for the definition but will not be
  5895. X
  5896. X
  5897. X
  5898. XAnastasios Kotsikonas                                               6
  5899. X
  5900. X
  5901. X
  5902. X
  5903. X
  5904. X
  5905. Xserver(1)                USER COMMANDS                  server(1)
  5906. X
  5907. X
  5908. X
  5909. X          part of the actual string.  A list's  comment  is  also
  5910. X          used  for  the  _l_i_s_t_s request to specify the purpose of
  5911. X          the particular mailing list. No  'X-Comment:'  line  is
  5912. X          included  if this directive is not defined for the par-
  5913. X          ticular list and/or server.
  5914. X
  5915. X     _d_i_g_e_s_t list_alias lines hours
  5916. X          If any subscriber to the list requests digests, a  dig-
  5917. X          est will be sent when its length exceeds _l_i_n_e_s, or when
  5918. X          _h_o_u_r_s have passed without a digest being sent.  Digests
  5919. X          for  a  list  are collected only if at least one of its
  5920. X          subscribers has set his mail mode to _d_i_g_e_s_t.
  5921. X
  5922. X     _a_r_c_h_i_v_e list_alias dir filename [archive]  [password]  [dig-
  5923. X          est]
  5924. X          Request that  all  public  messages  are  automatically
  5925. X          archived;  _l_i_s_t__a_l_i_a_s  is  the  list's name, _d_i_r is the
  5926. X          directory that the archived files will  be  located  (a
  5927. X          full path has to be specified, and the directory has to
  5928. X          be  writable  by  the  server  uid),  _a_r_c_h_i_v_e  is   the
  5929. X          archive's name and is a relative path under the default
  5930. X          archive (listserver) or "-" for the  default,  _p_a_s_s_w_o_r_d
  5931. X          is an optional password ("-" if none) to be used if the
  5932. X          archive is meant to be private, and the  optional  key-
  5933. X          word  _d_i_g_e_s_t  will  force  only digests to be archived;
  5934. X          _f_i_l_e_n_a_m_e specifies the format of  the  archived  files,
  5935. X          and  may contain any lower case characters and numbers,
  5936. X          as well as the following special sequences:
  5937. X
  5938. X            %m: Numeric month (01 - 12)
  5939. X
  5940. X            %d: Numeric day of the month (01 - 31)
  5941. X
  5942. X            %y: Year (00 - 99)
  5943. X
  5944. X            %j: Julian date (001 - 366)
  5945. X
  5946. X            %h: Month name (Jan - Dec)
  5947. X
  5948. X            %a: Contents of the  Archive-Name:  header  line,  if
  5949. X            present;  cannot  be  used  if archiving digests. The
  5950. X            Archive-Name: header line has to be manually inserted
  5951. X            by  the  sender of the message; it may show up in the
  5952. X            body of the message as well.
  5953. X
  5954. X            %#: Digest number; can only be used if archiving dig-
  5955. X            ests.
  5956. X
  5957. X            %1: First word of the first  non-blank  line  of  the
  5958. X            message.
  5959. X
  5960. X            %v: Volume number, if the message contains a  'Volume
  5961. X
  5962. X
  5963. X
  5964. XAnastasios Kotsikonas                                               7
  5965. X
  5966. X
  5967. X
  5968. X
  5969. X
  5970. X
  5971. Xserver(1)                USER COMMANDS                  server(1)
  5972. X
  5973. X
  5974. X
  5975. X            # Number #' line before the actual message.
  5976. X
  5977. X            %n: Issue number, if the message contains a 'Volume #
  5978. X            Number #' line before the actual message.
  5979. X
  5980. X            %%: The character %
  5981. X
  5982. X          For example, to archive messages daily:
  5983. X
  5984. X          archive ermis HOMEDIR/archives/lists/ermis %y%m%d listserver/lists/ermis
  5985. X
  5986. X          or to archive only files sent to the list:
  5987. X
  5988. X          archive venus /ftp/lists/venus vol-%v.num-%n listserver/lists/venus johny-be-good
  5989. X
  5990. X          and in this case the sender that wants  a  file  to  be
  5991. X          archived would precede it with a line similar to:
  5992. X
  5993. X          Volume 10 Number 5
  5994. X
  5995. X          followed by the actual file.
  5996. X
  5997. X          When a new archive file is created, the  Subject:  line
  5998. X          is  used  as  the  short  descriptive  message  for the
  5999. X          archive.
  6000. X
  6001. X     _f_r_e_q_u_e_n_c_y seconds
  6002. X          How often should _s_e_r_v_e_r_d(1) check for  new  mail.  When
  6003. X          _s_e_c_o_n_d_s is set to zero, _s_e_r_v_e_r_d does not sleep.
  6004. X
  6005. X     _b_a_t_c_h start stop
  6006. X          Specify the hours (in military time) when requests  are
  6007. X          to  be  batched.   The defaults are 8 and 20. _s_t_a_r_t and
  6008. X          _s_t_o_p should be within the same day (e.g. 8 am and 1  am
  6009. X          the following day are not valid).
  6010. X
  6011. X     _l_i_m_i_t keyword arguments
  6012. X          Used to set certain limits in the system;  _k_e_y_w_o_r_d  can
  6013. X          be:
  6014. X
  6015. X            _m_e_s_s_a_g_e: limit the size of distributed messages to  a
  6016. X            certain  number  of bytes, which is the _a_r_g_u_m_e_n_t fol-
  6017. X            lowing this keyword.  A notification is sent back  to
  6018. X            the sender when this limit is exceeded, including the
  6019. X            first few  lines  of  his/her  original  message  for
  6020. X            reference.
  6021. X
  6022. X            _f_i_l_e_s: limit the size of archive files  that  can  be
  6023. X            sent  out  to a certain number of bytes, which is the
  6024. X            _a_r_g_u_m_e_n_t following this keyword.  When this limit  is
  6025. X            reached,  the  file  is automatically split into sub-
  6026. X            parts.
  6027. X
  6028. X
  6029. X
  6030. XAnastasios Kotsikonas                                               8
  6031. X
  6032. X
  6033. X
  6034. X
  6035. X
  6036. X
  6037. Xserver(1)                USER COMMANDS                  server(1)
  6038. X
  6039. X
  6040. X
  6041. X     _p_r_e_c_e_d_e_n_c_e string
  6042. X          The header of each outgoing  message  contains  a  Pre-
  6043. X          cedence: line; _s_t_r_i_n_g can be:
  6044. X
  6045. X            bulk, junk, first-class,  none:  primarily  used  for
  6046. X            vacation programs.
  6047. X
  6048. X     _o_p_t_i_o_n keyword
  6049. X          This defines a series of system-dependent options; _k_e_y_-
  6050. X          _w_o_r_d can be:
  6051. X
  6052. X            _s_y_s_v__p_s: the system will assume a System V version of
  6053. X            ps(1).
  6054. X
  6055. X            _b_s_d__p_s: the system  will  assume  a  BSD  version  of
  6056. X            ps(1).
  6057. X
  6058. X            _b_s_d__m_a_i_l: define it if BSD (UCB) mail is available on
  6059. X            your  system;  if  this  is  the case, make sure that
  6060. X            /usr/ucb/mail is the path (or a link) to it; also see
  6061. X            src/Makefile.   This is used to notify the _m_a_n_a_g_e_r of
  6062. X            any error conditions.
  6063. X
  6064. X            _b_a_d__t_e_l_n_e_t: if the mail method used  (see  below)  is
  6065. X            _t_e_l_n_e_t and the system seems to send out only one mes-
  6066. X            sage and then go to sleep, use this option.
  6067. X
  6068. X            _p_o_s_t__m_a_i_l: this will force the system  to  post  mes-
  6069. X            sages to news groups (using _i_n_e_w_s), using the groups'
  6070. X            names (e.g. misc.test). Make sure that _i_n_e_w_s  resides
  6071. X            in /usr/lib/news, or /usr/lib/news/inews is a link to
  6072. X            it (also see src/Makefile).
  6073. X
  6074. X            _g_a_t_e__m_a_i_l: this will force the system  to  gate  mes-
  6075. X            sages to news, using the gateways' email addresses.
  6076. X
  6077. X            _i_g_n_o_r_e__i_n_v_a_l_i_d__r_e_q_u_e_s_t_s: ignore all unrecognized user
  6078. X            requests and process valid ones only; by default, the
  6079. X            system aborts  processing  requests  upon  the  first
  6080. X            invalid  one,  in  which  case a reply is sent to the
  6081. X            user and all subsequent requests are flushed.
  6082. X
  6083. X            _r_e_l_a_x_e_d__s_y_n_t_a_x: by default, the system complains when
  6084. X            a request is given more arguments than expected. This
  6085. X            turns such checking off.
  6086. X
  6087. X     _m_a_i_l_m_e_t_h_o_d method [arguments]
  6088. X          Every outgoing message should begin with a line of  the
  6089. X          form:
  6090. X
  6091. X            From listserver@your-domain
  6092. X
  6093. X
  6094. X
  6095. X
  6096. XAnastasios Kotsikonas                                               9
  6097. X
  6098. X
  6099. X
  6100. X
  6101. X
  6102. X
  6103. Xserver(1)                USER COMMANDS                  server(1)
  6104. X
  6105. X
  6106. X
  6107. X            or
  6108. X
  6109. X            From list_alias@your-domain
  6110. X
  6111. X          which depends on the mail _m_e_t_h_o_d used:
  6112. X
  6113. X            _s_y_s_t_e_m: the recommended method; it provides a unified
  6114. X            approach  to  sending mail and it has been ported and
  6115. X            tested  on  lots  of   systems   (see   the   section
  6116. X            PORT SPECIFIC  below).  In addition, since a full set
  6117. X            of the SMTP protocol is implemented, _m_a_n_a_g_e_r and list
  6118. X            owners  will  be  notified  of  invalid addresses and
  6119. X            various system  problems.   Moreover,  mail  will  be
  6120. X            queued  when it cannot be delivered, in the directory
  6121. X            HOMEDIR/mqueue; see _q_u_e_u_e(_1) for more information  on
  6122. X            how to process the mail queue.
  6123. X
  6124. X            This method requires host TCP/IP  and  internet  sup-
  6125. X            port;  consult  the src/README file for more informa-
  6126. X            tion.
  6127. X
  6128. X            _t_e_l_n_e_t: to be used only when _s_y_s_t_e_m is  inappropriate
  6129. X            and telnet(1) is available on your host.
  6130. X
  6131. X            _e_n_v__v_a_r: usually followed by _L_O_G_N_A_M_E  /_b_i_n/_r_m_a_i_l,  or
  6132. X            _L_O_G_N_A_M_E  /_u_s_r/_l_i_b/_s_e_n_d_m_a_i_l  -_b_a (-ba is mandatory) --
  6133. X            to be used only when the previous methods  are  inap-
  6134. X            propriate.
  6135. X
  6136. XMMMMAAAAIIIILLLL LLLLOOOOOOOOPPPPSSSS
  6137. X     The system uses the following  protocol  for  avoiding  mail
  6138. X     loops  between a list and news connections: In the header of
  6139. X     the outgoing message an "Originator: " field is  added.  For
  6140. X     each  list  plus  listserver, a log of the most recent (500)
  6141. X     Message-Id's is kept.  Whenever a message is  received,  the
  6142. X     Originator, Reply-To and Message-Id fields are extracted and
  6143. X     looked up in the ".ignored" and ".message.ids" files in  the
  6144. X     list's  subdirectory.  Gateways  that  feed back to the list
  6145. X     should preserve at least the Reply-To and Message-Id fields.
  6146. X     The  Originator  and Message-Id fields are preserved by this
  6147. X     system. A new Reply-To is tacked on when redistributing mail
  6148. X     locally from a peer or a news feed.
  6149. X
  6150. X     To avoid mail loops when forwarding ListServer  requests  to
  6151. X     peers,  the  system  looks  up  the  Message-Id field in the
  6152. X     ".message.ids" file  in  HOMEDIR.   If  this  field  is  not
  6153. X     preserved  by  the peer ListServer, it is suggested that you
  6154. X     turn off  request  forwarding  when  connecting  with  peers
  6155. X     served  by  such systems, until a unified approach is taken.
  6156. X     The Message-Id field is preserved by this  ListServer.  This
  6157. X     system  is  also  using  a  special  Subject  field, totally
  6158. X     proprietary and non-standard, in order to avoid  unnecessary
  6159. X
  6160. X
  6161. X
  6162. XAnastasios Kotsikonas                                              10
  6163. X
  6164. X
  6165. X
  6166. X
  6167. X
  6168. X
  6169. Xserver(1)                USER COMMANDS                  server(1)
  6170. X
  6171. X
  6172. X
  6173. X     forwarding of requests, thus cutting down on email traffic.
  6174. X
  6175. XCCCCRRRRAAAASSSSHHHH RRRREEEECCCCOOOOVVVVEEEERRRRYYYY
  6176. X     It is possible that a message delivery was interrupted by  a
  6177. X     user (_s_t_a_r_t -_k), or by the system (crash/reboot). A built-in
  6178. X     mechanism guarrantees to pick up delivery again  from  where
  6179. X     it left off, if the system is restarted using _s_t_a_r_t(1). Both
  6180. X     _s_t_a_r_t(1) and _l_i_s_t(1) report to the effect that mail delivery
  6181. X     was interrupted and will resume. On the other hand, process-
  6182. X     ing of interrupted requests will not resume and  all  unpro-
  6183. X     cessed requests will be lost.
  6184. X
  6185. XCCCCOOOOMMMMMMMMUUUUNNNNIIIICCCCAAAATTTTIIIINNNNGGGG
  6186. X     Users send requests  to  _l_i_s_t_s_e_r_v_e_r@_y_o_u_r-_d_o_m_a_i_n  and  public
  6187. X     messages to the various _l_i_s_t__a_l_i_a_s@_y_o_u_r-_d_o_m_a_i_n.
  6188. X
  6189. XAAAARRRRCCCCHHHHIIIIVVVVEEEESSSS
  6190. X     The server has an archiving capability  of  files.  Archives
  6191. X     may  be  public  so  that anyone can get files from them, or
  6192. X     private so that only privileged users may obtain files  from
  6193. X     them.      There      is     a     master     archive     in
  6194. X     HOMEDIR/archives/listserver  where   all   subarchives   are
  6195. X     defined. The archives keep lists of files that are available
  6196. X     to users via a _g_e_t request, and index  of  subarchives  that
  6197. X     are available to users via an _i_n_d_e_x request.
  6198. X
  6199. X     As outlined in _l_i_s_t(1),  each  list's  public  messages  are
  6200. X     automatically  saved  under  the  list's subdirectory in the
  6201. X     file _a_r_c_h_i_v_e.  This file may periodically be placed  in  the
  6202. X     system's  archives  by  hand (if not archiving automatically
  6203. X     via the _a_r_c_h_i_v_e directive), or may point to  /dev/null.  The
  6204. X     archived  files  may  not  necessarily reside in the archive
  6205. X     directories, as long as the archives  know  where  they  are
  6206. X     located. See the man page for _f_a_r_c_h(_1) for more information.
  6207. X
  6208. X     Alternatively, messages may be  automatically  archived  via
  6209. X     the _a_r_c_h_i_v_e directive in the _c_o_n_f_i_g file.
  6210. X
  6211. XHHHHEEEELLLLPPPP
  6212. X     The system comes configured with  default  help  topics  the
  6213. X     recognized requests. More topics may be added by editing the
  6214. X     file  HOMEDIR/help/TOPICS,  adding  the  topic(s)  and   the
  6215. X     file(s) where the actual text exists.
  6216. X
  6217. X     Help files may be simple text files  or  shell  scripts,  in
  6218. X     which  case  they  have to start with "#!" in the first line
  6219. X     and be followed by the path to the shell  to  be  used;  for
  6220. X     example: #!/bin/sh
  6221. X
  6222. XSSSSYYYYSSSSTTTTEEEEMMMM MMMMAAAAIIIINNNNTTTTEEEENNNNAAAANNNNCCCCEEEE
  6223. X     As mentioned below, all programs report  to  certain  files.
  6224. X     The  system's  manager  should  periodically check the files
  6225. X
  6226. X
  6227. X
  6228. XAnastasios Kotsikonas                                              11
  6229. X
  6230. X
  6231. X
  6232. X
  6233. X
  6234. X
  6235. Xserver(1)                USER COMMANDS                  server(1)
  6236. X
  6237. X
  6238. X
  6239. X     HOMEDIR/.report.server        and        the         various
  6240. X     HOMEDIR/lists/*/.report.list for any problems.  All messages
  6241. X     sent are saved under HOMEDIR/mbox  and  HOMEDIR/lists/*/mbox
  6242. X     and  they  should be cleaned up periodically.  For debugging
  6243. X     purposes, various warnings are written to  HOMEDIR/.warning;
  6244. X     this  file,  as  well  as HOMEDIR/.report.catmail are shrunk
  6245. X     every time _s_t_a_r_t(1) is run.
  6246. X
  6247. X     For whenever the necessity arises to administer  the  system
  6248. X     remotely,  the following scheme may be used to start or kill
  6249. X     the system, process the mail queue, force an application  to
  6250. X     execute immediately, etc: a mail message is sent to an alias
  6251. X     whose sole role is to fire up an application;  the  applica-
  6252. X     tion has to have been setuid before.
  6253. X
  6254. X     For instance, to start the system remotely, you may  set  up
  6255. X     an alias such as:
  6256. X
  6257. X       start-server: "|HOMEDIR/start -cr > /dev/null"
  6258. X
  6259. X     To kill the system, you may define another alias:
  6260. X
  6261. X       kill-server: "|HOMEDIR/start -crk > /dev/null"
  6262. X
  6263. X     To force requests to get processed now:
  6264. X
  6265. X       run-listserver: "|HOMEDIR/listserv -1 > /dev/null"
  6266. X
  6267. X     To start the queue daemon:
  6268. X
  6269. X       proc-queue: "|HOMEDIR/queued 60 & > /dev/null"
  6270. X
  6271. X     These aliases should be hard to guess for  obvious  reasons.
  6272. X     The actual message sent to such an alias is discarded.
  6273. X
  6274. XEEEEXXXXIIIITTTT CCCCOOOODDDDEEEESSSS
  6275. X     All applications except tlock use the following  exit  codes
  6276. X     for communication:
  6277. X
  6278. X
  6279. X     0    - OK, normal exit
  6280. X
  6281. X     1    - Could not open or lock file
  6282. X
  6283. X     2    - SIGINT signal (normal termination)
  6284. X
  6285. X     3    - Command line option error
  6286. X
  6287. X     4    - Syntax error in file
  6288. X
  6289. X     5    - Could not spawn (restart failed)
  6290. X
  6291. X
  6292. X
  6293. X
  6294. XAnastasios Kotsikonas                                              12
  6295. X
  6296. X
  6297. X
  6298. X
  6299. X
  6300. X
  6301. Xserver(1)                USER COMMANDS                  server(1)
  6302. X
  6303. X
  6304. X
  6305. X     6    - Shutdown request
  6306. X
  6307. X     7    - Restart request
  6308. X
  6309. X     8    - Received system  signal  (anything  but  SIGINT  will
  6310. X          bring the system down)
  6311. X
  6312. X     9    - Too many multiple recipients
  6313. X
  6314. X     10   - Could not deliver mail (unexpected reply  during  the
  6315. X          SMTP transaction)
  6316. X
  6317. X     11   - malloc() failed
  6318. X
  6319. X     12   - Cannot fork()
  6320. X
  6321. X     13   - Socket connection problem
  6322. X
  6323. X     14   - Semaphore error
  6324. X
  6325. X     15   - Cannot setuid()/setgid()
  6326. X
  6327. X     16   - Internal error or system call failure
  6328. X
  6329. X     tlock exits with:
  6330. X
  6331. X     -1   - File locking not functional
  6332. X
  6333. X     0    - No files locked
  6334. X
  6335. X     1    - Cannot open config
  6336. X
  6337. X     2 & up
  6338. X          - Number of files locked + 1
  6339. X
  6340. XRRRREEEEPPPPOOOORRRRTTTTSSSS
  6341. X     The system provides two ways of reporting progress: via sys-
  6342. X     log(3)  when available (by compiling with -DSYSLOG=facility)
  6343. X     with priority LOG_INFO and facility as specified, or through
  6344. X     its own report files (when not using syslog(3)); these are:
  6345. X
  6346. X     HOMEDIR/.report.catmail
  6347. X          Messages from _c_a_t_m_a_i_l(1) every time  new  messages  are
  6348. X          appended to the various mail files.
  6349. X
  6350. X     HOMEDIR/.report.daemon
  6351. X          Messages  from  _s_e_r_v_e_r_d(1)  every  time  new  mail  has
  6352. X          arrived.
  6353. X
  6354. X     HOMEDIR/.report.list
  6355. X          Error messages from _l_i_s_t(1) when attempting to  process
  6356. X          public messages.
  6357. X
  6358. X
  6359. X
  6360. XAnastasios Kotsikonas                                              13
  6361. X
  6362. X
  6363. X
  6364. X
  6365. X
  6366. X
  6367. Xserver(1)                USER COMMANDS                  server(1)
  6368. X
  6369. X
  6370. X
  6371. X     HOMEDIR/.report.pqueue
  6372. X          Messages from _p_q_u_e_u_e (see _q_u_e_u_e(1)).
  6373. X
  6374. X     HOMEDIR/.report.server
  6375. X          Messages from _l_i_s_t_s_e_r_v(1) every time new  requests  are
  6376. X          processed.
  6377. X
  6378. X     HOMEDIR/.report.start
  6379. X          Generated by _s_t_a_r_t(1) every time the system is started.
  6380. X
  6381. X     HOMEDIR/lists/LIST_ALIAS/.report.list
  6382. X          Messages from _l_i_s_t(1) when processing public messages.
  6383. X
  6384. X     HOMEDIR/.*.acc
  6385. X          Accumulated  reports  since  the   system   was   first
  6386. X          installed.
  6387. X
  6388. X     HOMEDIR/lists/*/.*.acc
  6389. X          Accumulated reports for each mailing list.
  6390. X
  6391. X     Every report includes a time stamp; every  list  and  server
  6392. X     report  also  includes the actual sender of the message, and
  6393. X     every server  report  includes  all  requests  made  by  the
  6394. X     sender.
  6395. X
  6396. X     Whenever a program dies abnormally (and BSD mail is present)
  6397. X     a  message  is  sent  to _m_a_n_a_g_e_r (as defined in _c_o_n_f_i_g). The
  6398. X     message is usually sent by _s_e_r_v_e_r_d(1) which then exits.  The
  6399. X     daemon  dies  with a different message according to the exit
  6400. X     status of the child; the various error conditions  that  may
  6401. X     occur are:
  6402. X
  6403. X     Could not open file
  6404. X          HOMEDIR is not a  valid  path;  file  was  accidentally
  6405. X          deleted;  insufficient access privileges. Run _s_e_t_u_p and
  6406. X          _s_t_a_r_t.
  6407. X
  6408. X     Could not lock file
  6409. X          HOMEDIR is not a  valid  path;  file  was  accidentally
  6410. X          deleted;  insufficient  access privileges; another pro-
  6411. X          gram is using the lock file. Run _t_l_o_c_k, and  if  neces-
  6412. X          sary,  _u_l_o_c_k;  then  _s_t_a_r_t.   _t_l_o_c_k  checks  for locked
  6413. X          files, and _u_l_o_c_k removes all lock files.
  6414. X
  6415. X     Command line option error
  6416. X          Check the _c_o_n_f_i_g file and restart.
  6417. X
  6418. X     Syntax error in file
  6419. X          Check _c_o_n_f_i_g, all  reports,  .subscribers,  .peers  and
  6420. X          .news files.
  6421. X
  6422. X     Could not spawn
  6423. X
  6424. X
  6425. X
  6426. XAnastasios Kotsikonas                                              14
  6427. X
  6428. X
  6429. X
  6430. X
  6431. X
  6432. X
  6433. Xserver(1)                USER COMMANDS                  server(1)
  6434. X
  6435. X
  6436. X
  6437. X          No more processes.
  6438. X
  6439. X     Received system signal
  6440. X          SIGQUIT, SIGTERM, SIGBUS, SIGSEGV, SIGILL.
  6441. X
  6442. XFFFFIIIILLLLEEEESSSS
  6443. X     HOMEDIR/.aliases
  6444. X          Aliases of email addresses of users having trouble get-
  6445. X          ting replies to requests.
  6446. X
  6447. X     HOMEDIR/.awk
  6448. X          awk program for formatting the _s_t_a_t_i_s_t_i_c_s request.
  6449. X
  6450. X     HOMEDIR/.grep
  6451. X          script used for counting the number of messages sent by
  6452. X          a subscriber.
  6453. X
  6454. X     HOMEDIR/.ignored
  6455. X          List of unwanted senders.
  6456. X
  6457. X     HOMEDIR/.lock.list
  6458. X          Lock file for _l_i_s_t(1).
  6459. X
  6460. X     HOMEDIR/.lock.pqueue
  6461. X          Lock file for _p_q_u_e_u_e (see _q_u_e_u_e(1)).
  6462. X
  6463. X     HOMEDIR/.lock.server
  6464. X          Lock file for _l_i_s_t_s_e_r_v(1).
  6465. X
  6466. X     HOMEDIR/.lock.serverd
  6467. X          Lock file for _s_e_r_v_e_r_d(1).
  6468. X
  6469. X     HOMEDIR/.message.ids
  6470. X          A database of recent message id's used to  detect  mail
  6471. X          loops.
  6472. X
  6473. X     HOMEDIR/.queue.id
  6474. X          Next id to be assigned to  next  undeliverable  message
  6475. X          placed in the mqueue/ directory.
  6476. X
  6477. X     HOMEDIR/.reply.listser
  6478. X          The reply code given to _s_e_r_v_e_r_d(1) during a  live  ses-
  6479. X          sion.
  6480. X
  6481. X     HOMEDIR/.rep.server.acc
  6482. X          Archived _l_i_s_t_s_e_r_v(1) reports.
  6483. X
  6484. X     HOMEDIR/.rep.serverd.acc
  6485. X          Archived _s_e_r_v_e_r_d(1) reports.
  6486. X
  6487. X     HOMEDIR/.rep.start.acc
  6488. X          Archived _s_t_a_r_t(1) reports.
  6489. X
  6490. X
  6491. X
  6492. XAnastasios Kotsikonas                                              15
  6493. X
  6494. X
  6495. X
  6496. X
  6497. X
  6498. X
  6499. Xserver(1)                USER COMMANDS                  server(1)
  6500. X
  6501. X
  6502. X
  6503. X     HOMEDIR/.report.catmail
  6504. X          Current _c_a_t_m_a_i_l(1) report.
  6505. X
  6506. X     HOMEDIR/.report.daemon
  6507. X          Current _s_e_r_v_e_r_d(1) report.
  6508. X
  6509. X     HOMEDIR/.report.list
  6510. X          Error messages from _l_i_s_t(1).
  6511. X
  6512. X     HOMEDIR/.report.server
  6513. X          Current _l_i_s_t_s_e_r_v(1) report.
  6514. X
  6515. X     HOMEDIR/.report.start
  6516. X          Last _s_t_a_r_t(1) action (system started or shut down).
  6517. X
  6518. X     HOMEDIR/.stats
  6519. X          Script used for the _s_t_a_t_i_s_t_i_c_s request.
  6520. X
  6521. X     HOMEDIR/.tag.id
  6522. X          Next id to be assigned to next moderated message.
  6523. X
  6524. X     HOMEDIR/.warning
  6525. X          Log of system calls' exit statuses.
  6526. X
  6527. X     HOMEDIR/batch
  6528. X          Batched user requests.
  6529. X
  6530. X     HOMEDIR/catmail
  6531. X          Incoming message redirection application.
  6532. X
  6533. X     HOMEDIR/config
  6534. X          The configuration file.
  6535. X
  6536. X     HOMEDIR/farch
  6537. X          File archiving utility.
  6538. X
  6539. X     HOMEDIR/iul
  6540. X          Interactive UNIX ListServer client; to be used to  con-
  6541. X          nect to the interactive part of the system.
  6542. X
  6543. X     HOMEDIR/list
  6544. X          The mailing list program.
  6545. X
  6546. X     HOMEDIR/listserv
  6547. X          The system's request server.
  6548. X
  6549. X     HOMEDIR/lost+found
  6550. X          Requests   that    could    not    be    appended    to
  6551. X          HOMEDIR/requests.
  6552. X
  6553. X     HOMEDIR/mbox
  6554. X          An archive of all requests sent to date to ListServer.
  6555. X
  6556. X
  6557. X
  6558. XAnastasios Kotsikonas                                              16
  6559. X
  6560. X
  6561. X
  6562. X
  6563. X
  6564. X
  6565. Xserver(1)                USER COMMANDS                  server(1)
  6566. X
  6567. X
  6568. X
  6569. X     HOMEDIR/news
  6570. X          Script used to add a news group to a list.
  6571. X
  6572. X     HOMEDIR/owners
  6573. X          List of list owners' addresses used for  authentication
  6574. X          of list maintenance requests.
  6575. X
  6576. X     HOMEDIR/peer
  6577. X          Script used to add a peer list.
  6578. X
  6579. X     HOMEDIR/pqueue
  6580. X          The mail queue processing program (see _q_u_e_u_e(_1)).
  6581. X
  6582. X     HOMEDIR/priv.hosts
  6583. X          List of hosts that may connect to the interactive  part
  6584. X          of the system.
  6585. X
  6586. X     HOMEDIR/queued
  6587. X          The mail queue processing daemon (see _q_u_e_u_e(_1)).
  6588. X
  6589. X     HOMEDIR/received
  6590. X          File containing the  messages  received  from  sendmail
  6591. X          during  the  last  message  distribution  -- the _s_y_s_t_e_m
  6592. X          mailmethod has to be in use.
  6593. X
  6594. X     HOMEDIR/requests
  6595. X          Newly arrived user requests.
  6596. X
  6597. X     HOMEDIR/requests.live
  6598. X          Repository for requests coming  in  from  live  connec-
  6599. X          tions.
  6600. X
  6601. X     HOMEDIR/sent
  6602. X          File containing the messages sent  to  sendmail  during
  6603. X          the  last message distribution -- the _s_y_s_t_e_m mailmethod
  6604. X          has to be in use.
  6605. X
  6606. X     HOMEDIR/serverd
  6607. X          The system's daemon.
  6608. X
  6609. X     HOMEDIR/setup
  6610. X          System setup script.
  6611. X
  6612. X     HOMEDIR/start
  6613. X          The system's housekeeping program.
  6614. X
  6615. X     HOMEDIR/tlock
  6616. X          Checks for any locked files.
  6617. X
  6618. X     HOMEDIR/ulock
  6619. X          Script to remove all lock files.
  6620. X
  6621. X
  6622. X
  6623. X
  6624. XAnastasios Kotsikonas                                              17
  6625. X
  6626. X
  6627. X
  6628. X
  6629. X
  6630. X
  6631. Xserver(1)                USER COMMANDS                  server(1)
  6632. X
  6633. X
  6634. X
  6635. X     HOMEDIR/unwanted.hosts
  6636. X          List of hosts that may not connect to  the  interactive
  6637. X          part of the system.
  6638. X
  6639. X     HOMEDIR/welcome.live
  6640. X          Welcoming message upon live connection establishment.
  6641. X
  6642. X     HOMEDIR/archives/listserver/DIR
  6643. X          Directory  of  all  files  available  from  the  master
  6644. X          archive (listserver).
  6645. X
  6646. X     HOMEDIR/archives/listserver/INDEX
  6647. X          The master archive index.
  6648. X
  6649. X     HOMEDIR/doc/catmail.1
  6650. X          Man page source for _c_a_t_m_a_i_l(1).
  6651. X
  6652. X     HOMEDIR/doc/catmail.nr
  6653. X          Formatted man page for _c_a_t_m_a_i_l(1).
  6654. X
  6655. X     HOMEDIR/doc/farch.1
  6656. X          Man page source for the _f_a_r_c_h(1) utility.
  6657. X
  6658. X     HOMEDIR/doc/farch.nr
  6659. X          Formatted man page for the _f_a_r_c_h(1) utility.
  6660. X
  6661. X     HOMEDIR/doc/iul.1
  6662. X          Man page source for the _i_u_l(1) utility.
  6663. X
  6664. X     HOMEDIR/doc/iul.nr
  6665. X          Formatted man page for _i_u_l(1).
  6666. X
  6667. X     HOMEDIR/doc/list.1
  6668. X          Man page source for _l_i_s_t(1).
  6669. X
  6670. X     HOMEDIR/doc/list.nr
  6671. X          Formatted man page for _l_i_s_t(1).
  6672. X
  6673. X     HOMEDIR/doc/listserv.1
  6674. X          Man page source for _l_i_s_t_s_e_r_v(1).
  6675. X
  6676. X     HOMEDIR/doc/listserv.nr
  6677. X          Formatted man page for _l_i_s_t_s_e_r_v(1).
  6678. X
  6679. X     HOMEDIR/doc/queue.1
  6680. X          Man page source for _p_q_u_e_u_e and _q_u_e_u_e_d(1).
  6681. X
  6682. X     HOMEDIR/doc/queue.nr
  6683. X          Formatted man page for _p_q_u_e_u_e and _q_u_e_u_e_d(1).
  6684. X
  6685. X     HOMEDIR/doc/server.1
  6686. X          Source of the system's main man page.
  6687. X
  6688. X
  6689. X
  6690. XAnastasios Kotsikonas                                              18
  6691. X
  6692. X
  6693. X
  6694. X
  6695. X
  6696. X
  6697. Xserver(1)                USER COMMANDS                  server(1)
  6698. X
  6699. X
  6700. X
  6701. X     HOMEDIR/doc/server.nr
  6702. X          Formatted main man page.
  6703. X
  6704. X     HOMEDIR/doc/serverd.1
  6705. X          Man page source for _s_e_r_v_e_r_d(1).
  6706. X
  6707. X     HOMEDIR/doc/serverd.nr
  6708. X          Formatted man page for _s_e_r_v_e_r_d(1).
  6709. X
  6710. X     HOMEDIR/doc/start.1
  6711. X          Man page source for _s_t_a_r_t(1).
  6712. X
  6713. X     HOMEDIR/doc/start.nr
  6714. X          Formatted man page for _s_t_a_r_t(1).
  6715. X
  6716. X     HOMEDIR/help/*
  6717. X          General and topic-specific help files available upon  a
  6718. X          _h_e_l_p request. The TOPICS is a special file where topics
  6719. X          are defined.
  6720. X
  6721. X     HOMEDIR/lists/LIST_ALIAS/.aliases
  6722. X          Aliases of email addresses of subscribers.
  6723. X
  6724. X     HOMEDIR/lists/LIST_ALIAS/.digest.toc
  6725. X          All the subject lines from the digest. It will be writ-
  6726. X          ten at the head of the digest when it is sent.
  6727. X
  6728. X     HOMEDIR/lists/LIST_ALIAS/.digest.msg
  6729. X          All the messages of the  digest,  separated  by  dashed
  6730. X          lines.
  6731. X
  6732. X     HOMEDIR/lists/LIST_ALIAS/.digest.time
  6733. X          The time that the last digest was sent, represented  as
  6734. X          the  value returned by time(2). It is used to calculate
  6735. X          when it is time to send out the next digest.
  6736. X
  6737. X     HOMEDIR/lists/LIST_ALIAS/.headers
  6738. X          An archive of  who  sent  each  message;  used  upon  a
  6739. X          _s_t_a_t_i_s_t_i_c_s request.
  6740. X
  6741. X     HOMEDIR/lists/LIST_ALIAS/.ignored
  6742. X          A list of unwanted senders.
  6743. X
  6744. X     HOMEDIR/lists/LIST_ALIAS/.info
  6745. X          Text sent upon an _i_n_f_o_r_m_a_t_i_o_n request.
  6746. X
  6747. X     HOMEDIR/lists/LIST_ALIAS/.limits
  6748. X          Used by _s_e_r_v_e_r_d(1) when placing various limits for  the
  6749. X          list.
  6750. X
  6751. X     HOMEDIR/lists/LIST_ALIAS/.message.ids
  6752. X          A database of recent message id's used to  detect  mail
  6753. X
  6754. X
  6755. X
  6756. XAnastasios Kotsikonas                                              19
  6757. X
  6758. X
  6759. X
  6760. X
  6761. X
  6762. X
  6763. Xserver(1)                USER COMMANDS                  server(1)
  6764. X
  6765. X
  6766. X
  6767. X          loops.
  6768. X
  6769. X     HOMEDIR/lists/LIST_ALIAS/.news
  6770. X          A list of all news groups connected to this list.
  6771. X
  6772. X     HOMEDIR/lists/LIST_ALIAS/.peers
  6773. X          A list of all peer lists for this mailing  list,  along
  6774. X          with the email addresses of their servers.
  6775. X
  6776. X     HOMEDIR/lists/LIST_ALIAS/.rep.list.acc
  6777. X          Archived reports from _l_i_s_t(1).
  6778. X
  6779. X     HOMEDIR/lists/LIST_ALIAS/.report.list
  6780. X          Current report from _l_i_s_t(1).
  6781. X
  6782. X     HOMEDIR/lists/LIST_ALIAS/.restricted
  6783. X          List of subscribers with alternate recipient files.
  6784. X
  6785. X     HOMEDIR/lists/LIST_ALIAS/.subscribers
  6786. X          A list of all subscribers along  with  preferences  and
  6787. X          settings.
  6788. X
  6789. X     HOMEDIR/lists/LIST_ALIAS/.un.digest
  6790. X          When a digest is constructed, it will be stored in this
  6791. X          file until it has been sent to all digest subscribers.
  6792. X
  6793. X     HOMEDIR/lists/LIST_ALIAS/.welcome
  6794. X          Text sent on a _s_u_b_s_c_r_i_b_e request.
  6795. X
  6796. X     HOMEDIR/lists/LIST_ALIAS/archive
  6797. X          Archive of all distributed messages since the file  was
  6798. X          last created.
  6799. X
  6800. X     HOMEDIR/lists/LIST_ALIAS/lost+found
  6801. X          Mail that could  not  be  appended  to  the  'mail'  or
  6802. X          'moderated' files (see next entries and _c_a_t_m_a_i_l(1)).
  6803. X
  6804. X     HOMEDIR/lists/LIST_ALIAS/mail
  6805. X          Newly arrived public messages to be distributed.
  6806. X
  6807. X     HOMEDIR/lists/LIST_ALIAS/mbox
  6808. X          An archive of all messages sent to date.
  6809. X
  6810. X     HOMEDIR/lists/LIST_ALIAS/moderated
  6811. X          Newly arrived public messages that need  to  be  edited
  6812. X          before distributed.
  6813. X
  6814. X     HOMEDIR/lists/LIST_ALIAS/removed.users
  6815. X          Entries from the .subscribers file for users  who  have
  6816. X          been automatically removed from the list.
  6817. X
  6818. X     HOMEDIR/lists/LIST_ALIAS/removed.alias
  6819. X
  6820. X
  6821. X
  6822. XAnastasios Kotsikonas                                              20
  6823. X
  6824. X
  6825. X
  6826. X
  6827. X
  6828. X
  6829. Xserver(1)                USER COMMANDS                  server(1)
  6830. X
  6831. X
  6832. X
  6833. X          Entries from the .aliases file for users who have  been
  6834. X          automatically removed from the list.
  6835. X
  6836. X     HOMEDIR/mqueue/*
  6837. X          Queued messages for later delivery.
  6838. X
  6839. XUUUUPPPPGGGGRRRRAAAADDDDIIIINNNNGGGG
  6840. X     When upgrading, it is not necessary to remove  your  current
  6841. X     system.   Old  key directories and files will be moved else-
  6842. X     where. Always run the _s_e_t_u_p script. In addition, if you  are
  6843. X     upgrading from:
  6844. X
  6845. X     5.5  The system may now go interactive with the -i  flag  to
  6846. X          _s_e_r_v_e_r_d(1).
  6847. X
  6848. X          _r_e_m_o_t_e lists may now specify  host  names  or  Internet
  6849. X          addresses  and  ports if they are served by interactive
  6850. X          UNIX ListServers.
  6851. X
  6852. X          The ULISTSERVER_UMASK environment variable is now used.
  6853. X
  6854. X          The IUL (_i_u_l(_1)) client  is  available  to  connect  to
  6855. X          interactive UNIX ListServers.
  6856. X
  6857. X          The  _h_e_l_p _l_i_v_e  request  explains  how  to  connect  to
  6858. X          interactive UNIX ListServers.
  6859. X
  6860. X          The _p_r_e_c_e_d_e_n_c_e directive has been added to  the  _c_o_n_f_i_g
  6861. X          file.
  6862. X
  6863. X          Precious header lines are preserved for each  list  via
  6864. X          the _h_e_a_d_e_r directive.
  6865. X
  6866. X          Regular expressions are implemented for the  ".aliases"
  6867. X          and ".ignored" files.
  6868. X
  6869. X          Lists may now automaticlly archive distributed messages
  6870. X          via the _a_r_c_h_i_v_e directive.
  6871. X
  6872. X          The manager may allow subscribers of a list to  execute
  6873. X          UNIX  commands via the _u_n_i_x__c_m_d directive. Users submit
  6874. X          a _r_u_n request in this case (CCRUN is added as a prefer-
  6875. X          ence).
  6876. X
  6877. X          _f_a_r_c_h now creates new archives and takes care of updat-
  6878. X          ing  and creating DIR and INDEX files as well as direc-
  6879. X          tories, and may archive true  binary  files  (does  not
  6880. X          uuencode  them)  if  requested (-B flag); the -p option
  6881. X          was introduced to accept a password for a  new  private
  6882. X          archive,  the  -D option to specify a short description
  6883. X          of the files, and the -r option to  remove  files  from
  6884. X          archives.
  6885. X
  6886. X
  6887. X
  6888. XAnastasios Kotsikonas                                              21
  6889. X
  6890. X
  6891. X
  6892. X
  6893. X
  6894. X
  6895. Xserver(1)                USER COMMANDS                  server(1)
  6896. X
  6897. X
  6898. X
  6899. X          Commands in the _c_o_n_f_i_g file may span multiple lines  if
  6900. X          each line is terminated by &\n.
  6901. X
  6902. X          The system intercepts requests sent to lists.
  6903. X
  6904. X          The _c_o_n_c_e_a_l user attribute has been introduced  to  the
  6905. X          subscribers files.
  6906. X
  6907. X          The _d_e_f_a_u_l_t directive has been introduced to the _c_o_n_f_i_g
  6908. X          file to set default values for new subscribers.
  6909. X
  6910. X          Users may change the address they are subscribed  with,
  6911. X          if the owner allows this.
  6912. X
  6913. X          The util/ directory has  been  introduced  for  general
  6914. X          utilities.
  6915. X
  6916. X          Help files may now  be  shell  scripts;  same  for  all
  6917. X          lists' ".welcome" and ".info" files.
  6918. X
  6919. X          syslog(3) is now supported for  progress  reporting  by
  6920. X          compiling with -DSYSLOG=facility.
  6921. X
  6922. X          Archive files may be split  on  the  way  out  if  they
  6923. X          exceed the _l_i_m_i_t specified in the _c_o_n_f_i_g file.
  6924. X
  6925. X          Lists may restrict the number of messages processed per
  6926. X          day with the _c_e_i_l_i_n_g directive.
  6927. X
  6928. X          The new request _f_a_x with its synonymous directive  have
  6929. X          been introduced.
  6930. X
  6931. X          Concealed lists are supported  via  the  -c  option  to
  6932. X          _l_i_s_t_s_e_r_v(1).
  6933. X
  6934. X          Error messages from  mailer  daemons  are  scanned  and
  6935. X          automatic   action   is   taken   if   compiling   with
  6936. X          -DERROR_MAIL_ANALYSIS=level (1=conservative, 9=full).
  6937. X
  6938. X          Archives may now be searched with the _s_e_a_r_c_h request.
  6939. X
  6940. X          Run the upgrade_to_6.0 script.
  6941. X
  6942. X     5.41 Moderated lists are now owner controlled,  rather  than
  6943. X          manager controlled.
  6944. X
  6945. X          Manager preferences have now been introduced.
  6946. X
  6947. X          See the UPGRADING section in farch(1).
  6948. X
  6949. X          Follow the upgrade instructions for 5.5
  6950. X
  6951. X
  6952. X
  6953. X
  6954. XAnastasios Kotsikonas                                              22
  6955. X
  6956. X
  6957. X
  6958. X
  6959. X
  6960. X
  6961. Xserver(1)                USER COMMANDS                  server(1)
  6962. X
  6963. X
  6964. X
  6965. X     5.4  _c_a_t_m_a_i_l(1) has been implemented, therefore the  various
  6966. X          aliases  in  the  aliases file have to be redefined (as
  6967. X          explained above) to take advantage.
  6968. X
  6969. X          Owner preferences have been introduced  in  the  _o_w_n_e_r_s
  6970. X          file.
  6971. X
  6972. X          Follow the upgrade instructions for 5.41
  6973. X
  6974. X     5.31 The _l_i_s_t directive in the _c_o_n_f_i_g  file  now  takes  two
  6975. X          extra  arguments:  the  list  owner's  address, and the
  6976. X          list's access password.
  6977. X
  6978. X          _q_u_e_u_e_d now takes only one argument, a frequency count.
  6979. X
  6980. X          The system supports 10 lists by  default  (see  LIMITA-
  6981. X          TIONS  below);  if  you are currently using the maximum
  6982. X          supported    number    of    lists,     consult     the
  6983. X          HOMEDIR/src/defs.h file.
  6984. X
  6985. X          The layout  and  structure  of  INDEX  files  has  been
  6986. X          extended; see _f_a_r_c_h(_1) for more information.
  6987. X
  6988. X          Follow the upgrade instructions for 5.4
  6989. X
  6990. X     5.3  The _l_i_s_t directive in the _c_o_n_f_i_g  file  now  takes  two
  6991. X          extra  arguments:  the  list  owner's  address, and the
  6992. X          list's access password.
  6993. X
  6994. X          The system supports 10 lists by  default  (see  LIMITA-
  6995. X          TIONS  below);  if  you are currently using the maximum
  6996. X          supported    number    of    lists,     consult     the
  6997. X          HOMEDIR/src/defs.h file.
  6998. X
  6999. X          The layout  and  structure  of  INDEX  files  has  been
  7000. X          extended; see _f_a_r_c_h(_1) for more information.
  7001. X
  7002. X          Follow the upgrade instructions for 5.4
  7003. X
  7004. X     5.2  Use the _s_y_s_t_e_m mailmethod.
  7005. X
  7006. X          For     every     list     you     need     to     edit
  7007. X          HOMEDIR/lists/LIST_ALIAS/.ignored   and  add  one  more
  7008. X          entry: the full email address of the server account.
  7009. X
  7010. X          Follow the upgrade instructions for 5.3
  7011. X
  7012. X     5.0, 5.1
  7013. X          For     every     list     you     need     to     edit
  7014. X          HOMEDIR/lists/LIST_ALIAS/.ignored  and add two entries:
  7015. X          the actual list alias, and the full  email  address  of
  7016. X          this list.
  7017. X
  7018. X
  7019. X
  7020. XAnastasios Kotsikonas                                              23
  7021. X
  7022. X
  7023. X
  7024. X
  7025. X
  7026. X
  7027. Xserver(1)                USER COMMANDS                  server(1)
  7028. X
  7029. X
  7030. X
  7031. X          _n_e_v_e_r_a_c_k is not a valid mail mode anymore. Change every
  7032. X          occurrence in ".subscribers" to NOACK, for every list.
  7033. X
  7034. X          Any peer lists and/or news groups appearing  in  ".sub-
  7035. X          scribers"  should  be  removed;  use  the _p_e_e_r and _n_e_w_s
  7036. X          scripts to put them back.
  7037. X
  7038. X          _s_e_r_v_e_r_d, _l_i_s_t and _l_i_s_t_s_e_r_v  no  longer  report  to  the
  7039. X          stdout by default -- use the -e command line option.
  7040. X
  7041. X          Follow the upgrade instructions for 5.2
  7042. X
  7043. XPPPPOOOORRRRTTTT SSSSPPPPEEEECCCCIIIIFFFFIIIICCCC
  7044. X     For various compilation options, consult  the  src/Makefile.
  7045. X     Starting with version 5.3, a universal mailmethod was intro-
  7046. X     duced: _s_y_s_t_e_m; It should be used in every  system  that  has
  7047. X     TCP/IP  installed,  as  it has been verified to work on many
  7048. X     systems below -- consult the src/README file.
  7049. X
  7050. X     IBM Risc
  7051. X          You should use _s_y_s_v__p_s as an option in the _c_o_n_f_i_g file,
  7052. X          and  compile with xlc -D_ALL_SOURCE -qnoro. You have to
  7053. X          use _s_y_s_t_e_m as the mailmethod.  Messages distributed  to
  7054. X          local  subscribers on the system may see their messages
  7055. X          arrive "From root...", but all other subscribers in the
  7056. X          outside  world  will  see "From listserver@..."  and/or
  7057. X          "From list@..." which is the correct header. If you use
  7058. X          _e_n_v__v_a_r _L_O_G_N_A_M_E /_b_i_n/_r_m_a_i_l  instead,  the behavior will
  7059. X          be reversed.  _t_e_l_n_e_t may not be used as  a  mailmethod.
  7060. X          Compile   with   -DHAVE_SELECT_H,  -DHAVE_ULIMIT_H  and
  7061. X          -DHAVE_SETJMP_H, and link with -lbsd.   In  defs.h  the
  7062. X          system is defined as having an SVR3 flavor.
  7063. X
  7064. X     SGI  You have to use the _s_y_s_t_e_m mailmethod.  All  Irix  ver-
  7065. X          sions  to date seem to have a serious problem with tel-
  7066. X          net (it corrupts file  descriptors).  Use  the  _s_y_s_v__p_s
  7067. X          option.   In  the  Makefile, define the symbol CC to be
  7068. X          'cc  -ansi'  or  'cc  -D__STDC__',  and  compile   with
  7069. X          -DHAVE_SETJMP_H  and  -D_POSIX_SOURCE.   In  defs.h the
  7070. X          system is defined as having an SVR3 flavor.
  7071. X
  7072. X     SUN  _s_y_s_t_e_m and _t_e_l_n_e_t work fine as  mailmethods.   Use  the
  7073. X          _b_s_d__p_s  option.  The  server  user id should not be the
  7074. X          same as root's.  If you use the native cc compiler  you
  7075. X          will  need  to  convert  to K&R C (by using the unproto
  7076. X          system  --   consult   the   src/Makefile);   otherwise
  7077. X          /usr/lang/acc  -w  (ANSI  C)  can be used. Compile with
  7078. X          -DHAVE_SETJMP_H.  In defs.h the system  is  defined  as
  7079. X          having  a  BSD flavor. On Solaris, compile with -Dsvr4.
  7080. X          If using the live part of the system and your host is a
  7081. X          YP/NIS  client  you  should  put the new service in the
  7082. X          master's services map, or if on the master, remake  the
  7083. X
  7084. X
  7085. X
  7086. XAnastasios Kotsikonas                                              24
  7087. X
  7088. X
  7089. X
  7090. X
  7091. X
  7092. X
  7093. Xserver(1)                USER COMMANDS                  server(1)
  7094. X
  7095. X
  7096. X
  7097. X          map.  Older  versions of SUNOS have problems with their
  7098. X          include files, and in this case you have to comment out
  7099. X          the line:
  7100. X
  7101. X          #include <netdb.h>
  7102. X
  7103. X          in src/*.c
  7104. X
  7105. X     DECstations
  7106. X          You have to use _s_y_s_t_e_m as the mailmethod;  if  you  use
  7107. X          _t_e_l_n_e_t  instead,  you  may  have  to use the _b_a_d__t_e_l_n_e_t
  7108. X          option; _b_s_d__p_s should be used. Ultrix 3.0 has  lots  of
  7109. X          system  bugs  and  you may experience strange behavior;
  7110. X          the file locking mechanism over NFS appears to be  non-
  7111. X          standard and is disabled by default; upgrade to 4.2A is
  7112. X          recommended.  An ANSI C compiler should be used. If you
  7113. X          are using the unproto system, use the -nocpp flag to cc
  7114. X          when  compiling.  Compile  with  -DHAVE_SETJMP_H.    In
  7115. X          defs.h  the  system  is defined as having a BSD flavor.
  7116. X          All Bourne shell scripts may  need  to  be  altered  to
  7117. X          invoke /bin/sh5, before they are used.
  7118. X
  7119. X     Convex
  7120. X          It is suggested that you use the _s_t_d_s script (available
  7121. X          via anonymous ftp from cs.bu.edu) and the non-ANSI com-
  7122. X          piler; _s_t_d_s should be used as follows:
  7123. X
  7124. X          stds src/nonansi/*.h src/*.c
  7125. X
  7126. X          This should be done after redefining the HOMEDIR  entry
  7127. X          in  src/Makefile  and  running  setup  to  make all the
  7128. X          necessary changes. Compiling under ANSI standards (-std
  7129. X          flag)  is  not  recommended, since system include files
  7130. X          are not ANSI-C compliant. The system cannot go interac-
  7131. X          tive since the system does not support semaphores. _s_y_s_-
  7132. X          _t_e_m works fine as a mailmethod. _p_a_s_t_e(_1) is missing and
  7133. X          _s_t_a_t_i_s_t_i_c_s requests will look erroneous.
  7134. X
  7135. X     Stardent GS series
  7136. X          _s_y_s_t_e_m and _t_e_l_n_e_t work fine as  mailmethods.   Use  the
  7137. X          _s_y_s_v__p_s option. The unproto system has to be used (con-
  7138. X          sult the src/Makefile) if not using an ANSI C compiler.
  7139. X          The system cannot go interactive due to a system() bug.
  7140. X          In defs.h the system is defined as having an SVR3  fla-
  7141. X          vor.
  7142. X
  7143. X     Stardent/KPC Titan series
  7144. X          _s_y_s_t_e_m  and  _e_n_v__v_a_r _L_O_G_N_A_M_E /_b_i_n/_r_m_a_i_l  work  fine  as
  7145. X          mailmethods.  Use the _s_y_s_v__p_s option. The system cannot
  7146. X          go interactive due to the  absence  of  waitpid(),  and
  7147. X          compiling  and  linking with -43 (to use wait3()) hangs
  7148. X          _s_e_r_v_e_r_d(_1) and the other applications.  In  defs.h  the
  7149. X
  7150. X
  7151. X
  7152. XAnastasios Kotsikonas                                              25
  7153. X
  7154. X
  7155. X
  7156. X
  7157. X
  7158. X
  7159. Xserver(1)                USER COMMANDS                  server(1)
  7160. X
  7161. X
  7162. X
  7163. X          system is defined as having an SVR3 flavor.
  7164. X
  7165. X     NeXT _t_e_l_n_e_t, _s_e_n_d_m_a_i_l, _s_y_s_t_e_m (if TCP/IP  is  installed  and
  7166. X          SMTP is used) work fine as mailmethods; however, 'mail-
  7167. X          method sendmail /usr/lib/sendmail -ba' has been charac-
  7168. X          terized  as  a  "DISASTER in terms of hogging the cpu."
  7169. X          Compile with  -D__NeXT__  if  your  compiler  does  not
  7170. X          define  this  symbol  (under version 3.0 of the OS this
  7171. X          symbol is automatically defined -- 3.0 is the only sup-
  7172. X          ported  environment).  Compile  with -I/usr/include/bsd
  7173. X          and -I/usr/include/bsd/sys.  File locking is turned off
  7174. X          because  of an OS bug.  In defs.h the system is defined
  7175. X          as having a BSD flavor. The system cannot  go  interac-
  7176. X          tive due to lack of semaphore support.
  7177. X
  7178. X     HP-UX
  7179. X          Compile  with  -Aa,  -D_HPUX_SOURCE,   -DHAVE_ULIMIT_H,
  7180. X          -DHAVE_SETJMP_H.   _s_y_s_t_e_m is the mailmethod to use.  In
  7181. X          defs.h the system is defined as having a BSD flavor.
  7182. X
  7183. X     SCO  Compile    with     -Dsco     and     possibly     with
  7184. X          -I/usr/include/netinet.   You  may  wish to link with a
  7185. X          special libbsd.a which can be obtained  from  /pub/sco-
  7186. X          ports/libbsd  on dribble.c-mols.siu.edu (131.230.93.2).
  7187. X          You need to link with -lsocket.  In defs.h  the  system
  7188. X          is  defined as having an SVR3 flavor. The port was done
  7189. X          under SCO version 3.2.4. The interactive part seems  to
  7190. X          hang for no apparent reason.
  7191. X
  7192. X     Apollo
  7193. X          Use the _s_y_s_t_e_m mailmethod. Do not compile with -A ansi,
  7194. X          or  if  you  do also compile with -Dapollo. The OS that
  7195. X          the port was performed under was SR10.4 and version 6.8
  7196. X          of   cc.   The   server   id's   path   should  include
  7197. X          /sys5.3/usr/bin so that 'paste' may be found. In defs.h
  7198. X          the  system is defined as having a BSD flavor. The sys-
  7199. X          tem cannot go interactive due to lack of semaphore sup-
  7200. X          port.
  7201. X
  7202. X     Xenix
  7203. X          Compile with -Dxenix; grep(1) is buggy and is suggested
  7204. X          that  another  version is used. In defs.h the system is
  7205. X          defined as having an SVR3 flavor.
  7206. X
  7207. X     Sequent
  7208. X          Compile with gcc -fwritable-strings  and  -Dsequent  if
  7209. X          the compiler does not define this symbol. In defs.h the
  7210. X          system is given a BSD flavor. If under Dynix/PTX,  com-
  7211. X          pile  with -Dsvr3 (PTX is a a System V R3.2 implementa-
  7212. X          tion; V2.0.3 includes an ANSI C compiler).
  7213. X
  7214. X     Data General
  7215. X
  7216. X
  7217. X
  7218. XAnastasios Kotsikonas                                              26
  7219. X
  7220. X
  7221. X
  7222. X
  7223. X
  7224. X
  7225. Xserver(1)                USER COMMANDS                  server(1)
  7226. X
  7227. X
  7228. X
  7229. X          Compile using gcc  -fwritable-strings;  in  defs.h  the
  7230. X          system  is given an SVR4 flavor and is advisable not to
  7231. X          give it a BSD one; keep in mind that signals frequently
  7232. X          get lost.
  7233. X
  7234. X     i860 This is a standard SVR4.2 UNIX; _s_y_s_t_e_m  works  fine  as
  7235. X          mailmethod. All features are functional.
  7236. X
  7237. X     i386 This  is  a  BSD  environment;  the  system  cannot  go
  7238. X          interactive  due to lack of semaphore support, and file
  7239. X          locking is turned off. _s_y_s_t_e_m works fine as mailmethod.
  7240. X          Compile with the -fwritable-strings flag.
  7241. X
  7242. X     OSF  This is a standard SVR3  UNIX;  _s_y_s_t_e_m  works  fine  as
  7243. X          mailmethod.  All  features are functional. Compile with
  7244. X          the -std1 flag. Do  not  compile  with  -DHAVE_SELECT_H
  7245. X          because of missing system header files.
  7246. X
  7247. X     Other
  7248. X          First, attempt compiling with -Dunknown_port.
  7249. X
  7250. XLLLLIIIIMMMMIIIITTTTAAAATTTTIIIIOOOONNNNSSSS
  7251. X     - Up to 10 mailing lists can be supported  (configurable  in
  7252. X     src/defs.h and src/Makefile).
  7253. X
  7254. X     - The system assumes a length of 32 bits or higher for  long
  7255. X     integers.
  7256. X
  7257. X     - A list alias may not be called "server".
  7258. X
  7259. XCCCCOOOOMMMMPPPPIIIILLLLEEEERRRR
  7260. X     gcc  If you are using gcc to compile,  use  the  -fwritable-
  7261. X          strings  flag.  Versions prior to 2.2.1 may cause prob-
  7262. X          lems.
  7263. X
  7264. XMMMMAAAAIIIILLLLEEEERRRR
  7265. X     Zmailer
  7266. X          If you are using the Zmailer to send mail, or any other
  7267. X          mailer  (like Smail) that requires a 'HELO hostname' to
  7268. X          start the  SMTP  transaction,  compile  with  -DZMAILER
  7269. X          (also see src/README and src/Makefile).
  7270. X
  7271. XRRRREEEEQQQQUUUUIIIIRRRREEEEMMMMEEEENNNNTTTTSSSS
  7272. X     The $path for the server account should include  all  neces-
  7273. X     sary  paths  to cut(1), paste(1), awk(1), grep(1), uptime(1)
  7274. X     and telnet(1).  In addition,  uptime(1)  should  report  the
  7275. X     number  of  users  and the system load; otherwise _s_e_r_v_e_r_d(1)
  7276. X     cannot be run with the -l option, and _l_i_s_t_s_e_r_v(1) cannot  be
  7277. X     run  with  the -r option. The output from uptime should look
  7278. X     like:
  7279. X
  7280. X     12:45pm up 5 days, 16 mins, 4 users, load average: 0.00, ...
  7281. X
  7282. X
  7283. X
  7284. XAnastasios Kotsikonas                                              27
  7285. X
  7286. X
  7287. X
  7288. X
  7289. X
  7290. X
  7291. Xserver(1)                USER COMMANDS                  server(1)
  7292. X
  7293. X
  7294. X
  7295. X     Also,  make  sure  that  when  posting,  /usr/lib/news/_i_n_e_w_s
  7296. X     exists  either  as  itself  or  as  a link to wherever _i_n_e_w_s
  7297. X     resides (also see src/Makefile).
  7298. X
  7299. X     Finally, grep(1) should support  the  -i  (case  insensitive
  7300. X     matching)  and  -v  (print  all  lines that do not match the
  7301. X     expression) flags.
  7302. X
  7303. XBBBBUUUUGGGGSSSS
  7304. X     uptime
  7305. X          When user and load restrictions are enforced, the  sys-
  7306. X          tem  assumes  that uptime outputs a line similar to the
  7307. X          one shown above, in which the number of  users  is  the
  7308. X          third  column (columns are separated by commas) and the
  7309. X          load average is the fourth column. The problem is  that
  7310. X          on  a  system  that  has been up for less than one day,
  7311. X          uptime will report the number of users  in  the  second
  7312. X          column,  and  the  load average in the third column. In
  7313. X          this case, such restrictions should not be enforced.
  7314. X
  7315. X     blanks
  7316. X          Although the system handles email addresses with blanks
  7317. X          in   them   fairly  well,  _s_t_a_t_i_s_t_i_c_s,  _r_e_c_i_p_i_e_n_t_s  and
  7318. X          _s_e_t _l_i_s_t (status query) requests  will  show  erroneous
  7319. X          results for these users.
  7320. X
  7321. X     special characters
  7322. X          The system does not accept addresses that contain  sin-
  7323. X          gle quotes, back-quotes or wild characters.
  7324. X
  7325. X     messages exceeding limits not caught
  7326. X          When all subscribers of a list have set their mail mode
  7327. X          to  _d_i_g_e_s_t,  messages  are  not subject to size limita-
  7328. X          tions.
  7329. X
  7330. X     no _s_t_a_t_i_s_t_i_c_s request for NeXT 2.1 hosts
  7331. X          Due to the absense of _c_u_t(_1) the ._s_t_a_t_s script  has  to
  7332. X          be modified to replace the use of _c_u_t(_1) with _a_w_k(_1).
  7333. X
  7334. X     _s_e_r_v_e_r_d(1) dies with 'no tty' error message
  7335. X          In the _c_o_n_f_i_g file use the -e flag in the _l_i_s_t,  _s_e_r_v_e_r
  7336. X          and _s_e_r_v_e_r_d definitions followed by '> /dev/null 2>&1'.
  7337. X          For example:
  7338. X
  7339. X                    serverd -i 600 -e > /dev/null 2>&1
  7340. X
  7341. X     incorrect auto-splitting of files on the way out
  7342. X          When splitting files that exceed the  specified  limit,
  7343. X          the  system  precalculates  the number of parts it will
  7344. X          send and puts this number in the Subject:  line.   How-
  7345. X          ever,  since  each  part may actually be less than that
  7346. X          limit (each part extends to the nearest newline without
  7347. X
  7348. X
  7349. X
  7350. XAnastasios Kotsikonas                                              28
  7351. X
  7352. X
  7353. X
  7354. X
  7355. X
  7356. X
  7357. Xserver(1)                USER COMMANDS                  server(1)
  7358. X
  7359. X
  7360. X
  7361. X          exceeding  the limit) it is possible to send more parts
  7362. X          than predicted, if the  total  number  of  bytes  back-
  7363. X          tracked  (for  all parts) is an integer multiple of the
  7364. X          limit; in this case the number of extra parts  will  be
  7365. X          this  integer multiple. The probability of this happen-
  7366. X          ing increases as the limit is decreased.
  7367. X
  7368. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  7369. X     catmail(1),   farch(1),   iul(1),   list(1),    listserv(1),
  7370. X     queue(1), serverd(1), start(1)
  7371. X
  7372. XAAAAUUUUTTTTHHHHOOOORRRR
  7373. X     Anastasios C. Kotsikonas
  7374. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  7375. X     Comments to tasos@cs.bu.edu
  7376. X
  7377. X
  7378. X
  7379. X
  7380. X
  7381. X
  7382. X
  7383. X
  7384. X
  7385. X
  7386. X
  7387. X
  7388. X
  7389. X
  7390. X
  7391. X
  7392. X
  7393. X
  7394. X
  7395. X
  7396. X
  7397. X
  7398. X
  7399. X
  7400. X
  7401. X
  7402. X
  7403. X
  7404. X
  7405. X
  7406. X
  7407. X
  7408. X
  7409. X
  7410. X
  7411. X
  7412. X
  7413. X
  7414. X
  7415. X
  7416. XAnastasios Kotsikonas                                              29
  7417. X
  7418. X
  7419. X
  7420. *-*-END-of-doc/server.nr-*-*
  7421. echo x - doc/serverd.nr
  7422. sed 's/^X//' >doc/serverd.nr <<'*-*-END-of-doc/serverd.nr-*-*'
  7423. X
  7424. X
  7425. X
  7426. Xserverd(1)               USER COMMANDS                 serverd(1)
  7427. X
  7428. X
  7429. X
  7430. XNNNNAAAAMMMMEEEE
  7431. X     sssseeeerrrrvvvveeeerrrrdddd - UNIX ListServer system daemon
  7432. X
  7433. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  7434. X     sssseeeerrrrvvvveeeerrrrdddd [----1111] [----eeee] [----llll llllooooaaaadddd] [----iiii dddduuuurrrraaaattttiiiioooonnnn]
  7435. X
  7436. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN::::
  7437. X     _s_e_r_v_e_r_d silently looks for any new messages for the  request
  7438. X     server  and  for  any of the supported mailing lists, checks
  7439. X     whether the time has arrived for processing the batch queue,
  7440. X     whether  digest time has been reached for the various lists,
  7441. X     and whether any live TCP/IP connections  are  requested.  It
  7442. X     then  spawns  _l_i_s_t_s_e_r_v(1)  and/or  _l_i_s_t(1) as necessary, and
  7443. X     sleeps until the  message(s)  is  (are)  processed.  _s_e_r_v_e_r_d
  7444. X     reads the _c_o_n_f_i_g file (see _s_e_r_v_e_r(1)).
  7445. X
  7446. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  7447. X     The following command line options are recognized:
  7448. X
  7449. X     -1   Execute only once -- to be used with cron(1).
  7450. X
  7451. X     -e   Echo reports to the screen; it has  no  effect  if  the
  7452. X          system has been compiled with -DSYSLOG.
  7453. X
  7454. X     -l load
  7455. X          Enforce load restrictions; _s_e_r_v_e_r_d will postpone spawn-
  7456. X          ing if the system load is above the limit specified.
  7457. X
  7458. X     -i duration
  7459. X          A child process is also spawned which listens for  live
  7460. X          TCP/IP  connections at port 372 (this is referred to as
  7461. X          the Listsener process, and its parent as  the  Master);
  7462. X          for  each such connection a child process is created to
  7463. X          process     the     live     requests     (see      the
  7464. X          INTERACTIVE LISTSERVER   section  below).  The  maximum
  7465. X          _d_u_r_a_t_i_o_n time is given in seconds.
  7466. X
  7467. XIIIINNNNTTTTEEEERRRRAAAACCCCTTTTIIIIVVVVEEEE LLLLIIIISSSSTTTTSSSSEEEERRRRVVVVEEEERRRR
  7468. X     Provided that the host supports  the  TCP/IP  protocol,  the
  7469. X     system  provides a mechanism for processing live requests by
  7470. X     specifying the -i flag to _s_e_r_v_e_r_d. Any  user  may  use  _t_e_l_-
  7471. X     _n_e_t(_1)  to  connect  to a host that runs this system at port
  7472. X     number 372, issue requests as he would by email, and receive
  7473. X     responses immediately. However, the proper way to connect to
  7474. X     the server is by using _i_u_l(_1) which lets the  user  download
  7475. X     files  through _g_e_t requests, and provides other amenities as
  7476. X     well.
  7477. X
  7478. X     What requests are allowed depends on the privileges assigned
  7479. X     upon  login: the user is asked for an email address (default
  7480. X     is no email address); then a password should be provided. If
  7481. X     the  user  needs  manager privileges, he has to provide both
  7482. X
  7483. X
  7484. X
  7485. XAnastasios Kotsikonas                                               1
  7486. X
  7487. X
  7488. X
  7489. X
  7490. X
  7491. X
  7492. Xserverd(1)               USER COMMANDS                 serverd(1)
  7493. X
  7494. X
  7495. X
  7496. X     the manager's email address and  the  system's  password  as
  7497. X     they   appear  in  the  _c_o_n_f_i_g  file.  If  he  wishes  owner
  7498. X     privileges, he has to provide both his email address  as  it
  7499. X     appears  in  the  _o_w_n_e_r_s  file and his list's password as it
  7500. X     appears in the _c_o_n_f_i_g file. To gain subscriber privileges he
  7501. X     has  to  provide his email address as subscribed to the list
  7502. X     where privileges are to be granted to, as well as the  pass-
  7503. X     word _s_e_t for that list.
  7504. X
  7505. X     A mismatch or no  email  address  reduces  privileges  to  a
  7506. X     minimum.  These  are  restricted to _h_e_l_p, _i_n_f_o_r_m_a_t_i_o_n, _r_e_c_i_-
  7507. X     _p_i_e_n_t_s and _s_t_a_t_i_s_t_i_c_s for nonprivate  lists,  _l_i_s_t_s,  _i_n_d_e_x,
  7508. X     _g_e_t,  _r_u_n and _r_e_l_e_a_s_e requests. Subscriber privileges extend
  7509. X     these to _s_e_t, _r_u_n, _u_n_s_u_b_s_c_r_i_b_e and _w_h_i_c_h  requests.   Owners
  7510. X     are  granted permission to also issue _s_y_s_t_e_m, _r_e_p_o_r_t_s, _e_d_i_t,
  7511. X     _p_u_t, _a_p_p_r_o_v_e and _d_i_s_c_a_r_d requests in addition  to  the  ones
  7512. X     above.  Finally,  the  _m_a_n_a_g_e_r  may issue any request except
  7513. X     _e_x_e_c_u_t_e.
  7514. X
  7515. X     Requests for remote lists are serviced by attempting to con-
  7516. X     nect to the remote servers serving these lists.
  7517. X
  7518. X     The system may restrict connections to certain hosts, and/or
  7519. X     reject  connections  from  certain  hosts. First, the system
  7520. X     looks for the file _p_r_i_v._h_o_s_t_s which lists  hostnames  and/or
  7521. X     IP  addresses  that are allowed access; only hosts listed in
  7522. X     this file are granted acces. For example, to allow access to
  7523. X     hosts on one's local network only, one could do:
  7524. X
  7525. X                 ln -s /etc/hosts HOMEDIR/priv.hosts
  7526. X
  7527. X     Next, the file _u_n_w_a_n_t_e_d._h_o_s_t_s is looked up, and  connections
  7528. X     from  hosts  listed  in it are rejected. Regular expressions
  7529. X     may be used in both files.
  7530. X
  7531. X     The duration of each connection is limited to the number  of
  7532. X     seconds  given  as  argument  to the -i flag. A maximum of 5
  7533. X     simultaneous connections can be accepted at  any  time.  All
  7534. X     requests  are  serialized and the server may be kept busy if
  7535. X     it has not finished sending data to a socket  (for  example,
  7536. X     when  a user pipes the output he receives to more(1) and the
  7537. X     amount of data to be sent is  more  than  the  the  socket's
  7538. X     buffer).
  7539. X
  7540. X     To set up your system to accept such connections,  the  fol-
  7541. X     lowing   line   has   to   be   inserted  into  your  host's
  7542. X     /etc/services file:
  7543. X
  7544. X                         ulistserv   372/tcp
  7545. X
  7546. X     This port is privileged, therefore _s_e_r_v_e_r_d has to be started
  7547. X     with  root privileges (the _s_e_t_u_p script takes care of this).
  7548. X
  7549. X
  7550. X
  7551. XAnastasios Kotsikonas                                               2
  7552. X
  7553. X
  7554. X
  7555. X
  7556. X
  7557. X
  7558. Xserverd(1)               USER COMMANDS                 serverd(1)
  7559. X
  7560. X
  7561. X
  7562. X     If you do not have root access you may choose any other port
  7563. X     number  above  1024,  and  in  this case _s_e_r_v_e_r_d will give a
  7564. X     warning every time it starts, which can be ignored.
  7565. X
  7566. X     Consult the src/README file for qualification tests for your
  7567. X     system  to  go  interactive and the Makefile for compilation
  7568. X     options; also see the PORT SPECIFIC  section  in  _s_e_r_v_e_r(1).
  7569. X     Lastly, the file HOMEDIR/welcome.live is copied upon log in,
  7570. X     and it may be modified.
  7571. X
  7572. X     If your setup uses a name server you may wish to  link  with
  7573. X     libraries that provide DNS support.
  7574. X
  7575. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  7576. X     iul(1), list(1), listserv(1), queue(1), server(1)
  7577. X
  7578. XAAAAUUUUTTTTHHHHOOOORRRR
  7579. X     Anastasios C. Kotsikonas
  7580. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  7581. X     Comments to tasos@cs.bu.edu
  7582. X
  7583. X
  7584. X
  7585. X
  7586. X
  7587. X
  7588. X
  7589. X
  7590. X
  7591. X
  7592. X
  7593. X
  7594. X
  7595. X
  7596. X
  7597. X
  7598. X
  7599. X
  7600. X
  7601. X
  7602. X
  7603. X
  7604. X
  7605. X
  7606. X
  7607. X
  7608. X
  7609. X
  7610. X
  7611. X
  7612. X
  7613. X
  7614. X
  7615. X
  7616. X
  7617. XAnastasios Kotsikonas                                               3
  7618. X
  7619. X
  7620. X
  7621. *-*-END-of-doc/serverd.nr-*-*
  7622. echo x - doc/start.nr
  7623. sed 's/^X//' >doc/start.nr <<'*-*-END-of-doc/start.nr-*-*'
  7624. X
  7625. X
  7626. X
  7627. Xstart(1)                 USER COMMANDS                   start(1)
  7628. X
  7629. X
  7630. X
  7631. XNNNNAAAAMMMMEEEE
  7632. X     ssssttttaaaarrrrtttt - start/stop the UNIX ListServer system
  7633. X
  7634. XSSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
  7635. X     ssssttttaaaarrrrtttt [----cccc] [----rrrr] [----kkkk]
  7636. X
  7637. XDDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
  7638. X     _s_t_a_r_t is used to start or stop the UNIX  ListServer  system.
  7639. X     When  starting  the  system,  any  previous server processes
  7640. X     still running are  killed,  all  necessary  lock  files  are
  7641. X     created,  any  previous reports are archived into files with
  7642. X     extension ._a_c_c, new files and directories  are  created  for
  7643. X     any  new  mailing  lists,  and  _s_e_r_v_e_r_d(1) is spawned. _s_t_a_r_t
  7644. X     reads the _c_o_n_f_i_g file (see server(1)), and should always  be
  7645. X     run from the server account (also see _s_e_r_v_e_r(1)).
  7646. X
  7647. XOOOOPPPPTTTTIIIIOOOONNNNSSSS
  7648. X     The following command line options are recognized:
  7649. X
  7650. X     -c   Suppress confirmation when killing  processes  or  when
  7651. X          creating new mailing directories and files.
  7652. X
  7653. X     -k   Just kill any old server system processes and exit.
  7654. X
  7655. X     -r   Restrict reporting to stdout.
  7656. X
  7657. XSSSSEEEEEEEE AAAALLLLSSSSOOOO
  7658. X     server(1), serverd(1)
  7659. X
  7660. XAAAAUUUUTTTTHHHHOOOORRRR
  7661. X     Anastasios C. Kotsikonas
  7662. X     Copyright (c) 1991-93, Anastasios Kotsikonas
  7663. X     Comments to tasos@cs.bu.edu
  7664. X
  7665. X
  7666. X
  7667. X
  7668. X
  7669. X
  7670. X
  7671. X
  7672. X
  7673. X
  7674. X
  7675. X
  7676. X
  7677. X
  7678. X
  7679. X
  7680. X
  7681. X
  7682. X
  7683. X
  7684. X
  7685. X
  7686. XAnastasios Kotsikonas                                               1
  7687. X
  7688. X
  7689. X
  7690. *-*-END-of-doc/start.nr-*-*
  7691. echo x - doc/README
  7692. sed 's/^X//' >doc/README <<'*-*-END-of-doc/README-*-*'
  7693. X
  7694. XTo install the man pages permanently on your system you will need to do the
  7695. Xfollowing as superuser:
  7696. X
  7697. X% cp *.nr /usr/man/cat1 <- or wherever the man pages are
  7698. X% cd /usr/man/cat1
  7699. X% compress *.nr
  7700. X% mv server.nr.Z server.1
  7701. X% mv farch.nr.Z farch.1
  7702. X% mv queue.nr.Z queue.1
  7703. X% mv catmail.nr.Z catmail.1
  7704. X% mv list.nr.Z list.1
  7705. X% mv listserv.nr.Z listserv.1
  7706. X% mv serverd.nr.Z serverd.1
  7707. X% mv start.nr.Z start.1
  7708. X% mv iul.nr.Z iul.1
  7709. X% chmod 444 server.1 farch.1 queue.1 catmail.1 list.1 listserv.1 serverd.1 \
  7710. X  start.1 iul.1
  7711. X% vi Index <--- if availbable
  7712. X  add the following lines in Index in the appropriate alphabetic location:
  7713. X    server.1:server:
  7714. X    farch.1:farch:
  7715. X    queue.1:queue:
  7716. X    catmail.1:catmail:
  7717. X    list.1:list:
  7718. X    listserv.1:listserv:
  7719. X    serverd.1:serverd:
  7720. X    start.1:start:
  7721. X    iul.1:iul:
  7722. X% vi /usr/man/whatis <-- or whatever file is used when doing man -k
  7723. X  add the following lines in whatis:
  7724. X    server(1)    - UNIX ListServer system description
  7725. X    farch(1)    - UNIX ListServer file archiving utility
  7726. X    queue(1)    - UNIX ListServer mail queue processing
  7727. X    catmail(1)    - UNIX ListServer mail redirection
  7728. X    list(1)        - UNIX ListServer mailing list processing
  7729. X    listserv(1)    - UNIX ListServer request processing
  7730. X    serverd(1)    - UNIX ListServer system daemon
  7731. X    start(1)    - UNIX ListServer housekeeper
  7732. X    iul(1)        - Interactive UNIX ListServer client
  7733. X
  7734. *-*-END-of-doc/README-*-*
  7735. echo x - src/README
  7736. sed 's/^X//' >src/README <<'*-*-END-of-src/README-*-*'
  7737. X
  7738. X
  7739. X                        UNIX LISTSERVER SYSTEM
  7740. X                        ----------------------
  7741. X
  7742. X           Copyright (c) 1991-93, Anastasios C. Kotsikonas
  7743. X
  7744. X                           tasos@cs.bu.edu
  7745. X                 June 1 1993
  7746. X
  7747. XDESCRIPTION:
  7748. X     This is a system that implements various mailing lists  with
  7749. X     one  list  server. It is automated, and obliterates the need
  7750. X     for user intervention and maintenance of multiple aliases of
  7751. X     the  form  "list,  list-owner,  list-request", etc. There is
  7752. X     support  provided  for  public  and   private   hierarchical
  7753. X     archives,  moderated  and  non-moderated  lists, peer lists,
  7754. X     peer servers, private lists, address aliasing, news  connec-
  7755. X     tions  and gateways, mail queueing, digests, list ownership,
  7756. X     owner preferences, crash recovery, batch processing,  confi-
  7757. X     gurable headers, regular expressions, archive searching, and
  7758. X     live user connections via TCP/IP.
  7759. X
  7760. XCOPYING: You may distribute the software freely, but you may not include
  7761. Xany part of the code in a commercial application whatsoever, directly or by
  7762. Ximplication. Modified code may NOT be distributed.
  7763. X
  7764. XAGREEMENT: This software can be used and distributed freely only as a
  7765. Xwhole and not in parts, as long as you do not remove or alter the author
  7766. Xand copyright notices in the file defs.h; this notices are #define'd in
  7767. Xthe symbols VERSION and COPYRIGHT. Although you may alter the code
  7768. Xprovided for your personal use, you you may not alter the functions
  7769. Xcreate_header(), create_multi_recipient_header() and main() in list.c,
  7770. Xlistserv.c and serverd.c (where applicable), and you may not redistribute
  7771. Xany changes you may have made. No part of the source code bearing a
  7772. Xcopyright notice can be included in commercial software systems without
  7773. Xwritten permission by the author.
  7774. XBy using this software you are bound by this agreement. 
  7775. XThis software comes with no warranties and cannot be sold for profit.
  7776. XThe AGREEMENT and COPYRIGHT notices should be included in all source
  7777. Xfiles when distributing this software.
  7778. XCOPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  7779. XUse, duplication or disclosure by the Federal Government is subject to the
  7780. Xrestrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  7781. Xfor Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  7782. X
  7783. XUPDATES: All updates can be obtained from cs.bu.edu (128.197.10.1) via
  7784. Xanonymous ftp, in the directory pub/listserv. If you downloaded this version
  7785. Xfrom another ftp site, please keep an eye on cs.bu.edu. Bug fixes will
  7786. Xbe posted periodically over there, and no notifications will be posted to
  7787. Xnews; you should check the directory periodically.
  7788. X
  7789. XCOMPILER: The programs are written to be ANSI C compliant (almost); if your
  7790. Xcompiler cannot handle them, I suggest you also download unproto.tar.Z
  7791. Xfrom cs.bu.edu; cd pub/unproto; this is a nice set of programs that will
  7792. Xconvert ANSI-isms to old style C -- please send any questions about unproto
  7793. Xto its author, not me. In this case, follow the instructions in the Makefile
  7794. Xin the src directory for adjustments to be able to use this package.
  7795. XFor those compilers that die when they see a contol-L in the source code, I
  7796. Xhave written a C program that "cleans" source files; it is called clean.c and
  7797. Xcan be found in pub/utils as well; compile as follows:
  7798. X        % cc -Dunix clean.c -o clean
  7799. XThe compiler should support symbol names longer than 8 characters. Also consult
  7800. Xthe Makefile, as well as the PORT SPECIFIC section in ../doc/server.1
  7801. X
  7802. XLINKING: If you are using the interactive part of ListServer and your
  7803. Xsetup uses a name server, you may wish to link with libraries that provide
  7804. XDNS support (for example, on SYSV R4 compile with -lsockdns instead of
  7805. X-lsocket).
  7806. X
  7807. XPREPROCESSOR: Strings are defined using both ANSI C specifications and
  7808. Xnon-ANSI standards, so that unproto will work correctly (unproto 2.0 does not
  7809. Xhandle ANSI string concatenations). Which ones are used during compilation 
  7810. Xdepends whether the macro __STDC__ is defined by the compiler/preprocessor.
  7811. XNote: the script 'stds' is now rarely needed and can be obtained from cs.bu.edu
  7812. Xin the directory pub/listserv/utils.
  7813. X
  7814. XSOURCE CODE MODIFICATIONS: If you modify the code to work around problems
  7815. Xwith your operating system, or enhance the system, please send me diff's
  7816. Xto be incorporated in the next release.
  7817. X
  7818. XTCP/IP SUPPORT: The 'system' mailmethod and the live ListServer require support
  7819. Xfor Berkeley sockets and internet support. The system defines the macro TCP_IP
  7820. Xin defs.h. Remove this definition if your host does not support sockets, etc.
  7821. XFailure to do so will lead to compiler errors.
  7822. X
  7823. XSEMAPHORE/SIGNAL SUPPORT: The interactive part of the system depends on
  7824. Xsemaphore support. If your host does not support semaphores, undefine the
  7825. Xsymbol GO_INTERACTIVE in defs.h; this symbol is automatically undefined if
  7826. XTCP_IP is not defined, or the SIGCLD/SIGCHLD, SIGUSR1 and SIGUSR2 signals are
  7827. Xnot present. The system uses the POSIX waipid() function which may not be
  7828. Xavailable on your system (like Sequent for example). You may use wait3()
  7829. Xinstead; see serverd.c, sighandle(). If you use wait3() and its first argument
  7830. Xwhould be a union, then compile with -DWAIT3_NEEDS_UNION (integer is used by
  7831. Xdefault).
  7832. X
  7833. XSPECIAL HEADER FILES: Platforms that have the <sys/select.h>, <ulimit.h>
  7834. Xand/or <setjmp.h> header files should use -DHAVE_SELECT_H -DHAVE_ULIMIT_H 
  7835. Xand -DHAVE_SETJMP_H when compiling.
  7836. X
  7837. XSIGNALS: Various UNIX versions deal with signals in a number of ways.
  7838. XIf your UNIX is strict SYSVR4 compile with -Dsvr4 -- SYSVR4 uses sighold() and
  7839. Xsigrelse(); if it is SYSVR3 compile with -Dsvr3 -- the same functions are
  7840. Xdefined; if it is strict BSD based compile with -Dbsd -- BSD uses
  7841. Xsigblock() and sigsetmask(). If your system does not define either of these
  7842. Xsets of routines or is not a strict implementation of the above, do not
  7843. Xuse the above flags and certain signals will be ignored at certain times
  7844. Xdue to an old-UNIX bug with system(). In defs.h certain ports are given
  7845. Xpredefined flavors.
  7846. X
  7847. XNON-BLOCKING I/O: The system employs a timeout mechanism that works
  7848. Xonly with the 'system' mailmethod, provided that the host supports
  7849. Xnon-blocking I/O; if it does not, undefine the symbol NONBLOCKING_IO
  7850. Xin defs.h (defined by default).
  7851. X
  7852. XLOCKS: The system relies heavily on locks; however, a number of systems
  7853. Xdo not support locking across NFS mounted file systems, or do not support
  7854. Xlocks at all. If you are experiencing locking problems, define the symbol
  7855. XNO_LOCKS in defs.h (or compile with -DNO_LOCKS) and pray, or move the system
  7856. Xto a local file system. The following ports have NO_LOCKS automatically
  7857. Xdefined: Minix, Ultrix, NeXT, Apollo, Xenix, Convex.
  7858. X
  7859. XSYSLOG: You may use syslog(3) for reporting if you compile with
  7860. X-DSYSLOG=facility.
  7861. X
  7862. XUSING ANOTHER HOST TO SEND MAIL: By default, the 'system' mailmethod connects
  7863. Xto "localhost" for mail delivery; you may use another host by altering the
  7864. Xsymbol SENDMAIL_HOST in sysmail.h
  7865. X
  7866. XSUBSCRIPTION SUSPENSION: The system scans error messages looking for addresses
  7867. Xto suspend sending mail to, and it allows by default a 7 day grace period. This
  7868. Xperiod may be changed by altering list.h or by compiling with
  7869. X-DGRACE_PERIOD=time_in_seconds.
  7870. X
  7871. XErrors-To: lines: If you do not want the system to put Errors-To: lines 
  7872. Xcompile with -DNO_ERRORS_TO.
  7873. X
  7874. XZMAILER and other non-sendmail mailers: If your mailer requires a
  7875. X'HELO hostname' or 'HELO ip-address' greeting, then compile with -DZMAILER.
  7876. XIf TCP/IP is available, the host's name and IP address are obtained with system
  7877. Xcalls. If not, they default to "localhost" and "127.0.0.1" (see defs.h) and
  7878. Xthey have to redefined. By default, the hostname is included in the greeting.
  7879. XIf the IP address is required, see list.c and listserv.c.
  7880. X
  7881. XUPGRADING: If you are upgrading from an earlier version, take a look at the
  7882. XUPGRADING and PORT SPECIFIC sections in ../doc/server.nr and run the
  7883. Xupgrade_to_6.0 shell script.
  7884. X
  7885. XPORTS: The code has been ported to the following UNIXes:
  7886. XSUN, IBM, SGI, DEC, HP, Convex, Stardent, KPC, NeXT, SCO, Apollo, Sequent, Data
  7887. XGeneral, i860, i386 (bsd) and OSF. If you are on a different host, try first
  7888. Xcompiling with -Dunknown_port.
  7889. X
  7890. XINSTALLATION DIRECTORY: Change the HOMEDIR symbol in Makefile to be the top
  7891. Xlevel directory where this system is installed.
  7892. X
  7893. XFORUM: You should join our forum at unix-listserv@stormking.com where we
  7894. Xdiscuss problems and enhancements about this system; send a subscribe request
  7895. Xto listserv@stormking.com
  7896. X
  7897. XACKNOWLEDGEMENTS: I would like to thank the following people for their
  7898. Xsuggestions and contributions to this system (not all suggestions have been
  7899. Xincorporated):
  7900. X1) Bob Boyd (rbn@epavax.rtpnc.epa.gov): IRIX port, gateway connections
  7901. X   feedback, 5.3 beta testing. [Since Dec. 1992 Bob is no longer at EPA 
  7902. X   and I wish him good luck]
  7903. X2) Stefan Schroer (Stefan.Schroer@cyber.urz.uni-wuppertal.dbp.de): MINIX port
  7904. X   (code not reported since 5.0), help files, original 'get' and 'index'
  7905. X   requests.
  7906. X3) Scott J. Ellentuch (tuc@stormking.com): IBM R6000 port, enhancements to
  7907. X   the farch utility, 5.3&up beta testing, setting up of the unix-listserv
  7908. X   forum, endless support on the net -- he is my buddy.
  7909. X4) David Warner (warner@austin.onu.edu): IBM R6000 bug fixing, 5.3 beta 
  7910. X   testing, tolerance with my obnoxious code -- I owe this gentleman a lot.
  7911. X5) Nathan F. Estey (nestey@copper.Denver.Colorado.EDU): 5.4 suggestions.
  7912. X6) Aad Nienhuis (aad@sconar.sco.uva.nl) for the catmail utility.
  7913. X7) Warren Burstein (warren@itexjct.jct.ac.il): digests, owner moderated lists
  7914. X   (listserv sends messages to owner, owner sends back the approved ones --
  7915. X   my scheme uses APPROVE and DISCARD requests), significant code rewriting,
  7916. X   manager preferences, automatic archiving of messages.
  7917. X8) Nicos Kontopoulos (nicos@cs.bu.edu) for a lot of tiny suggestions.
  7918. X9) Matthias Klose <doko@cs.tu-berlin.de>, John Neil <neil@dehn.mth.pdx.edu>
  7919. X   for the NeXT port.
  7920. X10) Ken Mayer (ken@visix.com) for the Precedence: stuff.
  7921. X11) Henry Spencer for the pattern matching routines.
  7922. X12) Carlos O'Ryan Lira (coryan@mat.puc.cl) for the Apollo port.
  7923. X13) Anand V Raman (A.Raman@massey.ac.nz) for modifying 'setup' to rebuild the
  7924. X    system under the HOMEDIR definition in Makefile.
  7925. X14) Kenneth Lorber (keni@oasys.dt.navy.mil) for providing fio.c and speeding up
  7926. X    the system by reducing the number of syscom()'s.
  7927. X15) All of those of you who made literally a myriad of small suggestions here
  7928. X    and there, and contributed even a single character of code, and especially
  7929. X    all of you who let me into your systems to do the ports myself.
  7930. X
  7931. X            The UNIX ListServer system includes 157 files:
  7932. X
  7933. X HOMEDIR/doc:
  7934. X   *.nr        -- proformatted man pages
  7935. X   catmail.1    -- man page for the catmail utility
  7936. X   farch.1    -- man page for the file archiving utility
  7937. X   iul.1    -- man page for the Interactive UNIX ListServer client
  7938. X   list.1    -- man page for the mailing list processing application
  7939. X   listserv.1    -- man page for the request processing application
  7940. X   queue.1    -- man page for the mail queue processing application
  7941. X   server.1    -- man page describing the system
  7942. X   serverd.1    -- man page for the system daemon
  7943. X   start.1    -- man page for the system's housekeeper
  7944. X   README    -- instructions for installing the man pages on your system
  7945. X
  7946. X HOMEDIR/help:
  7947. X   TOPICS    -- index file with topics and corresponding filenames
  7948. X   general      -- general help file
  7949. X   approve    -- help on the approve request
  7950. X   discard    -- help on the discard request
  7951. X   information  -- help on the information request
  7952. X   lists        -- help on the lists request
  7953. X   recipients   -- help on the recipients request
  7954. X   set          -- help on the set request
  7955. X   statistics   -- help on the statistics request
  7956. X   subscribe    -- help on the subscribe request
  7957. X   unsubscribe  -- help on the unsubscribe request
  7958. X   index    -- help on the index request
  7959. X   get        -- help on the get request
  7960. X   release    -- help on the release request
  7961. X   which    -- help on the which request
  7962. X   reports    -- help on the reports request
  7963. X   edit        -- help on the edit request
  7964. X   put        -- help on the put request
  7965. X   live        -- help on how to access the live ListServer
  7966. X   listserv    -- help on this system
  7967. X   fax        -- help on the fax request
  7968. X   search    -- help on the search request
  7969. X
  7970. X HOMEDIR/archives:
  7971. X   HOMEDIR/archives/listserver: Master archive:
  7972. X     DIR    -- info on files and directories they are located
  7973. X     INDEX    -- master index of all archives (listserver, pub, unix)
  7974. X     refcard    -- list of all commands
  7975. X     info    -- info on this archive
  7976. X     HOMEDIR/archives/listserver/example.dat:
  7977. X       example.dat1    -- part 1 of file example.dat in archive listserver
  7978. X       example.dat2    -- part 2 of file example.dat in archive listserver
  7979. X       example.dat3    -- part 3 of file example.dat in archive listserver
  7980. X   HOMEDIR/archives/iul: Source files for the IUL client:
  7981. X     DIR    -- info on files in this subdirectory
  7982. X     INDEX    -- index of all archives in this archive
  7983. X     iul.c    -- the IUL client
  7984. X     iul.h    -- specific definitions for iul.h
  7985. X     iulp.h    -- definition of IUL Protocol
  7986. X     iul.1    -- (as before)
  7987. X     iul.nr    -- (as before)
  7988. X     makefile    -- makefile to build the IUL client
  7989. X   HOMEDIR/archives/pub: Subarchive of listserver:
  7990. X     DIR    -- info on files and directories they are located
  7991. X     INDEX    -- index of all archives in this archive
  7992. X     info    -- info on this archive
  7993. X   HOMEDIR/archives/unix: Subarchive of listserver:
  7994. X     DIR    -- info on files and directories they are located
  7995. X     INDEX    -- index of all archives in this archive
  7996. X     info    -- info on this archive
  7997. X   HOMEDIR/archives/pub/unix: Subarchive of pub (duplicate name example):
  7998. X     DIR    -- info on files and directories they are located
  7999. X     INDEX    -- index of files in this archive
  8000. X     info    -- info on this archive
  8001. X   HOMEDIR/archives/pub/private: Subarchive of pub; example private archive
  8002. X     DIR    -- info on files and directories they are located
  8003. X     INDEX    -- index of files in this archive
  8004. X     info    -- info on this archive
  8005. X
  8006. X HOMEDIR/src:
  8007. X   REGISTRATION    -- registration form for using this software
  8008. X   README    -- this file
  8009. X   global.h    -- global variables definitions
  8010. X   struct.h    -- defines the server structure
  8011. X   defs.h    -- general definitions
  8012. X   tlock.c    -- tests for locks, i.e. whether any server programs are running
  8013. X             on another file system via NFS
  8014. X   list.h    -- specific definitions for list.c
  8015. X   list.c    -- the list's server
  8016. X   listserv.h    -- specific definitions for listserv.c
  8017. X   listserv.c    -- server for individual requests
  8018. X   pqueue.h    -- specific definitions for pqueue.c
  8019. X   pqueue.c    -- processes the mail queue
  8020. X   serverd.h    -- specific definitions for serverd.c
  8021. X   serverd.c    -- parent program that spawns list or listserv
  8022. X   start.h    -- specific definitions for start.c
  8023. X   start.c    -- does housekeeping before spawning serverd, makes sure that
  8024. X           files exist, kills any running server processes, etc
  8025. X   sysmail.h    -- specific definitions for sysmail.c
  8026. X   sysmail.c    -- system mailmethod routines
  8027. X   catmail.h    -- specific definitions for catmail.c
  8028. X   catmail.c    -- append incoming mail to the appropriate file
  8029. X   signals.c    -- signal processing routines
  8030. X   sender.c    -- sender address manipulation routines
  8031. X   misc.c    -- general purpose routines
  8032. X   farch.c    -- utility for easy archiving of files
  8033. X   next.h    -- specific definitions for NeXT hosts
  8034. X   sem.c    -- semaphore definitions for serverd's interactive part
  8035. X   rev.c    -- source to BSD 'rev'
  8036. X   iulp.h    -- Interactive UNIX ListServer Protocol definition
  8037. X   iul.h    -- specific definitions for iul.c
  8038. X   iul.c    -- client application to connect to an interactive system
  8039. X   siul.c    -- system iul used by ListServer to connect to remote servers
  8040. X   regex.c    -- fornt end to pattern matching routines
  8041. X   regerror.c    -- pattern matching routines -- Henry Spencer
  8042. X   regexp.c    -- pattern matching routines -- Henry Spencer
  8043. X   regexp.h    -- pattern matching routines -- Henry Spencer
  8044. X   regmagic.h    -- pattern matching routines -- Henry Spencer
  8045. X   regsub.c    -- pattern matching routines -- Henry Spencer
  8046. X   fwin.c    -- utility that returns subsets of files
  8047. X   fio.c    -- simple system calls submitted by keni@oasys.dt.navy.mil
  8048. X   strftime.c    -- UC Berkeley public domain version of this function
  8049. X   Makefile    -- to build your own server
  8050. X
  8051. X HOMEDIR/src/ansi:
  8052. X   *.h        -- specific ANSI string definitions for various programs
  8053. X
  8054. X HOMEDIR/src/nonansi:
  8055. X   *.h        -- specific non-ANSI string definitions for various programs
  8056. X
  8057. X HOMEDIR/gateway:
  8058. X   gateway.c    -- gateway for connecting your host to another on Internet
  8059. X   gateway.h    -- specific definitions for gateway.c
  8060. X   iulp.h    -- definition of the interactive UNIX ListServer Protocol
  8061. X   README    -- how to install and use the gateway
  8062. X   Makefile    -- how to build the gateway
  8063. X
  8064. X HOMEDIR/util:
  8065. X   combine.c    -- user utility to automatically combine archive files
  8066. X           received in multiple mail messages
  8067. X   expn.c    -- check if address is reachable
  8068. X   check_addr    -- script to check the validity of an incoming address
  8069. X   mmdfcatmail.c -- utility to use before catmail if using an MMDF mailer
  8070. X   which.sh    -- UCB "which" source
  8071. X   use_From:_address.sh -- program+script to use the From: address instead of
  8072. X               the "From " for identification
  8073. X
  8074. X HOMEDIR:
  8075. X   makefile    -- to build your system
  8076. X   IULP        -- description of the IUL protocol
  8077. X   setup        -- a script to be run before starting for the first time
  8078. X   systest    -- script that analyzes your system
  8079. X   queued    -- daemon controlling the processing of the mail queue
  8080. X   peer        -- script to add a peer list
  8081. X   news        -- script to add a news group to a list
  8082. X   redux        -- script that reduces the size of mbox by removing unnecessary
  8083. X                   fields from the header of each message
  8084. X   ulock        -- in conjunction with the 'flocks' file, this utility
  8085. X                   removes all locked files (unlocks them)
  8086. X   flocks       -- script to remove locked files
  8087. X   .awk        -- awk program used for the 'statistics' and 'recipients'
  8088. X           ListServer requests
  8089. X   .stats    -- shell script used for the 'statistics' ListServer request
  8090. X   .grep    -- shell program used for the 'statistics' ListServer request
  8091. X   .ignored    -- a list of email addresses whose messages are ignored
  8092. X   owners    -- a list of all list owner addresses
  8093. X   unwanted.hosts -- hosts not allowed to connect to IUL
  8094. X   upgrade_to_6.0 -- upgrade script
  8095. X   welcome.live    -- welcome message upon live log in
  8096. X   README    -- general guidelines for first time users
  8097. X   FAQ        -- most frequently asked questions
  8098. X   WHATS_NEW    -- what's with this version
  8099. X   config    -- the system's configuration file
  8100. X
  8101. X
  8102. X               |-->-----------> START
  8103. X               |                  |
  8104. X               |                  |
  8105. X               ^          (spawns-and-dies)
  8106. X               |                  |
  8107. X               |                  |
  8108. X               |--<--restart--- SERVERD <--shutdown-<--|
  8109. X                                  /\                   r
  8110. X                                 /  \                  e
  8111. X                                /    \                 s
  8112. X                    (spawns either one as necessary)   t       
  8113. X                              /        \               a
  8114. X                             /          \              r
  8115. X                           LIST        LISTSERV --->---t
  8116. X
  8117. X
  8118. XThe diagram shows that 'start' spawns 'serverd' and then dies, and that
  8119. X'listserv' may request 'serverd' to die (shutdown) or request that the
  8120. Xsystem is restarted, in which case 'serverd' spawns 'start' and dies.
  8121. X
  8122. XEnjoy!
  8123. X
  8124. XRevision history:
  8125. X
  8126. XVersion      Date     Status    Comments
  8127. X------------------------------------------------------------------------------
  8128. X 3.45      12/20/90  Outdated * First public version; bugs with listserv
  8129. X 3.67      01/03/91  Outdated   Bugs fixed
  8130. X 3.68      01/04/91  Outdated * v3.67 + tlock utility
  8131. X 4.0       04/09/91  Exprmntl   v3.68 + STATISTICS listserv command
  8132. X 4.1       04/16/91  Outdated   v4.0 + redux utility
  8133. X 4.2       05/02/91  Outdated   v4.1 w/ optimized source code, better doc.
  8134. X 4.21      05/03/91  Outdated   v4.2 w/ redux which was left out by mistake
  8135. X 4.3       05/03/91  Outdated * v4.21 w/ better mailer-daemon msg handling
  8136. X 4.4       05/22/91  Exprmntl   v4.3 w/ enhanced tlock,control,start,listserv
  8137. X 4.5       06/12/91  Exprmntl   v4.3 w/ enhanced listserv
  8138. X 5.0       07/17/91  Outdated * v4.4 + support for multiple lists
  8139. X 5.1       08/27/91  Outdated   v5.0 + bug fixes, enhanced listserv
  8140. X 5.1 Rev I 10/03/91  Outdated   v5.0 + more bug fixes
  8141. X 5.2       10/08/91  Outdated * v5.1 + archives, GET, INDEX requests,
  8142. X                        farch utility, moderated lists,
  8143. X                       disabled listserv commands on a per list
  8144. X                       basis, link with peer lists and news
  8145. X                       feeds
  8146. X 5.2 Rev A 10/10/91  Outdated   v5.2 + bug fixes
  8147. X 5.21      10/15/91  Exprmntl   v5.2A + multiple recipients in one message
  8148. X 5.3 beta  10/31/91  Exprmntl   v5.21 + system mailmethod, bug fixes
  8149. X 5.3        12/05/91  Outdated   v5.21 + bug fixes, universal system mailmethod,
  8150. X                    multiple recipients in one message,
  8151. X                    support for blanks in email addresses,
  8152. X                    user-set limit on size of messages,
  8153. X                    RFC 821 compliant SMTP implementation,
  8154. X                    extensive mail loop detection mechanism,
  8155. X                    new scripts (stds, reformat), enhanced
  8156. X                    GET request, and more.
  8157. X 5.31       12/09/91  PstdNews * v5.3 + mail queueing capability/subsystem +
  8158. X                       RELEASE request
  8159. X 5.4 beta  12/16/91  Exprmntl   v5.31 + crash recovery mechanism, manager
  8160. X                    approved subscriptions (private lists),
  8161. X                    multiple lines of text for describing
  8162. X                    archived files, batch processing,
  8163. X                    WHICH request, automatic use of
  8164. X                    unproto in the Makefile, private
  8165. X                    archives, list owners with restricted
  8166. X                    system privileges, email aliasing
  8167. X                    for requests, SYSTEM/REPORTS/PUT/EDIT
  8168. X                    list administration requests, automatic
  8169. X                    archiving of distributed messages only,
  8170. X                    enhanced INDEX/GET requests, same
  8171. X                    archive names allowed on different
  8172. X                    levels of the hierarchy (path spec. to
  8173. X                    an archive)
  8174. X 5.4       02/05/92  Outdated   v5.31 + v5.4 beta
  8175. X 5.41       03/05/92  PstdNews * v5.4 + catmail (system is now more secure), bug
  8176. X                    fixes, owner preferences
  8177. X 5.5 beta  04/08/92  Exprmntl   v5.41 + two ways for moderating lists by owners
  8178. X                    (+ APPROVE/DISCARD list administration
  8179. X                    requests), enhanced farch, fix to GET
  8180. X                    request, list digests, optional
  8181. X                    Comment: line, manager preferences,
  8182. X                    enhanced help system, GET/INDEX 
  8183. X                    requests now report file sizes, new
  8184. X                    config options ignore_invalid_requests
  8185. X                    and relaxed_syntax, EXECUTE request
  8186. X 5.5       05/18/92  Outdated   v5.5 beta + NeXT port
  8187. X 6.0beta   01/19/93  Exprmntl    v5.5 +    interactive system, ULISTSERVER_UMASK
  8188. X                    env var, Precedence:, configurable
  8189. X                    headers, regular expressions, auto
  8190. X                    archiving of lists' messages, enhanced
  8191. X                    farch, ability to execute UNIX commands
  8192. X                    on a per list basis, ability to
  8193. X                    continue commands in the config file on
  8194. X                    multiple lines, HP, Apollo, Sequent &
  8195. X                    DG ports, interception of requests sent
  8196. X                    to a list, list defaults, CONCEAL
  8197. X                    attribute, user settable subscription
  8198. X                    addresses, various user utilities,
  8199. X                    gateway client, screening and analysis
  8200. X                    of error messages, support for syslog,
  8201. X                    auto splitting of outgoing files, FAX
  8202. X                    request
  8203. X
  8204. X 6.0       06/01/93  Released * v6.0beta + ports + bug fixes + SEARCH request
  8205. X
  8206. X*Source for these versions has been posted to news.
  8207. *-*-END-of-src/README-*-*
  8208. echo x - src/REGISTRATION
  8209. sed 's/^X//' >src/REGISTRATION <<'*-*-END-of-src/REGISTRATION-*-*'
  8210. X
  8211. X              UNIX LISTSERVER SYSTEM
  8212. X              ----------------------
  8213. X
  8214. X              Copy Registration
  8215. X
  8216. X               tasos@cs.bu.edu
  8217. X
  8218. XKeep an eye on the anonymous ftp site cs.bu.edu (128.197.10.1) for any
  8219. Xupdates, in the directory pub/listserv
  8220. X
  8221. XThe list unix-listserv@stormking.com served by listserv@stormking.com
  8222. Xis a forum about this system.
  8223. X
  8224. XIf you use this software and have not filled out a registration form before,
  8225. Xplease email me the following information:
  8226. X
  8227. XName:
  8228. XEmail address:
  8229. XOrganization:
  8230. XAddress:
  8231. XPhone:
  8232. XType of computer system:
  8233. XVersion of server using (% list -v):
  8234. XComments:
  8235. *-*-END-of-src/REGISTRATION-*-*
  8236. echo x - src/Makefile
  8237. sed 's/^X//' >src/Makefile <<'*-*-END-of-src/Makefile-*-*'
  8238. X# Makefile for UNIX ListServer 6.0
  8239. X#
  8240. X# The programs are written to be fully ANSI C compliant. The symbol CC below
  8241. X# may have to be redefined if an ANSI C compiler is to be used. This ANSI
  8242. X# compiler should define the marco __STDC__
  8243. X#
  8244. X# Suggestions:
  8245. X# SGI: cc -ansi -D_POSIX_SOURCE, or cc -D__STDC__ -D_POSIX_SOURCE
  8246. X# SUN: Use /usr/lang/acc when available
  8247. X# NeXT: Compile with -D__NeXT__ if the compiler does not define this symbol,
  8248. X#  and -I/usr/include/bsd -I/usr/include/bsd/sys
  8249. X# HP-UX: cc -Aa -D_HPUX_SOURCE
  8250. X# IBM: xlc -D_ALL_SOURCE -qnoro
  8251. X# SYSVR4 Systems: link with -lnsl and -lsocket or -lsockdns if you are using
  8252. X#   a name server
  8253. X# SCO: Compile with -Dsco -I/usr/include/netinet
  8254. X# Apollo: Do not compile with -A ansi; if you need to, also compile with
  8255. X#   -Dapollo
  8256. X# Sequent: gcc -fwritable-strings
  8257. X# Data General: gcc -fwritable-strings
  8258. X# Stardent/KPC Titan: cc (do not use -43)
  8259. X# OSF: cc -std1
  8260. X# i386: cc -fwritable-strings
  8261. X# i860: cc
  8262. X#
  8263. X# To use the unproto package during compilation, uncomment the symbols
  8264. X# SRC and COMP below, and comment out the default ones.
  8265. X#
  8266. X# Also read the README file in this directory as well as ../doc/server.nr
  8267. X# (the PORT SPECIFIC section)
  8268. X#
  8269. X# On some systems that do not use BSD-style sockets and signals (SIGIO)
  8270. X# you need to link with a BSD library that defines them, although this is not
  8271. X# critical. See the man page for iul(1) for more details.
  8272. X#
  8273. X# Examples:
  8274. X# AIX: Link with -lbsd
  8275. X# SCO: Link with -lsocket
  8276. X#
  8277. X# SIGNALS: Various UNIX versions deal with signals in a number of ways.
  8278. X# If your UNIX is strict SYSVR4 compile with -Dsvr4 -- SYSVR4 uses sighold()
  8279. X# and sigrelse(); if it is SYSVR3 compile with -Dsvr3 -- the same functions are
  8280. X# defined; if it is strict BSD based compile with -Dbsd -- BSD uses
  8281. X# sigblock() and sigsetmask(). If your system does not define either of these
  8282. X# sets of routines or is not a strict implementation of the above, do not
  8283. X# use the above flags and certain signals will be ignored at certain times.
  8284. X# In defs.h certain ports are given predefined flavors.
  8285. X#
  8286. X# LINKING: If you are using the interactive part of ListServer and your
  8287. X# setup uses a name server, you may wish to link with libraries that provide
  8288. X# DNS support.
  8289. X#
  8290. X# Optional compiler flags that can be used:
  8291. X#   -DHAVE_SELECT_H: if your system provides the <sys/select.h> include file
  8292. X#   -DHAVE_ULIMIT_H: if your system provides the <ulimit.h> include file
  8293. X#   -DHAVE_SETJMP_H: if your system provides the <setjmp.h> include file
  8294. X#   -DHAVE_TZFILE_H: if your system provides the <tzfile.h> include file
  8295. X#   -DSYSLOG=facility: if you want to use syslog(3) for reports
  8296. X#   -DNO_LOCKS: if you do not want file locking
  8297. X#   -DNO_ERRORS_TO: if you do not want Errors-To: lines in messages
  8298. X#   -DERROR_MAIL_ANALYSIS=level: if you want the system to analyze 
  8299. X#    mailer-daemon error messages and take automatic action; default is
  8300. X#    off; level ranges from 1 (very conservative) to 9 (complete analysis +
  8301. X#    guess-attempts); see also GRACE_PERIOD below -- this option is still
  8302. X#    under development
  8303. X#   -DZMAILER: if you are using Zmailer or any other non-sendmail mailer that
  8304. X#    requires 'HELO hostname' to start the SMTP transaction; see also below
  8305. X#   -DLIST_CHECKING_FOR_REQUESTS: if you want to screen out requests sent to
  8306. X#    lists but allow ones that do not refer to local or remote lists
  8307. X#   -DLIST_ALIAS_IN_SUBJECT: if you want each subject line to contain the
  8308. X#    list's alias and the current message number
  8309. X#   -DNEED_DATE: if you need a Date: header line and your sendmail does not
  8310. X#    put one
  8311. X#   -DWAIT3_NEEDS_UNION: if using wait3() and its first argument is a union
  8312. X#   -DNEED_VSPRINTF: if your system does not provide vsprintf()
  8313. X#   -DMAX_LISTS=lists+1: number of lists defined plus one; default is 11
  8314. X#   -DUCB_MAIL=\"path\": path to UCB mail program; default is /usr/ucb/mail
  8315. X#   -DMAX_LINE=size: internal character buffer length; default is 1024
  8316. X#   -DMAX_CONNECTIONS=xxx: define the maximum number of live connections over
  8317. X#    TCP/IP; default is 5
  8318. X#   -DMAX_EMAILS=num: define the number of messages to send before sleeping
  8319. X#    to give time to sendmail to catch up; default is 10
  8320. X#   -DIUL_PORT=port: define another port for live connections if you do not
  8321. X#    have access to /etc/services
  8322. X#   -DINEWS=\"path\": path to the inews program for posting articles to news
  8323. X#    groups; default is /usr/lib/news/inews
  8324. X#   -Dbsd: if your host has a BSD flavor; default is defined in defs.h
  8325. X#   -Dsvr3: if your host has a SYSV R3 flavor; default is defined in defs.h
  8326. X#   -Dsvr4: if your host has a SYSV R4 flavor; default is defined in defs.h
  8327. X#   -Dunknown_port: if the system has not been ported to your host; should
  8328. X#    use one of the above system types (bsd, svr3, svr4)
  8329. X#   -fwritable-strings: specific to gcc; must be used with gcc
  8330. X#
  8331. X# Symbols automatically defined for various hosts (depending on the host):
  8332. X#   TCP_IP: undefine it in defs.h if you do not have TCP/IP installed
  8333. X#   GO_INTERACTIVE: defined if TCP_IP and SIGCLD (SIGCHLD), SIGUSR1 and SIGUSR2
  8334. X#    are defined; requires host support for either waitpid() or wait3(), and
  8335. X#    semaphores
  8336. X#   NO_LOCKS: defined when a system exhibits locking problems over NFS
  8337. X#   NONBLOCKING_IO: undefine it if your host does not support it
  8338. X#
  8339. X# Other symbols that may need tweaking:
  8340. X#   HOSTNAME: if TCP_IP is not defined then you need to set your hostname in
  8341. X#    defs.h only if you are compiling with -DZMAILER; default is "localhost"
  8342. X#   LOCAL_ADDR: same as above; default is 127.0.0.1
  8343. X#   SENDMAIL_HOST: default is "localhost"; it defines the host to connect to
  8344. X#    when using the 'system' mailmethod to deliver mail (defined in
  8345. X#    sysmail.h); compile as follows: -DSENDMAIL_HOST=\"hostname\".
  8346. X#   MAILER_DAEMON: email addresses that are given special treatment (defined
  8347. X#    in defs.h)
  8348. X#   SUSP_SUBJECT: suspicious Subject: lines that get special treatment (defined
  8349. X#    in defs.h)
  8350. X#   GRACE_PERIOD: time period before subscriptions of erroneous addresses are
  8351. X#    suspended; to be used as follows: -DGRACE_PERIOD=time_in_seconds.
  8352. X#
  8353. X# Always run 'setup' (in the parent directory); do not type 'make' in this
  8354. X# directory.
  8355. X
  8356. X# define your compiler:
  8357. XCC        = cc
  8358. X
  8359. X# define special symbols (system, preprocessor options, etc):
  8360. XDEFINES        = -DHAVE_SELECT_H -DHAVE_ULIMIT_H -DHAVE_SETJMP_H \
  8361. X          -DHAVE_TZFILE_H
  8362. X
  8363. X# define the optimization level
  8364. XOPTIMIZATION    = -g
  8365. X
  8366. X# define where the preprocessor is:
  8367. XCPP        = /lib/cpp
  8368. X
  8369. X# unproto specific definitions -- use either COMP symbol (second is preferred):
  8370. X#SRC        = /tmp/$<
  8371. X#COMP        = cat $< | unproto > $(SRC); $(CC)
  8372. X#COMP        = $(CPP) $(DEFINES) $< | unproto > $(SRC); $(CC)
  8373. X
  8374. X# default definitions (comment out if using unproto):
  8375. XSRC        = $<
  8376. XCOMP        = $(CC)
  8377. X
  8378. X# Reset HOMEDIR to the top level directory the system is installed under:
  8379. XHOMEDIR        = /usr/server
  8380. X
  8381. X# define linking options and libraries
  8382. XLDFLAGS        = $(OPTIMIZATION)
  8383. XLIBS        =
  8384. X
  8385. X# Nothing to change below
  8386. XSHELL        = /bin/sh
  8387. XLD        = $(CC)
  8388. XCFLAGS        = -c $(OPTIMIZATION) -I$(PWD) -I$(PWD)/src -I/usr/server/src \
  8389. X          -I/usr/include -I$(HOMEDIR)/src $(DEFINES)
  8390. XCLEAN_TMP    = @if [ $$USE_UNPROTO ]; then \
  8391. X            if [ `dirname $(SRC)` = "/tmp" ]; then \
  8392. X              rm -f $(SRC); \
  8393. X            fi; \
  8394. X          else \
  8395. X            echo > /dev/null; \
  8396. X          fi
  8397. X
  8398. XARCHIVED        = signals.o sender.o misc.o sysmail.o sem.o siul.o regex.o \
  8399. X          regsub.o regerror.o regexp.o fio.o strftime.o
  8400. XARCHIVE_LIB     = libserver.a
  8401. XTARGETS         = listserv list serverd start tlock farch pqueue catmail iul \
  8402. X          rev fwin
  8403. X
  8404. Xall: $(ARCHIVE_LIB) $(TARGETS)
  8405. X
  8406. X$(ARCHIVE_LIB): $(ARCHIVED)
  8407. X    @rm -f $(ARCHIVE_LIB)
  8408. X    ar cr $(ARCHIVE_LIB) $(ARCHIVED)
  8409. X    @if [ -f /usr/bin/ranlib -o -f /bin/ranlib ]; then \
  8410. X      echo ranlib $(ARCHIVE_LIB); \
  8411. X      ranlib $(ARCHIVE_LIB);\
  8412. X    else\
  8413. X      echo ar ts $(ARCHIVE_LIB); \
  8414. X      ar ts $(ARCHIVE_LIB); \
  8415. X    fi
  8416. X
  8417. Xlistserv: listserv.o $(ARCHIVE_LIB)
  8418. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS) -lm
  8419. X
  8420. Xlist: list.o $(ARCHIVE_LIB)
  8421. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS) -lm
  8422. X
  8423. Xserverd: serverd.o $(ARCHIVE_LIB)
  8424. X    @rm -f $@
  8425. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS) -lm
  8426. X
  8427. Xstart: start.o $(ARCHIVE_LIB)
  8428. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS)
  8429. X
  8430. Xtlock: tlock.o $(ARCHIVE_LIB)
  8431. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS)
  8432. X
  8433. Xfarch: farch.o $(ARCHIVE_LIB)
  8434. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS) -lm
  8435. X
  8436. Xpqueue: pqueue.o $(ARCHIVE_LIB)
  8437. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS)
  8438. X
  8439. Xcatmail: catmail.o $(ARCHIVE_LIB)
  8440. X    $(LD) $(LDFLAGS) $@.o $(ARCHIVE_LIB) -o $@ $(LIBS)
  8441. X    @chmod a+rx $@
  8442. X    @chmod u+s $@
  8443. X
  8444. Xiul:    iul.o
  8445. X    $(LD) $(LDFLAGS) $@.o -o $@ $(LIBS) -lm
  8446. X    @chmod a+rx $@
  8447. X
  8448. Xrev:    rev.o
  8449. X    $(LD) $(LDFLAGS) $@.o -o $@
  8450. X
  8451. Xfwin:    fwin.o
  8452. X    $(LD) $(LDFLAGS) $@.o -o $@ $(LIBS) -lm
  8453. X
  8454. Xinstall: $(ARCHIVE_LIB) $(TARGETS)
  8455. X    @for t in $(TARGETS); do \
  8456. X       echo Installing "$$t"; \
  8457. X       rm -f $(HOMEDIR)/"$$t"; \
  8458. X       if [ -r /bin/ln -o -r /usr/bin/ln -o -r /usr/ucb/ln -o \
  8459. X            -r /usr/bsd/ln ]; then \
  8460. X         ln -s $(HOMEDIR)/src/"$$t" $(HOMEDIR)/"$$t"; \
  8461. X       else \
  8462. X         cp "$$t" $(HOMEDIR); \
  8463. X       fi; \
  8464. X       if [ "`ls -l $$t | awk '{ print $$3 }'`" = "server" ]; then \
  8465. X         chmod a+rx $(HOMEDIR)/"$$t"; \
  8466. X       fi; \
  8467. X    done
  8468. X    @(cd $(HOMEDIR); chmod u+s catmail)
  8469. X
  8470. Xclean:
  8471. X    rm -f $(TARGETS) $(ARCHIVE_LIB) *.o
  8472. X
  8473. X# Hand-generated dependencies
  8474. Xlistserv.o:     listserv.c defs.h struct.h global.h listserv.h ansi/listserv.h \
  8475. X                nonansi/listserv.h ansi/misc.h nonansi/misc.h ansi/defs.h \
  8476. X        nonansi/defs.h
  8477. X    @PWD=`pwd`
  8478. X    $(COMP) $(CFLAGS) $(SRC)
  8479. X    @$(CLEAN_TMP)
  8480. X
  8481. Xlist.o:         list.c defs.h struct.h global.h list.h ansi/defs.h \
  8482. X        nonansi/defs.h
  8483. X    @PWD=`pwd`
  8484. X    $(COMP) $(CFLAGS) $(SRC)
  8485. X    @$(CLEAN_TMP)
  8486. X
  8487. Xserverd.o:      serverd.c defs.h struct.h global.h serverd.h ansi/serverd.h \
  8488. X                nonansi/serverd.h iulp.h ansi/defs.h \
  8489. X        nonansi/defs.h
  8490. X    @PWD=`pwd`
  8491. X    $(COMP) $(CFLAGS) $(SRC)
  8492. X    @$(CLEAN_TMP)
  8493. X
  8494. Xstart.o:        start.c defs.h struct.h global.h start.h ansi/start.h \
  8495. X        nonansi/start.h ansi/misc.h nonansi/misc.h ansi/defs.h \
  8496. X        nonansi/defs.h
  8497. X    @PWD=`pwd`
  8498. X    $(COMP) $(CFLAGS) $(SRC)
  8499. X    @$(CLEAN_TMP)
  8500. X
  8501. Xsender.o:       sender.c defs.h
  8502. X    @PWD=`pwd`
  8503. X    $(COMP) $(CFLAGS) $(SRC)
  8504. X    @$(CLEAN_TMP)
  8505. X
  8506. Xsignals.o:      signals.c defs.h struct.h
  8507. X    @PWD=`pwd`
  8508. X    $(COMP) $(CFLAGS) $(SRC)
  8509. X    @$(CLEAN_TMP)
  8510. X
  8511. Xsysmail.o:      sysmail.c defs.h struct.h sysmail.h
  8512. X    @PWD=`pwd`
  8513. X    $(COMP) $(CFLAGS) $(SRC)
  8514. X    @$(CLEAN_TMP)
  8515. X
  8516. Xmisc.o:         misc.c defs.h struct.h ansi/misc.h nonansi/misc.h ansi/defs.h \
  8517. X        nonansi/defs.h
  8518. X    @PWD=`pwd`
  8519. X    $(COMP) $(CFLAGS) $(SRC)
  8520. X    @$(CLEAN_TMP)
  8521. X
  8522. Xtlock.o:        tlock.c defs.h global.h
  8523. X    @PWD=`pwd`
  8524. X    $(COMP) $(CFLAGS) $(SRC)
  8525. X    @$(CLEAN_TMP)
  8526. X
  8527. Xfarch.o:        farch.c defs.h struct.h listserv.h ansi/defs.h nonansi/defs.h
  8528. X    @PWD=`pwd`
  8529. X    $(COMP) $(CFLAGS) $(SRC)
  8530. X    @$(CLEAN_TMP)
  8531. X
  8532. Xpqueue.o:       pqueue.c defs.h struct.h global.h pqueue.h ansi/defs.h \
  8533. X        nonansi/defs.h
  8534. X    @PWD=`pwd`
  8535. X    $(COMP) $(CFLAGS) $(SRC)
  8536. X    @$(CLEAN_TMP)
  8537. X
  8538. Xcatmail.o:    catmail.c defs.h struct.h global.h catmail.h ansi/catmail.h\
  8539. X        nonansi/catmail.h
  8540. X    @PWD=`pwd`
  8541. X    $(COMP) $(CFLAGS) $(SRC)
  8542. X    @$(CLEAN_TMP)
  8543. X
  8544. Xsem.o:        sem.c defs.h ansi/defs.h nonansi/defs.h
  8545. X    @PWD=`pwd`
  8546. X    $(COMP) $(CFLAGS) $(SRC)
  8547. X    @$(CLEAN_TMP)
  8548. X
  8549. Xiul.o:        iul.c iul.h iulp.h defs.h
  8550. X    @PWD=`pwd`
  8551. X    $(COMP) $(CFLAGS) $(SRC)
  8552. X    @$(CLEAN_TMP)
  8553. X
  8554. Xsiul.o:        siul.c iul.h iulp.h defs.h
  8555. X    @PWD=`pwd`
  8556. X    $(COMP) $(CFLAGS) $(SRC)
  8557. X    @$(CLEAN_TMP)
  8558. X
  8559. Xregex.o:    regex.c regexp.h
  8560. X    @PWD=`pwd`
  8561. X    $(COMP) $(CFLAGS) $(SRC)
  8562. X    @$(CLEAN_TMP)
  8563. X
  8564. Xregsub.o:    regsub.c regexp.h regmagic.h
  8565. X    @PWD=`pwd`
  8566. X    $(COMP) $(CFLAGS) $(SRC)
  8567. X    @$(CLEAN_TMP)
  8568. X
  8569. Xregexp.o:    regexp.c regexp.h regmagic.h
  8570. X    @PWD=`pwd`
  8571. X    $(COMP) $(CFLAGS) $(SRC)
  8572. X    @$(CLEAN_TMP)
  8573. X
  8574. Xregerror.o:    regerror.c
  8575. X    @PWD=`pwd`
  8576. X    $(COMP) $(CFLAGS) $(SRC)
  8577. X    @$(CLEAN_TMP)
  8578. X
  8579. Xrev.o:        rev.c
  8580. X    @PWD=`pwd`
  8581. X    $(COMP) $(CFLAGS) $(SRC)
  8582. X    @$(CLEAN_TMP)
  8583. X
  8584. Xfwin.o:        fwin.c
  8585. X    @PWD=`pwd`
  8586. X    $(COMP) $(CFLAGS) $(SRC)
  8587. X    @$(CLEAN_TMP)
  8588. X
  8589. Xfio.o:        fio.c
  8590. X    @PWD=`pwd`
  8591. X    $(COMP) $(CFLAGS) $(SRC)
  8592. X    @$(CLEAN_TMP)
  8593. X
  8594. Xstrftime.o:    strftime.c
  8595. X    @PWD=`pwd`
  8596. X    $(COMP) $(CFLAGS) $(SRC)
  8597. X    @$(CLEAN_TMP)
  8598. *-*-END-of-src/Makefile-*-*
  8599. echo x - src/catmail.h
  8600. sed 's/^X//' >src/catmail.h <<'*-*-END-of-src/catmail.h-*-*'
  8601. X/*
  8602. X  Below are the #define's pertinent to catmail.c (user contributed application).
  8603. X*/
  8604. X
  8605. X#ifdef __STDC__
  8606. X# include "ansi/catmail.h"
  8607. X#else
  8608. X# include "nonansi/catmail.h"
  8609. X#endif
  8610. X#ifdef __NeXT__
  8611. X# include "next.h"
  8612. X#endif
  8613. X
  8614. X#define LOST_MAIL        "lost+found"
  8615. X
  8616. Xint    lfd = 2, lfd2 = 2, lfd3 = 2; /* Set to stderr in case they are closed */
  8617. X                     /* without having been opened before */
  8618. Xint    listid;
  8619. XBOOLEAN tty_echo        = TRUE;
  8620. XBOOLEAN moderated       = FALSE;        /* -m flag off */
  8621. XBOOLEAN reformat        = FALSE;        /* -f flag off */
  8622. XBOOLEAN requests        = FALSE;        /* -r flag off */
  8623. XFILE    *report         = NULL;
  8624. *-*-END-of-src/catmail.h-*-*
  8625. echo x - src/defs.h
  8626. sed 's/^X//' >src/defs.h <<'*-*-END-of-src/defs.h-*-*'
  8627. X/*
  8628. X  AGREEMENT: This software can be used and distributed freely only as a
  8629. X  whole and not in parts, as long as you do not remove or alter the author
  8630. X  and copyright notices in the file defs.h; this notices are #define'd in
  8631. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  8632. X  provided for your personal use, you you may not alter the functions
  8633. X  create_header(), create_multi_recipient_header() and main() in list.c,
  8634. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  8635. X  any changes you may have made. No part of the source code bearing a
  8636. X  copyright notice can be included in commercial software systems without
  8637. X  written permission by the author.
  8638. X  By using this software you are bound by this agreement. 
  8639. X  This software comes with no warranties and cannot be sold for profit.
  8640. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  8641. X  files when distributing this software.
  8642. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  8643. X  Use, duplication or disclosure by the Federal Government is subject to the
  8644. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  8645. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  8646. X
  8647. X  General system definitions.
  8648. X
  8649. X  WARNING: DO NOT CHANGE THE NAME OF THE 'SERVERD', 'LIST' or 'LISTSERV'
  8650. X  PROGRAMS in the #define's below. If you do so, make sure that command line
  8651. X  options are separated by at least a space from the filename.
  8652. X  DO NOT INCLUDE ANY CHARACTERS SUCH AS &, |, <, >. etc.
  8653. X
  8654. X  Preserve any quotes and new lines that appear below; change only path names.
  8655. X
  8656. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  8657. X
  8658. X*/
  8659. X
  8660. X#ifdef __STDC__
  8661. X# include "ansi/defs.h"
  8662. X#else
  8663. X# include "nonansi/defs.h"
  8664. X#endif
  8665. X
  8666. X#define TCP_IP          /* Remove it if your host does not support it */
  8667. X
  8668. X#if defined (TCP_IP) && (defined (SIGCLD) || defined (SIGCHLD)) && \
  8669. X  defined (SIGUSR1) && defined (SIGUSR2)
  8670. X# ifndef GO_INTERACTIVE
  8671. X#  define GO_INTERACTIVE 
  8672. X   /* Remove this definition if your host doesn't support semaphores etc. */
  8673. X# endif
  8674. X#endif
  8675. X
  8676. X/* If you do not have TCP/IP and are using Zmailer, provide the following
  8677. X   information about your host.
  8678. X*/
  8679. X#ifndef TCP_IP
  8680. X# define HOSTNAME      "localhost" /* Replace w/ your host's name */
  8681. X# define LOCAL_ADDR      "127.0.0.1" /* Replace w/ your host's IP address */
  8682. X#endif
  8683. X
  8684. X#define VERSION          "6.0 -- UNIX ListServer by Anastasios Kotsikonas"
  8685. X#define COPYRIGHT      \
  8686. X"UNIX ListServer version 6.0 by Anastasios Kotsikonas, Copyright (c) 1991-93.\n\
  8687. XUse, duplication or disclosure by the U.S. Federal Government is subject to the\n\
  8688. Xrestrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,\n\
  8689. Xfor U.S. Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).\n\n"
  8690. X#define SERVICE          "ulistserv"
  8691. X#define COMPLETE_FILE(f)  if (!interactive) fprintf (f, ".\nQUIT\n")
  8692. X#define TELNET          "telnet `hostname` 25 > /dev/null 2>&1 "
  8693. X#ifndef INEWS
  8694. X# define INEWS          "/usr/lib/news/inews"
  8695. X#endif
  8696. X#ifdef xenix
  8697. X# define BINMAIL      "/usr/bin/mail > /dev/null 2>&1"
  8698. X#else
  8699. X# define BINMAIL      "/bin/mail > /dev/null 2>&1"
  8700. X#endif
  8701. X
  8702. X#define SUBSCRIBERS       ".subscribers"
  8703. X#define ALIASES          ".aliases"
  8704. X#define NEWSF          ".news"
  8705. X#define PEERS          ".peers"
  8706. X#define HEADERS          ".headers"
  8707. X#define RESTRICTED        ".restricted"
  8708. X#define IGNORED           ".ignored"
  8709. X#define INFO_FILE         ".info"
  8710. X#define WELCOME_FILE      ".welcome"
  8711. X#define LIST_LIMITS      ".limits"
  8712. X#define UNPROC_MESSAGES      ".un.messages"
  8713. X#define UNPROC_SUBSCRIBERS ".un.subscriber"
  8714. X#define UNPROC_PEERS      ".un.peers"
  8715. X#define UNPROC_NEWS      ".un.news"
  8716. X#define UNPROC_DIGEST     ".un.digest" /* digest ready to send */
  8717. X#define DIGEST_TOC        ".digest.toc" /* digest table of contents */
  8718. X#define DIGEST_MSG        ".digest.msg" /* digest of messages */
  8719. X#define DIGEST_TIME       ".digest.time" /* time last digest sent */
  8720. X#define REPORT_LIST       ".report.list"
  8721. X#define REPORT_LIST_ACC   ".rep.list.acc"
  8722. X#define LIST_MAIL_FILE    "mail"
  8723. X#define LIST_MODERATED_F  "moderated"
  8724. X
  8725. X#define MESSAGE_IDS_F     ".message.ids"
  8726. X
  8727. X#define INDEX          "INDEX"
  8728. X#define DIRF          "DIR"
  8729. X#define DEFAULT_ARCHIVE      "listserver"
  8730. X
  8731. X#define START_OPTIONS     "-crs"         /* provide start options here */
  8732. X#ifndef apollo
  8733. X# define CUT          "cut"
  8734. X#else
  8735. X# define CUT          "/sys5.3/usr/bin/cut"
  8736. X#endif
  8737. X#define AWK               "awk" /* Do a 'which awk' for proper path */
  8738. X#ifdef _AIX
  8739. X# define UPTIME          "ruptime"
  8740. X#else
  8741. X# define UPTIME            "uptime"  /* 'which uptime'; may use ruptime */
  8742. X#endif
  8743. X#define MAILER_DAEMON     "MAILER|<DA?EMON&~DEMON\\.CO\\.UK>|POST.*MAST|\
  8744. X^ROOT| WPUSER|MMDF|^SMT.*|\\$EMD|MRGATE|VMMAIL|MAIL.*SYSTEM|UUCP|-MAISER-|\
  8745. X^MAL@|MAIL.+AGENT|TCPMAIL|BITMAIL|MAILMAN|MAIL_SYSTEM"
  8746. X              /* Preserve upper case; put all possibilities above
  8747. X                 separated by a '|'; all of the above entries will
  8748. X                 be used to identify mailer daemon messages so
  8749. X                 they can get special treatment; entries are
  8750. X                 regular expressions */
  8751. X#define SUSP_SUBJECT      \
  8752. X"DELIVERY[ \t]+ERROR|\
  8753. XDELIVERY[ \t]+REPORT|\
  8754. XDELIVERY[ \t]+PROBLEM|\
  8755. XUSER[ \t]+UNKNOWN|\
  8756. XUNDELIVER.+[ \t]MAIL|\
  8757. XUNDELIVER.+[ \t]MESSAGE|\
  8758. XPROBLEMS.+DELIVERING.+MAIL|\
  8759. XPROBLEMS.+DELIVERING.+MESSAGE|\
  8760. XCAN[ \t]*['NO]*T.+DELIVER.+MAIL|\
  8761. XUNABLE.+DELIVER.+MAIL|\
  8762. XUNABLE.+DELIVER.+MESSAGE|\
  8763. XFAILED[ \t]+MAIL|\
  8764. XFAILED[ \t]+MESSAGE|\
  8765. XMAIL[ \t]+FAILED|\
  8766. XMAIL[ \t]+RETURNED|\
  8767. XRETURNED[ \t]+MAIL|\
  8768. XMAIL.*[ \t]ERROR|\
  8769. XMAIL[ \t]+RECEIVED|\
  8770. XMESSAGE[ \t]+RECEIVED|\
  8771. XREAD[ \t]+RECEIPT|\
  8772. XRECEIPT[ \t]+NOTIFICATION|\
  8773. XSTATUS.+SIGNAL[ \t]+[0-9]+|\
  8774. X^ERROR[ \t]+CONDITION[ \t]+RE:|\
  8775. XAUTO[ \t]+REPLY|\
  8776. XAUTOMATIC[ \t]+REPLY|\
  8777. XAUTOMATICALLY[ \t]+GENERATED|\
  8778. XWAITING.+MAIL|\
  8779. XON[ \t]+VACATION|\
  8780. XCONCIERGE[ \t]+NOTICE|\
  8781. XAWAY[ \t]+FROM.+MAIL|\
  8782. XCAN[ \t]*['NO]*T.+ANSWER|\
  8783. XCAN[ \t]*['NO]*T.+REPLY|\
  8784. XOUT[ \t]+OF[ \t]+TOWN|\
  8785. X^[ \t]*TEST[ \t]*$|\
  8786. X^[ \t]*TEST.+IGNORE|\
  8787. XPLEASE[ \t]+IGNORE"
  8788. X              /* List of suspicious subject lines; possible mail
  8789. X                 loop */
  8790. X#ifndef UCB_MAIL
  8791. X# define UCB_MAIL      "/usr/ucb/mail" /* Path to UCB mail program. Redefine
  8792. X              it if UCB mail is not installed on your system */
  8793. X#endif
  8794. X
  8795. X/*
  8796. X  These #define's should not be altered.
  8797. X*/
  8798. X
  8799. X#ifndef NSIG
  8800. X# ifdef MAXSIG
  8801. X#  define NSIG          MAXSIG
  8802. X# else
  8803. X#  define NSIG            32
  8804. X# endif
  8805. X#endif
  8806. X
  8807. X#define DEFAULT_IUL_PORT  372    /* As assigned by the IANA */
  8808. X#define MAX_COMMANDS      27    /* # of commands recognized */
  8809. X#ifndef MAX_EMAILS
  8810. X#define MAX_EMAILS      10    /* ListServer emails in one outgoing batch */
  8811. X#endif
  8812. X#define MAX_FILE_LENGTH   500    /* Number of lines of files when shrunk */
  8813. X#define BUFFSIZ          8192    /* Socket buffer size */
  8814. X#define DEFAULT_SERVER_ADDRESS       "listserver"
  8815. X#define DEFAULT_SERVER_CMDOPTIONS ""
  8816. X#define DEFAULT_SERVER_COMMENT      "Boston University ListServer"
  8817. X#define DEFAULT_MANAGER          "server"
  8818. X#define DEFAULT_PRECEDENCE      "bulk"
  8819. X#ifndef MAX_LINE
  8820. X# define MAX_LINE      1024
  8821. X#endif
  8822. X#define EOS          '\0'
  8823. X#define RESET(var)      (var[0]) = EOS
  8824. X#define BSD_PS          0x01
  8825. X#define    SYSV_PS          0x02
  8826. X#define    USE_TELNET      0x04
  8827. X#define USE_ENV_VAR      0x08
  8828. X#define USE_MY_SYSTEM      0x10
  8829. X#define BSD_MAIL      0x20
  8830. X#define POST_MAIL      0x40
  8831. X#define GATE_MAIL      0x80
  8832. X#define USE_SYSMAIL      0x100
  8833. X#define LIMIT_MSG      0x200
  8834. X#define LIMIT_FILES      0x400
  8835. X#define IGNR_INVLD_RQSTS  0x4000
  8836. X#define RELAXED_SYNTAX      0x8000
  8837. X#define NON_AUTO_SUB      0x10000
  8838. X#define CONCEAL_LIST      0x20000
  8839. X#define ARCHIVE_LIST      0x40000
  8840. X#define ARCHIVE_DIGEST      0x80000
  8841. X#define START_OF_MESSAGE  "From " /* UNIX mail messages start w/ this string */
  8842. X#define ACK          "ACK"   /* Send message back to sender */
  8843. X#define NOACK          "NOACK" /* Do not send message back to sender */
  8844. X#define POSTPONE      "POSTPONE"  /* Postpone sending mail */
  8845. X#define DIGEST            "DIGEST" /* send mail in digests */
  8846. X#define MAX_SET_OPTIONS   4
  8847. X
  8848. X#define MAX_OWNER_PREFS   15
  8849. X#define CCSET          "CCSET"
  8850. X#define    CCSUB          "CCSUBSCRIBE" /* Copy owner on subscribe request */
  8851. X#define CCUNSUB          "CCUNSUBSCRIBE" /* Copy owner on unsubscribe req */
  8852. X#define CCREC          "CCRECIPIENTS"
  8853. X#define CCINFO          "CCINFORMATION"
  8854. X#define CCSTAT          "CCSTATISTICS"
  8855. X#define CCGET          "CCGET"
  8856. X#define CCINDEX          "CCINDEX"
  8857. X#define CCLISTS          "CCLISTS"
  8858. X#define CCRELEASE      "CCRELEASE"
  8859. X#define CCHELP          "CCHELP"
  8860. X#define CCPRIVATE      "CCPRIVATE"
  8861. X#define CCRUN          "CCRUN"
  8862. X#define CCERRORS      "CCERRORS" /* Copy owner on errors */
  8863. X#define CCALL          "CCALL" /* Copy onwer on all activities */
  8864. X
  8865. X#define ccset          0x01
  8866. X#define ccsub          0x02
  8867. X#define ccunsub          0x04
  8868. X#define ccrec          0x08
  8869. X#define ccinfo          0x10
  8870. X#define ccstat          0x20
  8871. X#define ccget          0x40
  8872. X#define ccindex          0x80
  8873. X#define cclists          0x100
  8874. X#define ccrelease      0x200
  8875. X#define cchelp          0x400
  8876. X#define ccprivate      0x800
  8877. X#define ccrun          0x1000
  8878. X#define ccerrors      0x2000
  8879. X#define ccall          ccset | ccsub | ccunsub | ccrec | ccinfo | ccstat |\
  8880. X              ccget | ccindex | cclists | ccrelease | cchelp |\
  8881. X              ccprivate | ccrun | ccerrors
  8882. X
  8883. X#define MAX_SIGNAL      NSIG    /* Highest system signal caught */
  8884. X#define BOOLEAN          unsigned int
  8885. X#ifndef TRUE
  8886. X# define TRUE          1
  8887. X#endif
  8888. X#ifndef FALSE
  8889. X# define FALSE          0
  8890. X#endif
  8891. X#define CANT_OPEN      (-1)
  8892. X#define CANT_LOCK      (-2)
  8893. X#define SUBSCRIBED      TRUE    /* Subscribed sender */
  8894. X#define NOTSUBSCRIBED      FALSE   /* Sender is not subscribed */
  8895. X#define NEWS          TRUE+1  /* News feed */
  8896. X#define PEER          TRUE+2  /* Peer messages */
  8897. X#define OWNER          TRUE+3  /* Sender is a list owner */
  8898. X#define MANAGER          TRUE+4  /* Sender is the manager */
  8899. X#define NEW_ARRIVAL      "\n--- NEW MAIL HAS ARRIVED ---\n"
  8900. X#define PROCESSING_BATCH  "\n--- PROCESSING BATCH REQUESTS ---\n"
  8901. X#define DIGEST_TIME_      "\n--- DIGEST TIME ---\n"
  8902. X#ifndef MAX_LISTS
  8903. X# define MAX_LISTS      11 /* It should be one more than # desired */
  8904. X#endif
  8905. X
  8906. X#define RECEIVED      "^(Received:[ \t])"
  8907. X#define FROM          "^(From:[ \t])"
  8908. X#define SUBJECT          "^(Subject:[ \t])"
  8909. X#define MESSAGE_ID1       "^(Message-Id:[ \t])"
  8910. X#define MESSAGE_ID2      "^(Message-ID:[ \t])"
  8911. X#define MESSAGE_ID3      "^(Message-id:[ \t])"
  8912. X#define MESSAGE_TAG      "^(Message-Tag:[ \t])"
  8913. X#define ERROR_CONDITION      "Error Condition Re: "
  8914. X
  8915. X#define COMPLETE_TELNET(f) \
  8916. X if (sys.options & USE_TELNET) \
  8917. X   COMPLETE_FILE (f)
  8918. X
  8919. X#define OPEN_FILE(fp, file, mode, func) \
  8920. X  if ((fp = fopen (file, mode)) == NULL)\
  8921. X    report_progress (report, tsprintf ("\n%s(): Could not open %s: errno %d",\
  8922. X                       func, file, errno), TRUE),\
  8923. X    gexit (1)
  8924. X
  8925. X#define COPY_OWNER(mask) (BOOLEAN)\
  8926. X((listid < 0 ? sys.server.manager_prefs : sys.lists[listid].owner_prefs) &\
  8927. X (mask))
  8928. X
  8929. X#define PREPEND(str, buf) \
  8930. X  { char copy [1024];\
  8931. X    RESET (copy);\
  8932. X    strcat (copy, buf);\
  8933. X    sprintf (buf, "%s%s", str, copy);\
  8934. X  }
  8935. X
  8936. X/*
  8937. X  System specific definitions:
  8938. X*/
  8939. X
  8940. X#if defined (sequent) || defined (unknown_port)
  8941. X# ifndef SEEK_SET
  8942. X#  define SEEK_SET    0
  8943. X# endif
  8944. X# ifndef SEEK_CUR
  8945. X#  define SEEK_CUR    1
  8946. X# endif
  8947. X#endif
  8948. X
  8949. X#if defined (_MINIX) || defined (ultrix) || defined (__NeXT__) || \
  8950. X  defined (apollo) || defined (i386)
  8951. X# ifndef NO_LOCKS
  8952. X#  define NO_LOCKS
  8953. X# endif
  8954. X# if !defined (bsd) && !defined (svr3) && !defined (svr4)
  8955. X#  define bsd
  8956. X# endif
  8957. X# ifndef ultrix
  8958. X#  undef GO_INTERACTIVE
  8959. X# endif
  8960. X#endif
  8961. X
  8962. X#if defined (__convex__)
  8963. X# ifdef __STDC__
  8964. X#  ifndef NO_LOCKS
  8965. X#   define NO_LOCKS
  8966. X#  endif
  8967. X#  ifdef TCP_IP
  8968. X#   undef TCP_IP
  8969. X#  endif
  8970. X# endif
  8971. X# ifdef GO_INTERACTIVE
  8972. X#  undef GO_INTERACTIVE
  8973. X# endif
  8974. X#endif
  8975. X
  8976. X#if defined (sun) || defined (hpux) || defined (__hpux) || \
  8977. X  defined (sequent) || defined (ultrix) || defined (__convex__) || \
  8978. X  defined (__NeXT__)
  8979. X# if !defined (bsd) && !defined (svr3) && !defined (svr4)
  8980. X#  define bsd
  8981. X# endif
  8982. X#endif
  8983. X
  8984. X#if defined (sgi) || defined (__sgi) || defined (mips) || defined (__mips) ||\
  8985. X  defined (_AIX) || defined (stellar) || defined (titan) || defined (xenix) ||\
  8986. X  defined (sco) || defined (M_UNIX) || defined (M_XENIX) || defined (__osf__)
  8987. X# if !defined (svr3) && !defined (svr4) && !defined (bsd)
  8988. X#  define svr3
  8989. X# endif
  8990. X# ifdef xenix
  8991. X#  ifndef NO_LOCKS
  8992. X#   define NO_LOCKS
  8993. X#  endif
  8994. X# endif
  8995. X# if defined (titan) || defined (stellar)
  8996. X#  ifdef GO_INTERACTIVE
  8997. X#   undef GO_INTERACTIVE
  8998. X#  endif
  8999. X# endif
  9000. X#endif
  9001. X
  9002. X#if defined (i860) || defined (stardent) || defined (__DGUX__)
  9003. X# if !defined (bsd) && !defined (svr3) && !defined (svr4)
  9004. X#  define svr4
  9005. X# endif
  9006. X#endif
  9007. X
  9008. X#define NONBLOCKING_IO
  9009. X
  9010. X/*
  9011. X These functions don't have prototypes in SCO UNIX in the included files.
  9012. X
  9013. Xextern void exit (int);
  9014. Xextern int unlink (char *);
  9015. Xextern int stat (char *, struct stat *);
  9016. Xextern int mkdir (char *, int);
  9017. Xextern int lockf (int, int, int);
  9018. Xextern int open (char *, int, ...);
  9019. Xextern int creat (char *, int);
  9020. Xextern int close (int);
  9021. Xextern int getpid ();
  9022. Xextern int stat (char *, struct stat *);
  9023. Xextern int chmod (char *, int);
  9024. Xextern int chdir (char *);
  9025. Xextern int unlink (char *);
  9026. Xextern unsigned int sleep (unsigned int);
  9027. Xextern int execl (char *, ...);
  9028. Xextern int read (int, void *, unsigned);
  9029. Xextern int write (int, void *, unsigned);
  9030. Xextern int umask (int);
  9031. Xextern char *getenv (char *);
  9032. Xextern void free (void *);
  9033. Xextern int kill (int, int);
  9034. Xextern int getuid (void);
  9035. Xextern int abort (void);
  9036. Xextern int access (char *, int);
  9037. Xextern void *calloc (int, int);
  9038. X*/
  9039. *-*-END-of-src/defs.h-*-*
  9040. echo x - src/global.h
  9041. sed 's/^X//' >src/global.h <<'*-*-END-of-src/global.h-*-*'
  9042. X/*
  9043. X  AGREEMENT: This software can be used and distributed freely only as a
  9044. X  whole and not in parts, as long as you do not remove or alter the author
  9045. X  and copyright notices in the file defs.h; this notices are #define'd in
  9046. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  9047. X  provided for your personal use, you you may not alter the functions
  9048. X  create_header(), create_multi_recipient_header() and main() in list.c,
  9049. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  9050. X  any changes you may have made. No part of the source code bearing a
  9051. X  copyright notice can be included in commercial software systems without
  9052. X  written permission by the author.
  9053. X  By using this software you are bound by this agreement.
  9054. X  This software comes with no warranties and cannot be sold for profit.
  9055. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  9056. X  files when distributing this software.
  9057. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  9058. X  Use, duplication or disclosure by the Federal Government is subject to the
  9059. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  9060. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  9061. X*/
  9062. X
  9063. Xchar subscribersf [MAX_LINE];
  9064. Xchar newsf [MAX_LINE];
  9065. Xchar peersf [MAX_LINE];
  9066. Xchar aliasesf [MAX_LINE];
  9067. Xchar headersf [MAX_LINE];
  9068. Xchar restrictedf [MAX_LINE];
  9069. Xchar ignoredf [MAX_LINE];
  9070. Xchar list_mail_f [MAX_LINE];
  9071. Xchar list_moderated_f [MAX_LINE];
  9072. Xchar report_listf [MAX_LINE];
  9073. Xchar server_ignoredf [MAX_LINE];
  9074. Xchar infof [MAX_LINE];
  9075. Xchar welcomef [MAX_LINE];
  9076. Xchar unprocessed_messages [MAX_LINE];
  9077. Xchar unprocessed_subscribersf [MAX_LINE];
  9078. Xchar unprocessed_peersf [MAX_LINE];
  9079. Xchar unprocessed_newsf [MAX_LINE];
  9080. Xchar unprocessed_digestf [MAX_LINE];
  9081. Xchar message_idsf [MAX_LINE];
  9082. Xchar message_id [MAX_LINE];
  9083. Xchar digest_msgf [MAX_LINE];
  9084. Xchar digest_timef [MAX_LINE];
  9085. Xchar password_in_sub_file [MAX_LINE];
  9086. Xchar **alternate_addresses;
  9087. Xchar *prog;
  9088. XSYS  sys;
  9089. XCOMMANDS commands [MAX_COMMANDS]; /* Set of recognizable commands */
  9090. XREMOTE *rlists = NULL, *matched_rlists = NULL;
  9091. XBOOLEAN debug = FALSE;
  9092. X
  9093. X/*
  9094. X  Below are the valid SET options, their valid values and their
  9095. X  default values.
  9096. X*/
  9097. X
  9098. X/* valid SET options */
  9099. Xchar *options [] = { "ADDRESS", "MAIL", "PASSWORD", "CONCEAL" };
  9100. X
  9101. X/* and values */
  9102. Xchar *values [] =
  9103. X{ "^FIXED$|^VARIABLE$", "^ACK$|^NOACK$|^POSTPONE$|^DIGEST$", ".*", "^YES$|^NO$" };
  9104. X
  9105. Xchar *default_values [] = { "FIXED", "NOACK", ".*", "NO" };
  9106. X
  9107. *-*-END-of-src/global.h-*-*
  9108. echo x - src/iul.h
  9109. sed 's/^X//' >src/iul.h <<'*-*-END-of-src/iul.h-*-*'
  9110. X/*
  9111. X  AGREEMENT: This software can be used and distributed freely only as a
  9112. X  whole and not in parts, as long as you do not remove or alter the author
  9113. X  and copyright notices in the file defs.h; this notices are #define'd in
  9114. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  9115. X  provided for your personal use, you you may not alter the functions
  9116. X  create_header(), create_multi_recipient_header() and main() in list.c,
  9117. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  9118. X  any changes you may have made. No part of the source code bearing a
  9119. X  copyright notice can be included in commercial software systems without
  9120. X  written permission by the author.
  9121. X  By using this software you are bound by this agreement.
  9122. X  This software comes with no warranties and cannot be sold for profit.
  9123. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  9124. X  files when distributing this software.
  9125. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  9126. X  Use, duplication or disclosure by the Federal Government is subject to the
  9127. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  9128. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  9129. X
  9130. X  Below are the #define's pertinent to iul.c and siul.c
  9131. X*/
  9132. X
  9133. X#include "iulp.h"
  9134. X
  9135. X#define PORT                372    /* As assigned by IANA */
  9136. X#define MAX_HOPS        5    /* ... from IUL server to IUL server */
  9137. X#define TIMEOUT             180 /* How long to wait for server response */
  9138. X#ifndef BUFFSIZ
  9139. X# define BUFFSIZ             8192
  9140. X#endif
  9141. X#ifndef RESET
  9142. X# define RESET(v)            (v[0] = EOS)
  9143. X#endif
  9144. X#define PRINTF(code, str)    if (verbose) printf ("%d %s", code, str),\
  9145. X                fflush (stdout)
  9146. X#ifndef MIN
  9147. X# define MIN(a, b)        ((a) < (b) ? (a) : (b))
  9148. X#endif
  9149. X
  9150. X#define GENERAL_RESPONSES(cmd)\
  9151. X{\
  9152. X  switch (cmd) {\
  9153. X    case OK: PRINTF (OK, "OK\n"); break;\
  9154. X    case CONNECT: PRINTF (CONNECT, "Connected\n"); break;\
  9155. X    case SYNTAX_ERROR: PRINTF (SYNTAX_ERROR, "Syntax error in request\n");\
  9156. X     break;\
  9157. X    case INVALID_REQ: PRINTF (INVALID_REQ, "Invalid request\n"); break;\
  9158. X    case PEER_UNAVAIL: PRINTF (PEER_UNAVAIL, "Peer unavailable\n"); break;\
  9159. X    case BAD_ARCHIVE: PRINTF (BAD_ARCHIVE, "Bad archive\n"); break;\
  9160. X    case RESTRICTED_REQ: PRINTF (RESTRICTED_REQ,\
  9161. X     "Restriction in force for request\n"); break;\
  9162. X    case NOT_OWNER: PRINTF (NOT_OWNER, "Invalid onwer\n"); break;\
  9163. X    case SYS_ERROR: PRINTF (SYS_ERROR, "System error\n"); break;\
  9164. X    case MESSAGE: PRINTF (MESSAGE, "Message\n"); break;\
  9165. X    case PERMISSION_DENIED: PRINTF (PERMISSION_DENIED, "Permission denied\n");\
  9166. X     break;\
  9167. X    case CONN_CLOSED: PRINTF (CONN_CLOSED, "Closing connection\n"); break;\
  9168. X    case CONN_ABORTED: PRINTF (CONN_ABORTED, "Connection aborted\n");\
  9169. X     return -1; break;\
  9170. X    case CONN_TIMEOUT: PRINTF (CONN_TIMEOUT, "Connection timed out\n");\
  9171. X     return -1; break;\
  9172. X    case SERVER_BUSY: PRINTF (SERVER_BUSY, "Server busy\n"); break;\
  9173. X    case PASSWORD_REQUIRED: PRINTF (PASSWORD_REQUIRED, "Password required\n");\
  9174. X         if (read_from_fd (sock_fd, nbytes, NULL) < 0) return -1; break;\
  9175. X    case CONTINUED: PRINTF (CONTINUED, "[Command incomplete:]"); break;\
  9176. X    case MORE_INPUT_REQUIRED: PRINTF (MORE_INPUT_REQUIRED,\
  9177. X     "[Command incomplete:]"); break;\
  9178. X  }\
  9179. X}
  9180. *-*-END-of-src/iul.h-*-*
  9181. echo x - src/iulp.h
  9182. sed 's/^X//' >src/iulp.h <<'*-*-END-of-src/iulp.h-*-*'
  9183. X/*
  9184. X  AGREEMENT: This software can be used and distributed freely only as a
  9185. X  whole and not in parts, as long as you do not remove or alter the author
  9186. X  and copyright notices in the file defs.h; this notices are #define'd in
  9187. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  9188. X  provided for your personal use, you you may not alter the functions
  9189. X  create_header(), create_multi_recipient_header() and main() in list.c,
  9190. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  9191. X  any changes you may have made. No part of the source code bearing a
  9192. X  copyright notice can be included in commercial software systems without
  9193. X  written permission by the author.
  9194. X  By using this software you are bound by this agreement.
  9195. X  This software comes with no warranties and cannot be sold for profit.
  9196. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  9197. X  files when distributing this software.
  9198. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  9199. X  Use, duplication or disclosure by the Federal Government is subject to the
  9200. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  9201. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  9202. X
  9203. X  Define the Interactive UNIX ListServer Protocol.
  9204. X*/
  9205. X
  9206. X#define OK                      100
  9207. X#define MORE_INPUT_REQUIRED    101
  9208. X#define CONTINUED        102
  9209. X#define PASSWORD_REQUIRED    103
  9210. X#define CONNECT            105
  9211. X#define MESSAGE            106
  9212. X#define WRITE_TO_FILE_ASC    110
  9213. X#define WRITE_TO_FILE_BIN    120
  9214. X#define APPEND_TO_FILE_ASC    130
  9215. X#define APPEND_TO_FILE_BIN    140
  9216. X#define TEST_FILE_PERMISSIONS    154
  9217. X#define SYNTAX_ERROR            200
  9218. X#define INVALID_REQ             300
  9219. X#define PEER_UNAVAIL            400
  9220. X#define BAD_ARCHIVE             500
  9221. X#define RESTRICTED_REQ          600
  9222. X#define NOT_OWNER               700
  9223. X#define SYS_ERROR               800
  9224. X#define PERMISSION_DENIED    860
  9225. X#define SERVER_BUSY             870
  9226. X#define CONN_TIMEOUT        880
  9227. X#define CONN_ABORTED        890
  9228. X#define CONN_CLOSED        900
  9229. *-*-END-of-src/iulp.h-*-*
  9230. echo x - src/list.h
  9231. sed 's/^X//' >src/list.h <<'*-*-END-of-src/list.h-*-*'
  9232. X/* 
  9233. X  AGREEMENT: This software can be used and distributed freely only as a
  9234. X  whole and not in parts, as long as you do not remove or alter the author
  9235. X  and copyright notices in the file defs.h; this notices are #define'd in
  9236. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  9237. X  provided for your personal use, you you may not alter the functions
  9238. X  create_header(), create_multi_recipient_header() and main() in list.c,
  9239. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  9240. X  any changes you may have made. No part of the source code bearing a
  9241. X  copyright notice can be included in commercial software systems without
  9242. X  written permission by the author.
  9243. X  By using this software you are bound by this agreement.
  9244. X  This software comes with no warranties and cannot be sold for profit.
  9245. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  9246. X  files when distributing this software.
  9247. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  9248. X  Use, duplication or disclosure by the Federal Government is subject to the
  9249. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  9250. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  9251. X
  9252. X  Below are the #define's pertinent to list.c
  9253. X
  9254. X  Preserve any quotes and new lines that appear below; change only path names.
  9255. X
  9256. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  9257. X
  9258. X*/
  9259. X
  9260. X#ifdef __NeXT__
  9261. X# include "next.h"
  9262. X#endif
  9263. X
  9264. X#ifndef GRACE_PERIOD
  9265. X# define GRACE_PERIOD      604800  /* Time in secs after which offending */
  9266. X                  /* addresses are removed/suspended */
  9267. X#endif
  9268. X#define ONE_MONTH      2592000 /* 30 days: error messages in the database */
  9269. X                  /* older than this are removed */
  9270. X#define INEWS_REPLY      "/tmp/.inews.reply"
  9271. X#define ERRORSF          ".errors"
  9272. X#define ERRORS2F      ".errors.tmp"
  9273. X#define UNPROC_TMP      ".un.tmp"
  9274. X#define MAIL_COPY      ".messages"
  9275. X#define MSG               ".msg"
  9276. X#undef MAILFORWARD
  9277. X#define MAILFORWARD       ".mailforward"
  9278. X#define HEADER          ".header"
  9279. X#define MSG_NO            ".msgno"
  9280. X#define DIGEST_NO         ".digestno"
  9281. X#define REMOVED_USERS      "removed.users"
  9282. X#define REMOVED_ALIASES      "removed.alias"
  9283. X#define MBOX              "mbox"            /* Place to save list's messages */
  9284. X#define ARCHIVE          "archive"        /* Public messages */
  9285. X#define ORIGIN          "^(Originator:[ \t])"
  9286. X#define SENDER            "^(Sender:[ \t])"
  9287. X#define REPLY_TO      "^(Reply-To:[ \t])"
  9288. X#define DATE              "^(Date:[ \t])"
  9289. X#define ARCHIVE_NAME      "^(archive-name:[ \t])"
  9290. X#define CONTROL          "^(Control:[ \t])"
  9291. X#define NO_RECIPIENT_FILE "NONE"
  9292. X#define MESSAGE_SEPARATOR \
  9293. X"----------------------- Message requiring your approval ----------------------"
  9294. X#define REQUESTS \
  9295. X"(^[ \t]*APPR?O?V?E?[ \t]+([A-Z0-9.@-]+)[ \t]+.+[ \t]+[0-9]+[ \t]*$)|\
  9296. X(^[ \t]*DISC?A?R?D?[ \t]+([A-Z0-9.@-]+)[ \t]+.+[ \t]+[0-9]+[ \t]*$)|\
  9297. X(^[ \t]*EDIT[ \t]+([A-Z0-9.@-]+)[ \t]+.+[ \t]+[A-Z]+[ \t]*$)|\
  9298. X(^[ \t]*GET[ \t]+[A-Z0-9/.-]+.+)|\
  9299. X(^[ \t]*HELP[ \t]*[A-Z0-9]*$)|\
  9300. X(^[ \t]*INDEX[ \t]*[A-Z0-9/.-]*.*)|\
  9301. X(^[ \t]*INFO?R?M?A?T?I?O?N?[ \t]+([A-Z0-9.@-]+)[ \t]*$)|\
  9302. X(^[ \t]*LIST?S?[ \t]*$)|\
  9303. X(^[ \t]*PUT[ \t]+([A-Z0-9.@-]+)[ \t]+.+)|\
  9304. X(^[ \t]*RECI?P?I?E?N?T?S?[ \t]+([A-Z0-9.@-]+)[ \t]*$)|\
  9305. X(^[ \t]*REVI?E?W?[ \t]+([A-Z0-9.@-]+)[ \t]*$)|\
  9306. X(^[ \t]*RELE?A?S?E?[ \t]*$)|\
  9307. X(^[ \t]*REPO?R?T?S?[ \t]+([A-Z0-9.@-]+)[ \t]+.+$)|\
  9308. X(^[ \t]*RUN[ \t]+([A-Z0-9.@-]+))|\
  9309. X(^[ \t]*SET[ \t]+([A-Z0-9.@-]+))|\
  9310. X(^[ \t]*STAT?I?S?T?I?C?S?[ \t]+([A-Z0-9.@-]+))|\
  9311. X(^[ \t]*SUBS?C?R?I?B?E?[ \t]+([A-Z0-9.@-]+).+)|\
  9312. X(^[ \t]*SYST?E?M?[ \t]+([A-Z0-9.@-]+)[ \t]+.+[ \t]+#.+)|\
  9313. X(^[ \t]*UNSU?B?S?C?R?I?B?E?[ \t]*([A-Z0-9.@-]*))|\
  9314. X(^[ \t]*SIGN?O?F?F?[ \t]*([A-Z0-9.@-]*))|\
  9315. X(^[ \t]*PLEASE[ \t]+REMOVE[ \t]+)|\
  9316. X(^[ \t]*PLEASE[ \t]+UNSU?B?S?C?R?I?B?E?[ \t]+)|\
  9317. X(^[ \t]*PLEASE[ \t]+SIGN[ \t]+)|\
  9318. X(^[ \t]*PLEASE[ \t]+ADD[ \t]+)|\
  9319. X(^[ \t]*WHIC?H?[ \t]*$)|\
  9320. X(^[ \t]*SHUTDOWN[ \t]+.+$)|\
  9321. X(^[ \t]*RESTART[ \t]+.+$)|\
  9322. X(^[ \t]*EXEC?U?T?E?[ \t]+.+#.+)"
  9323. X
  9324. X#define APPEND_TELNET(func) \
  9325. X  if ((sys.options & USE_TELNET)) {\
  9326. X    if ((f = fopen (mailforwardf, "a")) == NULL)\
  9327. X      report_progress (report, tsprintf ("%s(): Could not open %s", func, \
  9328. X               mailforwardf), TRUE),\
  9329. X      gexit (1);\
  9330. X    COMPLETE_FILE (f);\
  9331. X    fclose (f);\
  9332. X  }
  9333. X
  9334. X#define DELIVER_MAIL(recipient) \
  9335. X  if (!interactive) {\
  9336. X    if ((++mails_sent) >= MAX_EMAILS)\
  9337. X      mails_sent = 0,\
  9338. X      sleep (30);\
  9339. X    if (sys.options & USE_SYSMAIL) \
  9340. X      sysmail (mailforwardf); \
  9341. X    else \
  9342. X      syscom ("%s '%s' < %s", sys.mail.method, \
  9343. X              (((sys.options & USE_TELNET) == 0) ? locase (recipient) : ""), \
  9344. X              mailforwardf);\
  9345. X  }
  9346. X
  9347. X#define NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS(__address__, __func__, from_sender) \
  9348. X  { char error [MAX_LINE];\
  9349. X    report_progress (report, tsprintf ("Syntax error in user address: %s\n%s",\
  9350. X __address__, (from_sender ? "Message not delivered to any recipients" : \
  9351. X"Message not delivered to this recipient")), TRUE);\
  9352. X    create_header (&f, mailforwardf, sys.server.address, sys.server.address,\
  9353. X           sys.manager, "Syntax error in user address", TRUE, FALSE,\
  9354. X           TRUE);\
  9355. X    fprintf (f, "Error detected in user address: %s\n", __address__);\
  9356. X    if (from_sender)\
  9357. X      fprintf (f, "Message not distributed to list %s.\n",\
  9358. Xsys.lists[listid].alias);\
  9359. X    else\
  9360. X      fprintf (f, "Message not delivered to this recipient.\n");\
  9361. X    fprintf (f, "The message is included below:\n\
  9362. X-----------------------------------------------------------------------------\n\
  9363. X");\
  9364. X    fclose (f);\
  9365. X    cat_append (headerf, mailforwardf);\
  9366. X    cat_append (msgf, mailforwardf);\
  9367. X    APPEND_TELNET (__func__);\
  9368. X    DELIVER_MAIL (sys.manager);\
  9369. X  }
  9370. X
  9371. X#define REMOVE_ADDRESS(address, from, to, append_to) \
  9372. X{\
  9373. X  FILE *fin, *fout;\
  9374. X  char line[MAX_LINE], linecopy[MAX_LINE], *error;\
  9375. X  long int len, written;\
  9376. X  OPEN_FILE (fin, from, "r", "process_message");\
  9377. X  OPEN_FILE (fout, to, "w", "process_message");\
  9378. X  while (!feof (fin)) {\
  9379. X    RESET (line);\
  9380. X    fgets (line, MAX_LINE - 2, fin);\
  9381. X    strcpy (linecopy, line);\
  9382. X    upcase (linecopy);\
  9383. X    if (line[0] != EOS) {\
  9384. X      if (linecopy[strlen (linecopy) - 1] == '\n')\
  9385. X    linecopy[strlen (linecopy) - 1] = EOS;\
  9386. X      if (removed || re_strcmp (address, linecopy, NULL) <= 0) {\
  9387. X    if ((written = write_to_fd (fileno (fout), line, (len = strlen (line))))\
  9388. X        < 0) {\
  9389. X      echo_append ((error = tsprintf ("write() failed; wrote %ld bytes \
  9390. Xout of %ld requested to file %s; errno %d", abs (written), len, to, errno)), WARNING);\
  9391. X      if (sys.options & BSD_MAIL)\
  9392. X        syscom ("echo '%s' | %s -s 'write() failed; system shut down' %s",\
  9393. X            error, UCB_MAIL, sys.manager);\
  9394. X      exit (16);\
  9395. X    }\
  9396. X      }\
  9397. X      else {\
  9398. X        if (line[strlen (line) - 1] == '\n')\
  9399. X      line[strlen (line) - 1] = EOS;\
  9400. X    echo_append (line, append_to);\
  9401. X        removed = TRUE;\
  9402. X      }\
  9403. X    }\
  9404. X  }\
  9405. X  fclose (fin);\
  9406. X  fclose (fout);\
  9407. X}
  9408. X
  9409. X#define SUSPEND_ADDRESS(address, from, to) \
  9410. X{\
  9411. X  FILE *fin, *fout;\
  9412. X  char line [MAX_LINE], linecopy [MAX_LINE], addr [MAX_LINE], *error;\
  9413. X  long int len, written;\
  9414. X  OPEN_FILE (fin, from, "r", "process_message");\
  9415. X  OPEN_FILE (fout, to, "w", "process_message");\
  9416. X  while (!feof (fin)) {\
  9417. X    RESET (line);\
  9418. X    fgets (line, MAX_LINE - 2, fin);\
  9419. X    strcpy (linecopy, line);\
  9420. X    upcase (linecopy);\
  9421. X    if (line[0] != EOS) {\
  9422. X      if (linecopy[strlen (linecopy) - 1] == '\n')\
  9423. X    linecopy[strlen (linecopy) - 1] = EOS;\
  9424. X      if (suspended || re_strcmp (address, linecopy, NULL) <= 0) {\
  9425. X    if ((written = write_to_fd (fileno (fout), line, (len = strlen (line))))\
  9426. X        < 0) {\
  9427. X      echo_append ((error = tsprintf ("write() failed; wrote %ld bytes \
  9428. Xout of %ld requested to file %s; errno %d", abs (written), len, to, errno)), WARNING);\
  9429. X      if (sys.options & BSD_MAIL)\
  9430. X        syscom ("echo '%s' | %s -s 'write() failed; system shut down' %s",\
  9431. X            error, UCB_MAIL, sys.manager);\
  9432. X      exit (16);\
  9433. X    }\
  9434. X      }\
  9435. X      else\
  9436. X    sscanf (line, "%s", addr),\
  9437. X    suspended = TRUE,\
  9438. X    fprintf (fout, "%s %s %s", addr, POSTPONE, skip_to_word (line, 3));\
  9439. X    }\
  9440. X  }\
  9441. X  fclose (fin);\
  9442. X  fclose (fout);\
  9443. X}
  9444. X
  9445. Xchar digest_tocf [MAX_LINE];
  9446. Xchar mboxf [MAX_LINE];
  9447. Xchar msg_nof [MAX_LINE];
  9448. Xchar digest_nof [MAX_LINE];
  9449. Xchar msgf [MAX_LINE];
  9450. Xchar mailforwardf [MAX_LINE];
  9451. Xchar archivef [MAX_LINE];
  9452. Xchar headerf [MAX_LINE];
  9453. Xchar mail_copyf [MAX_LINE];
  9454. Xchar unprocessed_tmp [MAX_LINE];
  9455. Xchar removed_usersf [MAX_LINE];
  9456. Xchar removed_aliasesf [MAX_LINE];
  9457. Xchar archive_name [MAX_LINE];
  9458. Xchar limitsf [MAX_LINE];
  9459. Xchar errorsf [MAX_LINE];
  9460. Xchar errors2f [MAX_LINE];
  9461. Xchar **multi_recipients;  /* List of multiple recipient addresses */
  9462. Xchar *list_alias  = NULL; /* arg to the -L command option */
  9463. Xchar *one_digest  = NULL; /* arg to the -i command option */
  9464. Xchar *mask;
  9465. Xchar hostname [256];
  9466. X
  9467. XFILE *mail        = NULL; /* Source of messages */
  9468. XFILE *report      = NULL; /* Progress report to the administrator */
  9469. XFILE *subscribers = NULL; /* List of subscribers */
  9470. XFILE *news      = NULL; /* List of newsgroups */
  9471. XFILE *peers      = NULL; /* List of peers */
  9472. XFILE *restricted  = NULL; /* List of people whose messages require special
  9473. X                              handling */
  9474. XFILE *ignored     = NULL; /* List of people whose messages are ignored */
  9475. XFILE *msg_no      = NULL; /* Last message count */
  9476. XFILE *digest_no   = NULL; /* Last digest count */
  9477. XFILE *headers     = NULL; /* File containing headers of messages only */
  9478. XFILE *message_ids = NULL; /* File containing message ids */
  9479. X
  9480. XBOOLEAN tty_echo        = FALSE; /* -e option off */
  9481. XBOOLEAN send_to_subscribers = TRUE;  /* -r option off */
  9482. XBOOLEAN execute_once        = FALSE; /* -1 option off */
  9483. XBOOLEAN errors_to_owner        = FALSE; /* -f option off */
  9484. XBOOLEAN multi_recip        = FALSE; /* -m option off */
  9485. XBOOLEAN force_digest        = FALSE; /* -d option off */
  9486. XBOOLEAN is_moderated        = FALSE; /* -M option off */
  9487. XBOOLEAN article_replies_to_author  = FALSE; /* -p option off */
  9488. XBOOLEAN message_replies_to_author  = FALSE; /* -P option off */
  9489. XBOOLEAN do_not_check_subscriptions = FALSE; /* -s option off */
  9490. XBOOLEAN append_to_digest;         /* gets set if anyone wants digests */
  9491. XBOOLEAN message_rejected    = FALSE;
  9492. XBOOLEAN interactive        = FALSE;
  9493. X
  9494. Xint     returned_msg        = 0;     /* Counts the invalid messages */
  9495. Xint     public_msg        = 0;     /* Counts the public messages */
  9496. Xint     digest_msg        = 0;     /* Counts the digest messages */
  9497. Xint    mails_sent        = 0;     /* Counts email sent */
  9498. Xint     listid            = -1;
  9499. Xint    maxrecipients        = 0;
  9500. Xint    lfd            = 2;
  9501. Xint    nlists            = 0;
  9502. X
  9503. Xtypedef struct _matched_prec_header {
  9504. X  char     *line;
  9505. X  struct _matched_prec_header *next;
  9506. X} MATCHED_PREC_HEADER;
  9507. X
  9508. XMATCHED_PREC_HEADER *matched_prec_header;
  9509. X
  9510. Xchar *mname[] = {
  9511. X  "jan", "feb", "mar", "apr", "may", "jun",
  9512. X  "jul", "aug", "sep", "oct", "nov", "dec",
  9513. X};
  9514. X
  9515. X/* The following warnings assume that the user address follows the SMTP
  9516. X   code where () are present -- not safe with messages from BITNET mailers.
  9517. X   list.c will have to be altered. Code still under testing. */
  9518. X
  9519. Xchar *warnings =    /* MAILER_DAEMON warnings */
  9520. X"^421 ([^ \t]+)|\
  9521. X^450 ([^ \t]+)|\
  9522. X^451 ([^ \t]+)|\
  9523. X^452 ([^ \t]+)|\
  9524. X^501 ([^ \t]+)|\
  9525. X^552 ([^ \t]+)|\
  9526. X^554 NO[ \t]+SUCH[ \t]+USER:?([^ \t]+)&~HOST[ \t]+UNKNOWN.+AUTHORITATIVE.+ANSWER.+FROM.+NAME.+SERVER|\
  9527. X^554 ([^ \t]+)&~HOST[ \t]+UNKNOWN.+AUTHORITATIVE.+ANSWER.+FROM.+NAME.+SERVER|\
  9528. XCONNECTION[ \t]+TIMED|\
  9529. XSERVICE[ \t]+UNAVAILABLE|\
  9530. XNETWORK[ \t]+IS[ \t]+UNREACHABLE|\
  9531. XUNKNOWN[ \t]+MAILER[ \t]+ERROR|\
  9532. XCONNECTION[ \t]+RESET|\
  9533. XREMOTE[ \t]+PROTOCOL[ \t]+ERROR|\
  9534. XTIMEOUT.+WAITING[ \t]+FOR[ \t]+INPUT|\
  9535. XPERMISSION[ \t]+DENIED|\
  9536. XCONNECTION[ \t]+ABORTED|\
  9537. XCONNECTION[ \t]+REFUSED|\
  9538. XQUOTA[ \t]+EXCEEDED|\
  9539. XDISK[ \t]+FULL|\
  9540. XUNKNOWN[ \t]+DOMAIN|\
  9541. XUNABLE.+SEND.+TO|\
  9542. XHOST[ \t]+UNKNOWN&~AUTHORITATIVE.+ANSWER.+FROM.+NAME.+SERVER|\
  9543. XNEVER.+HEARD.+OF.+HOST&~AUTHORITATIVE.+ANSWER.+FROM.+NAME.+SERVER|\
  9544. XUNABLE[ \t]+TO[ \t]+SEND[ \t]+MAIL";
  9545. X
  9546. Xchar *errors =        /* MAILER_DAEMON serious error messages */
  9547. X"UNKNOWN[ \t]+USER[ \t]+([^ \t]+)[ \t]+AT[ \t]+NODE[ \t]+([^ \t]+)|\
  9548. XNO[ \t]+SUCH[ \t]+USER[ \t]+([^ \t]+)[ \t]+AT[ \t]+NODE[ \t]+([^ \t]+)|\
  9549. XUNKNOWN[ \t]+USER[ \t]+([^ \t]+)[ \t]+AT[ \t]+SITE[ \t]+([^ \t]+)|\
  9550. XNO[ \t]+SUCH[ \t]+USER[ \t]+([^ \t]+)[ \t]+AT[ \t]+SITE[ \t]+([^ \t]+)|\
  9551. XUNKNOWN[ \t]+USER|\
  9552. XUSER[ \t]+UNKNOWN|\
  9553. XHOST[ \t]+UNKNOWN.+AUTHORITATIVE.+ANSWER.+FROM.+NAME.+SERVER|\
  9554. X^550 ";
  9555. X
  9556. Xchar *fatal_subjects =     /* Serious error messages in Subject: lines */
  9557. X"CAN.*T.+SEND.+FOR.+WEEK|\
  9558. XCAN.*T.+SEND.+FOR[ \t]+([^ \t]+)[ \t]+DAYS";
  9559. *-*-END-of-src/list.h-*-*
  9560. echo x - src/listserv.h
  9561. sed 's/^X//' >src/listserv.h <<'*-*-END-of-src/listserv.h-*-*'
  9562. X/*
  9563. X  AGREEMENT: This software can be used and distributed freely only as a
  9564. X  whole and not in parts, as long as you do not remove or alter the author
  9565. X  and copyright notices in the file defs.h; this notices are #define'd in
  9566. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  9567. X  provided for your personal use, you you may not alter the functions
  9568. X  create_header(), create_multi_recipient_header() and main() in list.c,
  9569. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  9570. X  any changes you may have made. No part of the source code bearing a
  9571. X  copyright notice can be included in commercial software systems without
  9572. X  written permission by the author.
  9573. X  By using this software you are bound by this agreement.
  9574. X  This software comes with no warranties and cannot be sold for profit.
  9575. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  9576. X  files when distributing this software.
  9577. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  9578. X  Use, duplication or disclosure by the Federal Government is subject to the
  9579. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  9580. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  9581. X
  9582. X  Below are the #define's pertinent to listserv.c
  9583. X
  9584. X  Preserve any quotes and new lines that appear below; change only path names.
  9585. X
  9586. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  9587. X
  9588. X*/
  9589. X
  9590. X#ifdef __STDC__
  9591. X# include "ansi/listserv.h"
  9592. X#else
  9593. X# include "nonansi/listserv.h"
  9594. X#endif
  9595. X#ifdef __NeXT__
  9596. X# include "next.h"
  9597. X#endif
  9598. X
  9599. X#define UPDATE_DATE      "June 1, 1993"
  9600. X#define RECIP_FILE        ".recip"
  9601. X#define USERS_FILE        "/tmp/users"
  9602. X#define PEER_SERVER_REQUEST "^(Peer Server Request:[ \t])"
  9603. X#define START_OF_SIGNATURE "--"
  9604. X#define ALIASES_TIMESTAMPF ".time.aliases"
  9605. X#define IGNORED_TIMESTAMPF ".time.ignored"
  9606. X#define INFO_TIMESTAMPF    ".time.info"
  9607. X#define SUBSCRIBERS_TIMESTAMPF ".time.subscrib"
  9608. X#define WELCOME_TIMESTAMPF ".time.welcome"
  9609. X#define NEWS_TIMESTAMPF    ".time.news"
  9610. X#define PEERS_TIMESTAMPF   ".time.peers"
  9611. X
  9612. X#define DELIVER_MAIL(recipient, copy_owner) \
  9613. X{\
  9614. X  if (fax_it) \
  9615. X    syscom ("%s < %s %s > /dev/null &", sys.fax.prog,\
  9616. X        MAILFORWARD, sys.fax.fax_no);\
  9617. X  else if (!interactive) {\
  9618. X    if ((++mails_sent) >= MAX_EMAILS)\
  9619. X      mails_sent = 0,\
  9620. X      sleep (30);\
  9621. X    if (sys.options & USE_SYSMAIL) \
  9622. X      sysmail (MAILFORWARD); \
  9623. X    else \
  9624. X      syscom ("%s '%s' '%s' < %s", sys.mail.method, \
  9625. X              (((sys.options & USE_TELNET) == 0) ? locase (recipient) : ""), \
  9626. X          ((copy_owner) ? \
  9627. X           ((listid >= 0 ? sys.lists[listid].owner : sys.manager)) \
  9628. X           : ""), MAILFORWARD);\
  9629. X  }\
  9630. X}
  9631. X
  9632. X#define APPEND_TELNET(func) \
  9633. X  if (!interactive && !fax_it && (sys.options & USE_TELNET)) {\
  9634. X    if ((f = fopen (MAILFORWARD, "a")) == NULL)\
  9635. X      report_progress (report, tsprintf ("%s(): Could not open %s", func, \
  9636. X                     MAILFORWARD), TRUE),\
  9637. X      gexit (1);\
  9638. X    COMPLETE_FILE (f);\
  9639. X    fclose (f);\
  9640. X  }
  9641. X
  9642. X#define NOTIFY_MANAGER(msg) \
  9643. X{\
  9644. X  create_header (&f, MAILFORWARD, sys.server.address, sys.manager, sender,\
  9645. X         FALSE, OK, TRUE, FALSE);\
  9646. X  fprintf (f, "%s %s\n", msg, sender);\
  9647. X  COMPLETE_TELNET (f);\
  9648. X  fclose (f);\
  9649. X  DELIVER_MAIL (sys.manager, FALSE);\
  9650. X  report_progress (report, tsprintf ("%s %s; forwarding message to %s\n", msg,\
  9651. Xsender, sys.manager), FALSE);\
  9652. X}
  9653. X
  9654. X#define NOTIFY_OF_BAD_ARCHIVE(msg, archive, reply_code) \
  9655. X{\
  9656. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,\
  9657. X         COPY_OWNER (ccerrors), reply_code, FALSE, TRUE);\
  9658. X  fprintf (f, msg, archive);\
  9659. X  COMPLETE_TELNET (f);\
  9660. X  fclose (f);\
  9661. X  DELIVER_MAIL (sender, COPY_OWNER (ccerrors));\
  9662. X}
  9663. X
  9664. X#define NOTIFY_OF_REQUEST_FORWARDING \
  9665. X{\
  9666. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,\
  9667. X         OK, FALSE, FALSE);\
  9668. X  if (interactive) {\
  9669. X    int ret;\
  9670. X    REMOTE *r = matched_rlists;\
  9671. X    fclose (f);\
  9672. X    while (r) {\
  9673. X      if (r->inet_addr[0] != EOS) {\
  9674. X    f = fopen (MAILFORWARD, "a");\
  9675. X        fprintf (f, "*** %s: Contacting UNIX ListServer %s @ %s, port %d ...\n",\
  9676. X         hostname, r->listserv, r->inet_addr, r->port);\
  9677. X        fclose (f);\
  9678. X        if ((ret = siul (r->inet_addr, r->port, sender, "", 60, MAILFORWARD,\
  9679. X                 request)) < 0)\
  9680. X      reply_code (SYS_ERROR),\
  9681. X      f = fopen (MAILFORWARD, "a"),\
  9682. X      fprintf (f, "### %s: Local system error. Please send email.\n",\
  9683. X           hostname),\
  9684. X      fclose (f);\
  9685. X    else if (ret == PEER_UNAVAIL)\
  9686. X      f = fopen (MAILFORWARD, "a"),\
  9687. X      fprintf (f, "### %s: Peer unavailable. Please send email.\n",\
  9688. X           hostname),\
  9689. X      fclose (f);\
  9690. X    else if (ret == CONN_ABORTED)\
  9691. X      f = fopen (MAILFORWARD, "a"),\
  9692. X      fprintf (f, "### %s: Connection aborted. Please send email.\n",\
  9693. X           hostname),\
  9694. X      fclose (f);\
  9695. X    else if (ret == CONN_TIMEOUT)\
  9696. X      f = fopen (MAILFORWARD, "a"),\
  9697. X      fprintf (f, "### %s: Connection timed out. Please send email.\n",\
  9698. X           hostname),\
  9699. X      fclose (f);\
  9700. X    else if (ret == SERVER_BUSY)\
  9701. X      reply_code (SERVER_BUSY),\
  9702. X      f = fopen (MAILFORWARD, "a"),\
  9703. X      fprintf (f, "### %s: Remote server busy. Please send email.\n",\
  9704. X           hostname),\
  9705. X      fclose (f);\
  9706. X    else if (ret == SYS_ERROR)\
  9707. X      reply_code (SYS_ERROR),\
  9708. X      f = fopen (MAILFORWARD, "a"),\
  9709. X      fprintf (f, "### %s: Remote system error. Please send email.\n",\
  9710. X           hostname),\
  9711. X      fclose (f);\
  9712. X      }\
  9713. X      else\
  9714. X    f = fopen (MAILFORWARD, "a"),\
  9715. X    fprintf (f, "??? %s: UNIX ListServer %s cannot be contacted; please \
  9716. Xsend email.\n", hostname, r->listserv),\
  9717. X    fclose (f);\
  9718. X      r = r->next;\
  9719. X    }\
  9720. X    return;\
  9721. X  }\
  9722. X  fprintf (f, "List %s is not local. Your request is forwarded to the \
  9723. Xfollowing list\nserver(s):\n\n", sys.lists[nlists].alias);\
  9724. X  {\
  9725. X    REMOTE *r = matched_rlists;\
  9726. X    while (r)\
  9727. X      fprintf (f, "%s (List address: %s)\n", r->listserv, r->address),\
  9728. X      r = r->next;\
  9729. X  }\
  9730. X  fprintf (f, "\nYou may wish to send any such future requests to this/these \
  9731. Xserver(s).\n");\
  9732. X  COMPLETE_TELNET (f);\
  9733. X  fclose (f);\
  9734. X  DELIVER_MAIL (sender, FALSE);\
  9735. X}
  9736. X
  9737. X#define FORWARD_REQUEST \
  9738. X  {\
  9739. X    REMOTE *r = matched_rlists;\
  9740. X    while (r) {\
  9741. X      create_header (&f, MAILFORWARD, sender, r->listserv, "", FALSE, OK, \
  9742. X             FALSE, FALSE);\
  9743. X      fprintf (f, "%s\n", request);\
  9744. X      COMPLETE_TELNET (f);\
  9745. X      fclose (f);\
  9746. X      DELIVER_MAIL (r->listserv, FALSE);\
  9747. X      r = r->next;\
  9748. X    }\
  9749. X  }
  9750. X
  9751. X#define MEMBERS_ONLY \
  9752. X{\
  9753. X  BOOLEAN ok_to_reset_address = FALSE;\
  9754. X  if ((sys.lists[listid].defaults.set_values[0][0] == EOS &&\
  9755. X       !strcmp (default_values [0], "VARIABLE")) ||\
  9756. X      (!strcmp (sys.lists[listid].defaults.set_values[0], "VARIABLE")))\
  9757. X    ok_to_reset_address = TRUE;\
  9758. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,\
  9759. X         COPY_OWNER (ccprivate), RESTRICTED_REQ, FALSE, FALSE);\
  9760. X  fprintf (f, "%s: List %s is private for members only.\nOnly subscribers may \
  9761. Xissue this request.\n", sender, sys.lists[listid].alias);\
  9762. X  if (alternate_addresses) {\
  9763. X    fprintf (f, "\nIn addition, the system found the following \
  9764. Xaddress(es) that resemble yours.\nIf one of these is you, please resend your \
  9765. Xmessage from that one%s:\n\n",\
  9766. X         (ok_to_reset_address ? \
  9767. X          ", or use the\n'set <list> address' request to change the \
  9768. Xaddress you are subscribed with" :\
  9769. X          ""));\
  9770. X    {\
  9771. X      int i;\
  9772. X      for (i = 0; alternate_addresses[i]; ++i)\
  9773. X    fprintf (f, "%s\n", alternate_addresses[i]),\
  9774. X    free ((char *) alternate_addresses[i]);\
  9775. X      free ((char **) alternate_addresses);\
  9776. X      alternate_addresses = NULL;\
  9777. X      fprintf (f, "\n");\
  9778. X    }\
  9779. X  }\
  9780. X  COMPLETE_TELNET (f);\
  9781. X  fclose (f);\
  9782. X  DELIVER_MAIL (sender, COPY_OWNER (ccprivate));\
  9783. X}
  9784. X
  9785. X#define NOT_LIST_OWNER \
  9786. X{\
  9787. X  reject_mail (sender, request, tsprintf ("%s: You are not the owner of this \
  9788. Xlist\n", sender), NOT_OWNER, 0);\
  9789. X  if (!interactive) {\
  9790. X    create_header (&f, MAILFORWARD, sys.server.address,sys.lists[listid].owner,\
  9791. X           "WARNING: Hacker attack", FALSE, NOT_OWNER, TRUE, FALSE);\
  9792. X    fprintf (f, "The following request was sent to this ListServer by %s:\n\n%s\
  9793. X\nThe password provided appears in the report file\n",\
  9794. X         sender, request);\
  9795. X    COMPLETE_TELNET (f);\
  9796. X    fclose (f);\
  9797. X    DELIVER_MAIL (sys.lists[listid].owner, FALSE);\
  9798. X  }\
  9799. X}
  9800. X
  9801. X#define NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS(__address__) \
  9802. X{\
  9803. X  report_progress (report, "Syntax error in user address\n", FALSE);\
  9804. X  create_header (&f, MAILFORWARD, sys.server.address, sys.manager,\
  9805. X                 "Syntax error in user address", FALSE, SYNTAX_ERROR, TRUE,\
  9806. X         TRUE);\
  9807. X  if (request [0] != EOS)\
  9808. X    fprintf (f, ">%s\n", request);\
  9809. X  fprintf (f, "Error detected in user address: %s\nNo requests processed.\n",\
  9810. X __address__);\
  9811. X  COMPLETE_TELNET (f);\
  9812. X  fclose (f);\
  9813. X  DELIVER_MAIL (sys.manager, FALSE);\
  9814. X}
  9815. X
  9816. X#define NO_SUCH_MESSAGE_TAG(_tag_)\
  9817. X{\
  9818. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,\
  9819. X         SYNTAX_ERROR, FALSE, TRUE);\
  9820. X  fprintf (f, "No message found with tag number %d.\n", _tag_);\
  9821. X  COMPLETE_TELNET (f);\
  9822. X  fclose (f);\
  9823. X  DELIVER_MAIL (sender, FALSE);\
  9824. X}
  9825. X
  9826. X#define CANNOT_LOCK_FILE(_file_)\
  9827. X{\
  9828. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,\
  9829. X         SYS_ERROR, FALSE, TRUE);\
  9830. X  fprintf (f, "Cannot lock file %s.\nYour request has to be resubmitted.\n",\
  9831. X_file_);\
  9832. X  COMPLETE_TELNET (f);\
  9833. X  fclose (f);\
  9834. X  DELIVER_MAIL (sender, FALSE);\
  9835. X}
  9836. X
  9837. X#define COMMAND(index, _name_, _mask_, _func_)\
  9838. X  commands[index].name = _name_;\
  9839. X  commands[index].mask = _mask_;\
  9840. X  commands[index].func = (FUNC) _func_
  9841. X
  9842. X#define PUT_TIMESTAMP(_targetfile_, _stampfile_) \
  9843. X  stat (_targetfile_, &stat_buf);\
  9844. X  echo (tsprintf ("%d", stat_buf.st_mtime), _stampfile_)
  9845. X
  9846. X#define COPY_MESSAGE \
  9847. X{\
  9848. X  char *error;\
  9849. X  long int len, written;\
  9850. X  sign[0] = RESET (line);\
  9851. X  signature = FALSE;\
  9852. X  sprintf (sign, "%s\n", START_OF_SIGNATURE);\
  9853. X  while (!feof (mail) && /* Copy till eof or next message */\
  9854. X         (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {\
  9855. X    if (!strcmp (line, sign))\
  9856. X      signature = TRUE;\
  9857. X    else if (!signature)\
  9858. X      if ((written = write_to_fd (fileno (f), line, (len = strlen (line)))) \
  9859. X      < 0) {\
  9860. X    echo_append ((error = tsprintf ("write() failed; wrote %ld bytes \
  9861. Xout of %ld requested; errno %d", abs (written), len, errno)), WARNING);\
  9862. X    if (sys.options & BSD_MAIL)\
  9863. X      syscom ("echo '%s' | %s -s 'write() failed; system shut down' %s",\
  9864. X          error, UCB_MAIL, sys.manager);\
  9865. X    exit (16);\
  9866. X      }\
  9867. X    RESET (line);\
  9868. X    fgets (line, MAX_LINE - 2, mail);\
  9869. X  }\
  9870. X  if (!strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))\
  9871. X    fseek (mail, -strlen (line), SEEK_CUR); /* Move back to beginning */\
  9872. X}
  9873. X
  9874. X#define CHECK_TIMESTAMP(_stampfile_, _targetfile_)\
  9875. X  if ((f = fopen (_stampfile_, "r")) != NULL) {\
  9876. X    fscanf (f, "%d\n", ×tamp);\
  9877. X    fclose (f);\
  9878. X    stat (_targetfile_, &stat_buf);\
  9879. X    if (stat_buf.st_mtime != timestamp) {\
  9880. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,\
  9881. X             FALSE, PERMISSION_DENIED, FALSE, TRUE);\
  9882. X      fprintf (f, "File %s has been modified since you last\nedited it. The \
  9883. Xfile has to be reedited again.\n%s\
  9884. XYour PUT request is returned to you unprocessed below:\
  9885. X\n\n%s\n", _targetfile_, \
  9886. X(!interactive ? \
  9887. X"An EDIT request will be forced now and the new file will arrive \
  9888. Xin a separate\nmessage.\n\n" : ""), \
  9889. Xrequest);\
  9890. X      COPY_MESSAGE;\
  9891. X      COMPLETE_TELNET (f);\
  9892. X      fclose (f);\
  9893. X      DELIVER_MAIL (sender, FALSE);\
  9894. X      upcase (sender);\
  9895. X      if (!interactive) /* No need to force EDIT for a live request */\
  9896. X        get_sys_files ("EDIT", params_copy, sender);\
  9897. X      return;\
  9898. X    }\
  9899. X  }
  9900. X
  9901. X#define REMOVE_ADDRESS(address, from, to) \
  9902. X{\
  9903. X  FILE *fin, *fout;\
  9904. X  long int len, written;\
  9905. X  char line[MAX_LINE], linecopy[MAX_LINE], *error;\
  9906. X  BOOLEAN removed = FALSE;\
  9907. X  OPEN_FILE (fin, from, "r", "unsubscribe");\
  9908. X  OPEN_FILE (fout, to, "w", "unsubscribe");\
  9909. X  while (!feof (fin)) {\
  9910. X    RESET (line);\
  9911. X    fgets (line, MAX_LINE - 2, fin);\
  9912. X    strcpy (linecopy, line);\
  9913. X    upcase (linecopy);\
  9914. X    if (line[0] != EOS) {\
  9915. X      if (linecopy[strlen (linecopy) - 1] == '\n')\
  9916. X    linecopy[strlen (linecopy) - 1] = EOS;\
  9917. X      if (removed || re_strcmp (address, linecopy, NULL) <= 0) {\
  9918. X    if ((written = write_to_fd (fileno (fout), line, (len = strlen (line))))\
  9919. X        < 0) {\
  9920. X      echo_append ((error = tsprintf ("write() failed; wrote %ld bytes \
  9921. Xout of %ld requested to file %s; errno %d", abs (written), len, to, errno)), WARNING);\
  9922. X      if (sys.options & BSD_MAIL)\
  9923. X        syscom ("echo '%s' | %s -s 'write() failed; system shut down' %s",\
  9924. X            error, UCB_MAIL, sys.manager);\
  9925. X      exit (16);\
  9926. X    }\
  9927. X      }\
  9928. X      else\
  9929. X    removed = TRUE;\
  9930. X    }\
  9931. X  }\
  9932. X  fclose (fin);\
  9933. X  fclose (fout);\
  9934. X}
  9935. X
  9936. X#define THANKS    "THANK|GRACIAS|TODA|MERCI|DANK|ARIGATO|XIE.*XIE|DZENKUJEM|\
  9937. XTAK|D'AKUJEM|MAHALO|BEDANKT|GROET|E.[XH]AR[IH]ST[OW]|SINCERELY|TRULY|LATER|\
  9938. XSPOCIBO"
  9939. X
  9940. X
  9941. Xchar recipf [MAX_LINE];      /* path to list + RECIP_FILE */
  9942. Xchar requests_file [MAX_LINE];
  9943. Xchar original_params [10240];
  9944. Xchar aliases_timestampf [MAX_LINE];
  9945. Xchar ignored_timestampf [MAX_LINE];
  9946. Xchar info_timestampf [MAX_LINE];
  9947. Xchar subscribers_timestampf [MAX_LINE];
  9948. Xchar welcome_timestampf [MAX_LINE];
  9949. Xchar news_timestampf [MAX_LINE];
  9950. Xchar peers_timestampf [MAX_LINE];
  9951. Xchar psr_string [MAX_LINE];
  9952. X
  9953. XFILE *mail        = NULL; /* Source of messages */
  9954. XFILE *report      = NULL; /* Progress report to the administrator */
  9955. XFILE *ignored     = NULL; /* List of people whose messages are ignored */
  9956. XFILE *msg_no      = NULL; /* Last message count */
  9957. XFILE *message_ids = NULL; /* List of message ids */
  9958. X
  9959. Xint     lfd            = 2;
  9960. Xint      listid            = -1;
  9961. Xint      request_no        = 0;    /* Counts the public messages */
  9962. Xint      nlists            = -1;    /* # of lists defined in CONFIG */
  9963. Xint     mails_sent        = 0;    /* Count mail sent */
  9964. Xlong int restricted_commands    = 0;    /* Mask of restrictions */
  9965. Xlong int disabled_commands    = 0;    /* Mask for disabling commands */
  9966. Xlong int batched_commands    = 0;    /* Mask for batching commands */
  9967. XBOOLEAN  one_rejection        = FALSE;
  9968. XBOOLEAN  restart_sys        = FALSE;
  9969. XBOOLEAN  tty_echo        = FALSE;    /* -e option off */
  9970. XBOOLEAN  do_not_notify_peer_server = FALSE;
  9971. XBOOLEAN  peer_server_request    = FALSE;
  9972. XBOOLEAN  process_batch        = FALSE;    /* -B option off */
  9973. XBOOLEAN  interactive        = FALSE;    /* -i option off */
  9974. XBOOLEAN  fax_it            = FALSE;
  9975. Xchar     hostname [256];
  9976. X
  9977. X/* Codes for helpful messages when a request is rejected. */
  9978. X#define REJECT_LIST    1
  9979. X#define REJECT_REQUEST    2
  9980. X#define REJECT_NAME    3
  9981. X#define REJECT_AT    4
  9982. *-*-END-of-src/listserv.h-*-*
  9983. echo x - src/next.h
  9984. sed 's/^X//' >src/next.h <<'*-*-END-of-src/next.h-*-*'
  9985. X/*
  9986. X  #define's specific to NeXT hosts.
  9987. X*/
  9988. X
  9989. X#ifndef S_IRWXU
  9990. X# define     S_IRWXU 0000700 /* rwx, owner */
  9991. X#endif
  9992. X#ifndef S_IRUSR
  9993. X# define         S_IRUSR 0000400 /* read permission, owner */
  9994. X#endif
  9995. X#ifndef S_IWUSR
  9996. X# define         S_IWUSR 0000200 /* write permission, owner */
  9997. X#endif
  9998. X#ifndef S_IXUSR
  9999. X# define         S_IXUSR 0000100 /* execute/search permission, owner */
  10000. X#endif
  10001. X#ifndef S_IRWXG
  10002. X# define     S_IRWXG 0000070 /* rwx, group */
  10003. X#endif
  10004. X#ifndef S_IRGRP
  10005. X# define         S_IRGRP 0000040 /* read permission, group */
  10006. X#endif
  10007. X#ifndef S_IWGRP
  10008. X# define         S_IWGRP 0000020 /* write permission, grougroup */
  10009. X#endif
  10010. X#ifndef S_IXGRP
  10011. X# define         S_IXGRP 0000010 /* execute/search permission, group */
  10012. X#endif
  10013. X#ifndef S_IRWXO
  10014. X# define     S_IRWXO 0000007 /* rwx, other */
  10015. X#endif
  10016. X#ifndef S_IROTH
  10017. X# define         S_IROTH 0000004 /* read permission, other */
  10018. X#endif
  10019. X#ifndef S_IWOTH
  10020. X# define         S_IWOTH 0000002 /* write permission, other */
  10021. X#endif
  10022. X#ifndef S_IXOTH
  10023. X# define         S_IXOTH 0000001 /* execute/search permission, other */
  10024. X#endif
  10025. *-*-END-of-src/next.h-*-*
  10026. echo x - src/pqueue.h
  10027. sed 's/^X//' >src/pqueue.h <<'*-*-END-of-src/pqueue.h-*-*'
  10028. X/*
  10029. X  AGREEMENT: This software can be used and distributed freely only as a
  10030. X  whole and not in parts, as long as you do not remove or alter the author
  10031. X  and copyright notices in the file defs.h; this notices are #define'd in
  10032. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10033. X  provided for your personal use, you you may not alter the functions
  10034. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10035. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10036. X  any changes you may have made. No part of the source code bearing a
  10037. X  copyright notice can be included in commercial software systems without
  10038. X  written permission by the author.
  10039. X  By using this software you are bound by this agreement.
  10040. X  This software comes with no warranties and cannot be sold for profit.
  10041. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10042. X  files when distributing this software.
  10043. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  10044. X  Use, duplication or disclosure by the Federal Government is subject to the
  10045. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10046. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10047. X
  10048. X  Below are the #define's pertinent to pqueue.c
  10049. X
  10050. X  Preserve any quotes and new lines that appear below; change only path names.
  10051. X
  10052. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  10053. X
  10054. X*/
  10055. X
  10056. X#ifdef __NeXT__
  10057. X# include "next.h"
  10058. X#endif
  10059. X
  10060. XFILE    *report        = NULL;  /* Progress report */
  10061. XBOOLEAN tty_echo    = FALSE; /* -e option off */
  10062. Xint    lfd        = 2;
  10063. Xint    listid        = -1;    /* Dummy */
  10064. *-*-END-of-src/pqueue.h-*-*
  10065. echo x - src/regexp.h
  10066. sed 's/^X//' >src/regexp.h <<'*-*-END-of-src/regexp.h-*-*'
  10067. X/*
  10068. X * Definitions etc. for regexp(3) routines.
  10069. X *
  10070. X * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
  10071. X * not the System V one.
  10072. X */
  10073. X#define NSUBEXP  10
  10074. Xtypedef struct regexp {
  10075. X    char *startp[NSUBEXP];
  10076. X    char *endp[NSUBEXP];
  10077. X    char regstart;        /* Internal use only. */
  10078. X    char reganch;        /* Internal use only. */
  10079. X    char *regmust;        /* Internal use only. */
  10080. X    int regmlen;        /* Internal use only. */
  10081. X    char program[1];    /* Unwarranted chumminess with compiler. */
  10082. X} regexp;
  10083. X
  10084. Xextern regexp *regcomp();
  10085. Xextern int regexec();
  10086. Xextern void regsub();
  10087. Xextern void regerror();
  10088. *-*-END-of-src/regexp.h-*-*
  10089. echo x - src/regmagic.h
  10090. sed 's/^X//' >src/regmagic.h <<'*-*-END-of-src/regmagic.h-*-*'
  10091. X/*
  10092. X * The first byte of the regexp internal "program" is actually this magic
  10093. X * number; the start node begins in the second byte.
  10094. X */
  10095. X#define    MAGIC    0234
  10096. *-*-END-of-src/regmagic.h-*-*
  10097. echo x - src/serverd.h
  10098. sed 's/^X//' >src/serverd.h <<'*-*-END-of-src/serverd.h-*-*'
  10099. X/*
  10100. X  AGREEMENT: This software can be used and distributed freely only as a
  10101. X  whole and not in parts, as long as you do not remove or alter the author
  10102. X  and copyright notices in the file defs.h; this notices are #define'd in
  10103. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10104. X  provided for your personal use, you you may not alter the functions
  10105. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10106. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10107. X  any changes you may have made. No part of the source code bearing a
  10108. X  copyright notice can be included in commercial software systems without
  10109. X  written permission by the author.
  10110. X  By using this software you are bound by this agreement.
  10111. X  This software comes with no warranties and cannot be sold for profit.
  10112. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10113. X  files when distributing this software.
  10114. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  10115. X  Use, duplication or disclosure by the Federal Government is subject to the
  10116. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10117. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10118. X
  10119. X  Below are the #define's pertinent to serverd.c
  10120. X
  10121. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  10122. X
  10123. X*/
  10124. X
  10125. X#ifdef __STDC__
  10126. X# include "ansi/serverd.h"
  10127. X#else
  10128. X# include "nonansi/serverd.h"
  10129. X#endif
  10130. X
  10131. X#ifdef __NeXT__
  10132. X# include "next.h"
  10133. X#endif
  10134. X
  10135. X#define MAX_TRIES     10        /* wait MAX_TRIES * 30 seconds */
  10136. X
  10137. XFILE    *report        = NULL;
  10138. XBOOLEAN tty_echo    = FALSE;    /* -e option off */
  10139. X
  10140. Xstruct _list_limits {
  10141. X  char list_limitsf [MAX_LINE],
  10142. X       list_mail_f [MAX_LINE],
  10143. X       digest_msgf [MAX_LINE],
  10144. X       digest_timef [MAX_LINE];
  10145. X  int  nmessages;
  10146. X  long int current_date;
  10147. X  BOOLEAN done_for_the_day;
  10148. X} lists [MAX_LISTS];
  10149. X
  10150. Xchar *exit_string[] = {  /* Define exit status strings */
  10151. X/* 0 */ "OK", 
  10152. X/* 1 */ "Could not open or lock file", 
  10153. X/* 2 */ "SIGINT signal",
  10154. X/* 3 */ "Command line option error",
  10155. X/* 4 */ "Syntax error in file",
  10156. X/* 5 */ "Could not spawn",
  10157. X/* 6 */ "Shutdown request",
  10158. X/* 7 */ "Restart request",
  10159. X/* 8 */ "Received system signal",
  10160. X/* 9 */ "Too many multiple recipients",
  10161. X/* 10 */"Could not deliver mail",
  10162. X/* 11 */"Malloc failed",
  10163. X/* 12 */"Cannot fork",
  10164. X/* 13 */"Socket connection problem",
  10165. X/* 14 */"Semaphore error",
  10166. X/* 15 */"Cannot setuid, setgid",
  10167. X/* 16 */"Internal error",
  10168. X/* 17 */"Unknown exit status"
  10169. X};
  10170. X
  10171. X#ifdef GO_INTERACTIVE
  10172. XBOOLEAN interactive    = FALSE;    /* -i option off */
  10173. X#endif
  10174. Xint    lfd     = 2;
  10175. Xint    nlists;
  10176. Xint    ppid;
  10177. X
  10178. X#ifndef WAIT3_NEEDS_UNION
  10179. X# if defined (sequent) || defined (stardent) || defined (stellar) || \
  10180. X  defined (titan) || defined (unknown_port)
  10181. X#  ifdef WEXITSTATUS
  10182. X#   undef WEXITSTATUS
  10183. X#  endif
  10184. X#  ifdef WTERMSIG
  10185. X#   undef WTERMSIG
  10186. X#  endif
  10187. X#  ifdef WIFSIGNALED
  10188. X#   undef WIFSIGNALED
  10189. X#  endif
  10190. X#  ifdef WIFEXITED
  10191. X#   undef WIFEXITED
  10192. X#  endif
  10193. X# endif
  10194. X#endif
  10195. X
  10196. X#ifndef WEXITSTATUS
  10197. X# define  WEXITSTATUS(stat)    ((int)(((stat)>>8)&0377))
  10198. X#endif
  10199. X
  10200. X#ifdef GO_INTERACTIVE
  10201. X# ifndef WTERMSIG
  10202. X#  define WTERMSIG(stat)    (((int)((stat)&0377))&0177)
  10203. X# endif
  10204. X# ifndef WIFSIGNALED
  10205. X#  define WIFSIGNALED(stat)    (((int)((stat)&0377))>0&&((int)(((stat)>>8)&\
  10206. X                0377))==0)
  10207. X# endif
  10208. X# ifndef WIFEXITED
  10209. X#  define WIFEXITED(stat)    (((int)((stat)&0377))==0)
  10210. X# endif
  10211. X# include "iulp.h"
  10212. X
  10213. X# ifndef MAX_CONNECTIONS
  10214. X#  define MAX_CONNECTIONS 5
  10215. X# endif
  10216. X# define TIMEOUT_SIG    SIGUSR1    /* Signal sent when client is preempted */
  10217. X# define ABORT_SIG    SIGUSR2 /* Signal sent when server shuts down */
  10218. X
  10219. X# define LOGIN        "email address [none]: "
  10220. X# define PASSWORD    "Password: "
  10221. X# define PROMPT        "request> "
  10222. X# define CONT_PROMPT    "> "
  10223. X
  10224. X# define MANAGER_LOGIN \
  10225. X"You have logged in with manager privileges; you may not issue 'execute'\n\
  10226. Xrequests.\n\n"
  10227. X
  10228. X# define OWNER_LOGIN \
  10229. X"You have logged in with owner privileges; valid requests are:\n\n\
  10230. Xhelp [topic]\n\
  10231. Xset <list> [<option> <arg[s]>] -\n\
  10232. X\toption: mail, password, address, conceal\n\
  10233. X\targ for 'mail': ack/noack/postpone/digest\n\
  10234. X\targs for 'password': <current-password> <new-password>\n\
  10235. X\targs for 'address': <current-password> <new-address>\n\
  10236. X\targ for 'conceal': yes/no\n\
  10237. Xunsubscribe <list> - alias signoff\n\
  10238. Xrecipients <list> - alias review\n\
  10239. Xinformation <list>\n\
  10240. Xstatistics <list> [subscriber email address(es)] [-all]\n\
  10241. Xrun <list> [password cmd [args]]\n\
  10242. Xlists\n\
  10243. Xwhich\n\
  10244. Xindex [archive | path-to-archive] [/password] [-all]\n\
  10245. Xget <archive | path-to-archive> <file> [/password] [parts]\n\
  10246. Xsearch <archive | path-to-archive> [/password] [-all] <pattern>\n\
  10247. Xrelease\n\
  10248. Xsystem <list> <password> <user-address> #user-request\n\
  10249. Xreports <list> <password>\n\
  10250. Xedit <list> <password> <file>\n\
  10251. X\tfile: subscribers/aliases/news/peers/ignored/info/welcome\n\
  10252. Xput <list> <password> <keyword> [args]\n\
  10253. X\tkeyword:alias/ignore/subscribers/aliases/news/peers/ignored/info/welcome\n\
  10254. X\targs:email address for alias/ignore\n\
  10255. Xapprove <list> <password> <tag>\n\
  10256. Xdiscard <list> <password> <tag>\n\n\
  10257. XYou may replace the administrative <password> with -\n\
  10258. XBuilt in commands are: quit/exit, ?/privileges, timeleft, binary, ascii\n\
  10259. XRequests may be continued on another line if they are terminated with &\\n\n\
  10260. XInput/output may be redirected with <, > and >>.\n\
  10261. XUNIX pipes are formed with the \"|\" symbol.\n\
  10262. XFor 'fax' requests, please send email.\n\
  10263. XUsing BINARY as default transfer mode.\n\n"
  10264. X
  10265. X# define SUBSCRIBER_LOGIN \
  10266. X"You have logged in with subscriber privileges; you may only issue the \
  10267. Xfollowing\nrequests:\n\n\
  10268. Xhelp [topic]\n\
  10269. Xset <list> [<option> <arg[s]>] -\n\
  10270. X\toption: mail, password, address, conceal\n\
  10271. X\targ for 'mail': ack/noack/postpone/digest\n\
  10272. X\targs for 'password': <current-password> <new-password>\n\
  10273. X\targs for 'address': <current-password> <new-address>\n\
  10274. X\targ for 'conceal': yes/no\n\
  10275. Xunsubscribe <list> - alias signoff\n\
  10276. Xrecipients <list> - alias review\n\
  10277. Xinformation <list>\n\
  10278. Xstatistics <list> [subscriber email address(es)] [-all]\n\
  10279. Xrun <list> [password cmd [args]]\n\
  10280. Xlists\n\
  10281. Xwhich\n\
  10282. Xindex [archive | path-to-archive] [/password] [-all]\n\
  10283. Xget <archive | path-to-archive> <file> [/password] [parts]\n\
  10284. Xsearch <archive | path-to-archive> [/password] [-all] <pattern>\n\
  10285. Xrelease\n\n\
  10286. X<current-password> can be replaced with -\n\
  10287. XBuilt in commands are: quit/exit, ?/privileges, timeleft, binary, ascii\n\
  10288. XRequests may be continued on another line if they are terminated with &\\n\n\
  10289. XInput/output may be redirected with <, > and >>.\n\
  10290. XUNIX pipes are formed with the \"|\" symbol.\n\
  10291. XFor 'fax' requests, please send email.\n\
  10292. XUsing BINARY as default transfer mode.\n\n"
  10293. X
  10294. X# define GENERAL_LOGIN \
  10295. X"You have logged in as a casual user; you may only issue the following \
  10296. Xrequests:\n\n\
  10297. Xhelp [topic]\n\
  10298. Xrecipients <list> - alias review\n\
  10299. Xinformation <list>\n\
  10300. Xstatistics <list> [subscriber email address(es)] [-all]\n\
  10301. Xlists\n\
  10302. Xindex [archive | path-to-archive] [/password] [-all]\n\
  10303. Xget <archive | path-to-archive> <file> [/password] [parts]\n\
  10304. Xsearch <archive | path-to-archive> [/password] [-all] <pattern>\n\
  10305. Xrelease\n\n\
  10306. XBuilt in commands are: quit/exit, ?/privileges, timeleft, binary, ascii\n\
  10307. XRequests may be continued on another line if they are terminated with &\\n\n\
  10308. XInput/output may be redirected with <, > and >>.\n\
  10309. XUNIX pipes are formed with the \"|\" symbol.\n\
  10310. XFor 'fax' requests, please send email.\n\
  10311. XUsing BINARY as default transfer mode.\n\n"
  10312. X
  10313. X# define SERVER_BUSY_ \
  10314. X"All interactive UNIX ListServer ports are busy. Please try again later.\n"
  10315. X
  10316. X# define GOOD_BYE \
  10317. X"UNIX ListServer closing connection.\n"
  10318. X
  10319. X# define CONN_TIMED_OUT \
  10320. X"Connection timed out.\n"
  10321. X
  10322. X# define SERVER_SHUTS_DOWN \
  10323. X"Server shutting down.\n"
  10324. X
  10325. X# define REMOTE_SYS_ERROR \
  10326. X"Remote system error.\n"
  10327. X
  10328. X# define MORE_INPUT \
  10329. X"[Enter text below, end with a '.' in a line by itself]\n"
  10330. X
  10331. X# define NULL_REDIRECT \
  10332. X"Invalid null output redirect\n"
  10333. X
  10334. X# define BINARY_XFER \
  10335. X"Transfer mode reset to binary\n"
  10336. X
  10337. X# define ASCII_XFER \
  10338. X"Transfer mode reset to ASCII\n"
  10339. X
  10340. X# define SERVICING_OTHER_CONN \
  10341. X"Server busy processing another request; please wait...\n"
  10342. X
  10343. X# define YOU_ARE_NEXT \
  10344. X"Processing your request...\n"
  10345. X
  10346. X# define CLIENT_LOST(exitcode) \
  10347. Xclose (msg_sock),\
  10348. X_exit (exitcode)  
  10349. X
  10350. X# define REPLY(msg_sock, code, bytes)\
  10351. X{\
  10352. X  sprintf (reply, "%d %d \n", code, (bytes));\
  10353. X  if (write_to_fd (msg_sock, reply, strlen (reply)) < 0)\
  10354. X    CLIENT_LOST (13);\
  10355. X}
  10356. X# define REPLY_FILE(msg_sock, code, bytes, file)\
  10357. X{\
  10358. X  sprintf (reply, "%d %d %s\n", code, (bytes), file);\
  10359. X  if (write_to_fd (msg_sock, reply, strlen (reply)) < 0)\
  10360. X    CLIENT_LOST (13);\
  10361. X}
  10362. X
  10363. X# define CLOSE_CLIENT(msg_sock) \
  10364. X  if (msg_sock >= 0) {\
  10365. X    REPLY (msg_sock, CONN_CLOSED, strlen (GOOD_BYE));\
  10366. X    write_to_fd (msg_sock, GOOD_BYE, strlen (GOOD_BYE));\
  10367. X    close (msg_sock);\
  10368. X  }
  10369. X
  10370. X# define CANNOT_CONNECT(__msg__, __code__, __reply__) \
  10371. X{\
  10372. X  sprintf (msg, "%d %d %s %d %d\n%d %d \n%s", CONNECT, conn_duration,\
  10373. X       version, strlen (PROMPT), strlen (CONT_PROMPT), __code__,\
  10374. X       strlen (__reply__), __reply__);\
  10375. X  write_to_fd (msg_sock, msg, strlen (msg));\
  10376. X  close (msg_sock);\
  10377. X  report_progress (report, __msg__, TRUE);\
  10378. X}
  10379. X
  10380. X# define GET_LOGIN(buf) \
  10381. X{\
  10382. X  ch = EOS;\
  10383. X  bytes_read = 0;\
  10384. X  while (ch != '\n' && bytes_read < MAX_LINE) {\
  10385. X    if (read (msg_sock, &ch, 1) <= 0 || ch == EOF)\
  10386. X      goto abort;\
  10387. X    if (time (0) - time_started > conn_duration)\
  10388. X      close_connection (TIMEOUT_SIG);\
  10389. X    buf [bytes_read++] = ((ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r')\
  10390. X|| (ch == (char) 127) ? ((char) 0) : ch);\
  10391. X  }\
  10392. X  buf [bytes_read] = EOS;\
  10393. X  clean_request (buf);\
  10394. X  l = 0;\
  10395. X  while (buf [l] != EOS) {\
  10396. X    if (buf [l] == '\n' || buf [l] == '\r')\
  10397. X      buf [l] = EOS;\
  10398. X    ++l;\
  10399. X  }\
  10400. X}
  10401. X
  10402. X# ifndef SYSLOG
  10403. X#  define IN_CRITICAL_SECTION(__func__, msg_sock) \
  10404. X{\
  10405. X  char msg [256];\
  10406. X  long int time_started, time_is, delay = 0;\
  10407. X  time (&time_started);\
  10408. X  while (interactive && msg_sock && !semctl (sid, 0, GETVAL)) {\
  10409. X    REPLY (msg_sock, MESSAGE, strlen (SERVICING_OTHER_CONN));\
  10410. X    write_to_fd (msg_sock, SERVICING_OTHER_CONN,strlen (SERVICING_OTHER_CONN));\
  10411. X    --time_started;\
  10412. X    while (((time (0) - time_started) % 10) && !semctl (sid, 0, GETVAL));\
  10413. X    delay = 1;\
  10414. X  }\
  10415. X  if (interactive && P (sid) < 0) {\
  10416. X    report_progress (report, tsprintf ("\n%s(): Error P()", __func__), TRUE);\
  10417. X    fclose (report);\
  10418. X    CLOSE_CLIENT (msg_sock);\
  10419. X    _exit (14);\
  10420. X  }\
  10421. X  if (delay) {\
  10422. X    REPLY (msg_sock, MESSAGE, strlen (YOU_ARE_NEXT));\
  10423. X    write_to_fd (msg_sock, YOU_ARE_NEXT, strlen (YOU_ARE_NEXT));\
  10424. X  }\
  10425. X}
  10426. X# else
  10427. X#  define IN_CRITICAL_SECTION(__func__, msg_sock) \
  10428. X{\
  10429. X  char msg [256];\
  10430. X  long int time_started, time_is, delay = 0;\
  10431. X  time (&time_started);\
  10432. X  while (interactive && msg_sock && !semctl (sid, 0, GETVAL)) {\
  10433. X    REPLY (msg_sock, MESSAGE, strlen (SERVICING_OTHER_CONN));\
  10434. X    write_to_fd (msg_sock, SERVICING_OTHER_CONN,strlen (SERVICING_OTHER_CONN));\
  10435. X    --time_started;\
  10436. X    while (((time (0) - time_started) % 10) && !semctl (sid, 0, GETVAL));\
  10437. X    delay = 1;\
  10438. X  }\
  10439. X  if (interactive && P (sid) < 0) {\
  10440. X    report_progress (report, tsprintf ("\n%s(): Error P()", __func__), TRUE);\
  10441. X    CLOSE_CLIENT (msg_sock);\
  10442. X    _exit (14);\
  10443. X  }\
  10444. X  if (delay) {\
  10445. X    REPLY (msg_sock, MESSAGE, strlen (YOU_ARE_NEXT));\
  10446. X    write_to_fd (msg_sock, YOU_ARE_NEXT, strlen (YOU_ARE_NEXT));\
  10447. X  }\
  10448. X}
  10449. X# endif
  10450. X
  10451. X# ifndef SYSLOG
  10452. X#  define OUT_OF_CRITICAL_SECTION(__func__) \
  10453. X{\
  10454. X  char msg [256];\
  10455. X  if (interactive && V (sid) < 0) {\
  10456. X    report_progress (report, tsprintf ("\n%s(): Error V()", __func__), TRUE);\
  10457. X    fclose (report);\
  10458. X    CLOSE_CLIENT (msg_sock);\
  10459. X    _exit (14);\
  10460. X  }\
  10461. X}
  10462. X# else
  10463. X#  define OUT_OF_CRITICAL_SECTION(__func__) \
  10464. X{\
  10465. X  char msg [256];\
  10466. X  if (interactive && V (sid) < 0) {\
  10467. X    report_progress (report, tsprintf ("\n%s(): Error V()", __func__), TRUE);\
  10468. X    CLOSE_CLIENT (msg_sock);\
  10469. X    _exit (14);\
  10470. X  }\
  10471. X}
  10472. X# endif
  10473. X
  10474. Xtypedef struct {
  10475. X  long int pid,            /* Client pid */
  10476. X         time,        /* Time connection established */
  10477. X         connid;        /* Client id */
  10478. X  char name [MAX_LINE];        /* Remote host's IP address or name */
  10479. X} CLIENT;
  10480. X
  10481. XCLIENT clients [MAX_CONNECTIONS];
  10482. X  
  10483. Xlong int chpid, nforks, sock_fd, msg_sock;
  10484. Xint sid, connid, conn_duration;
  10485. Xstruct passwd *pwentry;
  10486. Xchar requests_file [MAX_LINE];
  10487. X
  10488. XBOOLEAN chdied = FALSE;
  10489. X#endif
  10490. *-*-END-of-src/serverd.h-*-*
  10491. echo x - src/start.h
  10492. sed 's/^X//' >src/start.h <<'*-*-END-of-src/start.h-*-*'
  10493. X/*
  10494. X  AGREEMENT: This software can be used and distributed freely only as a
  10495. X  whole and not in parts, as long as you do not remove or alter the author
  10496. X  and copyright notices in the file defs.h; this notices are #define'd in
  10497. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10498. X  provided for your personal use, you you may not alter the functions
  10499. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10500. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10501. X  any changes you may have made. No part of the source code bearing a
  10502. X  copyright notice can be included in commercial software systems without
  10503. X  written permission by the author.
  10504. X  By using this software you are bound by this agreement.
  10505. X  This software comes with no warranties and cannot be sold for profit.
  10506. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10507. X  files when distributing this software.
  10508. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  10509. X  Use, duplication or disclosure by the Federal Government is subject to the
  10510. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10511. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10512. X
  10513. X  Below are the #define's pertinent to start.c
  10514. X
  10515. X  Preserve any quotes that appear below; change only path names.
  10516. X
  10517. X  ALWAYS SPECIFY ABSOLUTE PATHS.
  10518. X
  10519. X*/
  10520. X
  10521. X#ifdef __STDC__
  10522. X# include "ansi/start.h"
  10523. X#else
  10524. X# include "nonansi/start.h"
  10525. X#endif
  10526. X
  10527. X#ifdef __NeXT__
  10528. X# include "next.h"
  10529. X#endif
  10530. X
  10531. X#define MODERATED_MAIL_FILE "moderated"
  10532. X
  10533. X#define START_ABORT \
  10534. X  fprintf (stderr, "### start aborted; system not started. ###\n"),\
  10535. X  exit (1);
  10536. X
  10537. X#define DEFAULT_ALIASES \
  10538. X"^@.*:(.*)@(.*) \\1@\\2"
  10539. X
  10540. Xchar    report_list_accf [MAX_LINE];
  10541. Xchar    *pids [] = { PID_SERVERD, PID_LIST, PID_SERVER, PID_PQUEUE, PID_QUEUED,
  10542. X             NULL };
  10543. Xchar    *mask;
  10544. XBOOLEAN tty_echo = TRUE;
  10545. XFILE    *report  = NULL;
  10546. *-*-END-of-src/start.h-*-*
  10547. echo x - src/struct.h
  10548. sed 's/^X//' >src/struct.h <<'*-*-END-of-src/struct.h-*-*'
  10549. X/*
  10550. X  AGREEMENT: This software can be used and distributed freely only as a
  10551. X  whole and not in parts, as long as you do not remove or alter the author
  10552. X  and copyright notices in the file defs.h; this notices are #define'd in
  10553. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10554. X  provided for your personal use, you you may not alter the functions
  10555. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10556. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10557. X  any changes you may have made. No part of the source code bearing a
  10558. X  copyright notice can be included in commercial software systems without
  10559. X  written permission by the author.
  10560. X  By using this software you are bound by this agreement.
  10561. X  This software comes with no warranties and cannot be sold for profit.
  10562. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10563. X  files when distributing this software.
  10564. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  10565. X  Use, duplication or disclosure by the Federal Government is subject to the
  10566. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10567. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10568. X*/
  10569. X
  10570. Xtypedef struct _prec_header {    /* Header lines to be saved */
  10571. X  char   *line;
  10572. X  struct _prec_header *next;
  10573. X} PRECIOUS_HEADER;
  10574. X
  10575. Xtypedef struct _unix_cmds {
  10576. X  char password [MAX_LINE],    /* Password for this UNIX command */
  10577. X       name [MAX_LINE],        /* Name of the UNIX command users may execute */
  10578. X       *cmd,            /* Actual UNIX command to execute */
  10579. X       *comment;        /* Syntax message, or any other message */
  10580. X  struct _unix_cmds *next;    /* Pointer to next structure */
  10581. X} UNIX_CMDS;
  10582. X
  10583. Xtypedef struct {
  10584. X  char set_values [MAX_SET_OPTIONS][MAX_LINE];
  10585. X} DEFAULTS;
  10586. X
  10587. Xtypedef struct {
  10588. X  struct {
  10589. X    char alias [MAX_LINE],    /* As it appears in the aliases file */
  10590. X     comment [MAX_LINE],    /* Comment: line in the outgoing mail message */
  10591. X         address [MAX_LINE],    /* Full email address of the list */
  10592. X     owner [MAX_LINE],    /* Email address of the list's owner */
  10593. X     password [MAX_LINE],    /* Password that owner uses */
  10594. X         cmdoptions [MAX_LINE],    /* List-specific command line options */
  10595. X     arch_dir [MAX_LINE],    /* Directory to put archive files in */
  10596. X     farch_dir [MAX_LINE],    /*     " in which to record archive in DIR */
  10597. X     arch_spec [MAX_LINE],    /* Specifies name of archive files */
  10598. X     arch_pass [MAX_LINE];    /* Password (if any) for the archive */
  10599. X    int     owner_prefs,        /* Owner preferences */
  10600. X     disabled_commands,    /* Mask of disabled commands for this list */
  10601. X     digest_lines,          /* Max number of lines in digest */
  10602. X     digest_hours,          /* Send out digest every so many hours */
  10603. X     ncmds,            /* Count of UNIX commands that may be executed*/
  10604. X     max_messages,        /* Maximum number of messages per day */
  10605. X     options;        /* Mask of options: autosub, conceal, archive */
  10606. X    PRECIOUS_HEADER *header;    /* Precious header lines */
  10607. X    UNIX_CMDS *unix_cmds;    /* UNIX commands that users may execute */
  10608. X    DEFAULTS defaults;        /* Default list settings */
  10609. X  } lists [MAX_LISTS];        /* Structure for each list */
  10610. X  struct {
  10611. X    char address [MAX_LINE],    /* Full email address of the server */
  10612. X     comment [MAX_LINE],    /* Comment: line in the outgoing mail message */
  10613. X         cmdoptions [MAX_LINE],    /* ListServer-specific command line options */
  10614. X     password [MAX_LINE];    /* For 'shutdown', 'restart' and 'execute' */
  10615. X    int manager_prefs;        /* System manager preferences */
  10616. X  } server;            /* Structure for the server */
  10617. X  struct {
  10618. X    char *method,        /* Mail method to use */
  10619. X     env_var [MAX_LINE],    /* Environment variable to use */
  10620. X     mail_prog [MAX_LINE],    /* Which mail program to use */
  10621. X     precedence [MAX_LINE];    /* Which mail precedence to use */
  10622. X  } mail;            /* Mail method structure */
  10623. X  struct {
  10624. X    long int msg,        /* Maximum message limit in bytes */
  10625. X         files;        /* Maximum file size before auto splitting */
  10626. X  } limits;            /* Various limits are defined here */
  10627. X  struct {
  10628. X    unsigned int start,
  10629. X         stop;
  10630. X  } batch;            /* When to batch requests */
  10631. X  struct {
  10632. X    char prog [MAX_LINE],    /* Faxing program */
  10633. X     fax_no [MAX_LINE];    /* Fax number */
  10634. X  } fax;
  10635. X  char serverd_cmdoptions [MAX_LINE],/* Command line options */
  10636. X       manager [MAX_LINE],    /* Manager of the system */
  10637. X       arg [MAX_LINE],        /* Temporary storage */
  10638. X       organization [MAX_LINE]; /* Organization's name */
  10639. X       int users,        /* Used by listserv when -r is given */
  10640. X       frequency;        /* How often to read mail */
  10641. X  long int options;        /* Various flags: BSD_PS, USE_TELNET, etc. */
  10642. X} SYS;
  10643. X
  10644. Xtypedef void (*FUNC)();
  10645. X
  10646. Xtypedef struct {
  10647. X  char *name;
  10648. X  long int mask;
  10649. X  FUNC func;
  10650. X} COMMANDS;            /* Structure for requests */
  10651. X
  10652. Xtypedef struct remote {
  10653. X  char alias [MAX_LINE],
  10654. X       address [MAX_LINE],
  10655. X       comment [MAX_LINE],
  10656. X       listserv [MAX_LINE],
  10657. X       inet_addr [MAX_LINE];
  10658. X  int  port;
  10659. X  struct remote *next;
  10660. X} REMOTE;            /* Structure for remote lists */
  10661. *-*-END-of-src/struct.h-*-*
  10662. echo x - src/sysmail.h
  10663. sed 's/^X//' >src/sysmail.h <<'*-*-END-of-src/sysmail.h-*-*'
  10664. X/*
  10665. X  AGREEMENT: This software can be used and distributed freely only as a
  10666. X  whole and not in parts, as long as you do not remove or alter the author
  10667. X  and copyright notices in the file defs.h; this notices are #define'd in
  10668. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10669. X  provided for your personal use, you you may not alter the functions
  10670. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10671. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10672. X  any changes you may have made. No part of the source code bearing a
  10673. X  copyright notice can be included in commercial software systems without
  10674. X  written permission by the author.
  10675. X  By using this software you are bound by this agreement.
  10676. X  This software comes with no warranties and cannot be sold for profit.
  10677. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10678. X  files when distributing this software.
  10679. X  COPYRIGHT: Copyright (c) 1991/92, Anastasios C. Kotsikonas
  10680. X  Use, duplication or disclosure by the Federal Government is subject to the
  10681. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10682. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10683. X*/
  10684. X
  10685. X#ifdef __STDC__
  10686. X# include "ansi/sysmail.h"
  10687. X#else
  10688. X# include "nonansi/sysmail.h"
  10689. X#endif
  10690. X
  10691. X#include <errno.h>
  10692. X
  10693. X#define PORT          25    /* sendmail port */
  10694. X#define TIMEOUT           600    /* 10 mins timeout connecting to sendmail */
  10695. X#define CONN_TIMEOUT      -1
  10696. X#define MAX_CALLS      1    /* if > 1, retry delivery that many times */
  10697. X#ifndef SENDMAIL_HOST
  10698. X# define SENDMAIL_HOST      "localhost"
  10699. X#endif
  10700. X
  10701. X/* List of SMTP commands recognized */
  10702. X
  10703. X#define ACKNOWLEDGE      220
  10704. X#define CLOSE_CONNECTION  221
  10705. X#define OK                250
  10706. X#define WILL_FORWARD      251
  10707. X#define DATA          354
  10708. X#define SERVICE_UNAVAIL      421
  10709. X#define PERMISSION_DENIED 450
  10710. X#define HOST_ABORTED      451
  10711. X#define DISK_FULL      452
  10712. X#define NOT_RECOGNIZED    500
  10713. X#define SYNTAX_ERROR      501
  10714. X#define CMD_NOT_IMPL      502
  10715. X#define BAD_SEQUENCE      503
  10716. X#define PARAM_NOT_IMPL    504
  10717. X#define USER_UNKNOWN      550
  10718. X#define USER_NOT_LOCAL    551
  10719. X#define TOO_MUCH_DATA      552
  10720. X#define USER_AMBIGUOUS    553
  10721. X#define TRANS_FAILED        554
  10722. X#define END_OF_TEXT      ".\n"
  10723. X
  10724. X#define CLOSEF \
  10725. X  fclose (msg),\
  10726. X  close (sock_fd)
  10727. X
  10728. X#define NOTIFY_MANAGER(error) \
  10729. X  if (sys.options & BSD_MAIL)\
  10730. X    syscom ("echo '%s' | %s -s 'Error during message delivery: ' %s &",\
  10731. X        error, UCB_MAIL, sys.manager)
  10732. X
  10733. X#define WARN_MANAGER_AND_OWNER(warning) \
  10734. X  if (sys.options & BSD_MAIL) {\
  10735. X    syscom ("echo '%s' | %s -s '%s: Warning during message delivery: ' %s &",\
  10736. X        warning, UCB_MAIL,\
  10737. X(listid < 0 ? "LISTSERV" : sys.lists[listid].alias), sys.manager);\
  10738. X    if (listid >= 0 && strcmp (sys.manager, sys.lists[listid].owner))\
  10739. X      syscom ("echo '%s' | %s -s '%s: Warning during message delivery: ' %s &",\
  10740. X            warning, UCB_MAIL,\
  10741. X(listid < 0 ? "LISTSERV" : sys.lists[listid].alias), sys.lists[listid].owner);\
  10742. X  }
  10743. X
  10744. X#define ABORT_CONNECTION \
  10745. X  if ((int) write (sock_fd, "QUIT\n", 5) < 5)\
  10746. X    report_progress (report, "_sysmail(): WARNING: Error writing to \
  10747. Xsocket, while closing connection", TRUE);\
  10748. X  if (debug)\
  10749. X    fprintf (sent, "QUIT\n[ transaction aborted ]\n"),\
  10750. X    fflush (sent);\
  10751. X  cmd = server_response (sock_fd);
  10752. X
  10753. X#define CHECK_SERVER_RESPONSE(cmd, arg, cont)\
  10754. X  if (cmd != OK && cmd != arg) {\
  10755. X    char error [1024];\
  10756. X    if (cmd == SYNTAX_ERROR || cmd == TRANS_FAILED ||\
  10757. X        cmd == NOT_RECOGNIZED) {\
  10758. X      sprintf (error, "_sysmail(): Command: %snot recognized by sendmail.\
  10759. X\n%s\nCould not deliver mail", buf, message);\
  10760. X      report_progress (report, error, TRUE);\
  10761. X      NOTIFY_MANAGER (error);\
  10762. X      ABORT_CONNECTION;\
  10763. X      queue = TRUE;\
  10764. X      goto abort;\
  10765. X    }\
  10766. X    else if (cmd == CMD_NOT_IMPL || cmd == PARAM_NOT_IMPL) {\
  10767. X      sprintf (error, "_sysmail(): Command: %snot implemeted.\n%s\n\
  10768. XCould not deliver mail", buf, message);\
  10769. X      report_progress (report, error, TRUE);\
  10770. X      NOTIFY_MANAGER (error);\
  10771. X      ABORT_CONNECTION;\
  10772. X      queue = TRUE;\
  10773. X      goto abort;\
  10774. X    }\
  10775. X    else if (cmd == BAD_SEQUENCE) {\
  10776. X      sprintf (error, "_sysmail(): Command: %sissued too soon.\
  10777. X\n%s\nCould not deliver mail", buf, message);\
  10778. X      report_progress (report, error, TRUE);\
  10779. X      NOTIFY_MANAGER (error);\
  10780. X      ABORT_CONNECTION;\
  10781. X      queue = TRUE;\
  10782. X      goto abort;\
  10783. X    }\
  10784. X    else if (cmd == SERVICE_UNAVAIL || cmd == HOST_ABORTED) {\
  10785. X      sprintf (error, "_sysmail(): Service unavailable.\
  10786. X\n%s\nCould not deliver mail", message);\
  10787. X      report_progress (report, error, TRUE);\
  10788. X      NOTIFY_MANAGER (error);\
  10789. X      ABORT_CONNECTION;\
  10790. X      queue = TRUE;\
  10791. X      goto abort;\
  10792. X    }\
  10793. X    else if (cmd == DISK_FULL) {\
  10794. X      sprintf (error, "_sysmail(): File system full.\n%s\nCould not \
  10795. Xdeliver mail", message);\
  10796. X      report_progress (report, error, TRUE);\
  10797. X      NOTIFY_MANAGER (error);\
  10798. X      ABORT_CONNECTION;\
  10799. X      queue = TRUE;\
  10800. X      goto abort;\
  10801. X    }\
  10802. X    else if (cmd == TOO_MUCH_DATA) {\
  10803. X      sprintf (error, "_sysmail(): Too many recipients or message \
  10804. Xtoo long.\n%s\nCould not deliver mail", message);\
  10805. X      report_progress (report, error, TRUE);\
  10806. X      NOTIFY_MANAGER (error);\
  10807. X      ABORT_CONNECTION;\
  10808. X      queue = TRUE;\
  10809. X      goto abort;\
  10810. X    }\
  10811. X    else if (cmd == CONN_TIMEOUT) {\
  10812. X      sprintf (error, "_sysmail(): Connection timed out with %s. \
  10813. XCould not deliver mail", SENDMAIL_HOST);\
  10814. X      report_progress (report, error, TRUE);\
  10815. X      NOTIFY_MANAGER (error);\
  10816. X      queue = TRUE;\
  10817. X      goto abort;\
  10818. X    }\
  10819. X    else if (cmd == USER_UNKNOWN) {\
  10820. X      sprintf (error, "_sysmail(): Address: %snot recognized.\n%s\nMessage \
  10821. Xnot delivered to this recipient", buf, message);\
  10822. X      report_progress (report, error, TRUE);\
  10823. X      WARN_MANAGER_AND_OWNER (error);\
  10824. X      cont;\
  10825. X    }\
  10826. X    else if (cmd == USER_NOT_LOCAL) {\
  10827. X      sprintf (error, "_sysmail(): Address: %snot local; %s", buf, message);\
  10828. X      report_progress (report, error, TRUE);\
  10829. X      WARN_MANAGER_AND_OWNER (error);\
  10830. X      cont;\
  10831. X    }\
  10832. X    else if (cmd == USER_AMBIGUOUS) {\
  10833. X      sprintf (error, "_sysmail(): Address ambiguous: %s%s\nMessage not \
  10834. Xdelivered to this address", buf, message);\
  10835. X      report_progress (report, error, TRUE);\
  10836. X      WARN_MANAGER_AND_OWNER (error);\
  10837. X      cont;\
  10838. X    }\
  10839. X    else if (cmd == PERMISSION_DENIED) {\
  10840. X      sprintf (error, "_sysmail(): Permission denied for address %s%s\n\
  10841. XMessage not delivered to this recipient", buf, message);\
  10842. X      report_progress (report, error, TRUE);\
  10843. X      WARN_MANAGER_AND_OWNER (error);\
  10844. X      cont;\
  10845. X    }\
  10846. X    else if (cmd == WILL_FORWARD) {\
  10847. X      sprintf (error, "_sysmail(): Address: %snot local; %s", buf, message);\
  10848. X      report_progress (report, error, TRUE);\
  10849. X      WARN_MANAGER_AND_OWNER (error);\
  10850. X      cont;\
  10851. X    }\
  10852. X    else {\
  10853. X      sprintf (error, "_sysmail(): ERROR: Return value %d for command: %s%s\n\
  10854. XPlease notify tasos@cs.bu.edu", cmd, buf, message);\
  10855. X      report_progress (report, error, TRUE);\
  10856. X      NOTIFY_MANAGER (error);\
  10857. X      if (call < MAX_CALLS)\
  10858. X        CLOSEF,\
  10859. X        sleep (60),\
  10860. X        _sysmail (file, call + 1);\
  10861. X      report_progress (report, "_sysmail(): ERROR: Could not deliver mail", \
  10862. XTRUE);\
  10863. X      CLOSEF,\
  10864. X      gexit (10);\
  10865. X    }\
  10866. X  }
  10867. X
  10868. X#define WRITE_TO_SOCKET(sock_fd, buf)\
  10869. X{ char bufcopy [1024];\
  10870. X  strcpy (bufcopy, buf);\
  10871. X  bytes_to_write = strlen (bufcopy);\
  10872. X  errno = 0;\
  10873. X  while ((bytes_written = write (sock_fd, bufcopy, strlen (bufcopy))) <\
  10874. X         bytes_to_write) {\
  10875. X    if (errno && errno != EWOULDBLOCK && errno != EAGAIN) {\
  10876. X      char error [MAX_LINE];\
  10877. X      switch (errno) {\
  10878. X    case EBADF: sprintf (error, "_sysmail(): Bad file number"); break;\
  10879. X    case EFAULT: sprintf (error, "_sysmail(): Bad address"); break;\
  10880. X    case EFBIG: sprintf (error, "_sysmail(): File limit reached"); break;\
  10881. X    case EINTR: sprintf (error, "_sysmail(): Received interrupt signal");\
  10882. X            break;\
  10883. X    case EINVAL: sprintf (error, "_sysmail(): Negative seek pointer");\
  10884. X             break;\
  10885. X    case EIO: sprintf (error, "_sysmail(): I/O error"); break;\
  10886. X     case ENOSPC: sprintf (error, "_sysmail(): No space left on device");\
  10887. X             break;\
  10888. X    case ENXIO: sprintf (error, "_sysmail(): No such device or address");\
  10889. X            break;\
  10890. X    case ERANGE: sprintf (error, "_sysmail(): Bytes to write (%d) out of \
  10891. Xrange", bytes_to_write);\
  10892. X             break;\
  10893. X    default: sprintf (error, "_sysmail(): Error number %d", errno);\
  10894. X      }\
  10895. X      report_progress (report, error, TRUE);\
  10896. X      queue = TRUE;\
  10897. X      goto abort;\
  10898. X    }\
  10899. X    if (debug) {\
  10900. X      for (i = 0; i < bytes_written; fprintf (sent, "%c", bufcopy [i++]));\
  10901. X      fflush (sent);\
  10902. X    }\
  10903. X    if (bytes_written > 0)\
  10904. X      bytes_to_write -= bytes_written;\
  10905. X    if (bytes_written > 0)\
  10906. X      sprintf (bufcopy, "%s", bufcopy + bytes_written);\
  10907. X    errno = 0;\
  10908. X  }\
  10909. X  if (debug)\
  10910. X    fprintf (sent, "%s", bufcopy),\
  10911. X    fflush (sent);\
  10912. X}
  10913. X
  10914. X#define PROTOCOL(arg) \
  10915. X  while (!feof (msg) && cmd != arg) {\
  10916. X    RESET (buf);\
  10917. X    fgets (buf, MAX_LINE - 2, msg);\
  10918. X    WRITE_TO_SOCKET (sock_fd, buf);\
  10919. X    if ((cmd = server_response (sock_fd)) == CONN_TIMEOUT) {\
  10920. X      queue = TRUE;\
  10921. X      goto abort;\
  10922. X    }\
  10923. X    CHECK_SERVER_RESPONSE (cmd, arg, continue);\
  10924. X  }
  10925. X
  10926. Xstatic char message [1024];
  10927. Xstatic FILE *sent, *received;
  10928. Xstatic BOOLEAN queue;
  10929. *-*-END-of-src/sysmail.h-*-*
  10930. echo x - src/ansi/catmail.h
  10931. sed 's/^X//' >src/ansi/catmail.h <<'*-*-END-of-src/ansi/catmail.h-*-*'
  10932. X#define LOST_REQUESTS        PATH "/lost+found"
  10933. X#define TAG_IDF            PATH "/.tag.id"
  10934. X#define    CATMAIL_TMP        PATH "/.catmail.tmp"
  10935. *-*-END-of-src/ansi/catmail.h-*-*
  10936. echo x - src/ansi/defs.h
  10937. sed 's/^X//' >src/ansi/defs.h <<'*-*-END-of-src/ansi/defs.h-*-*'
  10938. X/*
  10939. X  AGREEMENT: This software can be used and distributed freely only as a
  10940. X  whole and not in parts, as long as you do not remove or alter the author
  10941. X  and copyright notices in the file defs.h; this notices are #define'd in
  10942. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  10943. X  provided for your personal use, you you may not alter the functions
  10944. X  create_header(), create_multi_recipient_header() and main() in list.c,
  10945. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  10946. X  any changes you may have made. No part of the source code bearing a
  10947. X  copyright notice can be included in commercial software systems without
  10948. X  written permission by the author.
  10949. X  By using this software you are bound by this agreement.
  10950. X  This software comes with no warranties and cannot be sold for profit.
  10951. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  10952. X  files when distributing this software.
  10953. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  10954. X  Use, duplication or disclosure by the Federal Government is subject to the
  10955. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  10956. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  10957. X*/
  10958. X
  10959. X#define PATH              "/usr/server"
  10960. X#define WARNING           PATH "/.warning"
  10961. X#define REPORT_SERVER     PATH "/.report.server"
  10962. X#define REPORT_SERVERD    PATH "/.report.daemon"
  10963. X#define REPORT_PQUEUE     PATH "/.report.pqueue"
  10964. X#define REPORT_CATMAIL      PATH "/.report.catmai"
  10965. X#define CONFIG            PATH "/config"
  10966. X#define LIST              PATH "/list -1 -L "
  10967. X#define SERVER            PATH "/listserv -1 "
  10968. X#define SERVER_MAIL_FILE  PATH "/requests"
  10969. X#define LIVE_REQUESTS_F      PATH "/requests.live"
  10970. X#define BATCH_FILE      PATH "/batch"
  10971. X#define SERVERD           PATH "/serverd"
  10972. X#define PQUEUE            PATH "/pqueue"
  10973. X#define START             PATH "/start"
  10974. X#define OWNERSF           PATH "/owners"
  10975. X#define ALIASESF      PATH "/.aliases"
  10976. X#define SERVERD_LOCK_FILE PATH "/.lock.serverd"
  10977. X#define LIST_LOCK_FILE    PATH "/.lock.list"
  10978. X#define SERVER_LOCK_FILE  PATH "/.lock.server"
  10979. X#define PQUEUE_LOCK_FILE  PATH "/.lock.pqueue"
  10980. X#define PID_PQUEUE        PATH "/.pid.pqueue"
  10981. X#define PID_SERVERD       PATH "/.pid.daemon"
  10982. X#define PID_SERVER        PATH "/.pid.server"
  10983. X#define PID_LIST          PATH "/.pid.list"
  10984. X#define PID_QUEUED      PATH "/.pid.queued"
  10985. X#define MAILFORWARD       PATH "/.mailforward"
  10986. X#define ULISTSERVER_REPLY PATH "/.reply.listser"
  10987. X#define ARCHIVE_DIR       PATH "/archives"
  10988. X#define OLD_SUBSCRIBERS   PATH "/.oldsubscriber"
  10989. X#define OLD_ALIASES      PATH "/.oldaliases"
  10990. X#define NEW_SUBSCRIBERS   PATH "/.newsubscriber"
  10991. X#define NEW_ALIASES      PATH "/.newaliases"
  10992. *-*-END-of-src/ansi/defs.h-*-*
  10993. echo x - src/ansi/listserv.h
  10994. sed 's/^X//' >src/ansi/listserv.h <<'*-*-END-of-src/ansi/listserv.h-*-*'
  10995. X/*
  10996. X  AGREEMENT: This software can be used and distributed freely only as a
  10997. X  whole and not in parts, as long as you do not remove or alter the author
  10998. X  and copyright notices in the file defs.h; this notices are #define'd in
  10999. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11000. X  provided for your personal use, you you may not alter the functions
  11001. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11002. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11003. X  any changes you may have made. No part of the source code bearing a
  11004. X  copyright notice can be included in commercial software systems without
  11005. X  written permission by the author.
  11006. X  By using this software you are bound by this agreement.
  11007. X  This software comes with no warranties and cannot be sold for profit.
  11008. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11009. X  files when distributing this software.
  11010. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11011. X  Use, duplication or disclosure by the Federal Government is subject to the
  11012. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11013. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11014. X*/
  11015. X
  11016. X#define MAIL_COPY         PATH "/.messages"
  11017. X#define MSG_NO            PATH "/.msgno"
  11018. X#define AWK_PROG          PATH "/.awk"
  11019. X#define STATS_PROG        PATH "/.stats"
  11020. X#define SERVER_MBOX       PATH "/mbox"    /* place to save server's messages */
  11021. X#define HELP_TOPICS      PATH "/help/TOPICS" /* Index of topics and files */
  11022. X#define STDOUT          PATH "/stdout"
  11023. X#define STDERR          PATH "/stderr"
  11024. X#define SETUP_MESSAGE_IDSF sprintf (message_idsf, "%s/%s", PATH, MESSAGE_IDS_F)
  11025. X#define EXEC_STATS \
  11026. X  syscom ("%s %s %s %s %s '%s'", STATS_PROG, PATH, subscribersf,\
  11027. X          headersf, MAILFORWARD, params)
  11028. X
  11029. X#define REARRANGE_SUBSCRIBERS \
  11030. X  syscom ("cat %s | %s/rev | awk '{print $NF \"\\t\" $0}' | sort | \
  11031. Xsed 's/^.*\t//' | %s/rev > %s/sub.%s", subscribersf,\
  11032. X      PATH, PATH, PATH, sys.lists[listid].alias);\
  11033. X  mv (tsprintf ("%s/sub.%s", PATH, sys.lists[listid].alias), subscribersf)
  11034. X
  11035. X#define CAT_FILE \
  11036. X  syscom ("%s %s | %s/fwin -n -o %ld -b %ld | sed -e 's/^From />From /' | \
  11037. Xsed -e 's/^\\.$/\\\\./' >> %s", \
  11038. X      (compressed_source ? "zcat" : "cat"), fullname, PATH, offset,\
  11039. X      nbytes, MAILFORWARD)
  11040. *-*-END-of-src/ansi/listserv.h-*-*
  11041. echo x - src/ansi/misc.h
  11042. sed 's/^X//' >src/ansi/misc.h <<'*-*-END-of-src/ansi/misc.h-*-*'
  11043. X/*
  11044. X  AGREEMENT: This software can be used and distributed freely only as a
  11045. X  whole and not in parts, as long as you do not remove or alter the author
  11046. X  and copyright notices in the file defs.h; this notices are #define'd in
  11047. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11048. X  provided for your personal use, you you may not alter the functions
  11049. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11050. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11051. X  any changes you may have made. No part of the source code bearing a
  11052. X  copyright notice can be included in commercial software systems without
  11053. X  written permission by the author.
  11054. X  By using this software you are bound by this agreement.
  11055. X  This software comes with no warranties and cannot be sold for profit.
  11056. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11057. X  files when distributing this software.
  11058. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11059. X  Use, duplication or disclosure by the Federal Government is subject to the
  11060. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11061. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11062. X*/
  11063. X
  11064. X#define SETUP_STRING sprintf (s, "%s/lists/%s/%s", PATH, alias, filename)
  11065. X#define SETUP_IGNOREDF sprintf (server_ignoredf, "%s/%s", PATH, IGNORED)
  11066. *-*-END-of-src/ansi/misc.h-*-*
  11067. echo x - src/ansi/serverd.h
  11068. sed 's/^X//' >src/ansi/serverd.h <<'*-*-END-of-src/ansi/serverd.h-*-*'
  11069. X/*
  11070. X  AGREEMENT: This software can be used and distributed freely only as a
  11071. X  whole and not in parts, as long as you do not remove or alter the author
  11072. X  and copyright notices in the file defs.h; this notices are #define'd in
  11073. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11074. X  provided for your personal use, you you may not alter the functions
  11075. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11076. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11077. X  any changes you may have made. No part of the source code bearing a
  11078. X  copyright notice can be included in commercial software systems without
  11079. X  written permission by the author.
  11080. X  By using this software you are bound by this agreement.
  11081. X  This software comes with no warranties and cannot be sold for profit.
  11082. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11083. X  files when distributing this software.
  11084. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11085. X  Use, duplication or disclosure by the Federal Government is subject to the
  11086. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11087. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11088. X*/
  11089. X
  11090. X#define LOAD_FILE         PATH "/.load"
  11091. X#define UNWANTED_HOSTSF      PATH "/unwanted.hosts"
  11092. X#define PRIVILEGED_HOSTSF PATH "/priv.hosts"
  11093. X#define WELCOMEF      PATH "/welcome.live"
  11094. *-*-END-of-src/ansi/serverd.h-*-*
  11095. echo x - src/ansi/start.h
  11096. sed 's/^X//' >src/ansi/start.h <<'*-*-END-of-src/ansi/start.h-*-*'
  11097. X/*
  11098. X  AGREEMENT: This software can be used and distributed freely only as a
  11099. X  whole and not in parts, as long as you do not remove or alter the author
  11100. X  and copyright notices in the file defs.h; this notices are #define'd in
  11101. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11102. X  provided for your personal use, you you may not alter the functions
  11103. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11104. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11105. X  any changes you may have made. No part of the source code bearing a
  11106. X  copyright notice can be included in commercial software systems without
  11107. X  written permission by the author.
  11108. X  By using this software you are bound by this agreement.
  11109. X  This software comes with no warranties and cannot be sold for profit.
  11110. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11111. X  files when distributing this software.
  11112. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11113. X  Use, duplication or disclosure by the Federal Government is subject to the
  11114. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11115. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11116. X*/
  11117. X
  11118. X#define REPORT_SERVER_ACC   PATH "/.rep.server.ac"
  11119. X#define REPORT_SERVERD_ACC  PATH "/.rep.serverd.a"
  11120. X#define REPORT_START_ACC    PATH "/.rep.start.acc"
  11121. X#define REPORT_PQUEUE_ACC   PATH "/.rep.pqueue.ac"
  11122. X#define REPORT_START        PATH "/.report.start"
  11123. X#define CATMAIL            PATH "/catmail"
  11124. X#define SETUP_DIR sprintf (dir, "%s/lists/%s", PATH, sys.lists[i].alias)
  11125. *-*-END-of-src/ansi/start.h-*-*
  11126. echo x - src/ansi/sysmail.h
  11127. sed 's/^X//' >src/ansi/sysmail.h <<'*-*-END-of-src/ansi/sysmail.h-*-*'
  11128. X/*
  11129. X  AGREEMENT: This software can be used and distributed freely only as a
  11130. X  whole and not in parts, as long as you do not remove or alter the author
  11131. X  and copyright notices in the file defs.h; this notices are #define'd in
  11132. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11133. X  provided for your personal use, you you may not alter the functions
  11134. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11135. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11136. X  any changes you may have made. No part of the source code bearing a
  11137. X  copyright notice can be included in commercial software systems without
  11138. X  written permission by the author.
  11139. X  By using this software you are bound by this agreement.
  11140. X  This software comes with no warranties and cannot be sold for profit.
  11141. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11142. X  files when distributing this software.
  11143. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11144. X  Use, duplication or disclosure by the Federal Government is subject to the
  11145. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11146. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11147. X*/
  11148. X
  11149. X#define SENT              PATH "/sent"
  11150. X#define RECEIVED_         PATH "/received"
  11151. X#define IDF               PATH "/.queue.id"
  11152. X#define QUEUE_DIR         PATH "/mqueue"
  11153. *-*-END-of-src/ansi/sysmail.h-*-*
  11154. echo x - src/nonansi/catmail.h
  11155. sed 's/^X//' >src/nonansi/catmail.h <<'*-*-END-of-src/nonansi/catmail.h-*-*'
  11156. X#define LOST_REQUESTS        PATH/lost+found"
  11157. X#define TAG_IDF            PATH/.tag.id"
  11158. X#define CATMAIL_TMP             PATH/.catmail.tmp"
  11159. *-*-END-of-src/nonansi/catmail.h-*-*
  11160. echo x - src/nonansi/defs.h
  11161. sed 's/^X//' >src/nonansi/defs.h <<'*-*-END-of-src/nonansi/defs.h-*-*'
  11162. X/*
  11163. X  AGREEMENT: This software can be used and distributed freely only as a
  11164. X  whole and not in parts, as long as you do not remove or alter the author
  11165. X  and copyright notices in the file defs.h; this notices are #define'd in
  11166. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11167. X  provided for your personal use, you you may not alter the functions
  11168. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11169. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11170. X  any changes you may have made. No part of the source code bearing a
  11171. X  copyright notice can be included in commercial software systems without
  11172. X  written permission by the author.
  11173. X  By using this software you are bound by this agreement.
  11174. X  This software comes with no warranties and cannot be sold for profit.
  11175. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11176. X  files when distributing this software.
  11177. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11178. X  Use, duplication or disclosure by the Federal Government is subject to the
  11179. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11180. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11181. X*/
  11182. X
  11183. X#define PATH              "/usr/server
  11184. X#define WARNING           PATH/.warning"
  11185. X#define REPORT_SERVER     PATH/.report.server"
  11186. X#define REPORT_SERVERD    PATH/.report.daemon"
  11187. X#define REPORT_PQUEUE     PATH/.report.pqueue"
  11188. X#define REPORT_CATMAIL      PATH/.report.catmai"
  11189. X#define CONFIG            PATH/config"
  11190. X#define LIST              PATH/list -1 -L "
  11191. X#define SERVER            PATH/listserv -1 "
  11192. X#define SERVER_MAIL_FILE  PATH/requests"
  11193. X#define LIVE_REQUESTS_F   PATH/requests.live"
  11194. X#define BATCH_FILE      PATH/batch"
  11195. X#define SERVERD           PATH/serverd"
  11196. X#define PQUEUE            PATH/pqueue"
  11197. X#define START             PATH/start"/* Do not give ANY command line options */
  11198. X#define OWNERSF           PATH/owners"
  11199. X#define ALIASESF      PATH/.aliases"
  11200. X#define SERVERD_LOCK_FILE PATH/.lock.serverd"
  11201. X#define LIST_LOCK_FILE    PATH/.lock.list"
  11202. X#define SERVER_LOCK_FILE  PATH/.lock.server"
  11203. X#define PQUEUE_LOCK_FILE  PATH/.lock.pqueue"
  11204. X#define PID_PQUEUE        PATH/.pid.pqueue"
  11205. X#define PID_SERVERD       PATH/.pid.daemon"
  11206. X#define PID_SERVER        PATH/.pid.server"
  11207. X#define PID_LIST          PATH/.pid.list"
  11208. X#define PID_QUEUED      PATH/.pid.queued"
  11209. X#define MAILFORWARD       PATH/.mailforward"
  11210. X#define ULISTSERVER_REPLY PATH/.reply.listser"
  11211. X#define ARCHIVE_DIR      PATH/archives"
  11212. X#define OLD_SUBSCRIBERS   PATH/.oldsubscriber"
  11213. X#define OLD_ALIASES      PATH/.oldaliases"
  11214. X#define NEW_SUBSCRIBERS   PATH/.newsubscriber"
  11215. X#define NEW_ALIASES      PATH/.newaliases"
  11216. *-*-END-of-src/nonansi/defs.h-*-*
  11217. echo x - src/nonansi/listserv.h
  11218. sed 's/^X//' >src/nonansi/listserv.h <<'*-*-END-of-src/nonansi/listserv.h-*-*'
  11219. X/*
  11220. X  AGREEMENT: This software can be used and distributed freely only as a
  11221. X  whole and not in parts, as long as you do not remove or alter the author
  11222. X  and copyright notices in the file defs.h; this notices are #define'd in
  11223. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11224. X  provided for your personal use, you you may not alter the functions
  11225. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11226. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11227. X  any changes you may have made. No part of the source code bearing a
  11228. X  copyright notice can be included in commercial software systems without
  11229. X  written permission by the author.
  11230. X  By using this software you are bound by this agreement.
  11231. X  This software comes with no warranties and cannot be sold for:w profit.
  11232. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11233. X  files when distributing this software.
  11234. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11235. X  Use, duplication or disclosure by the Federal Government is subject to the
  11236. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11237. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11238. X*/
  11239. X
  11240. X#define MAIL_COPY         PATH/.messages"
  11241. X#define MSG_NO            PATH/.msgno"
  11242. X#define AWK_PROG          PATH/.awk"
  11243. X#define STATS_PROG        PATH/.stats"
  11244. X#define SERVER_MBOX       PATH/mbox"    /* place to save server's messages */
  11245. X#define HELP_TOPICS       PATH/help/TOPICS" /* Index of topics and files */
  11246. X#define STDOUT          PATH/stdout"
  11247. X#define STDERR          PATH/stderr"
  11248. X#define SETUP_MESSAGE_IDSF sprintf (message_idsf, "%s/%s", PATH", MESSAGE_IDS_F)
  11249. X#define EXEC_STATS \
  11250. X  syscom ("%s %s %s %s %s '%s'", STATS_PROG, PATH", subscribersf,\
  11251. X          headersf, MAILFORWARD, params)
  11252. X
  11253. X#define REARRANGE_SUBSCRIBERS \
  11254. X  syscom ("cat %s | %s/rev | awk '{print $NF \"\\t\" $0}' | sort | \
  11255. Xsed 's/^.*\t//' | %s/rev > %s/sub.%s", subscribersf,\
  11256. X      PATH", PATH", PATH", sys.lists[listid].alias);\
  11257. X  mv (tsprintf ("%s/sub.%s", PATH", sys.lists[listid].alias), subscribersf)
  11258. X
  11259. X#define CAT_FILE \
  11260. X  syscom ("%s %s | %s/fwin -n -o %ld -b %ld | sed -e 's/^From />From /' | \
  11261. Xsed -e 's/^\\.$/\\\\./' >> %s", \
  11262. X      (compressed_source ? "zcat" : "cat"), fullname, PATH", offset,\
  11263. X          nbytes, MAILFORWARD)
  11264. *-*-END-of-src/nonansi/listserv.h-*-*
  11265. echo x - src/nonansi/misc.h
  11266. sed 's/^X//' >src/nonansi/misc.h <<'*-*-END-of-src/nonansi/misc.h-*-*'
  11267. X/*
  11268. X  AGREEMENT: This software can be used and distributed freely only as a
  11269. X  whole and not in parts, as long as you do not remove or alter the author
  11270. X  and copyright notices in the file defs.h; this notices are #define'd in
  11271. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11272. X  provided for your personal use, you you may not alter the functions
  11273. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11274. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11275. X  any changes you may have made. No part of the source code bearing a
  11276. X  copyright notice can be included in commercial software systems without
  11277. X  written permission by the author.
  11278. X  By using this software you are bound by this agreement.
  11279. X  This software comes with no warranties and cannot be sold for profit.
  11280. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11281. X  files when distributing this software.
  11282. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11283. X  Use, duplication or disclosure by the Federal Government is subject to the
  11284. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11285. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11286. X*/
  11287. X
  11288. X#define SETUP_STRING sprintf (s, "%s/lists/%s/%s", PATH", alias, filename)
  11289. X#define SETUP_IGNOREDF sprintf (server_ignoredf, "%s/%s", PATH", IGNORED)
  11290. *-*-END-of-src/nonansi/misc.h-*-*
  11291. echo x - src/nonansi/serverd.h
  11292. sed 's/^X//' >src/nonansi/serverd.h <<'*-*-END-of-src/nonansi/serverd.h-*-*'
  11293. X/*
  11294. X  AGREEMENT: This software can be used and distributed freely only as a
  11295. X  whole and not in parts, as long as you do not remove or alter the author
  11296. X  and copyright notices in the file defs.h; this notices are #define'd in
  11297. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11298. X  provided for your personal use, you you may not alter the functions
  11299. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11300. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11301. X  any changes you may have made. No part of the source code bearing a
  11302. X  copyright notice can be included in commercial software systems without
  11303. X  written permission by the author.
  11304. X  By using this software you are bound by this agreement.
  11305. X  This software comes with no warranties and cannot be sold for profit.
  11306. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11307. X  files when distributing this software.
  11308. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11309. X  Use, duplication or disclosure by the Federal Government is subject to the
  11310. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11311. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11312. X*/
  11313. X
  11314. X#define LOAD_FILE         PATH/.load"
  11315. X#define UNWANTED_HOSTSF      PATH/unwanted.hosts"
  11316. X#define PRIVILEGED_HOSTSF PATH/priv.hosts"
  11317. X#define WELCOMEF      PATH/welcome.live"
  11318. *-*-END-of-src/nonansi/serverd.h-*-*
  11319. echo x - src/nonansi/start.h
  11320. sed 's/^X//' >src/nonansi/start.h <<'*-*-END-of-src/nonansi/start.h-*-*'
  11321. X/*
  11322. X  AGREEMENT: This software can be used and distributed freely only as a
  11323. X  whole and not in parts, as long as you do not remove or alter the author
  11324. X  and copyright notices in the file defs.h; this notices are #define'd in
  11325. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11326. X  provided for your personal use, you you may not alter the functions
  11327. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11328. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11329. X  any changes you may have made. No part of the source code bearing a
  11330. X  copyright notice can be included in commercial software systems without
  11331. X  written permission by the author.
  11332. X  By using this software you are bound by this agreement.
  11333. X  This software comes with no warranties and cannot be sold for profit.
  11334. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11335. X  files when distributing this software.
  11336. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11337. X  Use, duplication or disclosure by the Federal Government is subject to the
  11338. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11339. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11340. X*/
  11341. X
  11342. X#define REPORT_SERVER_ACC   PATH/.rep.server.ac"
  11343. X#define REPORT_SERVERD_ACC  PATH/.rep.serverd.a"
  11344. X#define REPORT_START_ACC    PATH/.rep.start.acc"
  11345. X#define REPORT_PQUEUE_ACC   PATH/.rep.pqueue.ac"
  11346. X#define REPORT_START        PATH/.report.start"
  11347. X#define CATMAIL            PATH/catmail"
  11348. X#define SETUP_DIR sprintf (dir, "%s/lists/%s", PATH", sys.lists[i].alias)
  11349. *-*-END-of-src/nonansi/start.h-*-*
  11350. echo x - src/nonansi/sysmail.h
  11351. sed 's/^X//' >src/nonansi/sysmail.h <<'*-*-END-of-src/nonansi/sysmail.h-*-*'
  11352. X/*
  11353. X  AGREEMENT: This software can be used and distributed freely only as a
  11354. X  whole and not in parts, as long as you do not remove or alter the author
  11355. X  and copyright notices in the file defs.h; this notices are #define'd in
  11356. X  the symbols VERSION and COPYRIGHT. Although you may alter the code
  11357. X  provided for your personal use, you you may not alter the functions
  11358. X  create_header(), create_multi_recipient_header() and main() in list.c,
  11359. X  listserv.c and serverd.c (where applicable), and you may not redistribute
  11360. X  any changes you may have made. No part of the source code bearing a
  11361. X  copyright notice can be included in commercial software systems without
  11362. X  written permission by the author.
  11363. X  By using this software you are bound by this agreement.
  11364. X  This software comes with no warranties and cannot be sold for profit.
  11365. X  The AGREEMENT and COPYRIGHT notices should be included in all source
  11366. X  files when distributing this software.
  11367. X  COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  11368. X  Use, duplication or disclosure by the Federal Government is subject to the
  11369. X  restrictions set forth in FAR 52.227-19(c), Commercial Computer Software or,
  11370. X  for Department of Defense Users, by DFAR 252.227-7013(c)(1)(ii).
  11371. X*/
  11372. X
  11373. X#define SENT              PATH/sent"
  11374. X#define RECEIVED_         PATH/received"
  11375. X#define IDF               PATH/.queue.id"
  11376. X#define QUEUE_DIR         PATH/mqueue"
  11377. *-*-END-of-src/nonansi/sysmail.h-*-*
  11378. echo x - src/catmail.c
  11379. sed 's/^X//' >src/catmail.c <<'*-*-END-of-src/catmail.c-*-*'
  11380. X/*
  11381. X  ----------------------------------------------------------------------------
  11382. X  |                CATMAIL UTILITY                     |
  11383. X  |                                         |
  11384. X  |                  version 2.5                     |
  11385. X  |                                         |
  11386. X  | User contributed application.                         |
  11387. X  | Original author (1.0): Aad Nienhuis <Aad_Nienhuis@sconar.sco.uva.nl>     |
  11388. X  | Modified by (1.1): Tasos Kotsikonas                         |
  11389. X  | Enhanced by (2.0): Tasos Kotsikonas, Warren Burstein             |
  11390. X  | Enhanced by (2.1): Tasos Kotsikonas
  11391. X  ----------------------------------------------------------------------------
  11392. X
  11393. X  This is a utility that appends a mail message supplied by sendmail in 
  11394. X  stdin to the appropriate file, depending on the command line options
  11395. X  supplied. The application has to be setuid. If the incoming message
  11396. X  is for a moderated list and not from the moderator, append a NOTIFY request
  11397. X  to the requests file so that listserv will later notify the list owner,
  11398. X  soliciting his approval for posting the message.
  11399. X
  11400. X  The utility is to be used primarily in the host's aliases file when 
  11401. X  setting up aliases for various lists. To append to the system's requests
  11402. X  file it may be used as follows:
  11403. X
  11404. X    listserver: "|HOMEDIR/catmail -r -f"
  11405. X
  11406. X  To append to a list's mail file:
  11407. X
  11408. X    list_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f"
  11409. X
  11410. X  To append to a list's moderated file:
  11411. X
  11412. X    list_alias: "|HOMEDIR/catmail -L LIST_ALIAS -f -m"
  11413. X
  11414. X  COMMAND LINE OPTIONS:
  11415. X    -L: The input is appened to the specified list's "mail" file.
  11416. X    -l: Same as -L.
  11417. X    -m: The input is appened to the specified list's "moderated" file.
  11418. X    and a copy is appended to the requests file to be forwarded
  11419. X    by listserv to the owner for approval.
  11420. X    -r: The input is appened to HOMEDIR/requests.
  11421. X    -f: The input is reformatted while appended.
  11422. X*/
  11423. X
  11424. X#include <stdio.h>
  11425. X#include <stdio.h>
  11426. X#ifdef SYSLOG
  11427. X# ifdef ultrix
  11428. X#  include <sys/syslog.h>
  11429. X# else
  11430. X#  include <syslog.h>
  11431. X# endif
  11432. X#endif
  11433. X#include <string.h>
  11434. X#ifndef unknown_port
  11435. X# ifndef __NeXT__
  11436. X#  include <unistd.h>
  11437. X# else
  11438. X#  include <libc.h>
  11439. X# endif
  11440. X#endif
  11441. X#include <signal.h>
  11442. X#include <sys/types.h>
  11443. X#include <sys/stat.h>
  11444. X#include <pwd.h>
  11445. X#include <fcntl.h>
  11446. X#include <errno.h>
  11447. X#ifdef unknown_port
  11448. Xextern int errno;
  11449. X#endif
  11450. X#include <time.h>
  11451. X#include "defs.h"
  11452. X#include "catmail.h"
  11453. X#include "struct.h"
  11454. X#include "global.h"
  11455. X#if defined (__NeXT__) || defined (unknown_port)
  11456. X# include "next.h"
  11457. X#endif
  11458. X
  11459. X#ifdef __STDC__
  11460. X# include <stdarg.h>
  11461. Xextern char *tsprintf (char *, ...);
  11462. X#else
  11463. X# include <varargs.h>
  11464. Xextern char *tsprintf ();
  11465. X#endif
  11466. Xextern int  sys_config (FILE *, SYS *);
  11467. Xextern void setup_string (char *, char *, char *);
  11468. Xextern int  _getopt (int, char **, char *);
  11469. Xextern char *upcase (char *);
  11470. Xextern int  get_list_id (char *, SYS *, int);
  11471. Xextern void report_progress (FILE *, char *, int);
  11472. Xextern int  lock_file (char *, int, int, BOOLEAN);
  11473. Xextern void unlock_file (int);
  11474. Xextern BOOLEAN extract_sender (char *);
  11475. Xextern BOOLEAN owner_listed (char *, char *, char *, FILE *);
  11476. Xextern int  otoi (char *);
  11477. Xextern int cat_append (char *, char *);
  11478. Xextern int echo (char *, char *);
  11479. Xextern BOOLEAN strinstr (char *, char *);
  11480. X
  11481. Xvoid   main (int, char **, char **);
  11482. Xvoid   catmail (FILE *, FILE *, FILE *, FILE *, int);
  11483. Xint    get_tag_id (void);
  11484. Xvoid   usage (void);
  11485. Xint    gexit (int);
  11486. X
  11487. Xvoid main (int argc, char **argv, char **envp)
  11488. X{
  11489. X  char *options = "rfml:L:", *getenv();
  11490. X  extern char *optarg;
  11491. X  extern int optopt;
  11492. X  long int t;
  11493. X  int c, nlists, tag = 0;
  11494. X  char *list_alias = NULL, *mask;
  11495. X  char file [MAX_LINE];
  11496. X  char header [MAX_LINE];
  11497. X  char msg [MAX_LINE];
  11498. X  FILE *mail, *mailf = NULL, *pipe = NULL;
  11499. X  struct passwd *pwentry;
  11500. X
  11501. X  while ((c = _getopt (argc, argv, options)) != EOF)
  11502. X    switch ((char) c) {
  11503. X      case 'm': moderated = TRUE; break;
  11504. X      case 'f': reformat = TRUE; break;
  11505. X      case 'r': requests = TRUE; moderated = FALSE; break;
  11506. X      case 'l':
  11507. X      case 'L': list_alias = upcase (optarg); break;
  11508. X      case ':':
  11509. X    fprintf (stderr, "catmail: Option '%c' requires an argument.\n",
  11510. X         optopt);
  11511. X    exit (3);
  11512. X      case '?':
  11513. X      default:
  11514. X        usage();
  11515. X    }
  11516. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  11517. X    umask (otoi (mask));
  11518. X  else
  11519. X    mask = "066",
  11520. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  11521. X
  11522. X#ifdef SYSLOG
  11523. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  11524. X# ifndef i386
  11525. X       |LOG_NOWAIT
  11526. X# endif
  11527. X       , SYSLOG);
  11528. X# ifndef ultrix
  11529. X  setlogmask (LOG_UPTO (LOG_INFO));
  11530. X# endif
  11531. X#else
  11532. X  if ((report = fopen (REPORT_CATMAIL, "a+")) == NULL)
  11533. X    fprintf (stderr, "catmail: Could not open %s\n", REPORT_CATMAIL),
  11534. X    exit (1);
  11535. X  chmod (REPORT_CATMAIL, 384);
  11536. X#endif
  11537. X
  11538. X  if ((pwentry = getpwuid (getuid ())) == NULL)
  11539. X    report_progress (report, "main(): Invalid user account", TRUE),
  11540. X    exit (3);
  11541. X  if (requests)        /* Select file to append to */
  11542. X    tty_echo = FALSE,
  11543. X    report_progress (report, "\n--- NEW MAIL FOR LISTSERV ---\n", FALSE),
  11544. X    report_progress (report, tsprintf ("Access granted to user id %d (%s)",
  11545. X                       getuid(), pwentry->pw_name), TRUE),
  11546. X    strcpy (file, SERVER_MAIL_FILE);
  11547. X  else {
  11548. X    if (list_alias == NULL)
  11549. X      report_progress (report, "\ncatmail: No list to process", TRUE),
  11550. X      exit (3);
  11551. X    nlists = sys_config (report, &sys);
  11552. X    if ((listid = get_list_id (list_alias, &sys, nlists)) < 0)
  11553. X      report_progress (report, tsprintf ("\ncatmail: Unknown list %s",
  11554. X                     list_alias), TRUE),
  11555. X      exit (3);
  11556. X    setup_string (file, list_alias,
  11557. X     (moderated ? LIST_MODERATED_F : LIST_MAIL_FILE));
  11558. X    tty_echo = FALSE;
  11559. X    report_progress (report, tsprintf ("\n--- NEW MAIL FOR %s ---\n",
  11560. X                       list_alias), FALSE);
  11561. X    report_progress (report, tsprintf ("Access granted to user id %d (%s)",
  11562. X                       getuid(), pwentry->pw_name), TRUE);
  11563. X    setup_string (list_mail_f, list_alias, LIST_MAIL_FILE);
  11564. X  }
  11565. X#ifndef NO_LOCKS
  11566. X  signal (SIGINT, (void (*)()) gexit);
  11567. X  if ((lfd = lock_file (file, O_RDWR | O_CREAT, 0640, TRUE)) < 0)
  11568. X    switch (lfd) {
  11569. X    case CANT_OPEN:
  11570. X      report_progress (report, tsprintf ("\nCould not stat file %s", file),
  11571. X               TRUE);
  11572. X      exit (1);
  11573. X    case CANT_LOCK:
  11574. X      if (requests)
  11575. X    strcpy (file, LOST_REQUESTS);
  11576. X      else
  11577. X        setup_string (file, list_alias, LOST_MAIL);
  11578. X      report_progress (report, tsprintf ("\nCANNOT LOCK FILE: SAVING UNDER %s",
  11579. X                     file), TRUE);
  11580. X    }
  11581. X  if (moderated) { /* Also lock SERVER_MAIL_FILE and LIST_MAIL_FILE */
  11582. X    if ((lfd2 = lock_file (SERVER_MAIL_FILE, O_RDWR | O_CREAT, 0640, TRUE)) < 0)
  11583. X      switch (lfd2) {
  11584. X      case CANT_OPEN:
  11585. X        report_progress (report, tsprintf ("\nCould not stat file %s",
  11586. X                       SERVER_MAIL_FILE), TRUE);
  11587. X        gexit (1);
  11588. X      case CANT_LOCK:
  11589. X        report_progress (report,
  11590. X             tsprintf ("\nCANNOT LOCK FILE %s: TAKING MY CHANCES",
  11591. X                   SERVER_MAIL_FILE), TRUE);
  11592. X      }
  11593. X    if ((lfd3 = lock_file (list_mail_f, O_RDWR | O_CREAT, 0640, TRUE)) < 0)
  11594. X      switch (lfd3) {
  11595. X      case CANT_OPEN:
  11596. X        report_progress (report, tsprintf ("\nCould not stat file %s",
  11597. X                       list_mail_f), TRUE);
  11598. X        gexit (1);
  11599. X      case CANT_LOCK:
  11600. X        report_progress (report,
  11601. X             tsprintf ("\nCANNOT LOCK FILE %s: TAKING MY CHANCES",
  11602. X                   list_mail_f), TRUE);
  11603. X      }
  11604. X  }
  11605. X#endif
  11606. X  OPEN_FILE (mail, file, "a+", "main");
  11607. X  sprintf (header, "/tmp/.%d.1.catmail", getpid());
  11608. X  sprintf (msg, "/tmp/.%d.2.catmail", getpid());
  11609. X  if (moderated) {
  11610. X    tag = get_tag_id();
  11611. X    OPEN_FILE (pipe, header, "w", "main");
  11612. X    t = time (0);
  11613. X    fprintf (pipe, "From %s %s\nNOTIFY\n\
  11614. XApproval request from %s for posting \
  11615. Xthe following\nmessage to moderated list %s. If approved, send the following \
  11616. Xrequest to\n%s:\n\nAPPROVE %s <password> %d\n\n\
  11617. XIf the message is to be discarded, reply with the following request:\n\n\
  11618. XDISCARD %s <password> %d\n\n\
  11619. X----------------------------- message follows ------------------------------\n",
  11620. X         sys.lists[listid].owner, ctime (&t), sys.server.address,
  11621. X         list_alias, sys.server.address, list_alias, tag, list_alias, tag);
  11622. X    fclose (pipe);
  11623. X    OPEN_FILE (pipe, msg, "w", "main");
  11624. X    OPEN_FILE (mailf, list_mail_f, "a+", "main");
  11625. X  }
  11626. X  catmail (stdin, mail, mailf, pipe, tag);
  11627. X  fclose (mail);
  11628. X  if (pipe)
  11629. X    fclose (pipe);
  11630. X  if (mailf)
  11631. X    fclose (mailf);
  11632. X#ifdef SYSLOG
  11633. X  closelog ();
  11634. X#else
  11635. X  fclose (report);
  11636. X#endif
  11637. X  if (moderated) /* Message was not from moderator */
  11638. X    cat_append (header, SERVER_MAIL_FILE),
  11639. X    cat_append (msg, SERVER_MAIL_FILE);
  11640. X  unlink (header);
  11641. X  unlink (msg);
  11642. X  gexit (0);
  11643. X}
  11644. X
  11645. X/*
  11646. X  Append the input file to the output file, possibly pipe it also to another
  11647. X  output file, and possibly reformat it.
  11648. X  Turn moderation flag off if the message is from one of the list owners.
  11649. X*/
  11650. X
  11651. Xvoid catmail (FILE *in, FILE *out, FILE *mailf, FILE *copy, int tag)
  11652. X{
  11653. X  char buf [MAX_LINE];
  11654. X  char sender [MAX_LINE];
  11655. X
  11656. X  sender[0] = RESET (buf);
  11657. X  fgets (buf, MAX_LINE - 2, in);  /* Do not format very first "From " line */
  11658. X  if (feof (in)) {
  11659. X    moderated = FALSE;
  11660. X    return;
  11661. X  }
  11662. X  strcpy (sender, buf);
  11663. X
  11664. X  extract_sender (sender); /* Get sender; ignore address syntax correctness */
  11665. X  upcase (sender);
  11666. X  if (moderated &&
  11667. X      (owner_listed (OWNERSF, sender, sys.lists[listid].alias, report) ||
  11668. X       strinstr (MAILER_DAEMON, sender)))
  11669. X    out = mailf, /* Output file is now 'mail' instead of 'moderated' */
  11670. X    moderated = FALSE; /* Message from moderator */
  11671. X  fputs (buf, out);
  11672. X  if (moderated && !strncmp (buf, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))
  11673. X    fprintf (out, "Message-Tag: %d\n", tag),
  11674. X    fprintf (copy, ">%sMessage-Tag: %d\n", buf, tag);
  11675. X  RESET (buf);
  11676. X  while (!feof (in)) {
  11677. X    fgets (buf, MAX_LINE - 2, in);
  11678. X    if (buf[0] != EOS) {
  11679. X      if (reformat &&
  11680. X      !strncmp (buf, START_OF_MESSAGE, strlen (START_OF_MESSAGE))) {
  11681. X        putc ('>', out);
  11682. X    if (copy)
  11683. X      putc ('>', copy);
  11684. X      }
  11685. X      fputs (buf, out);
  11686. X      if (copy)
  11687. X    fputs (buf, copy);
  11688. X    }
  11689. X    RESET (buf);
  11690. X  }
  11691. X}
  11692. X
  11693. X/*
  11694. X  Get unique tag id for moderated message.
  11695. X*/
  11696. X
  11697. Xint get_tag_id ()
  11698. X{
  11699. X  FILE *id;
  11700. X  int id_no = 1;
  11701. X
  11702. X  if ((id = fopen (TAG_IDF, "r")) != NULL)
  11703. X    fscanf (id, "%d\n", &id_no),
  11704. X    fclose (id);
  11705. X  echo (tsprintf ("%d", id_no + 1), TAG_IDF);
  11706. X  return id_no;
  11707. X}
  11708. X
  11709. Xvoid usage ()
  11710. X{
  11711. X  fprintf (stderr, "Usage: catmail {<<-L | -l> LIST_ALIAS [-m]> | <-r>} [-f]]\n\
  11712. X-L: Append to HOMEDIR/lists/LIST_ALIAS/mail.\n\
  11713. X-l: Same -L.\n\
  11714. X-m: Append to HOMEDIR/lists/LIST_ALIAS/moderated instead.\n\
  11715. X-r: Append to HOMEDIR/requests instead.\n\
  11716. X-f: Reformat messages before appending.\n\
  11717. X");
  11718. X  exit (3);
  11719. X}
  11720. X
  11721. X/*
  11722. X  Graceful exit.
  11723. X*/
  11724. X
  11725. Xint gexit (int exitcode)
  11726. X{
  11727. X#ifndef NO_LOCKS
  11728. X  unlock_file (lfd);
  11729. X  unlock_file (lfd2);
  11730. X  unlock_file (lfd3);
  11731. X#endif
  11732. X  exit (exitcode);
  11733. X}
  11734. *-*-END-of-src/catmail.c-*-*
  11735. echo x - src/farch.c
  11736. sed 's/^X//' >src/farch.c <<'*-*-END-of-src/farch.c-*-*'
  11737. X/*
  11738. X  ----------------------------------------------------------------------------
  11739. X  |                        FILE ARCHIVING UTILITY                 |
  11740. X  |                                                                          |
  11741. X  |                               Version 3.0                     |
  11742. X  |                                                                          |
  11743. X  |                (or, when Computer Science gets to you)                   |
  11744. X  |                                                                          |
  11745. X  |                    Written by Anastasios Kotsikonas                      |
  11746. X  |                           (tasos@cs.bu.edu)                              |
  11747. X  |                                                                          |
  11748. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  11749. X  | whole and not in parts, as long as you do not remove or alter the author |
  11750. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  11751. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  11752. X  | provided for your personal use, you you may not alter the functions      |
  11753. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  11754. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  11755. X  | any changes you may have made. No part of the source code bearing a         |
  11756. X  | copyright notice can be included in commercial software systems without  |
  11757. X  | written permission by the author.                         |
  11758. X  | By using this software you are bound by this agreement.                  |
  11759. X  | This software comes with no warranties and cannot be sold for profit.    |
  11760. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  11761. X  | files when distributing this software.                                   |
  11762. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  11763. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  11764. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer         |
  11765. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  11766. X  | (ii).                                     |
  11767. X  ----------------------------------------------------------------------------
  11768. X
  11769. X  farch archives files into the specified directories, possibly splitting
  11770. X  them into smaller parts. It then updates the DIR file of the appropriate
  11771. X  archive. Split files have numbers appended to their original names;
  11772. X  non-split files have their names intact. Binary files are uuencoded before
  11773. X  processed, and all output files are compressed.
  11774. X
  11775. X  COMMAND LINE OPTIONS:
  11776. X    -n: Do not split input files.
  11777. X    -t: Tar all input files.
  11778. X    -b: Input files are binary; uuencode.
  11779. X    -B: Input files are binary; do not uuencode, do not split.
  11780. X    -s: Set the maximum size of each of the split subparts in kilobytes.
  11781. X    -d: Specify the actual directory that the archived files will reside.
  11782. X    -p: Specify the password for the private archive.
  11783. X    -D: Specify a descriptive string to be appended to each DIR file.
  11784. X    -r: Remove the specified files from the specified archive.
  11785. X    -a: Specify the archive where the input files will be archived.
  11786. X    -u: Print usage.
  11787. X
  11788. X  WARNING: The program can also archive directory files, if these can be
  11789. X  of any use.
  11790. X
  11791. X  Algorithm:
  11792. X  {
  11793. X    Process command line arguments; allocate buffer_size
  11794. X    Open master archive and all subarchives as necessary to get to the
  11795. X      specified (path-to-) archive; get path to specified archive
  11796. X    Verify existsence of target directory -- create it if necessary
  11797. X    Tar files, if so requested
  11798. X    for (each input file) {
  11799. X      open
  11800. X      get filesize
  11801. X      if (-r)
  11802. X        remove file
  11803. X      else {
  11804. X        if (-b)
  11805. X      uuencode file
  11806. X        if (-n or filesize <= buffer_size) { -- Do not split --
  11807. X      if (-b)
  11808. X        copy uuencoded file into target directory
  11809. X      if (file does not exist in target directory)
  11810. X        copy it to target directory
  11811. X        compress it
  11812. X      update (archive's directory)
  11813. X        }
  11814. X        else split file {
  11815. X      while (not eof) {
  11816. X        get unique output filename
  11817. X        fwrite (leftover bytes from previous chunk)
  11818. X        fread (new chunk)
  11819. X        if (! -b) {
  11820. X          locate nearest newline from the end of the buffer
  11821. X          copy those skipped bytes to leftover
  11822. X        }
  11823. X        fwrite (new modified chunk)
  11824. X        compress it
  11825. X      }
  11826. X      fwrite (any leftovers)
  11827. X      compress part
  11828. X      update (archive's directory)
  11829. X        }
  11830. X      }
  11831. X    }
  11832. X  }
  11833. X*/
  11834. X
  11835. X#include <stdio.h>
  11836. X#include <sys/types.h>
  11837. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  11838. X && !defined (sequent) && !defined (unknown_port)
  11839. X# include <malloc.h>
  11840. X#endif
  11841. X#ifndef unknown_port
  11842. X# ifndef __NeXT__
  11843. X#  include <unistd.h>
  11844. X# else
  11845. X#  include <libc.h>
  11846. X# endif
  11847. X#endif
  11848. X#include <sys/stat.h>
  11849. X#include <string.h>
  11850. X#include <errno.h>
  11851. X#ifdef unknown_port
  11852. Xextern int errno;
  11853. X#endif
  11854. X#include <signal.h>
  11855. X#include "defs.h"
  11856. X#include "struct.h"
  11857. X#include "global.h"
  11858. X#include "listserv.h"
  11859. X
  11860. X#define DEFAULT_SIZE    64 * 1024
  11861. X
  11862. X#ifdef __STDC__
  11863. X# include <stdarg.h>
  11864. Xextern int  syscom (char *, ...);
  11865. X#else
  11866. X# include <varargs.h>
  11867. Xextern int  syscom ();
  11868. X#endif
  11869. Xextern char *extract_filename (char *);
  11870. Xextern char *locase (char *);
  11871. X#ifndef __NeXT__
  11872. Xextern long int atol (char *);
  11873. X#else
  11874. Xextern long int atol (const char *);
  11875. X#endif
  11876. Xextern int  _getopt (int, char **, char *);
  11877. Xextern BOOLEAN make_indexes (char *, char *, char *, char *, char *);
  11878. Xextern BOOLEAN mkdir1 (char *, char *, char *);
  11879. Xextern char *mystrdup (char *);
  11880. X
  11881. Xvoid   main (int , char **);
  11882. Xvoid   uuencode (FILE **, char *, char *, struct stat *, BOOLEAN);
  11883. Xint    update (char *, char *, long int, long int *, char *, char *,
  11884. X           struct stat, BOOLEAN);
  11885. Xvoid   remove_files (char *, char *, long int, struct stat);
  11886. Xvoid   usage (void);
  11887. Xvoid   do_archive (int, int, char **, char *, char *, char *, char *, char *,
  11888. X           long int, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN);
  11889. Xint    get_archive (char **, char *, char *, BOOLEAN);
  11890. Xint    get_dir (char *, char **, char *);
  11891. Xint    tar_files (int, int, char **, char *);
  11892. Xvoid   rmfiles (int, int, char **, char *);
  11893. Xint    gexit (int);
  11894. X
  11895. Xchar *uue_file;
  11896. X
  11897. Xvoid main (int argc, char **argv)
  11898. X{
  11899. X  long int size = DEFAULT_SIZE;
  11900. X  char *buf, *arch = NULL, *newdir = NULL, *dir, fullpath[10240],
  11901. X       *tarf, *password = NULL, *options = "nbBs:a:d:t:p:D:ur", *text = "";
  11902. X  int c;
  11903. X  BOOLEAN bin = FALSE, tar = FALSE, split = TRUE, uue = FALSE,
  11904. X    remove_files = FALSE;
  11905. X  extern char *optarg;
  11906. X  extern int optopt, optind;
  11907. X
  11908. X  buf = (char *) malloc (size * sizeof (char));
  11909. X  dir = (char *) malloc (sizeof (char));
  11910. X  while ((c = _getopt (argc, argv, options)) != EOF)
  11911. X    switch ((char) c) {
  11912. X    case 'n': split = FALSE; break;
  11913. X    case 't': tar = TRUE; tarf = optarg;
  11914. X    case 'b': bin = TRUE; uue = TRUE; break;
  11915. X    case 'B': bin = TRUE; uue = FALSE; split = FALSE; break;
  11916. X    case 's': size = (long) atol (optarg) * 1024;
  11917. X                if (size <= 0)
  11918. X                fprintf (stderr, "How am I supposed to allocate %ld bytes?\n",
  11919. X                         size),
  11920. X                exit (3);
  11921. X              free ((char *) buf);
  11922. X              if ((buf = (char *) malloc (size * sizeof (char))) == NULL)
  11923. X                fprintf (stderr, "Size too big; not enough memory.\n"),
  11924. X                exit (11);
  11925. X              break;
  11926. X    case 'a': arch = locase (optarg); break;
  11927. X    case 'd': newdir = optarg;
  11928. X              if (*newdir != '/')
  11929. X                fprintf (stderr, "Must specify full path for the directory.\n"),
  11930. X                exit (3);
  11931. X              break;
  11932. X    case 'p': password = locase (optarg); break;
  11933. X    case 'D': text = optarg; break;
  11934. X    case 'r': remove_files = TRUE; break;
  11935. X    case 'u': usage ();
  11936. X    case ':': fprintf (stderr, "Option '%c' requires an argument.\n", optopt);
  11937. X              exit (3);
  11938. X    case '?':
  11939. X    default:
  11940. X      fprintf (stderr, "Unrecognized option '%c'.\n", optopt);
  11941. X      usage ();
  11942. X    }
  11943. X
  11944. X  if (optind == argc) {
  11945. X    fprintf (stderr, "farch: filename(s) missing.\n");
  11946. X    goto abort;
  11947. X  }
  11948. X  if (get_archive (&arch, fullpath, password, remove_files) &&
  11949. X      (remove_files || get_dir (newdir, &dir, fullpath))) {
  11950. X    if (remove_files)
  11951. X      rmfiles (optind, argc, argv, fullpath);
  11952. X    else {
  11953. X      if (tar)
  11954. X    if (tar_files (optind, argc, argv, tarf))
  11955. X      argc = optind + 1;
  11956. X    else 
  11957. X      goto abort;
  11958. X      do_archive (optind, argc, argv, buf, fullpath, arch, dir, text, size, bin,
  11959. X          uue, split, tar);
  11960. X      if (tar)
  11961. X    unlink (tarf);
  11962. X    }
  11963. X  }
  11964. X  abort:
  11965. X  free ((char *) dir);
  11966. X  free ((char *) buf);
  11967. X}
  11968. X
  11969. X/*
  11970. X  uuencode a file.
  11971. X*/
  11972. X
  11973. Xvoid uuencode (FILE **fin, char *file, char *infile, struct stat *finbuf,
  11974. X           BOOLEAN tar)
  11975. X{
  11976. X  fclose (*fin);
  11977. X  printf ("\t- uuencoding...\n");
  11978. X  syscom ("uuencode %s %s%s > %s", file, infile, (tar ? ".tar" : ""),
  11979. X      (uue_file = mystrdup (tmpnam (NULL))));
  11980. X  *fin = fopen (uue_file, "r");
  11981. X  stat (uue_file, finbuf);
  11982. X}
  11983. X
  11984. X/*
  11985. X  tar all input files into 'tarf'.
  11986. X*/
  11987. X
  11988. Xint tar_files (int optind, int argc, char **argv, char *tarf)
  11989. X{
  11990. X  FILE *fin, *fout;
  11991. X  char files[10000];
  11992. X  int original = optind;
  11993. X
  11994. X  if ((fout = fopen (tarf, "w")) == NULL) {
  11995. X    fprintf (stderr, "Cannot write to tar file %s\n", tarf);
  11996. X    return 0;
  11997. X  }
  11998. X  fclose (fout);
  11999. X  unlink (tarf);
  12000. X  printf ("tarring...\n");
  12001. X  RESET (files);
  12002. X  while (optind < argc) {
  12003. X    if ((fin = fopen (argv[optind], "r")) == NULL) {
  12004. X      fprintf (stderr, "Unable to open %s for reading.\n", argv[optind]);
  12005. X      return 0;
  12006. X    }
  12007. X    fclose (fin);
  12008. X    sprintf (files + strlen (files), "%s ", argv[optind++]);
  12009. X  }
  12010. X  syscom ("tar -cf %s %s", tarf, files);
  12011. X  argv[original] = tarf;
  12012. X  return 1;
  12013. X}
  12014. X
  12015. X/*
  12016. X  Remove the file from the archive, if found.
  12017. X*/
  12018. X
  12019. Xvoid rmfiles (int optind, int argc, char **argv, char *path)
  12020. X{
  12021. X  char dirf[10240];
  12022. X  char file[10240];
  12023. X  char fullpath[10240];
  12024. X  char _fullpath[10240];
  12025. X  char fullname[10240];
  12026. X  char desc[10240];
  12027. X  char *s, *tmpdir;
  12028. X  BOOLEAN continued, found, match;
  12029. X  int cnt, _cnt, i;
  12030. X  long int count;
  12031. X  FILE *fin, *fout;
  12032. X  struct stat sbuf;
  12033. X
  12034. X  while (optind < argc) { /* Process each file */
  12035. X
  12036. X    s = argv[optind] + strlen (argv[optind]) - 1;
  12037. X    while (s != argv[optind] && *s == '/')  /* Remove trailing / */
  12038. X      *(s--) = EOS;
  12039. X
  12040. X    i = strlen (argv[optind]);
  12041. X    if (i > 2 && argv[optind][i - 2] == '.' && argv[optind][i - 1] == 'Z')
  12042. X      argv[optind][i - 2] = EOS;
  12043. X
  12044. X    printf ("%s: ", argv[optind]);
  12045. X    fflush (stdout);
  12046. X    RESET (dirf);
  12047. X    sprintf (dirf, "%s/%s", path, DIRF);
  12048. X    if (stat (dirf, &sbuf)) {
  12049. X      printf ("not removed\n");
  12050. X      fprintf (stderr, "Cannot access index %s for reading.\n", dirf);
  12051. X      exit (1);
  12052. X    }
  12053. X    signal (SIGINT, SIG_IGN);
  12054. X    syscom ("mv %s %s", dirf, (tmpdir = mystrdup (tmpnam (NULL))));
  12055. X    if ((fout = fopen (dirf, "w")) == NULL) {
  12056. X      fprintf (stderr, "Unable to open %s for writing.\nSEVERE ERROR: The \
  12057. Xarchive is now in an inconsistent state with no DIR file.\nIts DIR file can be \
  12058. Xfound in /tmp. Move %s to %s\n", dirf, tmpdir, dirf);
  12059. X      free ((char *) tmpdir);
  12060. X      exit (1);
  12061. X    }
  12062. X    if ((fin = fopen (tmpdir, "r")) == NULL) { 
  12063. X      fprintf (stderr, "Unable to open %s for reading. Cannot proceed.\n",
  12064. X           tmpdir);
  12065. X      if (stat (dirf, &sbuf))
  12066. X    fputs ("SEVERE ERROR: The archive now has NO DIR file; DIR file \
  12067. Xlost!!!\n", stderr);
  12068. X      else
  12069. X    fputs ("Archive intact!\n", stderr);
  12070. X      free ((char *) tmpdir);
  12071. X      exit (1);
  12072. X    }
  12073. X    RESET (fullpath);
  12074. X    found = FALSE;
  12075. X    while (!feof (fin)) { /* Get location and file-count of file */
  12076. X      file[0] = RESET (_fullpath);
  12077. X      fscanf (fin, "%s %d ", file, &_cnt);
  12078. X      match = FALSE;
  12079. X      if (file[0] != EOS) {
  12080. X    locase (file);
  12081. X    if (!strcmp (argv[optind], file))
  12082. X      match = found = TRUE;
  12083. X    if (!match)
  12084. X      fprintf (fout, "%s %d ", file, _cnt);
  12085. X    for (i = 0; i < abs (_cnt); ++i) {
  12086. X      fscanf (fin, "%ld ", &count);
  12087. X      if (!match)
  12088. X        fprintf (fout, "%ld ", count);
  12089. X    }
  12090. X    fscanf (fin, "%s", _fullpath);
  12091. X    if (!match)
  12092. X      fprintf (fout, "%s", _fullpath);
  12093. X    else
  12094. X      cnt = _cnt,
  12095. X      strcpy (fullpath, _fullpath);
  12096. X    do { /* Get file description */
  12097. X      RESET (desc);
  12098. X      fgets (desc, MAX_LINE - 2, fin);
  12099. X      if (desc [0] != EOS && desc[strlen (desc) - 1] == '\n')
  12100. X        desc[strlen (desc) - 1] = EOS;
  12101. X      continued = FALSE;
  12102. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  12103. X        desc[strlen (desc) - 1] = EOS,
  12104. X        continued = TRUE;
  12105. X      if (!match) {
  12106. X        fprintf (fout, "%s", desc);
  12107. X        if (continued)
  12108. X          fprintf (fout, "\\");
  12109. X        fputs ("\n", fout);
  12110. X      }
  12111. X    } while (continued);
  12112. X      }
  12113. X    }
  12114. X    if (!found)
  12115. X      printf ("not found in %s", dirf);
  12116. X    else { /* Remove all parts */
  12117. X      printf ("removing parts: ");
  12118. X      fflush (stdout);
  12119. X      for (i = 1; i <= abs (cnt); i++) {
  12120. X    RESET (fullname);
  12121. X    if (abs (cnt) > 1)
  12122. X      sprintf (fullname, "%s/%s%d", fullpath, argv[optind], i);
  12123. X    else
  12124. X      sprintf (fullname, "%s/%s", fullpath, argv[optind]);
  12125. X    if (stat (fullname, &sbuf)) {
  12126. X      strcat (fullname, ".Z"); /* Check for compressed file */
  12127. X      if (stat (fullname, &sbuf))
  12128. X        printf ("%d (not found) ", i),
  12129. X        fflush (stdout);
  12130. X      else {
  12131. X        printf ("%d ", i);
  12132. X        if (unlink (fullname))
  12133. X          printf ("(errno %d) ", errno);
  12134. X        fflush (stdout);
  12135. X      }
  12136. X    }
  12137. X    else {
  12138. X      printf ("%d ", i);
  12139. X      if (unlink (fullname))
  12140. X        printf ("(errno %d) ", errno);
  12141. X      fflush (stdout);
  12142. X    }
  12143. X      }
  12144. X    }
  12145. X    fclose (fin);
  12146. X    fclose (fout);
  12147. X    signal (SIGINT, SIG_DFL);
  12148. X    ++optind;
  12149. X    puts ("");
  12150. X  }
  12151. X  unlink (tmpdir);
  12152. X  free ((char *) tmpdir);
  12153. X}
  12154. X
  12155. X/*
  12156. X  Check for duplicate file name and return if so. Otherwise, update the
  12157. X  archive's directory.
  12158. X*/
  12159. X
  12160. Xint update (char *path, char *filename, long int count, long int *filesizes,
  12161. X        char *dir, char *text, struct stat finbuf, BOOLEAN pure_bin)
  12162. X{
  12163. X  char dirf[10240];
  12164. X  char file[10240];
  12165. X  char fullpath[10240];
  12166. X  char desc[10240];
  12167. X  char stripped_file[10240];
  12168. X  BOOLEAN continued, found = FALSE;
  12169. X  int cnt, i;
  12170. X  FILE *fout;
  12171. X
  12172. X  strcpy (stripped_file, filename);
  12173. X  i = strlen (stripped_file);
  12174. X  if (i > 2 && stripped_file [i - 2] == '.' && stripped_file [i - 1] == 'Z')
  12175. X    stripped_file [i - 2] = EOS;
  12176. X  RESET (dirf);
  12177. X  sprintf (dirf, "%s/%s", path, DIRF);
  12178. X  if ((fout = fopen (dirf, "r")) == NULL) {
  12179. X    fprintf (stderr, "Unable to open index %s for reading.\nFile %s \
  12180. Xnot archived. Remove output file(s) from %s\n", dirf, filename, dir);
  12181. X    exit (1);
  12182. X  }
  12183. X  while (!feof (fout)) { /* Get location and file-count of file */
  12184. X    file[0] = RESET (fullpath);
  12185. X    fscanf (fout, "%s %d %s", file, &cnt, fullpath);
  12186. X    do { /* Get file description */
  12187. X      RESET (desc);
  12188. X      fgets (desc, MAX_LINE - 2, fout);
  12189. X      if (desc [0] != EOS && desc[strlen (desc) - 1] == '\n')
  12190. X        desc[strlen (desc) - 1] = EOS;
  12191. X      continued = FALSE;
  12192. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  12193. X        desc[strlen (desc) - 1] = EOS,
  12194. X        continued = TRUE;
  12195. X    } while (continued);
  12196. X    if (file[0] != EOS) {
  12197. X      locase (file);
  12198. X      if (!strcmp (stripped_file, file)) {
  12199. X        found = TRUE;
  12200. X        break;
  12201. X      }
  12202. X    }
  12203. X  }
  12204. X  fclose (fout);
  12205. X  if (found) {
  12206. X    fprintf (stderr, "\t- file %s already exists in %s\n\
  12207. X\t- file not archived\n",
  12208. X         stripped_file, dirf);
  12209. X    remove_files (dir, filename, count, finbuf);
  12210. X    return 0;
  12211. X  }
  12212. X  signal (SIGINT, SIG_IGN);
  12213. X  if ((fout = fopen (dirf, "a")) == NULL) {
  12214. X    fprintf (stderr, "Unable to open index %s for update.\nFile %s \
  12215. Xnot archived. Exiting.\n", dirf, filename);
  12216. X    remove_files (dir, filename, count, finbuf);
  12217. X    exit (1);
  12218. X  }
  12219. X  fprintf (fout, "%s %ld ", stripped_file, (pure_bin ? -count : count));
  12220. X  for (i = 0; i < count; i++)
  12221. X    fprintf (fout, "%ld ", filesizes[i]);
  12222. X  fprintf (fout, "%s%s%s\n", dir, (text[0] != EOS ? " " : ""), text);
  12223. X  fclose (fout);
  12224. X  signal (SIGINT, SIG_DFL);
  12225. X  return 1;
  12226. X}
  12227. X
  12228. X/*
  12229. X  Remove all parts of the specified file from the specified directory.
  12230. X*/
  12231. X
  12232. Xvoid remove_files (char *dir, char *filename, long int count,
  12233. X           struct stat finbuf)
  12234. X{
  12235. X  char file[10240];
  12236. X  char fout[10240];
  12237. X  struct stat foutbuf;
  12238. X  char yn;
  12239. X  BOOLEAN split = (count > 1 ? 1 : 0);
  12240. X
  12241. X  if (!split) {
  12242. X    sprintf (fout, "%s/%s", dir, filename);
  12243. X    syscom ("uncompress %s.Z  > /dev/null 2>&1 < /dev/null", fout);
  12244. X    if (stat (fout, &foutbuf)) {
  12245. X      printf ("Input file %s may be the same as output file %s/%s.\n\
  12246. XRemove %s/%s [y]? ",
  12247. X          filename, dir, filename, dir, filename);
  12248. X      fflush (stdout);
  12249. X      scanf ("%c", &yn);
  12250. X      if (yn == 'n' || yn == 'N')
  12251. X        return;
  12252. X    }
  12253. X    if ((finbuf.st_ino == foutbuf.st_ino) &&
  12254. X    (finbuf.st_dev == foutbuf.st_dev)) {
  12255. X      printf ("\t- output file matches input: not removed\n");
  12256. X      return;
  12257. X    }
  12258. X  }
  12259. X  printf ("\t- removing output file(s)\n");
  12260. X  while (count) {
  12261. X    RESET (file);
  12262. X    if (split)
  12263. X      sprintf (file, "%s/%s%d", dir, filename, count);
  12264. X    else
  12265. X      sprintf (file, "%s/%s", dir, filename);
  12266. X    unlink (file);
  12267. X    strcat (file, ".Z");
  12268. X    unlink (file);
  12269. X    --count;
  12270. X  }
  12271. X}
  12272. X
  12273. Xvoid usage ()
  12274. X{
  12275. X  fprintf (stderr, "farch {[-n] [-b | -B] [-s size] \
  12276. X[-d dir] [-p password] [-D 'description'] [-t file]} | {<-r>} \
  12277. X[-a archive | path-to-archive] filename(s)\n");
  12278. X  fprintf (stderr, "-n: do not split input file(s)\n\
  12279. X-b: input files are binary: uuencode (on if -t specified)\n\
  12280. X-B input files are binary: do not uuencode and do not split\n\
  12281. X-s: maximum size of each output file (in kilobytes) -- default %ld\n\
  12282. X-d: actual directory to put output file(s)\n    -- default %s/%s\n\
  12283. X-p: password for a new private archive\n\
  12284. X-D: description of the file to go into the DIR file\n\
  12285. X-t: tar all input files into 'file' and archive that\n\
  12286. X-a: which archive index to update (subdir of %s)\n    -- \
  12287. Xdefault %s\n\
  12288. X-r: remove the specified file(s) from the archive\n",
  12289. X(long) DEFAULT_SIZE / 1024, ARCHIVE_DIR, DEFAULT_ARCHIVE, ARCHIVE_DIR,
  12290. XDEFAULT_ARCHIVE);
  12291. X  exit (3);
  12292. X}
  12293. X
  12294. X/*
  12295. X  Archive all files given in 'argv'.
  12296. X*/
  12297. X
  12298. Xvoid do_archive (int optind, int argc, char **argv, char *buf, char *fullpath,
  12299. X             char *archive, char *dir, char *text, long int size,
  12300. X         BOOLEAN bin, BOOLEAN uue, BOOLEAN split, BOOLEAN tar)
  12301. X{
  12302. X  FILE *fin, *fout, *flast;
  12303. X  long int l, count, nread, nchars, total, *filesizes = NULL;
  12304. X  char *leftovers = NULL, *s, *infile = NULL, filename[10240],
  12305. X    compressed[10240];
  12306. X  struct stat sbuf, finbuf;
  12307. X
  12308. X  while (optind < argc) { /* Split and archive each file */
  12309. X
  12310. X    s = argv[optind] + strlen (argv[optind]) - 1;
  12311. X    while (s != argv[optind] && *s == '/')  /* Remove trailing / */
  12312. X      *(s--) = EOS;
  12313. X
  12314. X    if ((fin = fopen (argv[optind], "r")) == NULL) { /* Open file */
  12315. X      fprintf (stderr, "Cannot open file %s for reading.\n", argv[optind]);
  12316. X      goto abort;
  12317. X    }
  12318. X
  12319. X    printf ("%s:\n", argv[optind]);
  12320. X    count = 1;
  12321. X    nchars = 0;
  12322. X
  12323. X    if (infile) /* free previous allocation */
  12324. X      free ((char *) infile);
  12325. X    infile = extract_filename (argv[optind]); /* get filename from path */
  12326. X    locase (infile);
  12327. X    l = strlen (infile);
  12328. X    if (l > 2 && infile [l - 2] == '.' && infile [l - 1] == 'z') {
  12329. X      infile [l - 2] = EOS;
  12330. X      l = strlen (argv[optind]);
  12331. X      argv[optind][l - 2] = EOS;
  12332. X      printf ("\t- uncompressing...\n");
  12333. X      syscom ("uncompress %s > /dev/null 2>&1 < /dev/null", argv[optind]);
  12334. X      fclose (fin);
  12335. X      fin = fopen (argv[optind], "r");
  12336. X    }
  12337. X
  12338. X    stat (argv[optind], &finbuf); /* Get size of input file */
  12339. X    if (bin && uue) /* uuencode */
  12340. X      uuencode (&fin, argv[optind], infile, &finbuf, tar);
  12341. X
  12342. X    if (!split || finbuf.st_size <= size) { /* Not splitting;may have to copy */
  12343. X      fclose (fin);
  12344. X      sprintf (filename, "%s%s%s", (strcmp (dir, "/") ? dir : ""),
  12345. X               ((strcmp (dir, infile) && strcmp (infile, "/")) ? "/" : ""),
  12346. X               infile);
  12347. X
  12348. X      if (bin) { /* Copy (possibly) uue_file to target directory */
  12349. X        if (uue && !stat (filename, &sbuf)) {
  12350. X      fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  12351. X           filename, argv[optind]);
  12352. X      unlink (uue_file);
  12353. X      free ((char *) uue_file);
  12354. X      goto abort;
  12355. X    }
  12356. X        if (uue && (fout = fopen (filename, "w")) == NULL) { /* Test */
  12357. X          fprintf (stderr, "Cannot write to directory %s; cannot \
  12358. Xproceed with %s\n",
  12359. X                   dir, argv[optind]);
  12360. X      unlink (uue_file);
  12361. X      free ((char *) uue_file);
  12362. X          goto abort;
  12363. X        }
  12364. X    if (uue)
  12365. X          fclose (fout),
  12366. X          syscom ("mv %s %s > /dev/null 2>&1", uue_file, filename);
  12367. X    else if (stat (filename, &sbuf)) { /* File does not exist in target dir */
  12368. X      if ((fout = fopen (filename, "w")) == NULL) { /* Test */
  12369. X        fprintf (stderr, "Cannot write to directory %s; cannot \
  12370. Xproceed with %s\n",
  12371. X             dir, argv[optind]);
  12372. X        goto abort;
  12373. X      }
  12374. X      fclose (fout);
  12375. X      syscom ("cp %s %s > /dev/null 2>&1", argv[optind], filename);
  12376. X    }
  12377. X      }
  12378. X      else if (stat (filename, &sbuf)) { /* File does not exist in target dir */
  12379. X        if ((fout = fopen (filename, "w")) == NULL) {
  12380. X          fprintf (stderr, "Cannot write to directory %s; cannot \
  12381. Xproceed with %s\n",
  12382. X                   dir, argv[optind]);
  12383. X          goto abort;
  12384. X        }
  12385. X        fclose (fout);
  12386. X        syscom ("cp %s %s > /dev/null 2>&1", argv[optind], filename);
  12387. X      }
  12388. X
  12389. X      sprintf (compressed, "%s.Z", filename);
  12390. X      if (!stat (compressed, &sbuf)) {
  12391. X    fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  12392. X         compressed, argv[optind]);
  12393. X        if (bin && uue)
  12394. X      unlink (uue_file),
  12395. X      free ((char *) uue_file);
  12396. X    goto abort;
  12397. X      }
  12398. X
  12399. X      filesizes = (long int *) malloc (sizeof (long int));
  12400. X      *filesizes = (long int) finbuf.st_size;
  12401. X      syscom ("compress %s > /dev/null 2>&1 < /dev/null", filename);
  12402. X      if (update (fullpath, infile, 1, filesizes, dir, text, finbuf,bin & !uue))
  12403. X        printf ("\t- file not split\n\t- archived in %s\n\t- directory: %s\n",
  12404. X                archive, dir);
  12405. X      free ((long int *) filesizes);
  12406. X      filesizes = NULL;
  12407. X    }
  12408. X    else { /* Split file */
  12409. X      while (!feof (fin)) {
  12410. X        sprintf (filename, "%s%s%s%d", (strcmp (dir, "/") ? dir : ""),
  12411. X                 ((strcmp (dir, infile) && strcmp (infile, "/")) ? "/" : ""),
  12412. X                 infile, count);
  12413. X
  12414. X        if (!stat (filename, &sbuf)) {
  12415. X          fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  12416. X                   filename, argv[optind]);
  12417. X      if (bin)
  12418. X        unlink (uue_file),
  12419. X        free ((char *) uue_file);
  12420. X          fout = (FILE *) -1;
  12421. X          break;
  12422. X        }
  12423. X        if ((fout = fopen (filename, "w")) == NULL) {
  12424. X          fprintf (stderr, "Cannot write to directory %s; cannot proceed \
  12425. Xwith %s\n",
  12426. X                   dir, argv[optind]);
  12427. X          fout = (FILE *) -1;
  12428. X          break;
  12429. X        }
  12430. X
  12431. X        total = 0;  /* Do the actual splitting */
  12432. X        total += fwrite (leftovers, sizeof (char), nchars, fout);
  12433. X        nread = fread (buf, sizeof (char), size - nchars, fin);
  12434. X        if (nchars)
  12435. X          free ((char *) leftovers);
  12436. X        s = buf + nread - (nread > 0 ? 1 : 0);
  12437. X        nchars = 0;
  12438. X        while (s != buf && *s != '\n') /* Look for first \n from the end */
  12439. X          ++nchars,
  12440. X          --s;
  12441. X        if (s == buf) /* No new line found; write as is */
  12442. X          nchars = 0;
  12443. X        nread -= nchars;
  12444. X        leftovers = (char *) malloc (nchars * sizeof (char));
  12445. X        strncpy (leftovers, ++s, nchars); /* Copy anything after \n */
  12446. X        total += fwrite (buf, sizeof (char), nread, fout);
  12447. X        fclose (fout);
  12448. X
  12449. X        if (total == 0)
  12450. X          unlink (filename);
  12451. X        else { /* OK, compress */
  12452. X          sprintf (compressed, "%s.Z", filename);
  12453. X          if (!stat (compressed, &sbuf)) {
  12454. X            fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  12455. X                     compressed, argv[optind]);
  12456. X        if (bin)
  12457. X          unlink (uue_file),
  12458. X          free ((char *) uue_file);
  12459. X        unlink (filename);
  12460. X            goto abort;
  12461. X          }
  12462. X      stat (filename, &sbuf);
  12463. X      filesizes = (long int *)
  12464. X        (filesizes ?
  12465. X          (realloc ((long int *) filesizes, count * sizeof (long int))) :
  12466. X          (malloc (count * sizeof (long int))));
  12467. X      *(filesizes + (count - 1)) = (long int) sbuf.st_size;
  12468. X          syscom ("compress %s > /dev/null 2>&1 < /dev/null", filename),
  12469. X      ++count; /* Always one ahead */
  12470. X    }
  12471. X      }
  12472. X
  12473. X      fclose (fin);
  12474. X      if (bin)
  12475. X        unlink (uue_file),
  12476. X    free ((char *) uue_file);
  12477. X      if (nchars) /* write any leftovers */
  12478. X        flast = fopen (filename, "a"),
  12479. X        fwrite (leftovers, sizeof (char), nchars, flast),
  12480. X        fclose (flast),
  12481. X        free ((char *) leftovers),
  12482. X    stat (filename, &sbuf),
  12483. X    *(filesizes + (count - 2)) = (long int) sbuf.st_size;
  12484. X
  12485. X      if (fout != (FILE *) -1) { /* Splitting successful, update DIR file */
  12486. X        if (update (fullpath, infile, count - 1, filesizes, dir, text, finbuf,
  12487. X        bin & !uue))
  12488. X          printf ("\t- file split in %ld parts\n\t- archived in %s\n\t\
  12489. X- directory: %s\n",
  12490. X                  (long) count - 1, archive, dir);
  12491. X    free ((long int *) filesizes);
  12492. X    filesizes = NULL;
  12493. X      }
  12494. X    }
  12495. X    abort:
  12496. X    ++optind;
  12497. X  }
  12498. X}
  12499. X
  12500. X/*
  12501. X  Get archive to update.
  12502. X*/
  12503. X
  12504. Xint get_archive (char **archive, char *fullpath, char *password,
  12505. X         BOOLEAN remove_file)
  12506. X{
  12507. X  FILE *master;
  12508. X  char indexf[10240], line[10240], cur_archive[10240], arch[10240], dirf[10240],
  12509. X  error [10240], *slash;
  12510. X  char original[10240];
  12511. X  BOOLEAN found = FALSE;
  12512. X
  12513. X  if (!*archive)
  12514. X    *archive = DEFAULT_ARCHIVE;
  12515. X  strcpy (cur_archive, (char *) *archive);
  12516. X  strcpy (original, *archive);
  12517. X  if ((slash = strchr (cur_archive, '/')))
  12518. X    *slash = EOS;
  12519. X  sprintf (indexf, "%s/%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE, INDEX);
  12520. X  while (*archive[0] != EOS) { /* Check all archives specified */
  12521. X    if ((master = fopen (indexf, "r")) == NULL) {
  12522. X      fprintf (stderr, "Sorry, no master index found.\n");
  12523. X      return 0;
  12524. X    }
  12525. X    found = FALSE;
  12526. X    while (!feof (master)) { /* Look at the current index for fullpath */
  12527. X      indexf[0] = arch[0] = RESET (line);
  12528. X      fgets (line, MAX_LINE - 2, master);
  12529. X      if (line[0] != EOS) {
  12530. X        sscanf (line, "%s %s\n", arch, indexf);
  12531. X        locase (arch);
  12532. X        if (!strcmp (arch, cur_archive)) {
  12533. X          found = TRUE;
  12534. X          break;
  12535. X        }
  12536. X      }
  12537. X    }
  12538. X    fclose (master);
  12539. X    if (!found && remove_file) {
  12540. X      fprintf (stderr, "%s: not a valid archive or path.\n", cur_archive);
  12541. X      return 0;
  12542. X    }
  12543. X    sprintf (dirf, "%s/%s/%s", ARCHIVE_DIR, original, DIRF);
  12544. X    if (!found) { 
  12545. X      sprintf (dirf, "%s/%s/%s", ARCHIVE_DIR, original, DIRF);
  12546. X      printf ("New archive %s; creating all directories and necessary files\n",
  12547. X          original);
  12548. X      if (!make_indexes (dirf, original, password, error, "077")) {
  12549. X    fprintf (stderr, "%s", error);
  12550. X    return 0;
  12551. X      }
  12552. X      sprintf (indexf, "%s/%s", ARCHIVE_DIR, original);
  12553. X    }
  12554. X    if ((slash = strchr (*archive, '/')))
  12555. X      sprintf (*archive, "%s", slash + 1); /* Move down the path */
  12556. X    else
  12557. X      sprintf (*archive, "%s", *archive + strlen (cur_archive));
  12558. X    strcpy (cur_archive, *archive);
  12559. X    if ((slash = strchr (cur_archive, '/')))
  12560. X      *slash = EOS;
  12561. X    if (cur_archive[0] != EOS)
  12562. X      sprintf (indexf, "%s/%s", indexf, INDEX);
  12563. X  }
  12564. X  strcpy (fullpath, indexf);
  12565. X  strcpy (*archive, original);
  12566. X  return 1;
  12567. X}
  12568. X
  12569. X/*
  12570. X  Get output directory.
  12571. X*/
  12572. X
  12573. Xint get_dir (char *newdir, char **dir, char *fullpath)
  12574. X{
  12575. X  char *s;
  12576. X  char msg [MAX_LINE];
  12577. X  struct stat sbuf;
  12578. X
  12579. X  free ((char *) *dir);
  12580. X  if (!newdir)
  12581. X    *dir = (char *) malloc ((strlen (fullpath) + 1) * sizeof (char)),
  12582. X    sprintf (*dir, "%s", fullpath);
  12583. X  else {
  12584. X    *dir = (char *) malloc ((strlen (newdir) + 1) * sizeof (char));
  12585. X    sprintf (*dir, "%s", newdir);
  12586. X    s = *dir + strlen (*dir) - 1;
  12587. X    while (s != *dir && *s == '/')
  12588. X      *(s--) = EOS;
  12589. X  }
  12590. X  if (stat (*dir, &sbuf)) {
  12591. X    if (!mkdir1 (*dir, msg, "077")) {
  12592. X      fprintf (stderr, "Unable to create new directory %s\n%s", *dir, msg);
  12593. X      return 0;
  12594. X    }
  12595. X    printf ("Creating new directory %s\n", *dir);
  12596. X  }
  12597. X  return 1;
  12598. X}
  12599. X
  12600. X/*
  12601. X  Required to avoid undefined symbols.
  12602. X*/
  12603. X
  12604. Xint gexit (int exitcode)
  12605. X{
  12606. X  exit (exitcode);
  12607. X}
  12608. *-*-END-of-src/farch.c-*-*
  12609. echo x - src/fio.c
  12610. sed 's/^X//' >src/fio.c <<'*-*-END-of-src/fio.c-*-*'
  12611. X#include <stdio.h>
  12612. X#include <string.h>
  12613. X#include <sys/types.h>
  12614. X#include <sys/stat.h>
  12615. X#include <sys/file.h>
  12616. X#include <fcntl.h>
  12617. X#include <errno.h>
  12618. X# ifdef unknown_port
  12619. Xextern int errno;
  12620. X# endif
  12621. X#if !defined (stellar) && !defined (unknown_port)
  12622. X# include <time.h>
  12623. X#endif
  12624. X#include <sys/time.h>
  12625. X#if !defined (__NeXT__) && !defined (stardent) && !defined (unknown_port)
  12626. X# include <utime.h>      /* not in NeXT OS 2.1; Under 3.0, included by sys/types.h */
  12627. X#else
  12628. X# include "next.h"
  12629. X#endif
  12630. X#include "defs.h"
  12631. X
  12632. X/*
  12633. X  Speed up the system by not forking off processes for things that
  12634. X  can be done with a syscall or two (or 50 for that matter).
  12635. X
  12636. X  Copyright 1993
  12637. X  Kenneth Lorber (keni@oasys.dt.navy.mil)
  12638. X  David Taylor Model Basin
  12639. X  Carderock Division, Naval Surface Warfare Center
  12640. X
  12641. X  This code may be freely redistributed.
  12642. X
  12643. X  [tasos: the code has been expanded to use the ULISTSERVER_UMASK environment
  12644. X  variable, fixed spacing to match the rest of the system and some function
  12645. X  prototyping problems; also altered syntax/use of utime() for NeXT hosts,
  12646. X  and removed const declarations which are not removed by the unproto package,
  12647. X  plus some bug fixing as well]
  12648. X*/
  12649. X
  12650. X#ifdef __STDC__
  12651. X# include <stdarg.h>
  12652. Xchar *tsprintf (char *, ...);
  12653. X#else
  12654. X# include <varargs.h>
  12655. Xchar *tsprintf ();
  12656. X#endif
  12657. X
  12658. Xextern char *extract_filename (char *);
  12659. Xextern void shrink (char *);
  12660. Xextern int otoi (char *);
  12661. Xextern char *getenv ();
  12662. X
  12663. Xtypedef enum append { NOAPPEND, APPEND } _append;
  12664. Xstatic int echo_internal (char *, char *, _append);
  12665. Xstatic int cat_internal (char *, char *, _append);
  12666. Xstatic int log_warn (char *);
  12667. X
  12668. Xint echo (char *, char *);
  12669. Xint echo_append (char *, char *);
  12670. Xint mv (char *, char *);
  12671. Xint cp (char *, char *);
  12672. Xint cat (char *, char *);
  12673. Xint cat_append (char *, char *);
  12674. Xint touch (char *);
  12675. X
  12676. Xint echo (char *text, char *file)
  12677. X{
  12678. X  return echo_internal (text, file, NOAPPEND);
  12679. X}
  12680. X
  12681. Xint echo_append (char *text, char *file)
  12682. X{
  12683. X  return echo_internal (text, file, APPEND);
  12684. X}
  12685. X
  12686. Xstatic int echo_internal (char *text, char *file, _append append)
  12687. X{
  12688. X  int d;
  12689. X  long int len;
  12690. X  char *mask;
  12691. X
  12692. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  12693. X    umask (otoi (mask));
  12694. X  else
  12695. X    mask = "066",
  12696. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  12697. X  if (append == APPEND)
  12698. X    d = open (file, O_CREAT|O_APPEND|O_WRONLY, 0666 & (0666 ^ otoi (mask)));
  12699. X  else
  12700. X    d = open (file, O_CREAT|O_TRUNC|O_WRONLY, 0666 & (0666 ^ otoi (mask)));
  12701. X  if (d == -1) {
  12702. X    log_warn (tsprintf ("echo: open: %s", file));
  12703. X    return 1;
  12704. X  }
  12705. X
  12706. X  len = strlen (text);
  12707. X  if (len != write (d, text, len))
  12708. X    goto write_error;
  12709. X  if (1 != write (d, "\n", 1)) {
  12710. X  write_error:
  12711. X    close (d);
  12712. X    log_warn (tsprintf ("echo: write: %s", file));
  12713. X    return 1;
  12714. X  }
  12715. X    
  12716. X  if (close (d)) {
  12717. X    log_warn (tsprintf ("echo: close: %s", file));
  12718. X    return 1;
  12719. X  }
  12720. X  return 0;
  12721. X}
  12722. X
  12723. Xint mv (char *oldfile, char *newfile)
  12724. X{
  12725. X  (void) unlink (newfile);
  12726. X  errno = 0;
  12727. X  if (link (oldfile, newfile)) {
  12728. X    if (errno == EXDEV) {
  12729. X      if (cp (oldfile, newfile))
  12730. X    return 1; /* can't copy either */
  12731. X    }
  12732. X    else {
  12733. X      log_warn (tsprintf ("mv: %s %s", oldfile, newfile));
  12734. X      return 0;
  12735. X    }
  12736. X  }
  12737. X  unlink (oldfile);
  12738. X  return 0;
  12739. X}
  12740. X
  12741. Xint cp (char *oldfile, char *newfile)
  12742. X{
  12743. X  struct stat oldstat, newstat;
  12744. X  int oldfd, newfd;
  12745. X  char *newname, *buffer, *mask, buf[256];
  12746. X  long int size;
  12747. X
  12748. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  12749. X    umask (otoi (mask));
  12750. X  else
  12751. X    mask = "066",
  12752. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  12753. X  oldfd = open (oldfile, O_RDONLY, 0);
  12754. X  if (oldfd < 0) {
  12755. X    log_warn (tsprintf ("cp: open: %s", oldfile));
  12756. X    return 1;
  12757. X  }
  12758. X  if (fstat (oldfd, &oldstat)) {
  12759. X    close (oldfd);
  12760. X    log_warn (tsprintf ("cp: fstat: %s", oldfile));
  12761. X    return 1;
  12762. X  }
  12763. X
  12764. X  newname = newfile;
  12765. X  if (!stat (newfile, &newstat)) {
  12766. X    if (newstat.st_mode & S_IFDIR) {
  12767. X      char *s;
  12768. X      sprintf (buf, "%s/%s", newfile, (s = extract_filename (oldfile)));
  12769. X      newname = buf;
  12770. X      free ((char *) s);
  12771. X    }
  12772. X  }
  12773. X
  12774. X  newfd = open (newname, O_WRONLY|O_TRUNC|O_CREAT,
  12775. X        oldstat.st_mode & (0666 ^ otoi (mask)));
  12776. X  if (newfd < 0) {
  12777. X    close (oldfd);
  12778. X    log_warn (tsprintf ("cp: open: %s", newname));
  12779. X    return 1;
  12780. X  }
  12781. X
  12782. X  buffer = (char *) malloc (65536 * sizeof (char));
  12783. X  while ((size = read (oldfd, buffer, 65536)) > 0) {
  12784. X    if (size != write (newfd, buffer, size)) {
  12785. X      free ((char *) buffer);
  12786. X      close (oldfd);
  12787. X      close (newfd);
  12788. X      log_warn (tsprintf ("cp: write %s", newname));
  12789. X      return 1;
  12790. X    }
  12791. X  }
  12792. X  free ((char *) buffer);
  12793. X  close (oldfd);
  12794. X  close (newfd);
  12795. X  if (size < 0) {
  12796. X    log_warn (tsprintf ("cp: read: %s", oldfile));
  12797. X    return 1;
  12798. X  }
  12799. X  return 0;
  12800. X}
  12801. X
  12802. Xint cat (char *srcfile, char *dstfile)
  12803. X{
  12804. X  return cat_internal (srcfile, dstfile, NOAPPEND);
  12805. X}
  12806. X
  12807. Xint cat_append (char *srcfile, char *dstfile)
  12808. X{
  12809. X  return cat_internal (srcfile, dstfile, APPEND);
  12810. X}
  12811. X
  12812. Xstatic int cat_internal (char *srcfile, char *dstfile, _append append)
  12813. X{
  12814. X  struct stat srcstat;
  12815. X  int srcfd, dstfd;
  12816. X  char *buffer, *mask;
  12817. X  long int size;
  12818. X
  12819. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  12820. X    umask (otoi (mask));
  12821. X  else
  12822. X    mask = "066",
  12823. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  12824. X  srcfd = open (srcfile, O_RDONLY, 0);
  12825. X  if (srcfd < 0) {
  12826. X    log_warn (tsprintf ("cat: open: %s", srcfile));
  12827. X    return 1;
  12828. X  }
  12829. X  if (fstat (srcfd, &srcstat)) {
  12830. X    close (srcfd);
  12831. X    log_warn (tsprintf ("cat: fstat: %s", srcfile));
  12832. X    return 1;
  12833. X  }
  12834. X
  12835. X  if (append == APPEND)
  12836. X    dstfd = open (dstfile, O_WRONLY|O_APPEND|O_CREAT,
  12837. X          srcstat.st_mode & (0666 ^ otoi (mask)));
  12838. X  else
  12839. X    dstfd = open (dstfile, O_WRONLY|O_TRUNC|O_CREAT,
  12840. X          srcstat.st_mode & (0666 ^ otoi (mask)));
  12841. X  if (dstfd < 0) {
  12842. X    close (srcfd);
  12843. X    log_warn (tsprintf ("cat: open: %s", dstfile));
  12844. X    return 1;
  12845. X  }
  12846. X
  12847. X  buffer = (char *) malloc (65536 * sizeof (char));
  12848. X  while ((size = read (srcfd, buffer, 65536)) > 0) {
  12849. X    if (size != write (dstfd, buffer, size)) {
  12850. X      free ((char *) buffer);
  12851. X      close (srcfd);
  12852. X      close (dstfd);
  12853. X      log_warn (tsprintf ("cat: write: %s", dstfile));
  12854. X      return 1;
  12855. X    }
  12856. X  }
  12857. X  free ((char *) buffer);
  12858. X  close (srcfd);
  12859. X  close (dstfd);
  12860. X  if (size < 0) {
  12861. X    log_warn (tsprintf ("cat: read: %s", srcfile));
  12862. X    return 1;
  12863. X  }
  12864. X  return 0;
  12865. X}
  12866. X
  12867. Xint touch (char *file)
  12868. X{
  12869. X  char *mask;
  12870. X  int d;
  12871. X#ifdef __NeXT__
  12872. X  struct timeval tvp[2];
  12873. X#endif
  12874. X
  12875. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  12876. X    umask (otoi (mask));
  12877. X  else
  12878. X    mask = "066",
  12879. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  12880. X  d = open (file, O_CREAT|O_EXCL, 0666 & (0666 ^ otoi (mask)));
  12881. X#ifdef __NeXT__
  12882. X  tvp[0].tv_sec = tvp[0].tv_usec = tvp[1].tv_sec = tvp[1].tv_usec = 0;
  12883. X#endif
  12884. X
  12885. X  if (d < 0) {
  12886. X    if (errno != EEXIST) {
  12887. X      log_warn (tsprintf ("touch: open: %s", file));
  12888. X      return 1;
  12889. X    }
  12890. X  }
  12891. X  else {
  12892. X    close (d);
  12893. X    return 0;
  12894. X  }
  12895. X#ifndef __NeXT__
  12896. X  if (utime (file, NULL)) {
  12897. X#else
  12898. X  if (utime (file, tvp)) {
  12899. X#endif
  12900. X    log_warn (tsprintf ("touch: utime: %s",file));
  12901. X    return 1;
  12902. X  }
  12903. X  return 0;
  12904. X}
  12905. X
  12906. X/* support routines */
  12907. X
  12908. X#ifdef __STDC__
  12909. Xchar *tsprintf (char *control, ...)
  12910. X#else
  12911. Xchar *tsprintf (control, va_alist)
  12912. Xchar *control;
  12913. Xva_dcl
  12914. X#endif
  12915. X{
  12916. X  static char command [10240];
  12917. X  va_list ap;
  12918. X
  12919. X#ifdef __STDC__
  12920. X  va_start (ap, control);
  12921. X#else
  12922. X  va_start (ap);
  12923. X#endif
  12924. X  RESET (command);
  12925. X  vsprintf (command, control, ap);
  12926. X  va_end (ap);
  12927. X  return command;
  12928. X}
  12929. X
  12930. Xstatic int log_warn (char *command)
  12931. X{
  12932. X  extern BOOLEAN tty_echo;
  12933. X  FILE *f;
  12934. X  struct tm *t;
  12935. X  long int time_is = 0;
  12936. X  int _errno = errno;
  12937. X
  12938. X  if ((f = fopen (WARNING, "a")) != NULL)
  12939. X    fprintf (f, "\nWARNING: System call errno %d: %s\n", _errno, command),
  12940. X    time (&time_is),
  12941. X    t = localtime (&time_is),
  12942. X    fprintf (f, "Time/Date: %2d:%.2d:%.2d, %2d/%.2d/%2d\n",
  12943. X         t->tm_hour, t->tm_min, t->tm_sec, t->tm_mon + 1, t->tm_mday,
  12944. X         t->tm_year),
  12945. X    fclose (f);
  12946. X  if (tty_echo)
  12947. X    printf ("\nWARNING: System call errno %d: %s\n", _errno, command);
  12948. X}
  12949. *-*-END-of-src/fio.c-*-*
  12950. echo x - src/fwin.c
  12951. sed 's/^X//' >src/fwin.c <<'*-*-END-of-src/fwin.c-*-*'
  12952. X/*
  12953. X  ----------------------------------------------------------------------------
  12954. X  |                FILE WINDOW                     |
  12955. X  |                                         |
  12956. X  |                             Version 1.0                     |
  12957. X  |                                                                          |
  12958. X  |                (or, when Computer Science gets to you)                   |
  12959. X  |                                                                          |
  12960. X  |                    Written by Anastasios Kotsikonas                      |
  12961. X  |                           (tasos@cs.bu.edu)                              |
  12962. X  |                                                                          |
  12963. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  12964. X  | whole and not in parts, as long as you do not remove or alter the author |
  12965. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  12966. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  12967. X  | provided for your personal use, you you may not alter the functions      |
  12968. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  12969. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  12970. X  | any changes you may have made. No part of the source code bearing a         |
  12971. X  | copyright notice can be included in commercial software systems without  |
  12972. X  | written permission by the author.                         |
  12973. X  | By using this software you are bound by this agreement.                  |
  12974. X  | This software comes with no warranties and cannot be sold for profit.    |
  12975. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  12976. X  | files when distributing this software.                                   |
  12977. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  12978. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  12979. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  12980. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  12981. X  | (ii).                                                                    |
  12982. X  ----------------------------------------------------------------------------
  12983. X
  12984. X  Copy a window of the input (stdin) to output (stdout); the window is defined
  12985. X  as an offset from the beginning and a byte count. If no byte count is defined
  12986. X  then MAXINT is used.
  12987. X
  12988. X  COMMAND LINE OPTIONS:
  12989. X    -o: Set the offset from the beginning of the file (default 0).
  12990. X    -b: Set the byte count (default MAXINT).
  12991. X    -n: Pad with new line at the end if not there.
  12992. X*/
  12993. X
  12994. X#include <stdio.h>
  12995. X#include <sys/types.h>
  12996. X#ifndef __NeXT__
  12997. X# ifndef unknown_port
  12998. X#  include <unistd.h>
  12999. X# endif
  13000. X# if !defined (sequent) && !defined (__convex__) && !defined (apollo) && \
  13001. X  !defined (unknown_port)
  13002. X#  include <values.h>
  13003. X# endif
  13004. X#else
  13005. X# include <libc.h>
  13006. X#endif
  13007. X
  13008. X#ifndef __NeXT__
  13009. Xextern long int atol (char *);
  13010. X#else
  13011. Xextern long int atol (const char *);
  13012. X#endif
  13013. X
  13014. X#define BUFFSIZ        8192
  13015. X#ifndef MAXINT
  13016. X# define MAXINT        0x7FFFFFFF    /* assumes 32-bit hardware */
  13017. X#endif
  13018. X
  13019. Xmain (int argc, char **argv)
  13020. X{
  13021. X  char *options = "o:b:n", last_byte;
  13022. X  long int offset = 0, bytes = MAXINT, bytes_read = 0, total_bytes = 0;
  13023. X  int pad_with_newline = 0, c;
  13024. X  char buf [BUFFSIZ];
  13025. X  extern char *optarg;
  13026. X
  13027. X  while ((c = getopt (argc, argv, options)) != EOF)
  13028. X    switch ((char) c) {
  13029. X    case 'o':
  13030. X      if ((offset = atol (optarg)) < 0)
  13031. X    fprintf (stderr, "Negative offset (%d) not allowed.\n", offset),
  13032. X    exit (3);
  13033. X      break;
  13034. X    case 'b':
  13035. X      if ((bytes = atol (optarg)) < 0)
  13036. X    fprintf (stderr, "Negative number of bytes to output (%d) not allowed.\n", bytes),
  13037. X    exit (3);
  13038. X      break;
  13039. X    case 'n': pad_with_newline = 1; break;
  13040. X    default: 
  13041. X      printf ("Usage: %s [-n] [-o offset] [-b bytes]\n", argv[0]);
  13042. X      exit (3);
  13043. X    }
  13044. X
  13045. X  /* Skip to offset */
  13046. X  while ((bytes_read = read (fileno (stdin), buf, BUFFSIZ)) > 0) {
  13047. X    total_bytes += bytes_read;
  13048. X    if (total_bytes >= offset)
  13049. X      break;
  13050. X  }
  13051. X  if (total_bytes >= offset && bytes_read > 0) {
  13052. X    last_byte = 
  13053. X      buf[bytes_read - total_bytes + offset +
  13054. X      (total_bytes - offset <= bytes ? total_bytes - offset : bytes) - 1];
  13055. X    total_bytes = 
  13056. X      write (fileno (stdout),
  13057. X         &buf[bytes_read - total_bytes + offset],
  13058. X         (total_bytes - offset <= bytes ? total_bytes - offset : bytes));
  13059. X    if (total_bytes < bytes)
  13060. X      while ((bytes_read = read (fileno (stdin), buf, BUFFSIZ)) > 0) {
  13061. X    total_bytes += bytes_read;
  13062. X    write (fileno (stdout), buf,
  13063. X           (total_bytes <= bytes ?
  13064. X        bytes_read :
  13065. X        bytes_read - total_bytes + bytes));
  13066. X    last_byte = buf [(total_bytes <= bytes ? bytes_read :
  13067. X              bytes_read - total_bytes + bytes) - 1];
  13068. X    if (total_bytes >= bytes)
  13069. X      break;
  13070. X      }
  13071. X  }
  13072. X  if (pad_with_newline && last_byte != '\n')
  13073. X    write (fileno (stdout), "\n", 1);
  13074. X  fclose (stdout);
  13075. X  if (bytes_read > 0)
  13076. X    while (read (fileno (stdin), buf, BUFFSIZ) > 0);
  13077. X  exit (0);
  13078. X}
  13079. *-*-END-of-src/fwin.c-*-*
  13080. echo x - src/iul.c
  13081. sed 's/^X//' >src/iul.c <<'*-*-END-of-src/iul.c-*-*'
  13082. X/*
  13083. X  ----------------------------------------------------------------------------
  13084. X  |                   INTERACTIVE UNIX-LISTSERVER CLIENT             |
  13085. X  |                                         |
  13086. X  |                  Version 1.0                     |
  13087. X  |                                         |
  13088. X  |                (or, when Computer Science gets to you)                   |
  13089. X  |                                         |
  13090. X  |               Written by Anastasios Kotsikonas                      |
  13091. X  |                      (tasos@cs.bu.edu)                          |
  13092. X  |                                         |
  13093. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  13094. X  | whole and not in parts, as long as you do not remove or alter the author |
  13095. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  13096. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  13097. X  | provided for your personal use, you you may not alter the functions      |
  13098. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  13099. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  13100. X  | any changes you may have made. No part of the source code bearing a         |
  13101. X  | copyright notice can be included in commercial software systems without  |
  13102. X  | written permission by the author.                         |
  13103. X  | By using this software you are bound by this agreement.             |
  13104. X  | This software comes with no warranties and cannot be sold for profit.    |
  13105. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  13106. X  | files when distributing this software.                                   |
  13107. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  13108. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  13109. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  13110. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  13111. X  | (ii).                                                                    |
  13112. X  ----------------------------------------------------------------------------
  13113. X
  13114. X  This program is to be used for connecting to an interactive UNIX ListServer
  13115. X  server (version 6.0 and up). The following files are required:
  13116. X
  13117. X  iul.c (this file)
  13118. X  iul.h
  13119. X  iulp.h (definition of the Interactive UNIX ListServer Protocol)
  13120. X  makefile
  13121. X
  13122. X  Usage: iul [-v] [-t timeout] [-b buffer-size] <host> [port]
  13123. X
  13124. X  To connect to a host you may specify its name or IP address. The default
  13125. X  port is 372; another port may be specified as an extra argument. To echo
  13126. X  server responses to client requests, use the -v flag.
  13127. X
  13128. X  The default time out for a server response is 180 seconds; to reset
  13129. X  use the -t flag. The default socket buffer size is 8K; to reset use
  13130. X  the -b flag (the argument specifies kilobytes).
  13131. X
  13132. X  This client is to be used as a model and better ones can certainly be
  13133. X  written.
  13134. X
  13135. X  SCO UNIX system should compile with -Dsco.
  13136. X
  13137. X  Refer to the man page for more information on how to use this program.
  13138. X*/
  13139. X
  13140. X#include <signal.h>
  13141. X#include "defs.h"
  13142. X#undef     NSIG
  13143. X#ifdef GO_INTERACTIVE
  13144. X# include <stdio.h>
  13145. X# include <sys/types.h>
  13146. X# include <string.h>
  13147. X# if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  13148. X && !defined (sequent) && !defined (unknown_port)
  13149. X# include <malloc.h>
  13150. X# endif
  13151. X# ifndef unknown_port
  13152. X#  ifndef __NeXT__
  13153. X#   include <unistd.h>
  13154. X#  else
  13155. X#   include <libc.h>
  13156. X#  endif
  13157. X# endif
  13158. X# if defined (stardent) || defined (stellar) || defined (titan)
  13159. X#  include <rpc/types.h>
  13160. X# endif
  13161. X# include <sys/stat.h>
  13162. X# include <fcntl.h>
  13163. X# include <errno.h>
  13164. X# ifdef unknown_port
  13165. Xextern int errno;
  13166. X# endif
  13167. X# include <sys/socket.h>
  13168. X# include <netinet/in.h>
  13169. X# include <netdb.h>
  13170. X# include <sys/file.h>
  13171. X# include <sys/ioctl.h>
  13172. X# if defined (sco) || defined (M_XENIX) || defined (M_UNIX)
  13173. X#  include <sys/stropts.h>
  13174. X# endif
  13175. X# if (defined (sco) || defined (M_XENIX) || defined (M_UNIX)) && \
  13176. X  defined (HAVE_SELECT_H)
  13177. X#  include <sys/times.h>
  13178. X# else
  13179. X#  include <sys/time.h>
  13180. X# endif
  13181. X# ifdef HAVE_SELECT_H
  13182. X#  include <sys/select.h>
  13183. X# endif
  13184. X# ifdef HAVE_ULIMIT_H
  13185. X#  include <ulimit.h>
  13186. X# endif
  13187. X# include "iul.h"
  13188. X
  13189. X# ifndef UL_GDESLIM
  13190. X#  define UL_GDESLIM    4
  13191. X# endif
  13192. X# ifndef FD_SET          /* for 4.2BSD */
  13193. X#  define FD_SETSIZE      (sizeof(fd_set) * 8)
  13194. X#  define FD_SET(n, p)    (((fd_set *) (p))->fds_bits[0] |= (1 << ((n) % 32)))
  13195. X#  define FD_CLR(n, p)    (((fd_set *) (p))->fds_bits[0] &= ~(1 << ((n) % 32)))
  13196. X#  define FD_ISSET(n, p)  (((fd_set *) (p))->fds_bits[0] & (1 << ((n) % 32)))
  13197. X#  define FD_ZERO(p)      memset ((char *)(p), '\0', sizeof(*(p)))
  13198. X# endif
  13199. X
  13200. X# ifndef __NeXT__
  13201. Xextern    long int atoi (char *);
  13202. X# else
  13203. Xextern    int atoi (const char *);
  13204. X# endif
  13205. Xextern  int optind;
  13206. X# if !defined (hpux) && !defined (__hpux)
  13207. Xextern  int getopt (int, char **, char *);
  13208. X# endif
  13209. X
  13210. Xint      main (int, char **);
  13211. Xint     server_response (int);
  13212. Xint      build_tcp_connection (char *, int);
  13213. Xint     sighandle (int);
  13214. Xint     urg_data (int);
  13215. Xlong int read_from_fd (int, long int, FILE *);
  13216. Xlong int write_to_fd (int, char *, long int);
  13217. Xint     open_file (char *, int, int);
  13218. Xint      check_server_response (int, char *);
  13219. Xint     check_for_redirection (char *, char *);
  13220. XFILE     *check_for_pipe (char *);
  13221. X
  13222. Xlong int nbytes, sock_fd, buffsiz = BUFFSIZ;
  13223. Xint  to_file, prompt_len, verbose, check_sio, response_timeout = TIMEOUT,
  13224. X     fd = -1, broken_pipe = 0, sigint = 1;
  13225. Xchar args [256];
  13226. XFILE *pipefp = NULL;
  13227. X#endif
  13228. X
  13229. X/*
  13230. X  Main function. Connect to server, issue requests and receive replies.
  13231. X
  13232. X  Returns: 0 on success, 1 on command line option error, or an IULP
  13233. X       command if the transaction was terminated normally.
  13234. X*/
  13235. X
  13236. Xmain (int argc, char **argv)
  13237. X{
  13238. X#ifndef GO_INTERACTIVE
  13239. X  printf ("%s not functional. Try compiling archives/iul/iul.c\n", argv[0]);
  13240. X#else
  13241. X  char *options = "vt:b:";
  13242. X  char *buf, *tmp, infile [256], wbuf [256], version [80];
  13243. X  int cmd, i, port, timeout, sprompt_len, c, rfd, bytes_alloced = 0;
  13244. X  struct stat stat_buf;
  13245. X  extern char *optarg;
  13246. X  port = PORT;
  13247. X  while ((c = getopt (argc, argv, options)) != EOF)
  13248. X    switch ((char) c) {
  13249. X      case 'v': verbose = 1; break;
  13250. X      case 't':
  13251. X    if ((response_timeout = atoi (optarg)) < 1) {
  13252. X      printf ("-t %d\nBe real.\n", response_timeout);
  13253. X      return 1;
  13254. X    }
  13255. X    break;
  13256. X      case 'b':
  13257. X    if ((buffsiz = atol (optarg) * 1024) < 1024) {
  13258. X      printf ("-b %ld\nBe real.\n", buffsiz);
  13259. X      return 1;
  13260. X    }
  13261. X    break;
  13262. X      case '?':
  13263. X      default:
  13264. X    fprintf (stderr, "Usage: %s [-v] [-t timeout] [-b buffer-size] \
  13265. X<host> [port]\n", argv[0]);
  13266. X    return 1;
  13267. X    }
  13268. X
  13269. X  if (optind == argc) {
  13270. X    fprintf (stderr, "Usage: %s [-v] [-t timeout] [-b buffer-size] \
  13271. X<host> [port]\n", argv[0]);
  13272. X    return 1;
  13273. X  }
  13274. X  else if (optind + 1 < argc)
  13275. X    port = atoi (argv [optind + 1]);
  13276. X# ifdef SIGIO
  13277. X  signal (SIGIO, (void (*)()) urg_data);
  13278. X# endif
  13279. X# ifdef SIGURG
  13280. X  signal (SIGURG, (void (*)()) urg_data);
  13281. X# endif
  13282. X  if ((sock_fd = build_tcp_connection (argv[optind], port)) < 0)
  13283. X    return SYS_ERROR;
  13284. X  if ((cmd = server_response (sock_fd)) != CONNECT) {
  13285. X    PRINTF (cmd, "Handshake failed\n");
  13286. X    printf ("Not an interactive UNIX ListServer.\n");
  13287. X    return cmd;
  13288. X  }
  13289. X
  13290. X  for (i = SIGHUP; i <= SIGPIPE; i++)
  13291. X    signal (i, (void (*)()) sighandle);
  13292. X
  13293. X  if (check_server_response (cmd, args)) goto abort;
  13294. X  timeout = nbytes;
  13295. X  sscanf (args, "%s %d %d\n", version, &prompt_len, &sprompt_len);
  13296. X
  13297. X  if ((cmd = server_response (sock_fd)) < 0) goto abort; /* Get greeting */
  13298. X  check_server_response (cmd, args);
  13299. X  if (cmd != CONN_CLOSED && cmd != SERVER_BUSY && cmd != PEER_UNAVAIL &&
  13300. X      cmd != CONN_ABORTED && cmd != SYS_ERROR && cmd != CONN_TIMEOUT)
  13301. X    printf ("\nHit ^\\ (control-backslash) to abort at any time.\n");
  13302. X  if (read_from_fd (sock_fd, nbytes, NULL) < 0) goto abort;
  13303. X  if (cmd == CONN_CLOSED || cmd == SERVER_BUSY || cmd == PEER_UNAVAIL ||
  13304. X      cmd == CONN_ABORTED || cmd == SYS_ERROR || cmd == CONN_TIMEOUT)
  13305. X    goto abort;
  13306. X  bytes_alloced = 256;
  13307. X  if ((buf = (char *) malloc (bytes_alloced * sizeof (char))) == NULL) {
  13308. X    printf ("FATAL: malloc() failed\n");
  13309. X    goto abort;
  13310. X  }
  13311. X  check_sio = 1;
  13312. X  fgets (buf, bytes_alloced - 1, stdin);        /* Put email address */
  13313. X  if (strlen (buf) == 0)
  13314. X    printf ("\n"),
  13315. X    strcpy (buf, "\n");
  13316. X  check_sio = 0;
  13317. X  if (write_to_fd (sock_fd, buf, strlen (buf)) < 0) goto abort;
  13318. X  if ((cmd = server_response (sock_fd)) < 0) /* See if "Password: " follows */
  13319. X    goto abort;
  13320. X  if (check_server_response (cmd, args)) goto abort;
  13321. X  if (cmd == PASSWORD_REQUIRED) {
  13322. X    RESET (buf);
  13323. X    check_sio = 1;
  13324. X    fgets (buf, 255, stdin);
  13325. X    if (strlen (buf) == 0)
  13326. X      printf ("\n"),
  13327. X      strcpy (buf, "\n");
  13328. X    check_sio = 0;
  13329. X    if (write_to_fd (sock_fd, buf, strlen (buf)) < 0)
  13330. X      goto abort;
  13331. X  }
  13332. X  if (cmd == PEER_UNAVAIL) {
  13333. X    read_from_fd (sock_fd, nbytes, NULL);
  13334. X    goto abort;
  13335. X  }
  13336. X
  13337. X  sigint = 0;
  13338. X  RESET (buf);
  13339. X  while (cmd != CONN_CLOSED && cmd != CONN_ABORTED && cmd != CONN_TIMEOUT &&
  13340. X     cmd != PEER_UNAVAIL) {
  13341. X    if ((cmd = server_response (sock_fd)) < 0) break;
  13342. X    if (check_server_response (cmd, args)) break;
  13343. X    if (cmd == TEST_FILE_PERMISSIONS) continue;
  13344. X    if (cmd != CONN_ABORTED && cmd != CONN_TIMEOUT)
  13345. X      if (read_from_fd (sock_fd, nbytes, (cmd != MESSAGE ? pipefp : NULL)) < 0)
  13346. X    break;
  13347. X    broken_pipe = 0;
  13348. X    if (cmd == MESSAGE) continue;
  13349. X    if (cmd != CONN_CLOSED && cmd != CONN_ABORTED && cmd != CONN_TIMEOUT &&        cmd != PEER_UNAVAIL) {
  13350. X      check_sio = 1;
  13351. X      if (pipefp)
  13352. X    strcpy (buf, "\n");
  13353. X      if (buf [0] == EOS) {
  13354. X        RESET (infile);
  13355. X        fgets (buf, bytes_alloced - 1, stdin);
  13356. X        if (strlen (buf) == 0)    /* EOF */
  13357. X      printf ("\n"),
  13358. X      strcpy (buf, "\n");
  13359. X        if ((rfd = check_for_redirection (buf, infile)) < 0)
  13360. X      strcpy (buf, "\n");
  13361. X        if (rfd >= 0 && infile [0] != EOS) { /* Input redirection */
  13362. X      fstat (rfd, &stat_buf);
  13363. X      if (!(stat_buf.st_mode & S_IFREG)) {
  13364. X        printf ("%s: Not a regular file\n", infile);
  13365. X        strcpy (buf, "\n");
  13366. X        goto skip;
  13367. X      }
  13368. X      if (stat_buf.st_size + strlen (buf) + 2 > bytes_alloced) {
  13369. X        bytes_alloced = stat_buf.st_size + strlen (buf) + 2;
  13370. X        if ((buf = (char *) realloc (buf, bytes_alloced * sizeof (char))) ==
  13371. X            NULL) {
  13372. X          printf ("FATAL: realloc() failed\n");
  13373. X          break;
  13374. X        }
  13375. X      }
  13376. X      i = strlen (buf);
  13377. X      if (read (rfd, &buf [strlen (buf)], stat_buf.st_size) <
  13378. X          stat_buf.st_size) {
  13379. X        printf ("FATAL: Failed to read all of the input file\n");
  13380. X        break;
  13381. X      }
  13382. X      buf [i + stat_buf.st_size] = EOS;
  13383. X      if (buf [i + stat_buf.st_size - 1] != '\n')
  13384. X        strcat (&buf [i + stat_buf.st_size], "\n");
  13385. X      close (rfd);
  13386. X        }
  13387. X      }
  13388. X      skip:
  13389. X      strncpy (wbuf, buf, 254);
  13390. X      tmp = strchr (wbuf, '\n');
  13391. X      if (!tmp)
  13392. X    wbuf [254] = '\n',
  13393. X    wbuf [255] = EOS;
  13394. X      else
  13395. X    *(tmp + 1) = EOS;
  13396. X      if (pipefp)
  13397. X    pclose (pipefp);
  13398. X      check_sio = 0;
  13399. X      pipefp = check_for_pipe (wbuf);
  13400. X      if (write_to_fd (sock_fd, wbuf, strlen (wbuf)) < 0) break;
  13401. X      sprintf (buf, "%s", strchr (buf, '\n') + 1);
  13402. X    }
  13403. X  }
  13404. X
  13405. X  abort:
  13406. X  if (pipefp)
  13407. X    pclose (pipefp);
  13408. X  close (sock_fd);
  13409. X  printf ("Connection closed.\n");
  13410. X  if (buf)
  13411. X    free ((char *) buf);
  13412. X  if (cmd == CONN_CLOSED) 
  13413. X    return 0;
  13414. X  return cmd;
  13415. X#endif
  13416. X}
  13417. X
  13418. X#ifdef GO_INTERACTIVE
  13419. X/*
  13420. X  Get server response. Store in 'nbytes' the number of bytes in the actual
  13421. X  message that follows, and in 'args' the (optional) file name.
  13422. X
  13423. X  Returns: the server reply code, CONN_TIMEOUT, CONN_ABORTED, or -1 on 
  13424. X  protocol errors.
  13425. X*/
  13426. X
  13427. Xint server_response (int sock_fd)
  13428. X{
  13429. X  char buf [256];
  13430. X  int cmd = -1, i, bytes_to_read = 4, bytes_read = 0, err, l = sizeof (int);
  13431. X  long int time_started;
  13432. X
  13433. X  time_started = time (0);
  13434. X  memset (buf, EOS, 256);
  13435. X  while (bytes_to_read) {
  13436. X    errno = 0;
  13437. X    /* Get server command */
  13438. X    bytes_read = read (sock_fd, &buf [4 - bytes_to_read], bytes_to_read);
  13439. X    if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  13440. X    errno == ECONNREFUSED) {
  13441. X      nbytes = 0;
  13442. X      return CONN_ABORTED;
  13443. X    }
  13444. X    if (!getsockopt (sock_fd, SOL_SOCKET, SO_ERROR, (char *) &err, (char *) &l)){
  13445. X      if (err || buf [4 - bytes_to_read] == EOF) {
  13446. X    nbytes = 0;
  13447. X    return CONN_ABORTED;
  13448. X      }
  13449. X    }
  13450. X    else
  13451. X      perror ("getsockopt() error");
  13452. X    if (errno || bytes_read < 1)
  13453. X      if ((time (0) - time_started) > response_timeout) {
  13454. X    nbytes = 0;
  13455. X    return CONN_TIMEOUT;
  13456. X      }
  13457. X    if (bytes_read > 0)
  13458. X      bytes_to_read -= bytes_read;
  13459. X  }
  13460. X  buf[3] = EOS;
  13461. X  cmd = atoi (buf);
  13462. X  i = 0;
  13463. X  do {        /* Get # of bytes in actual message */
  13464. X    again1:
  13465. X    if (read (sock_fd, &buf[i], 1) < 1) {
  13466. X      if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  13467. X      errno == ECONNREFUSED) {
  13468. X    nbytes = 0;
  13469. X    return CONN_ABORTED;
  13470. X      }
  13471. X      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
  13472. X    if ((time (0) - time_started) > response_timeout) {
  13473. X      nbytes = 0;
  13474. X      return CONN_TIMEOUT;
  13475. X    }
  13476. X    goto again1;
  13477. X      }
  13478. X      perror ("Protocol error in control string");
  13479. X      return -1;
  13480. X    }
  13481. X    i++;
  13482. X  } while (buf[i - 1] != ' ');
  13483. X
  13484. X  buf[i - 1] = EOS;
  13485. X  nbytes = atoi (buf);
  13486. X  RESET (args);
  13487. X  i = 0;
  13488. X  do {        /* Get filename (optional) */
  13489. X    again2:
  13490. X    if (read (sock_fd, &args[i], 1) < 1) {
  13491. X      if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  13492. X          errno == ECONNREFUSED)
  13493. X        return CONN_ABORTED;
  13494. X      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
  13495. X        if ((time (0) - time_started) > response_timeout) {
  13496. X          nbytes = 0;
  13497. X          return CONN_TIMEOUT;
  13498. X        }
  13499. X        goto again2;
  13500. X      }
  13501. X      perror ("Protocol error in control string");
  13502. X      return -1;
  13503. X    }
  13504. X    ++i;
  13505. X  } while (args[i - 1] != '\n');
  13506. X  args[i - 1]= EOS;
  13507. X  return cmd;
  13508. X}
  13509. X
  13510. X/*
  13511. X  Establish connection with unix-listserver. The socket is marked as
  13512. X  non-blocking.
  13513. X
  13514. X  Returns: the socket file descriptor, or -1 on error.
  13515. X*/
  13516. X
  13517. Xint build_tcp_connection (char *host, int port)
  13518. X{
  13519. X  int sock_fd, sendbuf = buffsiz, recvbuf = buffsiz, value = 1, nfds, naddr = 0;
  13520. X  struct sockaddr_in sin;
  13521. X  struct hostent *hostentry;
  13522. X  struct timeval timeout;
  13523. X  fd_set readfds, writefds;
  13524. X  timeout.tv_sec = timeout.tv_usec = 0;
  13525. X  if (!(hostentry = gethostbyname (host))) { /* Host name failed; try IP */
  13526. X    sin.sin_addr.s_addr = inet_addr (host);
  13527. X    if (! (hostentry = gethostbyaddr ((char *) &sin.sin_addr,
  13528. X                      sizeof (struct in_addr),
  13529. X                      AF_INET))) {
  13530. X      printf ("%s: No such host.\n", host);
  13531. X      return -1;
  13532. X    }
  13533. X  }
  13534. X
  13535. X  do {    /* Check all addresses */
  13536. X    if ((sock_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  13537. X      perror ("Could not create socket");
  13538. X      return -1;
  13539. X    }
  13540. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_SNDBUF, (char *) &sendbuf,
  13541. X            sizeof (sendbuf)) < 0)
  13542. X      perror ("WARNING: Could not set send-buffer size: setsockopt() error");
  13543. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_RCVBUF, (char *) &recvbuf,
  13544. X            sizeof (recvbuf)) < 0)
  13545. X      perror ("WARNING: Could not set receive-buffer size: setsockopt() error");
  13546. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &value,
  13547. X            sizeof (value)) < 0)
  13548. X      perror ("WARNING: Cannot toggle keep-alive connections: setsockopt() error");
  13549. X
  13550. X# ifdef h_addr
  13551. X    memcpy ((char *) &sin.sin_addr.s_addr,
  13552. X        (char *) hostentry->h_addr_list[naddr++],
  13553. X        hostentry->h_length);
  13554. X# else
  13555. X    memcpy ((char *) &sin.sin_addr.s_addr,
  13556. X        (char *) hostentry->h_addr,
  13557. X        hostentry->h_length);
  13558. X# endif
  13559. X    sin.sin_family = AF_INET;
  13560. X    sin.sin_port = htons (port);
  13561. X    memset (sin.sin_zero, EOS, sizeof (sin.sin_zero));
  13562. X    printf ("Trying %s ...\n", inet_ntoa (sin.sin_addr));
  13563. X    if (connect (sock_fd, (struct sockaddr *) &sin, 
  13564. X         sizeof (struct sockaddr_in)) < 0) {
  13565. X      if (errno != EINPROGRESS) {
  13566. X# ifdef h_addr
  13567. X    if (!hostentry->h_addr_list[naddr]) {
  13568. X# endif    
  13569. X      perror ("Could not connect to host");
  13570. X      close (sock_fd);
  13571. X      return -1;
  13572. X# ifdef h_addr
  13573. X    }
  13574. X    else {
  13575. X      close (sock_fd);
  13576. X      continue;
  13577. X    }
  13578. X# endif
  13579. X      }
  13580. X      FD_ZERO (&readfds);
  13581. X      FD_ZERO (&writefds);
  13582. X      do {
  13583. X    FD_SET (sock_fd, &readfds);
  13584. X    FD_SET (sock_fd, &writefds);
  13585. X    errno = 0;
  13586. X# if defined (sequent) || defined (__NeXT__) || defined (__convex__) || \
  13587. X  defined (apollo) || defined (unknown_port)
  13588. X    nfds = getdtablesize ();
  13589. X# else
  13590. X    nfds = ulimit (UL_GDESLIM);
  13591. X# endif
  13592. X    value = select ((nfds > 0 ? nfds : 20), &readfds, &writefds, NULL,
  13593. X            &timeout);
  13594. X      } while (value == -1 && errno == EINTR);
  13595. X
  13596. X      if (value < 0) {
  13597. X    perror ("select() error");
  13598. X    close (sock_fd);
  13599. X    return -1;
  13600. X      }
  13601. X      break;    /* Successful connection */
  13602. X    }
  13603. X    else
  13604. X      break;
  13605. X  } while (007);
  13606. X# ifdef NONBLOCKING_IO
  13607. X  if (fcntl (sock_fd, F_SETFL, (fcntl (sock_fd, F_GETFL, 0) | O_NDELAY)) < 0) {
  13608. X    perror ("Could not set non-blocking I/O");
  13609. X    close (sock_fd);
  13610. X    return -1;
  13611. X  }
  13612. X# endif
  13613. X# if defined (sco) || defined (M_XENIX) || defined (M_UNIX)
  13614. X  if (ioctl (sock_fd, I_SETSIG, S_INPUT) < 0) {
  13615. X    perror ("Cannot set SIGIO");
  13616. X    close (sock_fd);
  13617. X    return -1;
  13618. X  }
  13619. X# else
  13620. X#  ifdef F_SETOWN
  13621. X  if (fcntl (sock_fd, F_SETOWN, getpid()) < 0) {
  13622. X    perror ("Cannot assign socket to process group");
  13623. X    close (sock_fd);
  13624. X    return -1;
  13625. X  }
  13626. X#  elif defined (SIOCSPGRP)
  13627. X  value = -getpid();
  13628. X  if (ioctl (sock_fd, SIOCSPGRP, (char *) &value) < 0) {
  13629. X    perror ("Cannot assign socket to process group");
  13630. X    close (sock_fd);
  13631. X    return -1;
  13632. X  }
  13633. X#  else
  13634. X  perror ("Cannot assign socket to process group");
  13635. X  close (sock_fd);
  13636. X  return -1;
  13637. X#  endif
  13638. X#  ifdef FASYNC
  13639. X  if (fcntl (sock_fd, F_SETFL, (fcntl (sock_fd, F_GETFL, 0) | FASYNC)) < 0) {
  13640. X    perror ("Cannot set asynchronous I/O for socket");
  13641. X    close (sock_fd);
  13642. X    return -1;
  13643. X  }
  13644. X#  elif defined (FIOASYNC)
  13645. X  value = 1;
  13646. X  if (ioctl (sock_fd, FIOASYNC, (char *) &value) < 0) {
  13647. X    perror ("Cannot set asynchronous I/O for socket");
  13648. X    close (sock_fd);
  13649. X    return -1;
  13650. X  }
  13651. X#  else
  13652. X  perror ("Cannot set asynchronous I/O for socket");
  13653. X  close (sock_fd);
  13654. X  return -1;
  13655. X#  endif
  13656. X# endif
  13657. X  return sock_fd;
  13658. X}
  13659. X
  13660. X/*
  13661. X  Handle signals; the client sends an '__abort__' command and exits; '__abort__'
  13662. X  causes the other end to shut down.
  13663. X*/
  13664. X
  13665. Xint sighandle (int sig)
  13666. X{
  13667. X  if (sig == SIGHUP) {
  13668. X    signal (sig, (void (*)()) sighandle);
  13669. X    return;
  13670. X  }
  13671. X  else if (sig == SIGPIPE) {
  13672. X    if (!broken_pipe)
  13673. X      printf ("Broken pipe\n");
  13674. X    broken_pipe = 1;
  13675. X    signal (sig, (void (*)()) sighandle);
  13676. X    return;
  13677. X  }
  13678. X  else if (sig == SIGINT) {
  13679. X    if (!sigint) {
  13680. X      signal (sig, (void (*)()) sighandle);
  13681. X      return;
  13682. X    }
  13683. X  }
  13684. X  check_sio = 0;
  13685. X  write_to_fd (sock_fd, "__abort__\n", 10);
  13686. X  close (sock_fd);
  13687. X  if (pipefp)
  13688. X    pclose (pipefp);
  13689. X  printf ("Connection closed.\n");
  13690. X  exit (sig);
  13691. X}
  13692. X
  13693. X/*
  13694. X  Urgent data from server; read it and exit. Urgent data is received
  13695. X  when a connection is timed out or when the server shuts down.
  13696. X*/
  13697. X
  13698. Xint urg_data (int sig)
  13699. X{
  13700. X  int cmd;
  13701. X
  13702. X  if (!check_sio) {
  13703. X    signal (sig, (void (*)()) urg_data);
  13704. X    return;
  13705. X  }
  13706. X  signal (sig, SIG_IGN);
  13707. X  if ((cmd = server_response (sock_fd)) >= 0)
  13708. X    if (cmd == CONN_ABORTED || cmd == CONN_TIMEOUT || cmd == CONN_CLOSED)
  13709. X      check_server_response (cmd, args),
  13710. X      read_from_fd (sock_fd, nbytes, NULL);
  13711. X  shutdown (sock_fd, 2);
  13712. X  kill (0, SIGHUP);
  13713. X  if (pipefp)
  13714. X    pclose (pipefp);
  13715. X  printf ("Connection closed.\n");
  13716. X  exit (cmd);
  13717. X}
  13718. X
  13719. X/*
  13720. X  Read from a socket and either echo to tty or save to a file.
  13721. X
  13722. X  Returns: the actual number of bytes read on succes, or the negative of
  13723. X  that number (or -1) on error.
  13724. X*/
  13725. X
  13726. Xlong int read_from_fd (int rfd, long int bytes_to_read, FILE *pipefp)
  13727. X{
  13728. X  long int bytes_read, total_bytes = 0, time_started;
  13729. X  int to_pipe = 1;
  13730. X  char *buf;
  13731. X
  13732. X  time_started = time (0);
  13733. X  if (bytes_to_read <= 0)
  13734. X    return 0;
  13735. X  if ((buf = (char *) malloc (buffsiz * sizeof (char))) == NULL) {
  13736. X    printf ("malloc() failed while attempting to allocate %ld bytes\n",
  13737. X         buffsiz);
  13738. X    return -1;
  13739. X  }
  13740. X  errno = 0;
  13741. X  while ((bytes_read = read (rfd, buf, MIN (bytes_to_read, buffsiz))) <
  13742. X     bytes_to_read) {
  13743. X    if (bytes_read < 0 && errno && errno != EWOULDBLOCK && errno != EAGAIN &&
  13744. X    errno != EINTR
  13745. X#ifdef ERESTART
  13746. X    && errno != ERESTART
  13747. X#endif
  13748. X    ) {
  13749. X      char error [256];
  13750. X      switch (errno) {
  13751. X    case EBADF: sprintf (error, "Bad file number"); break;
  13752. X    case EFAULT: sprintf (error, "Bad address"); break;
  13753. X    case EFBIG: sprintf (error, "File limit reached"); break;
  13754. X    case EINVAL: sprintf (error, "Negative seek pointer"); break;
  13755. X    case EIO: sprintf (error, "I/O error"); break;
  13756. X    case ENOSPC: sprintf (error, "No space left on device"); break;
  13757. X    case ENXIO: sprintf (error, "No such device or address"); break;
  13758. X    case ERANGE: sprintf (error, "Bytes to read (%d) out of \
  13759. Xrange", bytes_to_read); break;
  13760. X    default: sprintf (error, "Error number %d", errno);
  13761. X      }
  13762. X      fprintf (stderr, "%s\n", error);
  13763. X      free ((char *) buf);
  13764. X      return -1;
  13765. X    }
  13766. X    else if (!pipefp && (time (0) - time_started) > response_timeout) {
  13767. X      printf ("Server response timeout.\n");
  13768. X      free ((char *) buf);
  13769. X      return (total_bytes > 0 ? -total_bytes : -1);
  13770. X    }
  13771. X    if (bytes_read > 0) {
  13772. X      total_bytes += bytes_read;
  13773. X      bytes_to_read -= bytes_read;
  13774. X      if (to_file) {
  13775. X    if (bytes_to_read < prompt_len)
  13776. X      write_to_fd (fileno (stdout),
  13777. X               &buf[bytes_read - prompt_len + bytes_to_read],
  13778. X               prompt_len - bytes_to_read),
  13779. X      to_file = 0;
  13780. X    if (write_to_fd (fd, buf,
  13781. X             (bytes_to_read < prompt_len ? 
  13782. X              bytes_read - prompt_len + bytes_to_read :
  13783. X              bytes_read)) < 0) {
  13784. X      free ((char *) buf);
  13785. X      return (total_bytes > 0 ? -total_bytes : -1);
  13786. X    }
  13787. X      }
  13788. X      else if (pipefp) {
  13789. X    if (to_pipe && !broken_pipe) {
  13790. X      write_to_fd (fileno (pipefp), buf,
  13791. X               (bytes_to_read < prompt_len ? 
  13792. X            bytes_read - prompt_len + bytes_to_read :
  13793. X            bytes_read));
  13794. X      if (errno) {
  13795. X        if (!broken_pipe && errno == EPIPE)
  13796. X          printf ("Broken pipe\n");
  13797. X        broken_pipe = 1;
  13798. X        if (errno != EPIPE && errno != EIO
  13799. X#ifdef ERESTART
  13800. X        && errno != ERESTART
  13801. X#endif
  13802. X        )
  13803. X          printf ("errno %d\n", errno);
  13804. X      }
  13805. X    }
  13806. X    if (bytes_to_read < prompt_len)
  13807. X      to_pipe = 0;
  13808. X      }
  13809. X      else
  13810. X    write_to_fd (fileno (stdout), buf, bytes_read);
  13811. X    }
  13812. X    errno = 0;
  13813. X  }
  13814. X  if (bytes_read > 0) {
  13815. X    total_bytes += bytes_read;
  13816. X    if (to_file && bytes_read > prompt_len) {
  13817. X      write_to_fd (fileno (stdout), &buf [bytes_read - prompt_len], prompt_len);
  13818. X      if (write_to_fd (fd, buf, 
  13819. X               (bytes_read > prompt_len ?
  13820. X            bytes_read - prompt_len : bytes_read)) < 0) {
  13821. X    free ((char *) buf);
  13822. X    return (total_bytes > 0 ? -total_bytes : -1);
  13823. X      }
  13824. X    }
  13825. X    else if (pipefp) {
  13826. X      if (!broken_pipe) {
  13827. X    write_to_fd (fileno (pipefp), buf,
  13828. X             (bytes_read > prompt_len ? bytes_read - prompt_len
  13829. X              : 0));
  13830. X    if (errno) {
  13831. X      if (!broken_pipe && errno == EPIPE)
  13832. X        printf ("Broken pipe\n");
  13833. X      if (errno != EPIPE && errno != EIO
  13834. X#ifdef ERESTART
  13835. X          && errno != ERESTART
  13836. X#endif
  13837. X          )
  13838. X        printf ("errno %d\n", errno);
  13839. X    }
  13840. X      }
  13841. X    }
  13842. X    else
  13843. X      write_to_fd (fileno (stdout), buf, bytes_read);
  13844. X  }
  13845. X  if (fd >= 0)
  13846. X    close (fd),
  13847. X    fd = -1;
  13848. X  to_file = 0;
  13849. X  free ((char *) buf);
  13850. X  fflush (stdout);
  13851. X  if (pipefp)
  13852. X    fflush (pipefp);
  13853. X  return total_bytes;
  13854. X}
  13855. X
  13856. X/*
  13857. X  Write to a file descriptor (socket, or regular file).
  13858. X
  13859. X  Returns: the actual number of bytes written on succes, or the negative of
  13860. X  that number (or -1) on error.
  13861. X*/
  13862. X
  13863. Xlong int write_to_fd (int wfd, char *buf, long int bytes_to_write)
  13864. X{
  13865. X  long int bytes_written, total_bytes = 0, bytes_requested = bytes_to_write;
  13866. X
  13867. X  if (bytes_to_write == 0)
  13868. X    return 0;
  13869. X  errno = 0;
  13870. X  while ((bytes_written = write (wfd, buf, bytes_to_write)) < bytes_to_write) {
  13871. X    if (bytes_written < 0 && errno && errno != EWOULDBLOCK && errno != EAGAIN
  13872. X    && errno != EINTR
  13873. X#ifdef ERESTART
  13874. X    && errno != ERESTART
  13875. X#endif
  13876. X    ) {
  13877. X      char error [256];
  13878. X      switch (errno) {
  13879. X    case EBADF: sprintf (error, "Bad file number"); break;
  13880. X    case EFAULT: sprintf (error, "Bad address"); break;
  13881. X    case EFBIG: sprintf (error, "File limit reached"); break;
  13882. X    case EINVAL: sprintf (error, "Negative seek pointer"); break;
  13883. X    case EIO: sprintf (error, "I/O error"); break;
  13884. X    case ENOSPC: sprintf (error, "No space left on device"); break;
  13885. X    case ENXIO: sprintf (error, "No such device or address"); break;
  13886. X    case ERANGE: sprintf (error, "Bytes to write (%d) out of \
  13887. Xrange", bytes_to_write); break;
  13888. X    case EPIPE: sprintf (error, "Server disappeared"); break;
  13889. X    default: sprintf (error, "Error number %d", errno);
  13890. X      }
  13891. X      fprintf (stderr, "%s\n", error);
  13892. X      if (bytes_written > 0)
  13893. X    total_bytes += bytes_written;
  13894. X      return (total_bytes > 0 ? -total_bytes : -1);
  13895. X    }
  13896. X    if (bytes_written > 0)
  13897. X      bytes_to_write -= bytes_written,
  13898. X      total_bytes += bytes_written,
  13899. X      buf += bytes_written;
  13900. X    errno = 0;
  13901. X  }
  13902. X  return bytes_requested;
  13903. X}
  13904. X
  13905. X/*
  13906. X  Open a file for writing or appending. If 'test' is set, make sure
  13907. X  the file is writeable, notify the server and close the file; else prepare
  13908. X  for the transfer. When the server is inquiring about a file's write
  13909. X  permissions it sends zero bytes as the length of the message.
  13910. X
  13911. X  Returns: 0 on succes, -1 otherwise.
  13912. X*/
  13913. X
  13914. Xint open_file (char *file, int mode, int test)
  13915. X{
  13916. X  char msg [4];
  13917. X
  13918. X  if ((fd = open (file, O_CREAT | mode, 0600)) < 0)
  13919. X    to_file = 0,
  13920. X    printf ("%s: Permission denied.\n", args),
  13921. X    nbytes = prompt_len,
  13922. X    sprintf (msg, "%d", PERMISSION_DENIED);
  13923. X  else {
  13924. X    if (nbytes > 0)
  13925. X      to_file = 1,
  13926. X      printf ("Transferring %ld bytes to file %s...\n", nbytes - prompt_len,
  13927. X          file);
  13928. X    else
  13929. X      close (fd),
  13930. X      sprintf (msg, "%d", OK);
  13931. X  }
  13932. X  if (test)
  13933. X    if (write_to_fd (sock_fd, msg, strlen (msg)) < 0)
  13934. X      return -1;
  13935. X  return 0;
  13936. X}
  13937. X
  13938. X/*
  13939. X  Identify the server's response and take appropriate action.
  13940. X
  13941. X  Returns: 0 on success, -1 otherwise.
  13942. X*/
  13943. X
  13944. Xint check_server_response (int cmd, char *file)
  13945. X{
  13946. X    switch (cmd) {
  13947. X    case OK:
  13948. X    case CONNECT:
  13949. X    case SYNTAX_ERROR:
  13950. X    case INVALID_REQ:
  13951. X    case PEER_UNAVAIL:
  13952. X    case BAD_ARCHIVE:
  13953. X    case RESTRICTED_REQ:
  13954. X    case NOT_OWNER:
  13955. X    case SYS_ERROR:
  13956. X    case SERVER_BUSY:
  13957. X    case PASSWORD_REQUIRED:
  13958. X    case PERMISSION_DENIED:
  13959. X    case MESSAGE:
  13960. X    case CONTINUED:
  13961. X    case MORE_INPUT_REQUIRED:
  13962. X    case CONN_ABORTED:
  13963. X    case CONN_TIMEOUT:
  13964. X    case CONN_CLOSED: GENERAL_RESPONSES (cmd); break;
  13965. X    case TEST_FILE_PERMISSIONS: PRINTF (TEST_FILE_PERMISSIONS,
  13966. X     "Testing file permissions\n");
  13967. X     if (open_file (file, O_WRONLY | O_APPEND, 1)) return -1;
  13968. X     break;
  13969. X    case WRITE_TO_FILE_ASC: PRINTF (WRITE_TO_FILE_ASC,
  13970. X     "Writing to file (ASCII)\n");
  13971. X     if (open_file (file, O_WRONLY | O_TRUNC, 0)) return -1;
  13972. X     break;
  13973. X    case WRITE_TO_FILE_BIN: PRINTF (WRITE_TO_FILE_BIN,
  13974. X     "Writing to file (BIN)\n");
  13975. X     if (open_file (file, O_WRONLY | O_TRUNC, 0)) return -1;
  13976. X     break;
  13977. X    case APPEND_TO_FILE_ASC: PRINTF (APPEND_TO_FILE_ASC,
  13978. X     "Appending to file (ASCII)\n");
  13979. X     if (open_file (file, O_WRONLY | O_APPEND, 0)) return -1;
  13980. X     break;
  13981. X    case APPEND_TO_FILE_BIN: PRINTF (APPEND_TO_FILE_BIN,
  13982. X     "Appending to file (BIN)\n");
  13983. X     if (open_file (file, O_WRONLY | O_APPEND, 0)) return -1;
  13984. X     break;
  13985. X    default: printf ("Protocol error: %d\n", cmd); return -1;
  13986. X  }
  13987. X  return 0;
  13988. X}
  13989. X
  13990. X/*
  13991. X  Check for input redirection, and if so check for for permissions too.
  13992. X
  13993. X  Returns: the opened file descriptor on succes, -1 on error.
  13994. X*/
  13995. X
  13996. Xint check_for_redirection (char *buf, char *infile)
  13997. X{
  13998. X  char *r, *s = strrchr (buf, EOS);
  13999. X  int fd = 0, nquote = 0;
  14000. X
  14001. X  while (s >= buf) {
  14002. X    if (!nquote) {
  14003. X      if (*s == '\'' && (s == buf || *(s - 1) != '\\')) /* Count single quotes */
  14004. X    nquote = 1;
  14005. X      else if (*s == '"' && (s == buf || *(s - 1) != '\\')) /* Count double quotes */
  14006. X    nquote = 2;
  14007. X      else if (*s == '<')
  14008. X    if (s != buf && *(s - 1) == '\\')
  14009. X      sprintf (s - 1, "%s", s), /* Remove \ */
  14010. X      --s;
  14011. X    else {
  14012. X      RESET (infile);
  14013. X      sscanf (s + 1, "%s", infile);
  14014. X      if (infile [0] == EOS) {
  14015. X        printf ("Invalid null input redirect\n");
  14016. X        return -1;
  14017. X      }
  14018. X      if ((fd = open (infile, O_RDONLY)) < 0) {
  14019. X        printf ("%s: No such file or inadequate permissions\n", infile);
  14020. X        return -1;
  14021. X      }
  14022. X      r = s + 1; /* Remove < and file name */
  14023. X      while (*r == ' ' || *r == '\t') ++r;
  14024. X      while (*r != ' ' && *r != '\t' && *r != '\n') ++r;
  14025. X      sprintf (s, "%s", r);
  14026. X    }
  14027. X    }
  14028. X    else if ((nquote == 1 && *s == '\'' &&
  14029. X          (s != buf ? *(s - 1) != '\\' : 1)) ||
  14030. X         (nquote == 2 && *s == '"' && 
  14031. X          (s != buf ? *(s - 1) != '\\' : 1)))
  14032. X      nquote = 0;
  14033. X    --s;
  14034. X  }
  14035. X  if (nquote) {
  14036. X    printf ("Mismatched quotes\n");
  14037. X    strcpy (buf, "\n");
  14038. X    if (fd > 0)
  14039. X      close (fd);
  14040. X    return -1;
  14041. X  }
  14042. X  return fd;
  14043. X}
  14044. X
  14045. X/*
  14046. X  Check for UNIX pipe.
  14047. X
  14048. X  Returns: the open file pointer, or NULL.
  14049. X*/
  14050. X
  14051. XFILE *check_for_pipe (char *buf)
  14052. X{
  14053. X  char cmd [1024], *s = buf;
  14054. X  int nquote = 0;
  14055. X  FILE *pipe = NULL;
  14056. X
  14057. X  RESET (cmd);
  14058. X  while (*s != EOS) {
  14059. X    if (!nquote) {
  14060. X      if (*s == '\'' && (s == buf || *(s - 1) != '\\')) /* Count single quotes */
  14061. X    nquote = 1;
  14062. X      else if (*s == '"' && (s == buf || *(s - 1) != '\\')) /* Count double quotes */
  14063. X    nquote = 2;
  14064. X      else if (*s == '|' && cmd[0] == EOS)
  14065. X    if (s != buf && *(s - 1) == '\\')
  14066. X      sprintf (s - 1, "%s", s), /* Remove \ */
  14067. X      --s;
  14068. X    else {
  14069. X      sscanf (s + 1, "%s", cmd);
  14070. X      if (cmd [0] == EOS) {
  14071. X        printf ("Invalid null pipe\n");
  14072. X        strcpy (buf, "\n");
  14073. X        return NULL;
  14074. X      }
  14075. X      strcpy (cmd, s + 1);
  14076. X      strcpy (s, "\n");
  14077. X      pipe = popen (cmd, "w");
  14078. X    }
  14079. X    }
  14080. X    else if ((nquote == 1 && *s == '\'' && *(s - 1) != '\\') ||
  14081. X         (nquote == 2 && *s == '"' && *(s - 1) != '\\'))
  14082. X      nquote = 0;
  14083. X    ++s;
  14084. X  }
  14085. X  if (nquote)
  14086. X    printf ("Mismatched quotes\n"),
  14087. X    strcpy (buf, "\n");
  14088. X  return pipe;
  14089. X}
  14090. X#endif
  14091. *-*-END-of-src/iul.c-*-*
  14092. echo x - src/list.c
  14093. sed 's/^X//' >src/list.c <<'*-*-END-of-src/list.c-*-*'
  14094. X/*
  14095. X  ----------------------------------------------------------------------------
  14096. X  |            MAILING LIST MAIL-DISTRIBUTION PROGRAM             |
  14097. X  |                                         |
  14098. X  |                 Version 5.0                     |
  14099. X  |                                                                          |
  14100. X  |                (or, when Computer Science gets to you)                   |
  14101. X  |                                         |
  14102. X  |               Written by Anastasios Kotsikonas                      |
  14103. X  |                      (tasos@cs.bu.edu)                          |
  14104. X  |                                                                         |
  14105. X  | AGREEMENT: This software can be used and distributed freely as long      |
  14106. X  | as you do not remove or alter the author notice in the file defs.h;      |
  14107. X  | this notice is #define'd in the symbol VERSION. Although you may alter   |
  14108. X  | the code provided, you may not alter the functions create_header()       |
  14109. X  | and create_multi_recipient_header() in list.c and listserv.c.         |
  14110. X  | By using this software you are bound by this agreement.             |
  14111. X  | This software comes with no warranties and cannot be sold for profit.    |
  14112. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  14113. X  | files when distributing this software.                     |
  14114. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  14115. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  14116. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  14117. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  14118. X  | (ii).                                                                    |
  14119. X  ----------------------------------------------------------------------------
  14120. X
  14121. X  NOTE: Anything appearing in capital letters refers to #define's in the
  14122. X  header files provided.
  14123. X
  14124. X  PURPOSE: Create mailing lists. Members of the list send messages to
  14125. X  them, and each of these messages is forwarded to the rest of the members.
  14126. X  Any message(s) not from subscribers are returned to the original senders,
  14127. X  or can be forwarded to MANAGER. Messages from "undesired" senders can be
  14128. X  ignored by placing their email addresses in the IGNORED file (this would
  14129. X  usually include root and the list's login name to avoid infinite loops).
  14130. X  Distributed may be automatically archived.
  14131. X
  14132. X  OVERVIEW: A mailing list resides in a subdirectory of HOMEDIR/lists
  14133. X  whose name is the list's alias (in the aliases file) in capital letters.
  14134. X  When the program is killed or it abnormally dies, a message
  14135. X  is sent to MANAGER (if using UCB mail) along with a copy of the current 
  14136. X  report file (more on that below). Use the -1 flag when running the
  14137. X  program. The mailing list to be processed is given as argument to the
  14138. X  -L option in upper case. Any progress is reported to the list's REPORT_LIST
  14139. X  file and to the administrator's terminal. All messages sent to this list are
  14140. X  saved in the MBOX file. The program can be run as stand-alone, or in
  14141. X  conjunction with the other programs provided (start, serverd and listserv).
  14142. X  Please note that a line beginning with "From " and another one beginning
  14143. X  with "From: " must appear in the header of each message, and a blank line
  14144. X  must separate the header from the body of the message. Mailing lists
  14145. X  can be linked with peers and have access to news groups. A crash recovery
  14146. X  mechanism is built into the system, so that when the system is aborted
  14147. X  while a delivery is taking place, it will resume delivery from where
  14148. X  it left off.
  14149. X
  14150. X  COMMAND LINE OPTIONS:
  14151. X    -r: Restricted mail; since it is possible to have another distribution
  14152. X        list at some other site as a subscriber, then the following problem
  14153. X    arises: if a message is coming from a member of the other list, his/
  14154. X    her message was forwarded to the members of that list from the other
  14155. X    site; we do not want to send this message back to them, because they
  14156. X    will receive this message twice. Therefore, when this flag is on,
  14157. X    for every message received, its sender is checked against a list
  14158. X    of "restricted" mail addresses (a subset of the subscribers). If a
  14159. X    match is found, then mail is forwarded to the people listed in the
  14160. X    filename following this email address -- for the appropriate format
  14161. X    see below. If no match is found, then the message is forwarded to
  14162. X    to all of the subscribers. See also below.
  14163. X    -1: Execute only once; this is used when the program is running in
  14164. X        conjunction with listserv, in which case execution is interchanged
  14165. X        and controlled by the serverd program.
  14166. X    -e: Echo reports to the screen.
  14167. X    -s: Do not check for subscriptions.
  14168. X    -p: By default, replies to posted (to news) messages go to the list;
  14169. X    this option forces replies to be forwarded to the original author.
  14170. X    -P: By default, replies to distributed messages go to the list; this option
  14171. X    forces replies to be forwarded to the original author.
  14172. X    -m: Usually, each outgoing message has a single recipient. This switches
  14173. X        to multiple recipients -- the argument to it is the number of
  14174. X    multiple recipients to be included in this message.
  14175. X    -v: Display the version number of this package.
  14176. X    -f: Forward any message(s) from unsubscribed senders to the list's
  14177. X        owner. This way, any ordinary user account can be used as the list's
  14178. X        address.
  14179. X    -L: The argument following is the list name to process.
  14180. X    -D: Turn debug on. A transaction of the last email sent out is kept
  14181. X        in the files HOMEDIR/sent and HOMEDIR/received. This assumes
  14182. X        use of the 'system' mail method.
  14183. X    -M: list is moderated.  Incoming messages go to owner unless
  14184. X        they are from owner in which case they get posted.
  14185. X    -d: send out the digest even though it's not full
  14186. X    -i: send out a digest to one user (whose name is the argument)
  14187. X
  14188. X  DISCLAIMER: If for any reason during the use of this program, implied
  14189. X  or not, you happen to die, or suffer any injury of any kind (physical
  14190. X  or mental), I, Mr. Anastasios Kotsikonas, AM NOT RESPONSIBLE at all.
  14191. X  In fact, I AM NOT RESPONSIBLE FOR ANYTHING that may happen to you, or
  14192. X  your computer and operating system.
  14193. X
  14194. X  PLEASE: If you upgrade the code, send me a copy, and do not even attempt to
  14195. X  put your name for credit. Send to tasos@cs.bu.edu or tasos@bucsf.bu.edu.
  14196. X
  14197. X  EXIT CODES:
  14198. X    0: OK
  14199. X    1: Could not open or lock file
  14200. X    2: SIGINT signal
  14201. X    3: Command line option error
  14202. X    4: Syntax error in file
  14203. X    5: Could not spawn
  14204. X    6: Shutdown request
  14205. X    7: Restart request
  14206. X    8: Received system signal
  14207. X    9: Too many multiple recipients
  14208. X   10: Could not deliver mail
  14209. X   11: Malloc failed
  14210. X   12: Cannot fork
  14211. X   13: Socket connection problem
  14212. X   14: Semaphore error
  14213. X   15: Cannot setuid, setgid
  14214. X   16: Internal error
  14215. X
  14216. X  ENJOY!!!
  14217. X
  14218. X  Approximate algorithm:
  14219. X  {
  14220. X    If DIGEST_TMP file exists
  14221. X      send it to digest subscribers
  14222. X
  14223. X    If the -d flag is on
  14224. X      make a digest
  14225. X      send it to digest subscribers
  14226. X
  14227. X    Place a lock so that no other list program will access any files.
  14228. X    Read LIST_MAIL_FILE
  14229. X    If new message(s) have arrived then {
  14230. X      Lock LIST_MAIL_FILE so catmail can't append to it
  14231. X      Append messages to MBOX and truncate LIST_MAIL_FILE
  14232. X      Unlock LIST_MAIL_FILE
  14233. X
  14234. X      For each message do {
  14235. X        If the person is in the IGNORED file, go on to the next message.
  14236. X        If the person sending it is subscribed (listed in SUBSCRIBERS) then
  14237. X      If the person does not acknowledge his/her message, he/she
  14238. X        never receives his/her message back
  14239. X
  14240. X          If the -m flag is on then
  14241. X            If the article comes from someone who is not the owner
  14242. X              forward to the owner
  14243. X              go on to next message
  14244. X            Else
  14245. X              remove headers accumulated in passing to the moderator and back
  14246. X              figure out original sender and subject
  14247. X
  14248. X      If the -r flag is on then
  14249. X        check if the sender is listed in RESTRICTED
  14250. X        If so then
  14251. X          forward mail to all people listed in the file after the 
  14252. X          restricted-sender's address
  14253. X        Else
  14254. X          distribute to all people in SUBSCRIBERS
  14255. X      Else
  14256. X        distribute to all people in SUBSCRIBERS, NEWSF (only to those
  14257. X        newsgroups that are supposed to received messages) and PEERS
  14258. X        according to the following:
  14259. X          Email from regular SUBSCRIBERS is sent to NEWS and PEERS as well
  14260. X          Email from news is sent to SUBSCRIBERS and PEERS
  14261. X          Email from peers is sent to SUBSCRIBERS and NEWS
  14262. X    Else if it news feed (listed in NEWSF)
  14263. X      distribute to SUBSCRIBERS
  14264. X        Else 
  14265. X          if -f specified, forward it to MANAGER; otherwise return the
  14266. X      message to the sender.
  14267. X    Archive message is requested.
  14268. X      }
  14269. X      Remove mail files.
  14270. X    }
  14271. X    Repeat process after IDLE_TIME, or die if -1 specified.
  14272. X  }
  14273. X
  14274. X  Required files:
  14275. X    SUBSCRIBERS     <-- The list of subscribed people
  14276. X    ALIASES        <-- Aliases of email addresses of subscribers, news & peers
  14277. X    NEWSF        <-- List of news groups
  14278. X    PEERS        <-- List of peer lists
  14279. X    RESTRICTED      <-- Addresses of senders whose messages
  14280. X                        require special handling (usually 
  14281. X                addresses of other lists): mail is 
  14282. X            forwarded only to people found in the 
  14283. X            file after the sender's address; see below
  14284. X    IGNORED         <-- The list of undesired people
  14285. X    LIST_LOCK_FILE  <-- Lock file
  14286. X
  14287. X  Input files:
  14288. X    LIST_MAIL_FILE  <-- File where new messages go
  14289. X    MAIL_COPY       <-- Copy of this file (actual work file)
  14290. X    MSG_NO          <-- Current message count
  14291. X    DIGEST_NO       <-- Current digest count
  14292. X    SUBSCRIBERS
  14293. X    RESTRICTED
  14294. X    IGNORED
  14295. X
  14296. X  Output files:
  14297. X    MBOX            <-- A log of all messages sent to date
  14298. X    REPORT_LIST     <-- Progress report
  14299. X    HEADERS        <-- A log of all emails sent (just the sender's address)
  14300. X    MSG             <-- Body of message (no header)
  14301. X    MSG_NO          <-- Write last message count
  14302. X    DIGEST_NO       <-- Write last digest count
  14303. X    MAILFORWARD     <-- Completed message (with header and a copy
  14304. X                of MSG) to be forwarded
  14305. X
  14306. X  Format of the SUBSCRIBERS file:
  14307. X    One entry per line; each entry is the full email address of the subscriber
  14308. X    as it appears in the "From " field, followed by the word "ACK" (in which
  14309. X    case his/her message will be sent back to him/her as an acknowledgement)
  14310. X    "NOACK" (the opposite), POSTPONE (no mail will be sent until the
  14311. X    user changes mode again), or DIGEST (digests are periodically sent),
  14312. X    followed by a string that plays the role of a password, followed by either
  14313. X    YES or NO which play the role of the conceal attribute, followed by the
  14314. X    subscriber's name. Do not include any blank lines.
  14315. X
  14316. X  Format of the RESTRICTED file:
  14317. X    One entry per line; each entry is the full email address of the
  14318. X    subscriber, followed by a file name where email addresses of recipients
  14319. X    are listed (just like in the SUBSCRIBERS file).When mail arrives from a 
  14320. X    sender listed in the RESTRICTED file and the -r flag is on, then mail 
  14321. X    will not be forwarded to SUBSCRIBERS, but instead to the people 
  14322. X    listed in the file following the restricted-sender's address. Example:
  14323. X      tasos@bucsf.bu.edu  /grad/tasos/.recipients
  14324. X      tasos@cs.bu.edu     /grad/tasos/.otherrecipients
  14325. X    If the recipient file given is the word "NONE", then no one will receive
  14326. X    any messages. This is useful in the case that other distribution sites
  14327. X    are subscribers and do forward the message back to the sender, 
  14328. X    in which case we protect ourselves from multiple reception of the same
  14329. X    messages. 
  14330. X    For example, when two (or more) lists are mutual subscribers, and a 
  14331. X    message originated by someone in our list, this message, after being 
  14332. X    distributed locally, is sent to the other list; if the other site does
  14333. X    send messages back to the sender, this message will be forwarded to us
  14334. X    to be distributed again, something which is highly undesirable. 
  14335. X    This precludes that the other site sends messages identified only by
  14336. X    their original senders, something which is unlikely but possible.
  14337. X    In this case, we would put our list as one of the entries in the 
  14338. X    RESTRICTED file, with the word NONE next to it. Do not include 
  14339. X    any blank lines.
  14340. X
  14341. X  Format of the PEERS file:
  14342. X    One entry per line -- the email address of the peer list, followed
  14343. X    by its mail mode (NOACK), followed by the remote alias (how the peer list
  14344. X    is known in the remote host), followed by the email address of the
  14345. X    remote server that handles the remote peer list.
  14346. X
  14347. X  Format of the NEWSF file:
  14348. X    One entry per line -- the email address of the news group, followed
  14349. X    by its mail mode (POSTPONE or NOACK), followed by the news group's name.
  14350. X
  14351. X  Format of the IGNORED file:
  14352. X    One entry per line -- the email addresses of the people whose messages
  14353. X    are to be ignored. This is a good place to put root, sys and other
  14354. X    such undesired logins. See doc/server.nr for information.
  14355. X
  14356. X  Format of the ALIASES file:
  14357. X    One entry per line -- the new alias followed by the email address the
  14358. X    user is subscribed with. See doc/server.nr for information.
  14359. X
  14360. X*/
  14361. X
  14362. X#include <stdio.h>
  14363. X#include <sys/types.h>
  14364. X#ifdef SYSLOG
  14365. X# ifdef ultrix
  14366. X#  include <sys/syslog.h>
  14367. X# else
  14368. X#  include <syslog.h>
  14369. X# endif
  14370. X#endif
  14371. X#include <ctype.h>
  14372. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  14373. X  && !defined (sequent) && !defined (unknown_port)
  14374. X# include <malloc.h>
  14375. X#endif
  14376. X#include <string.h>
  14377. X#ifndef unknown_port
  14378. X# ifndef __NeXT__
  14379. X#  include <unistd.h>
  14380. X# else
  14381. X#  include <libc.h>
  14382. X# endif
  14383. X#endif
  14384. X#include <sys/stat.h>
  14385. X#if !defined (sequent) && !defined (__NeXT__) && !defined (__convex__) && \
  14386. X !defined (apollo) && !defined (i386) && !defined (unknown_port)
  14387. X# include <sys/termio.h>
  14388. X#endif
  14389. X#ifndef sun
  14390. X# include <sys/ioctl.h>
  14391. X#endif
  14392. X#include <fcntl.h>
  14393. X#include <signal.h>
  14394. X#include <time.h>
  14395. X#include <errno.h>
  14396. X#ifdef unknown_port
  14397. Xextern int errno;
  14398. X#endif
  14399. X#include "defs.h"
  14400. X#include "list.h"
  14401. X#include "struct.h"
  14402. X#include "global.h"
  14403. X#if defined (__NeXT__) || defined (unknown_port)
  14404. X# include "next.h"
  14405. X#endif
  14406. X
  14407. X#ifdef TCP_IP
  14408. X# include <sys/socket.h>
  14409. X# include <netdb.h>
  14410. X# include <netinet/in.h>
  14411. Xstruct     in_addr localaddr;
  14412. X#else
  14413. Xchar     *localaddr;
  14414. X#endif
  14415. X
  14416. X/* 
  14417. X  Function prototypes:
  14418. X*/
  14419. X
  14420. X#ifdef __STDC__
  14421. X# include <stdarg.h>
  14422. Xextern int  syscom (char *, ...);
  14423. Xextern char *tsprintf (char *, ...);
  14424. X#else
  14425. X# include <varargs.h>
  14426. Xextern int  syscom ();
  14427. Xextern char *tsprintf ();
  14428. X#endif
  14429. X#ifndef __NeXT__
  14430. Xextern long int atoi (char *);
  14431. X#else
  14432. Xextern int atoi (const char *);
  14433. X#endif
  14434. Xextern int  sys_config (FILE *, SYS *);
  14435. Xextern void report_progress (FILE *, char *, int);
  14436. Xextern void setup_string (char *, char *, char *);
  14437. Xextern void init_signals (void);
  14438. Xextern void catch_signals (void);
  14439. Xextern void extract_origin (char *);
  14440. Xextern void extract_address (char *);
  14441. Xextern int  get_list_id (char *, SYS *, int);
  14442. Xextern void clean_request (char *);
  14443. Xextern int  _getopt (int, char **, char *);
  14444. Xextern char *upcase (char *);
  14445. Xextern char *locase (char *);
  14446. Xextern void shrink (char *);
  14447. Xextern void free_remote (REMOTE **);
  14448. Xextern void distribute (FILE *, void (*)(char *, char *, BOOLEAN, BOOLEAN),
  14449. X            FILE *, char *, char *, char *, char *);
  14450. Xextern BOOLEAN extract_subscriber (FILE *, char *, BOOLEAN);
  14451. Xextern BOOLEAN sysmail (char *);
  14452. Xextern BOOLEAN strinstr (char *, char *);
  14453. Xextern BOOLEAN ignore_sender (FILE *, char *, FILE *, BOOLEAN);
  14454. Xextern BOOLEAN owner_listed (char *, char *, char *, FILE *);
  14455. Xextern int  lock_file (char *, int, int, BOOLEAN);
  14456. Xextern void unlock_file (int);
  14457. Xextern int  otoi (char *);
  14458. Xextern BOOLEAN mkdir1 (char *, char *, char *);
  14459. Xextern BOOLEAN make_indexes (char *, char *, char *, char *, char *);
  14460. Xextern int  re_strcmp (char *, char *, char *);
  14461. Xextern char *_strstr (char *, char *);
  14462. Xextern char *skip_to_word (char *, int);
  14463. Xextern char *mystrdup (char *);
  14464. Xextern int echo (char *, char *);
  14465. Xextern int echo_append (char *, char *);
  14466. Xextern int mv (char *, char *);
  14467. Xextern int cp (char *, char *);
  14468. Xextern int cat_append (char *, char *);
  14469. Xextern int touch (char *);
  14470. Xextern int ucb_strftime (char *, int, char *, struct tm *);
  14471. Xextern long int write_to_fd (int, char *, long int);
  14472. Xextern void escape_re (char *);
  14473. X
  14474. Xvoid   main (int, char **, char **);
  14475. Xvoid   create_header (FILE **, char *, char *, char *, char *, char *,
  14476. X              BOOLEAN, BOOLEAN, BOOLEAN);
  14477. Xvoid   create_multi_recipient_header (FILE **, char *, char *, char *, char *,
  14478. X                      char *, int);
  14479. Xvoid   create_news_header (FILE **, char *, char *, char *, char *, char *);
  14480. Xvoid   create_gate_header (FILE **, char *, char *, char *, char *, char *,
  14481. X               char *);
  14482. Xvoid   process_message (char *, char *, BOOLEAN, BOOLEAN);
  14483. Xvoid   distributions (BOOLEAN, char *, char *, BOOLEAN, char *, char *,
  14484. X              char *, char *, char *, long int, BOOLEAN);
  14485. Xvoid   do_distribute (char *, FILE *, char *, BOOLEAN, char *, BOOLEAN, char *,
  14486. X              char *, char *, char *, char *, FILE *,
  14487. X              BOOLEAN, BOOLEAN, long int, BOOLEAN, BOOLEAN, BOOLEAN);
  14488. XBOOLEAN unprocessed_users (char *, char *, FILE *);
  14489. Xvoid   update_unprocessed (char *, BOOLEAN, BOOLEAN, int);
  14490. Xvoid   update_unprocessed_messages (char *);
  14491. XBOOLEAN copy_msg (FILE *, char *, BOOLEAN, char *, long int, BOOLEAN);
  14492. Xvoid   sendmail (char *, BOOLEAN, BOOLEAN, int, int, char *);
  14493. Xvoid   usage (void);
  14494. Xvoid   list_config (char *);
  14495. Xvoid   version (void);
  14496. Xint    gexit (int);
  14497. Xvoid   fill_text (FILE *, char *);
  14498. XBOOLEAN read_recipient (FILE *, char *, char *, char *, BOOLEAN);
  14499. Xlong int count_lines_in_file (FILE *);
  14500. Xvoid   digest_make (BOOLEAN);
  14501. Xvoid   digest_distribute (void);
  14502. Xvoid   do_archive (char *, char *, char *, BOOLEAN);
  14503. Xvoid   farch (char *, char *, char *, char *, char *, char *);
  14504. Xvoid   reject_archive (char *, char *);
  14505. XBOOLEAN get_volume (char *, int *, int *);
  14506. XBOOLEAN get_archive_name (char *, char *);
  14507. XBOOLEAN limit_exceeded (char *, char *, char *);
  14508. X
  14509. X/*
  14510. X  The control structure of the mail-distributor. Check if mail has arrived.
  14511. X  If so, copy it to MAIL_COPY and proceed to lower level.
  14512. X*/
  14513. X
  14514. Xvoid main (int argc, char **argv, char **envp)
  14515. X{
  14516. X  struct stat stat_buf;
  14517. X  char *options = "1fvrL:em:spPDMdi:";
  14518. X  int c;
  14519. X  char error [MAX_LINE];
  14520. X  int rlfd, i;
  14521. X  long int sig_mask;
  14522. X  FILE *f;
  14523. X  extern char *optarg, *getenv();
  14524. X  extern int optopt;
  14525. X#ifdef TCP_IP
  14526. X  struct hostent *lhost;
  14527. X#endif
  14528. X
  14529. X  prog = argv[0];
  14530. X  while ((c = _getopt (argc, argv, options)) != EOF)
  14531. X    switch ((char) c) {
  14532. X      case '1': execute_once = TRUE; break;
  14533. X      case 'f': errors_to_owner = TRUE; break;
  14534. X      case 'r': send_to_subscribers = FALSE; break;
  14535. X      case 'L': list_alias = upcase (optarg); break;
  14536. X      case 'e': tty_echo = TRUE; break;
  14537. X      case 's': do_not_check_subscriptions = TRUE; break;
  14538. X      case 'p': article_replies_to_author = TRUE; break;
  14539. X      case 'P': message_replies_to_author = TRUE; break;
  14540. X      case 'v': version ();
  14541. X      case 'D': debug = TRUE; break;
  14542. X      case 'd': force_digest = TRUE; break;
  14543. X      case 'i': one_digest = optarg; break;
  14544. X      case 'M': is_moderated = TRUE; break;
  14545. X      case 'm':
  14546. X    multi_recip = TRUE;
  14547. X    if ((maxrecipients = atoi (optarg)) < 1)
  14548. X      fprintf (stderr, "-m %d -- yeah, right!\n", maxrecipients),
  14549. X      exit (3);
  14550. X    break;
  14551. X      case ':': 
  14552. X    fprintf (stderr, "list: Option '%c' requires an argument.\n", optopt);
  14553. X    exit (3);
  14554. X      case '?':
  14555. X      default:
  14556. X    usage ();
  14557. X    }
  14558. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  14559. X    umask (otoi (mask));
  14560. X  else
  14561. X    mask = "066",
  14562. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  14563. X#ifndef NO_LOCKS
  14564. X  if ((lfd = lock_file (LIST_LOCK_FILE, O_RDWR, 0, FALSE)) < 0)
  14565. X    fprintf (stderr, "list: Unable to lock %s. Aborting.\n", LIST_LOCK_FILE),
  14566. X    exit (1);
  14567. X#endif
  14568. X  init_signals();
  14569. X  catch_signals();
  14570. X  list_config (list_alias);
  14571. X#ifdef SYSLOG
  14572. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  14573. X# ifndef i386
  14574. X       |LOG_NOWAIT
  14575. X# endif
  14576. X       , SYSLOG);
  14577. X# ifndef ultrix
  14578. X  setlogmask (LOG_UPTO (LOG_INFO));
  14579. X# endif
  14580. X# ifndef ultrix
  14581. X  setlogmask (LOG_UPTO (LOG_INFO));
  14582. X# endif
  14583. X#else
  14584. X  if ((report = fopen (report_listf, "a")) == NULL)
  14585. X    if ((report = fopen (REPORT_LIST, "a")) == NULL)
  14586. X      fprintf (stderr, "list: Could not open %s and %s\n", report_listf,
  14587. X           REPORT_LIST),
  14588. X      exit (1);
  14589. X    else
  14590. X      chmod (REPORT_LIST, 384); /* 600 */
  14591. X  else
  14592. X    chmod (report_listf, 384); /* 600 */
  14593. X#endif
  14594. X  if (list_alias == NULL)
  14595. X    report_progress (report, "\nlist: No list to process", TRUE),
  14596. X    exit (3);
  14597. X  nlists = sys_config (report, &sys);
  14598. X  if ((listid = get_list_id (list_alias, &sys, nlists)) < 0)
  14599. X    report_progress (report, tsprintf ("\nlist: Unknown list %s", list_alias),
  14600. X             TRUE),
  14601. X    exit (3);
  14602. X  if (!execute_once)
  14603. X    printf ("%s", COPYRIGHT);
  14604. X  if (sys.options & USE_ENV_VAR) {
  14605. X    if ((sys.mail.method = (char *) malloc (256 * sizeof (char))) == NULL)
  14606. X      report_progress (report, "\nmain(): malloc() failed", TRUE),
  14607. X      exit (11);
  14608. X    sprintf (sys.mail.method, "env - %s=%s %s ", sys.mail.env_var,
  14609. X             sys.lists[listid].address, sys.mail.mail_prog);
  14610. X  }
  14611. X
  14612. X  if ((msg_no = fopen (msg_nof, "r")) != NULL)
  14613. X    fscanf (msg_no, "%d %d\n", &public_msg, &returned_msg),
  14614. X    fclose (msg_no);
  14615. X  if ((digest_no = fopen (digest_nof, "r")) != NULL)
  14616. X    fscanf (digest_no, "%d\n", &digest_msg),
  14617. X    fclose (digest_no);
  14618. X#if defined (TIOCNOTTY) && defined (SIGTTOU) && defined (SIGTTIN)
  14619. X  if (!tty_echo)
  14620. X    if ((i = open ("/dev/tty", 2)) >=0)
  14621. X      ioctl (i, TIOCNOTTY, 0),
  14622. X      close (i);
  14623. X#endif
  14624. X
  14625. X  if (multi_recip)
  14626. X    if ((multi_recipients = (char **) malloc (maxrecipients * sizeof (char *)))
  14627. X    == NULL)
  14628. X      report_progress (report, "\nmain(): malloc() failed", TRUE),
  14629. X      exit (11);
  14630. X
  14631. X  if ((f = fopen (PID_LIST, "w")) != NULL)
  14632. X    fprintf (f, "%d", getpid()),
  14633. X    fclose (f);
  14634. X  signal (SIGINT, (void (*)()) gexit);
  14635. X  signal (SIGALRM, SIG_IGN);
  14636. X#ifdef TCP_IP
  14637. X  gethostname (hostname, sizeof (hostname));
  14638. X  lhost = gethostbyname (hostname);
  14639. X  memcpy ((char *) &localaddr, (char *) lhost->h_addr, lhost->h_length);
  14640. X#else
  14641. X  strcpy (localaddr, LOCAL_ADDR);
  14642. X  strcpy (hostname, HOSTNAME);
  14643. X#endif
  14644. X
  14645. X  sprintf (error, "recipients of digest %d", digest_msg);
  14646. X  if (unprocessed_users (unprocessed_digestf, error, report)) {
  14647. X    /* Was interrupted while distributing a digest */
  14648. X    /* USER CONTIBUTED CODE: Warren Burstein */
  14649. X    OPEN_FILE (subscribers, subscribersf, "r", "main");
  14650. X    OPEN_FILE (news, newsf, "r", "main");
  14651. X    OPEN_FILE (peers, peersf, "r", "main");
  14652. X    OPEN_FILE (restricted, restrictedf, "r", "main");
  14653. X
  14654. X    digest_distribute();
  14655. X
  14656. X    fclose (subscribers);
  14657. X    fclose (news);
  14658. X    fclose (peers);
  14659. X    fclose (restricted);
  14660. X  }
  14661. X
  14662. X  if ((force_digest || one_digest) &&
  14663. X      (!stat (digest_msgf, &stat_buf) && stat_buf.st_size > 0)) {
  14664. X    OPEN_FILE (subscribers, subscribersf, "r", "main");
  14665. X    OPEN_FILE (news, newsf, "r", "main");
  14666. X    OPEN_FILE (peers, peersf, "r", "main");
  14667. X    OPEN_FILE (restricted, restrictedf, "r", "main");
  14668. X
  14669. X    if (force_digest) {
  14670. X      digest_make (TRUE);
  14671. X      digest_distribute ();
  14672. X    }
  14673. X    else { /* Make a partial digest, send to one_digest */
  14674. X      char subject[MAX_LINE];
  14675. X      FILE *forwardmail = NULL; /* Completed message to be forwarded */
  14676. X
  14677. X      digest_make (FALSE);
  14678. X
  14679. X      sprintf (subject, "%s partial digest %d", sys.lists[listid].alias,
  14680. X           digest_msg);
  14681. X
  14682. X      create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
  14683. X             sys.lists[listid].address, one_digest, subject,
  14684. X             FALSE, FALSE, FALSE);
  14685. X      if (copy_msg (forwardmail, msgf, FALSE, sys.lists[listid].address, 0,
  14686. X            FALSE))
  14687. X        sendmail (one_digest, FALSE, FALSE, 0, 0, mailforwardf);
  14688. X    }
  14689. X    fclose (subscribers);
  14690. X    fclose (news);
  14691. X    fclose (peers);
  14692. X    fclose (restricted);
  14693. X  }
  14694. X
  14695. X  do {
  14696. X    if (!stat (list_mail_f, &stat_buf) && stat_buf.st_size > 0) {
  14697. X#ifdef bsd
  14698. X      sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  14699. X#elif defined (svr4) || defined (svr3)
  14700. X      sighold (SIGINT);
  14701. X      sighold (SIGTERM);
  14702. X#endif
  14703. X#ifndef NO_LOCKS
  14704. X      if ((rlfd = lock_file (list_mail_f, O_RDWR, 0, FALSE)) < 0)
  14705. X    break;  /* Cannot lock file, so exit, regardless of execute_once */
  14706. X#endif
  14707. X      if (!sys.lists[listid].max_messages) {
  14708. X    if (cp (list_mail_f, mail_copyf))
  14709. X      exit (16);
  14710. X    unlink (list_mail_f);
  14711. X    touch (list_mail_f); /* rewrite file */
  14712. X    chmod (list_mail_f, /*416*/ 0666 & (0666 ^ otoi (mask)));
  14713. X      }
  14714. X      else if (limit_exceeded (limitsf, list_mail_f, mail_copyf)) {
  14715. X#ifndef NO_LOCKS
  14716. X        unlock_file (rlfd);
  14717. X#endif
  14718. X    break;
  14719. X      }
  14720. X      if (cat_append (mail_copyf, mboxf))
  14721. X    exit (16);
  14722. X      chmod (mboxf, 384);
  14723. X      if (cp (mail_copyf, unprocessed_messages))
  14724. X    exit (16);
  14725. X      echo_append ("", mboxf);
  14726. X      touch (list_moderated_f);
  14727. X      chmod (list_moderated_f, /*416*/ 0666 & (0666 ^ otoi (mask)));
  14728. X
  14729. X#ifndef NO_LOCKS
  14730. X      unlock_file (rlfd);
  14731. X#endif
  14732. X#ifdef bsd
  14733. X      sigsetmask (sig_mask);
  14734. X#elif defined (svr4) || defined (svr3)
  14735. X      sigrelse (SIGINT);
  14736. X      sigrelse (SIGTERM);
  14737. X#endif
  14738. X
  14739. X      OPEN_FILE (mail, mail_copyf, "r", "main");
  14740. X      OPEN_FILE (subscribers, subscribersf, "r", "main");
  14741. X      OPEN_FILE (news, newsf, "r", "main");
  14742. X      OPEN_FILE (peers, peersf, "r", "main");
  14743. X      OPEN_FILE (restricted, restrictedf, "r", "main");
  14744. X      OPEN_FILE (ignored, ignoredf, "r", "main");
  14745. X      OPEN_FILE (headers, headersf, "a", "main");
  14746. X      report_progress (report, NEW_ARRIVAL, FALSE);
  14747. X      distribute (mail,
  14748. X          (void (*)(char *, char *, BOOLEAN, BOOLEAN)) process_message,
  14749. X          report, subscribersf, newsf, peersf, aliasesf);
  14750. X      fclose (mail);  /* Done */
  14751. X      fclose (subscribers);
  14752. X      fclose (news);
  14753. X      fclose (peers);
  14754. X      fclose (restricted);
  14755. X      fclose (ignored);
  14756. X      fclose (headers);
  14757. X      shrink (message_idsf);
  14758. X      unlink (unprocessed_messages);
  14759. X      unlink (mail_copyf);  /* Done delivering */
  14760. X    }
  14761. X    else if (!execute_once) /* No mail to deliver */
  14762. X      if (sys.frequency > 0)
  14763. X        sleep (sys.frequency);
  14764. X  } while (!execute_once);
  14765. X#ifdef bsd
  14766. X  sigsetmask (sig_mask);
  14767. X#elif defined (svr4) || defined (svr3)
  14768. X  sigrelse (SIGINT);
  14769. X  sigrelse (SIGTERM);
  14770. X#endif
  14771. X#ifdef SYSLOG
  14772. X  closelog ();
  14773. X#else
  14774. X  fclose (report);
  14775. X#endif
  14776. X  free_remote (&rlists);
  14777. X  if (multi_recip)
  14778. X    free ((char **) multi_recipients);
  14779. X  gexit (0);
  14780. X}
  14781. X
  14782. X/* 
  14783. X  Create a mail header. If this is a reply to a rejected posting, 'copy_owner'
  14784. X  should be TRUE. If reply_to_sender is TRUE, message will reply to sender,
  14785. X  otherwise to list.
  14786. X*/
  14787. X
  14788. Xvoid create_header (FILE **f, char *filename, char *sender, char *originator,
  14789. X            char *recipient, char *subject, BOOLEAN copy_owner,
  14790. X            BOOLEAN reply_to_sender, BOOLEAN error_condition)
  14791. X{
  14792. X  char error [MAX_LINE];
  14793. X  char origin [MAX_LINE];
  14794. X  char reply_to [MAX_LINE];
  14795. X#ifdef LIST_ALIAS_IN_SUBJECT
  14796. X  char *s, *sb;
  14797. X#endif
  14798. X#ifdef NEED_DATE
  14799. X  char date [80];
  14800. X  long int time_is;
  14801. X  struct tm *t;
  14802. X#endif
  14803. X  MATCHED_PREC_HEADER *m = matched_prec_header;
  14804. X
  14805. X  strcpy (origin, originator);
  14806. X  locase (origin);
  14807. X  strcpy (reply_to, sender);
  14808. X  extract_address (reply_to);
  14809. X  OPEN_FILE (*f, filename, "w", "create_header");
  14810. X  locase (recipient);
  14811. X  if (subject [0] != EOS && subject [strlen (subject) - 1] == '\n')
  14812. X    subject [strlen (subject) - 1] = EOS;
  14813. X  if (sys.options & USE_TELNET) {
  14814. X    fprintf (*f, "HELO %s\nMAIL From: <%s>\nRCPT To: <%s>\n",
  14815. X#ifdef ZMAILER
  14816. X/*
  14817. X# ifdef TCP_IP
  14818. X         (char *) inet_ntoa (localaddr),
  14819. X# else
  14820. X         localaddr,
  14821. X# endif
  14822. X    Use either the local address or the host name.
  14823. X*/
  14824. X         hostname,
  14825. X#else
  14826. X         "",
  14827. X#endif
  14828. X         sys.lists[listid].address, recipient);
  14829. X    if (copy_owner)
  14830. X      fprintf (*f, "RCPT To: <%s>\n", sys.lists[listid].owner);
  14831. X    fprintf (*f, "DATA\n");
  14832. X  }
  14833. X  if (message_id[0] != EOS)
  14834. X    fprintf (*f, "Message-Id: %s\n", message_id);
  14835. X#ifdef NEED_DATE
  14836. X  time (&time_is);
  14837. X  t = localtime (&time_is);
  14838. X  ucb_strftime (date, 1024, "%a, %e %b %Y %T %Z", t);
  14839. X  fprintf (*f, "Date: %s\n", date);
  14840. X#endif
  14841. X#ifndef NO_ERRORS_TO
  14842. X  fprintf (*f, "Errors-To: %s\n", sys.lists[listid].owner);
  14843. X#endif
  14844. X  while (m) {
  14845. X    if (!strncmp ("Reply-To:", m->line, strlen ("Reply-To:")))
  14846. X      break;
  14847. X    m = m->next;
  14848. X  }
  14849. X  if (!m)
  14850. X    fprintf (*f, "Reply-To: %s\n",
  14851. X         ((reply_to_sender | message_replies_to_author) ? 
  14852. X          reply_to : sys.lists[listid].address));
  14853. X  fprintf (*f, "Originator: %s\nSender: %s\nPrecedence: %s\nFrom: %s\nTo: %s\n",
  14854. X       origin, sys.lists[listid].address, sys.mail.precedence, sender,
  14855. X       recipient);
  14856. X  if (copy_owner)
  14857. X    fprintf (*f, "Cc: %s\n", sys.lists[listid].owner);
  14858. X#ifdef LIST_ALIAS_IN_SUBJECT
  14859. X  if (!error_condition) {
  14860. X    /* Remove previous tag and amassing Re: */
  14861. X    if ((s = _strstr (subject, tsprintf ("[%s:", sys.lists[listid].alias)))) {
  14862. X      sprintf (s, "%s", ((sb = strchr (s, ']')) ? sb + 2 : ""));
  14863. X      if (re_strcmp ("^[ \t]*[Rr][Ee]:[ \t]+[Rr][Ee]:", subject, NULL) > 0)
  14864. X    sprintf (subject, "%s", subject + 4);
  14865. X    }
  14866. X    fprintf (*f, "Subject: [%s:%d] %s\n", sys.lists[listid].alias, public_msg,
  14867. X         subject);
  14868. X  }
  14869. X  else
  14870. X    fprintf (*f, "Subject: %s%s\n", ERROR_CONDITION, subject);
  14871. X#else
  14872. X  fprintf (*f, "Subject: %s%s\n", (error_condition ? ERROR_CONDITION : ""),
  14873. X       subject);
  14874. X#endif
  14875. X  fprintf (*f, "X-Listserver-Version: %s\n", VERSION);
  14876. X  if (sys.lists[listid].comment[0] != EOS)
  14877. X    fprintf (*f, "X-Comment: %s\n", sys.lists[listid].comment);
  14878. X  m = matched_prec_header;
  14879. X  while (m)
  14880. X    fprintf (*f, "%s", m->line),
  14881. X    m = m->next;
  14882. X  fprintf (*f, "\n");
  14883. X}
  14884. X
  14885. X/* 
  14886. X  Create a mail header with multiple recipients.
  14887. X*/
  14888. X
  14889. Xvoid create_multi_recipient_header (FILE **f, char *filename, char *sender,
  14890. X                    char *originator, char *recipient,
  14891. X                    char *subject, int nrecipients)
  14892. X{
  14893. X  char origin [MAX_LINE];
  14894. X  char reply_to [MAX_LINE];
  14895. X  int  i;
  14896. X  MATCHED_PREC_HEADER *m = matched_prec_header;
  14897. X#ifdef LIST_ALIAS_IN_SUBJECT
  14898. X  char *s, *sb;
  14899. X#endif
  14900. X#ifdef NEED_DATE
  14901. X  char date [80];
  14902. X  long int time_is;
  14903. X  struct tm *t;
  14904. X#endif
  14905. X
  14906. X  strcpy (origin, originator);
  14907. X  locase (origin);
  14908. X  strcpy (reply_to, sender);
  14909. X  extract_address (reply_to);
  14910. X  if (subject [0] != EOS && subject [strlen (subject) - 1] == '\n')
  14911. X    subject [strlen (subject) - 1] = EOS;
  14912. X  OPEN_FILE (*f, filename, "w", "create_multi_recipient_header");
  14913. X  if (sys.options & USE_TELNET) {
  14914. X    fprintf (*f, "HELO %s\nMAIL From: <%s>\n",
  14915. X#ifdef ZMAILER
  14916. X/*
  14917. X# ifdef TCP_IP
  14918. X         (char *) inet_ntoa (localaddr),
  14919. X# else
  14920. X         localaddr,
  14921. X# endif
  14922. X    Use either the local address or the host name.
  14923. X*/
  14924. X         hostname,
  14925. X#else
  14926. X         "",
  14927. X#endif
  14928. X         sys.lists[listid].address);
  14929. X    for (i = 0; i < nrecipients; i++)
  14930. X      fprintf (*f, "RCPT To: <%s>\n", multi_recipients[i]),
  14931. X      free ((char *) multi_recipients[i]);
  14932. X    fprintf (*f, "DATA\n");
  14933. X  }
  14934. X  if (message_id[0] != EOS)
  14935. X    fprintf (*f, "Message-Id: %s\n", message_id);
  14936. X#ifdef NEED_DATE
  14937. X  time (&time_is);
  14938. X  t = localtime (&time_is);
  14939. X  ucb_strftime (date, 1024, "%a, %e %b %Y %T %Z", t);
  14940. X  fprintf (*f, "Date: %s\n", date);
  14941. X#endif
  14942. X#ifndef NO_ERRORS_TO
  14943. X  fprintf (*f, "Errors-To: %s\n", sys.lists[listid].owner);
  14944. X#endif
  14945. X  while (m) {
  14946. X    if (!strncmp ("Reply-To:", m->line, strlen ("Reply-To:")))
  14947. X      break;
  14948. X    m = m->next;
  14949. X  }
  14950. X  if (!m)
  14951. X    fprintf (*f, "Reply-To: %s\n",
  14952. X         (message_replies_to_author ? reply_to : sys.lists[listid].address));
  14953. X  fprintf (*f, "Originator: %s\nSender: %s\nPrecedence: %s\nFrom: %s\nTo: %s\n",
  14954. X       origin, sys.lists[listid].address, sys.mail.precedence, sender,
  14955. X       recipient);
  14956. X#ifdef LIST_ALIAS_IN_SUBJECT
  14957. X  /* Remove previous tag and amassing Re: */
  14958. X  if ((s = _strstr (subject, tsprintf ("[%s:", sys.lists[listid].alias)))) {
  14959. X    sprintf (s, "%s", ((sb = strchr (s, ']')) ? sb + 2 : ""));
  14960. X    if (re_strcmp ("^[ \t]*[Rr][Ee]:[ \t]+[Rr][Ee]:", subject, NULL) > 0)
  14961. X      sprintf (subject, "%s", subject + 4);
  14962. X  }
  14963. X  fprintf (*f, "Subject: [%s:%d] %s\n", sys.lists[listid].alias, public_msg,
  14964. X       subject);
  14965. X#else
  14966. X  fprintf (*f, "Subject: %s\n", subject);
  14967. X#endif
  14968. X  fprintf (*f, "X-Listserver-Version: %s\n", VERSION);
  14969. X  if (sys.lists[listid].comment[0] != EOS)
  14970. X    fprintf (*f, "X-Comment: %s\n", sys.lists[listid].comment);
  14971. X  m = matched_prec_header;
  14972. X  while (m)
  14973. X    fprintf (*f, "%s", m->line),
  14974. X    m = m->next;
  14975. X  fprintf (*f, "\n");
  14976. X}
  14977. X
  14978. X/*
  14979. X  Create a news header for a message to be posted.
  14980. X*/
  14981. X
  14982. Xvoid create_news_header (FILE **f, char *filename, char *sender,
  14983. X             char *originator, char *group, char *subject)
  14984. X{
  14985. X  char origin [MAX_LINE];
  14986. X  char reply_to [MAX_LINE];
  14987. X  MATCHED_PREC_HEADER *m = matched_prec_header;
  14988. X#ifdef NEED_DATE
  14989. X  char date [80];
  14990. X  long int time_is;
  14991. X  struct tm *t;
  14992. X#endif
  14993. X
  14994. X  strcpy (origin, originator);
  14995. X  locase (origin);
  14996. X  strcpy (reply_to, sender);
  14997. X  extract_address (reply_to);
  14998. X  if (subject [0] != EOS && subject [strlen (subject) - 1] == '\n')
  14999. X    subject [strlen (subject) - 1] = EOS;
  15000. X  OPEN_FILE (*f, filename, "w", "create_news_header");
  15001. X  locase (group);
  15002. X  fprintf (*f, "Path: %s\nNewsgroups: %s\nDistribution: world\n\
  15003. XOrganization: %s\nOriginator: %s\n",
  15004. X       (article_replies_to_author ? reply_to : sys.lists[listid].address),
  15005. X       group, sys.organization, origin);
  15006. X  if (message_id[0] != EOS)
  15007. X    fprintf (*f, "Message-Id: %s\n", message_id);
  15008. X#ifdef NEED_DATE
  15009. X  time (&time_is);
  15010. X  t = localtime (&time_is);
  15011. X  ucb_strftime (date, 1024, "%a, %e %b %Y %T %Z", t);
  15012. X  fprintf (*f, "Date: %s\n", date);
  15013. X#endif
  15014. X  while (m) {
  15015. X    if (!strncmp ("Reply-To:", m->line, strlen ("Reply-To:")))
  15016. X      break;
  15017. X    m = m->next;
  15018. X  }
  15019. X  if (!m)
  15020. X    fprintf (*f, "Reply-To: %s\n",
  15021. X         (article_replies_to_author ? reply_to : sys.lists[listid].address));
  15022. X  fprintf (*f, "Sender: %s\nFrom: %s\nSubject: %s\n", 
  15023. X       sys.lists[listid].address, sender, subject);
  15024. X  m = matched_prec_header;
  15025. X  while (m)
  15026. X    fprintf (*f, "%s", m->line),
  15027. X    m = m->next;
  15028. X  fprintf (*f, "\n");
  15029. X}
  15030. X
  15031. X/*
  15032. X  Create a gateway header.
  15033. X*/
  15034. X
  15035. Xvoid create_gate_header (FILE **f, char *filename, char *sender,
  15036. X             char *originator, char *recipient, 
  15037. X             char *group, char *subject)
  15038. X{
  15039. X  char origin [MAX_LINE];
  15040. X  char reply_to [MAX_LINE];
  15041. X  MATCHED_PREC_HEADER *m = matched_prec_header;
  15042. X#ifdef NEED_DATE
  15043. X  char date [80];
  15044. X  long int time_is;
  15045. X  struct tm *t;
  15046. X#endif
  15047. X
  15048. X  strcpy (origin, originator);
  15049. X  locase (origin);
  15050. X  strcpy (reply_to, sender);
  15051. X  extract_address (reply_to);
  15052. X  if (subject [0] != EOS && subject [strlen (subject) - 1] == '\n')
  15053. X    subject [strlen (subject) - 1] = EOS;
  15054. X  OPEN_FILE (*f, filename, "w", "create_gate_header");
  15055. X  locase (group);
  15056. X  if (sys.options & USE_TELNET)
  15057. X    fprintf (*f, "HELO %s\nMAIL From: <%s>\nRCPT To: <%s>\nDATA\n",
  15058. X#ifdef ZMAILER
  15059. X/*
  15060. X# ifdef TCP_IP
  15061. X         (char *) inet_ntoa (localaddr),
  15062. X# else
  15063. X         localaddr,
  15064. X# endif
  15065. X    Use either the local address or the host name.
  15066. X*/
  15067. X         hostname,
  15068. X#else
  15069. X         "",
  15070. X#endif
  15071. X         sys.lists[listid].address, recipient);
  15072. X#ifndef NO_ERRORS_TO
  15073. X  fprintf (*f, "Errors-To: %s\n", sys.lists[listid].owner);
  15074. X#endif
  15075. X  fprintf (*f, "Newsgroups: %s\nDistribution: world\nOrganization: %s\n\
  15076. XOriginator: %s\n", group, sys.organization, origin);
  15077. X  if (message_id[0] != EOS)
  15078. X    fprintf (*f, "Message-Id: %s\n", message_id);
  15079. X#ifdef NEED_DATE
  15080. X  time (&time_is);
  15081. X  t = localtime (&time_is);
  15082. X  ucb_strftime (date, 1024, "%a, %e %b %Y %T %Z", t);
  15083. X  fprintf (*f, "Date: %s\n", date);
  15084. X#endif
  15085. X  while (m) {
  15086. X    if (!strncmp ("Reply-To:", m->line, strlen ("Reply-To:")))
  15087. X      break;
  15088. X    m = m->next;
  15089. X  }
  15090. X  if (!m)
  15091. X    fprintf (*f, "Reply-To: %s\n",
  15092. X         (article_replies_to_author ? reply_to : sys.lists[listid].address));
  15093. X  fprintf (*f, "Sender: %s\nFrom: %s\nTo: %s\nSubject: %s\n",
  15094. X       sys.lists[listid].address, sender, recipient, subject);
  15095. X  m = matched_prec_header;
  15096. X  while (m)
  15097. X    fprintf (*f, "%s", m->line),
  15098. X    m = m->next;
  15099. X  fprintf (*f, "\n");
  15100. X}
  15101. X
  15102. X/*
  15103. X  The heart of the distribution. Since we are now at the beginning of the
  15104. X  message (as guaranteed by distribute ()), gather the rest of the message
  15105. X  -- that is until the beginning of the next message, or EOF. Note that
  15106. X  only the "From: ", "Originator: " and "Subject: " lines from the header
  15107. X  are saved.
  15108. X  The beginning of the next and every message is "From ". The actual
  15109. X  text of each message is separated from its header by a blank line (universal
  15110. X  format). The message is processed only if the sender is not listed in
  15111. X  IGNORED.
  15112. X  The entire message is stored in MSG. To distribute the message, prepare
  15113. X  a new header; the completed message is stored in MAILFORWARD. Actually,
  15114. X  for each subscriber we prepare a different header (different "To:" field) 
  15115. X  and append MSG to MAILFORWARD. Distribute that mail to the members,
  15116. X  or, either return it to the sender if he/she is not subscribed, or
  15117. X  forward it to MANAGER if -f specified. Messages from MAILER_DAEMON are
  15118. X  always forwarded to MANAGER. A message from a mailer daemon is identified
  15119. X  by the presence of MAILER_DAEMON anywhere in the sender's email address,
  15120. X  to cover local and remote mailer daemon addresses. Please look at the
  15121. X  documentation for defs.h for the syntax of the MAILER_DAEMON string.
  15122. X  The parameter "sender" is used for report purposes and when we are sending
  15123. X  the sender's message back to him/her.
  15124. X  Messages from regular subscribers are sent to peer lists and news groups.
  15125. X  Messages from news groups are only distributed to local subscribers and
  15126. X  peer lists. Finally, messages from peer lists are distributed locally
  15127. X  and may be posted to news groups.
  15128. X  In the case of restricted mail, check if the sender is listed in 
  15129. X  RESTRICTED; if so, forward the message to the people listed in the
  15130. X  filename found after the restricted-sender's address in RESTRICTED.
  15131. X  Each public message (legitimate message) is automatically archived.
  15132. X*/
  15133. X
  15134. Xchar *msgs[] = { /* USER CONTRIBUTED CODE: Warren Burstein */
  15135. X    "If you forward it back to the list, it will be distributed without the",
  15136. X    "paragraphs above the dashed line.  You may edit the Subject: line and",
  15137. X    "the text of the message before forwarding it back.",
  15138. X    "",
  15139. X    "If you edit the messages you receive into a digest, you will need to",
  15140. X    "remove these paragraphs and the dashed line before mailing the result", 
  15141. X    "to the list. Finally, if you need more information from the author of",
  15142. X    "this message, you should be able to do so by simply replying to this",
  15143. X    "note.",
  15144. X    "", NULL
  15145. X};
  15146. X
  15147. Xvoid process_message (char *sender, char *linecopy, BOOLEAN address_ok,
  15148. X              BOOLEAN sender_subscribed)
  15149. X{
  15150. X  char line [MAX_LINE];            /* ... from the current message */
  15151. X  char sent_date [MAX_LINE];
  15152. X  char senders_subject [MAX_LINE]; /* the sender's subject */
  15153. X  char subject_copy [MAX_LINE];    /* a copy of the subject */
  15154. X  char original_sender [MAX_LINE]; /* as it appears in his message */
  15155. X  char originator [MAX_LINE];       /* Holds the Originator: address */
  15156. X  char reply_to [MAX_LINE];       /* Holds the Reply-To: address */
  15157. X  char id_copy [MAX_LINE];       /* Holds the Message-Id: */
  15158. X  char match [MAX_LINE];
  15159. X  char match2 [MAX_LINE];
  15160. X  char error [MAX_LINE];
  15161. X  char received [MAX_LINE];
  15162. X  char sender_copy [MAX_LINE];
  15163. X  char *at = NULL;
  15164. X  FILE *forwardmail = NULL;        /* completed message to be forwarded */
  15165. X  FILE *msg = NULL;
  15166. X  FILE *header = NULL;
  15167. X  FILE *in, *out, *f;
  15168. X  BOOLEAN already_sent = FALSE;
  15169. X  BOOLEAN message_forwarded = FALSE;
  15170. X  BOOLEAN mailer_daemon;
  15171. X  BOOLEAN susp_subject;
  15172. X  BOOLEAN fake_mail = TRUE;
  15173. X  BOOLEAN control_article = FALSE;
  15174. X  long int lines_to_skip = 0;      /* skip lines of incoming message */
  15175. X  long int sig_mask;
  15176. X  MATCHED_PREC_HEADER *out_header = matched_prec_header;
  15177. X  PRECIOUS_HEADER *pheader;
  15178. X  int request_found, i;
  15179. X
  15180. X  /* gets set if anyone wants digests */
  15181. X  append_to_digest = sys.lists[listid].options & ARCHIVE_DIGEST;
  15182. X
  15183. X  line[0] = sent_date[0] =
  15184. X    senders_subject[0] = 
  15185. X      subject_copy[0] = 
  15186. X    originator[0] =
  15187. X          archive_name[0] =
  15188. X        reply_to[0] =
  15189. X          message_id[0] =
  15190. X        id_copy[0]=
  15191. X          received[0] =
  15192. X            RESET (original_sender);
  15193. X
  15194. X  strcpy (sender_copy, sender);
  15195. X  upcase (sender_copy);
  15196. X  while (matched_prec_header)    /* Free previous precious header lines */
  15197. X    out_header = matched_prec_header->next,
  15198. X    free ((char *) matched_prec_header->line),
  15199. X    free ((MATCHED_PREC_HEADER *) matched_prec_header),
  15200. X    matched_prec_header = out_header;
  15201. X
  15202. X  /* Remove message header, but store the "From: " and "Subject: " fields to
  15203. X     be used later when sending the message to all subscribers. Also, preserve
  15204. X     user-defined header lines. */
  15205. X
  15206. X  OPEN_FILE (header, headerf, "w", "process_message");
  15207. X  fprintf (header, "%s", linecopy);
  15208. X  while (!feof (mail) && line[0] != '\n') {
  15209. X    strcpy (match, "\\1");
  15210. X    if (re_strcmp (FROM, line, match) > 0) {
  15211. X      strcpy (original_sender, line + strlen (match)); /* Save From: */
  15212. X      original_sender [strlen (original_sender) - 1] = EOS; /* \n -> \0 */
  15213. X      if (strchr (original_sender, '|') || original_sender[0] == ':' ||
  15214. X      strchr (original_sender, '`'))
  15215. X    original_sender[0] = EOS;    /* protect against Trojans */
  15216. X    }
  15217. X
  15218. X    else if (re_strcmp (DATE, line, match) > 0)
  15219. X      strcpy (sent_date, line + strlen (match)), /* Save Date: */
  15220. X      sent_date [strlen (sent_date) - 1] = EOS; /* \n -> \0 */
  15221. X
  15222. X    else if (re_strcmp (SUBJECT, line, match) > 0)
  15223. X      strcpy (senders_subject, line + strlen (match)), /* Save Subject: */
  15224. X      senders_subject [strlen (senders_subject) - 1] = EOS, /* \n -> \0 */
  15225. X      strcpy (subject_copy, senders_subject);
  15226. X
  15227. X    else if (re_strcmp (ORIGIN, line, match) > 0)
  15228. X      strcpy (originator, line + strlen (match)),  /* Remove "Originator: " */
  15229. X      extract_origin (originator),
  15230. X      upcase (originator);
  15231. X
  15232. X    else if (re_strcmp (ARCHIVE_NAME, line, match) > 0)
  15233. X      /* Remove "Archive-Name: " */
  15234. X      strcpy (archive_name, line + strlen (match)),
  15235. X      extract_origin (archive_name);
  15236. X
  15237. X    else if (re_strcmp (REPLY_TO, line, match) > 0)
  15238. X      strcpy (reply_to, line + strlen (match)), /* Remove "Reply-To: " */
  15239. X      extract_origin (reply_to),
  15240. X      upcase (reply_to);
  15241. X
  15242. X    else if (re_strcmp (RECEIVED, line, match) > 0) { /* Check for fake mail */
  15243. X      strcpy (received, line + strlen (match));
  15244. X      received [strlen (received) - 1] = EOS;
  15245. X      sscanf (received, "%s %s", error, received); /* Get host after "from" */
  15246. X      upcase (received);  /* Relay host */
  15247. X      if (fake_mail && (at = strchr (sender_copy, '@')))
  15248. X    if (re_strcmp (at + 1, received, NULL) > 0)
  15249. X      fake_mail = FALSE;
  15250. X    }
  15251. X
  15252. X    else if (re_strcmp (CONTROL, line, NULL) > 0)
  15253. X      control_article = TRUE;
  15254. X
  15255. X    else if (re_strcmp (MESSAGE_ID1, line, NULL) > 0 ||
  15256. X             re_strcmp (MESSAGE_ID2, line, NULL) > 0 ||
  15257. X         re_strcmp (MESSAGE_ID3, line, NULL) > 0)
  15258. X      strcpy (message_id, line + strlen ("Message-") + 4),
  15259. X      message_id [strlen (message_id) - 1] = EOS; /* \n -> \0 */
  15260. X
  15261. X    else {    /* Check if precious header line */
  15262. X      pheader = sys.lists[listid].header;
  15263. X      while (pheader) {
  15264. X        if (!strncmp (line, pheader->line, strlen (pheader->line))) {
  15265. X      if (! (out_header =
  15266. X         (MATCHED_PREC_HEADER *) malloc (sizeof (MATCHED_PREC_HEADER))))
  15267. X        report_progress (report, "\nprocess_message(): malloc() failed",
  15268. X                 TRUE),
  15269. X        exit (11);
  15270. X      if (! (out_header->line =
  15271. X         (char *) malloc ((strlen (line) + 1) * sizeof (char ))))
  15272. X        report_progress (report, "\nprocess_message(): malloc() failed",
  15273. X                 TRUE),
  15274. X        exit (11);
  15275. X      strcpy (out_header->line, line);
  15276. X      out_header->next = matched_prec_header;
  15277. X      matched_prec_header = out_header;
  15278. X    }
  15279. X    pheader = pheader->next;
  15280. X      }
  15281. X    }
  15282. X
  15283. X    RESET (line);
  15284. X    fgets (line, MAX_LINE - 2, mail);
  15285. X    fprintf (header, "%s", line);
  15286. X  }
  15287. X  fclose (header);
  15288. X
  15289. X  /* Gather message into MSG; check if we have reached the next message, 
  15290. X     or EOF; also check for possible requests sent to the list */
  15291. X  OPEN_FILE (msg, msgf, "w", "process_message");
  15292. X  RESET (line);
  15293. X  request_found = -1;
  15294. X  while (!feof (mail) && 
  15295. X     (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {
  15296. X    if (!strcmp (line, ".\n"))
  15297. X      PREPEND (".", line);
  15298. X    fprintf (msg, "%s", line);
  15299. X    upcase (line);
  15300. X    if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  15301. X      line [strlen (line) - 1] = EOS;
  15302. X    if (request_found < 0 && line[0] != EOS) { /* First non-empty line */
  15303. X      strcpy (match, "\\1");
  15304. X      if (re_strcmp (REQUESTS, line, match) > 0) { /* Possible request */
  15305. X#ifdef LIST_CHECKING_FOR_REQUESTS
  15306. X    strcpy (match2, "\\2");
  15307. X    re_strcmp (REQUESTS, line, match2); /* Get list specified (if any) */
  15308. X    if (match2[0] == EOS)
  15309. X      request_found = TRUE; /* Request does not take 'list' arg */
  15310. X    else if (get_list_id (match2, &sys, nlists) >= 0)
  15311. X#endif
  15312. X      request_found = TRUE;
  15313. X      }
  15314. X      if (request_found < 0)
  15315. X    request_found = FALSE;
  15316. X    }
  15317. X    fgets (line, MAX_LINE - 2, mail);
  15318. X  }
  15319. X  fclose (msg);
  15320. X
  15321. X  strcpy (linecopy, line); /*** VERY IMPORTANT: we are now at the next msg ***/
  15322. X
  15323. X  if (!address_ok) {        /* Abort message */
  15324. X    NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS (sender, "process_message", TRUE);
  15325. X    return;
  15326. X  }
  15327. X
  15328. X  if (control_article) {
  15329. X    report_progress (report, "Control message ignored", TRUE);
  15330. X    return;
  15331. X  }
  15332. X  /* Check the IGNORED file */
  15333. X  if (ignore_sender (ignored, sender, report, FALSE))
  15334. X    return;
  15335. X  if (originator[0] != EOS) /* Check for mail loop using Originator: */
  15336. X    if (ignore_sender (ignored, originator, report, FALSE))
  15337. X      return;
  15338. X  if (reply_to[0] != EOS) /* Check for mail loop using Reply-To: */
  15339. X    if (ignore_sender (ignored, reply_to, report, FALSE))
  15340. X      return;
  15341. X  if (message_id[0] != EOS) { /* Check for mail loop using Message-Id: */
  15342. X    strcpy (id_copy, message_id);
  15343. X    upcase (id_copy);
  15344. X    if (message_ids = fopen (message_idsf, "r")) {
  15345. X      if (ignore_sender (message_ids, id_copy, report, TRUE)) {
  15346. X        fclose (message_ids);
  15347. X        return;
  15348. X      }
  15349. X      fclose (message_ids);
  15350. X    }
  15351. X  }
  15352. X  if (sender_subscribed == NEWS)
  15353. X    if (ignore_sender (peers, originator, report, TRUE))
  15354. X      return;
  15355. X
  15356. X  if (originator[0] == EOS) /* Fresh message originating from this list */
  15357. X    sprintf (originator, "%s", sys.lists[listid].address);
  15358. X  upcase (originator);
  15359. X
  15360. X  if (do_not_check_subscriptions)
  15361. X    sender_subscribed = SUBSCRIBED;
  15362. X  mailer_daemon = strinstr (MAILER_DAEMON, sender) ||
  15363. X    (original_sender[0] != EOS && strinstr (MAILER_DAEMON, original_sender)) ||
  15364. X    *sender == EOS;
  15365. X  susp_subject = (senders_subject[0] != EOS &&
  15366. X          strinstr (SUSP_SUBJECT, senders_subject));
  15367. X  if (sender_subscribed == NOTSUBSCRIBED || mailer_daemon || susp_subject ||
  15368. X      request_found > 0) {
  15369. X    /* Send error message to sender */
  15370. X    report_progress (report,
  15371. X             tsprintf ("Invalid message #%04d (%s). Forwarding error \
  15372. Xmessage to %s.\n%s",
  15373. X                   ++returned_msg,
  15374. X                   (mailer_daemon ? "suspicious address" :
  15375. X                (susp_subject ? "suspicious subject" :
  15376. X                 (request_found > 0 ? "request sensed" : 
  15377. X                  (sender_subscribed == NOTSUBSCRIBED ?
  15378. X                   "sender not subscribed" :
  15379. X                   "???")))),
  15380. X                   ((mailer_daemon || susp_subject || errors_to_owner) ?
  15381. X                sys.lists[listid].owner : sender),
  15382. X                   (*sender != EOS ? sender : "\"\"")), TRUE);
  15383. X    OPEN_FILE (msg_no, msg_nof, "w", "process_message");
  15384. X    fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
  15385. X    fclose (msg_no);
  15386. X    OPEN_FILE (msg, msgf, "r", "process_message");
  15387. X    /* Prepare header */
  15388. X    create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
  15389. X      originator,
  15390. X      ((mailer_daemon || susp_subject || errors_to_owner) ?
  15391. X       sys.lists[listid].owner : sender),
  15392. X      senders_subject, COPY_OWNER (ccerrors), FALSE, TRUE);
  15393. X    if (errors_to_owner || mailer_daemon || susp_subject)
  15394. X      fprintf (forwardmail, "\nRejected message: sent to %s by %s \
  15395. Xfollows.\nReason for rejection: %s.\n",
  15396. X           sys.lists[listid].address, (*sender != EOS ? sender : "\"\""),
  15397. X           (mailer_daemon ? "suspicious address" :
  15398. X        (susp_subject ? "suspicious subject" :
  15399. X         (request_found > 0 ? "request sensed" : 
  15400. X          (sender_subscribed == NOTSUBSCRIBED ? "sender not subscribed" :
  15401. X           "???")))));
  15402. X    else if (request_found > 0)
  15403. X      if (sender_subscribed != PEER && sender_subscribed != NEWS)
  15404. X    /* First line of msg contained a request; send it back w/ apologies */
  15405. X    fprintf (forwardmail, "\nWe are sorry, but this system sensed the \
  15406. Xfollowing request which may have been\ninadvertedly sent to this list:\n\n%s\n\
  15407. X\nIf your posting was intentional, please accept our apologies and resend your\
  15408. X\nmail message, making sure you do not include anything that may look like a\
  15409. X\nrequest in the first line of the body of the actual message. If this was \
  15410. X\nindeed a request please resend it to %s. Your entire message\nis copied \
  15411. Xbelow.\n\n", match, sys.server.address);
  15412. X      else
  15413. X    report_progress (report, "Message from peer/news ignored: request \
  15414. Xsensed\n", FALSE);
  15415. X    else {
  15416. X      fprintf (forwardmail, "%s: You are not subscribed to %s.\n\
  15417. XYour message is returned to you unprocessed. If you want to subscribe,\n\
  15418. Xsend mail to %s with the following request:\n\n\t\tsubscribe %s Your Name\n\n",               sender, sys.lists[listid].address, sys.server.address,
  15419. X               sys.lists[listid].alias);
  15420. X      if (alternate_addresses) {
  15421. X    fprintf (forwardmail, "In addition, the system found the following \
  15422. Xaddress(es) that resemble yours.\nIf one of these is you, please resend your \
  15423. Xmessage from that one, or use the\n'set <list> address' request to change the \
  15424. Xaddress you are subscribed with:\n\n");
  15425. X    for (i = 0; alternate_addresses[i]; ++i)
  15426. X      fprintf (forwardmail, "%s\n", alternate_addresses[i]),
  15427. X      free ((char *) alternate_addresses[i]);
  15428. X    free ((char **) alternate_addresses);
  15429. X    alternate_addresses = NULL;
  15430. X    fprintf (forwardmail, "\n");
  15431. X      }
  15432. X    }
  15433. X
  15434. X#ifdef ERROR_MAIL_ANALYSIS
  15435. X    if (mailer_daemon) { /* See if we should remove the user and/or log error */
  15436. X      char line [1024], matches [MAX_LINE], matches2 [MAX_LINE],
  15437. X        subj [MAX_LINE];
  15438. X      BOOLEAN fatal_subject;
  15439. X
  15440. X      RESET (line);
  15441. X      rewind (msg);
  15442. X      strcpy (subj, subject_copy);
  15443. X      upcase (subj);
  15444. X      while (!feof (msg) &&
  15445. X         !_strstr (line, "-- Unsent message follows --")) {
  15446. X    fgets (line, 1023, msg);
  15447. X    upcase (line);
  15448. X    strcpy (matches, "\\1.*\\2");
  15449. X    strcpy (matches2, "\\1");
  15450. X    if (re_strcmp (errors, line, matches) > 0 ||
  15451. X        ((fatal_subject = re_strcmp (fatal_subjects, subj, matches2)) > 0 &&
  15452. X         ((atoi (matches2) >= (GRACE_PERIOD / 86400)) ||
  15453. X          matches2[0] == EOS))) {
  15454. X      /* Remove user if present */
  15455. X      char address [MAX_LINE], address_copy [MAX_LINE],_line [1024],
  15456. X        _address [MAX_LINE];
  15457. X
  15458. X# if (ERROR_MAIL_ANALYSIS == 9)
  15459. X      if (fatal_subject > 0)
  15460. X        strcpy (matches, ".*\\1"), /* See if warning and get host name */
  15461. X        re_strcmp (warnings, line, matches);
  15462. X      if (matches [0] != EOS && matches [strlen (matches) - 1] == '\n')
  15463. X        matches [strlen (matches) - 1] = EOS;
  15464. X# endif
  15465. X      rewind (subscribers);
  15466. X      while (!feof (subscribers)) {
  15467. X        address [0] = RESET (_line);
  15468. X        fgets (_line, MAX_LINE - 2, subscribers);
  15469. X        sscanf (_line, "%s", address);
  15470. X        upcase (_line);
  15471. X        upcase (address);
  15472. X        strcpy (address_copy, address);
  15473. X        escape_re (address);
  15474. X        if (
  15475. X# if (ERROR_MAIL_ANALYSIS == 9)
  15476. X        strcmp (matches, ".*") && strcmp (matches, ".*\\1") &&
  15477. X# endif
  15478. X        strcmp (matches, "\\1.*\\2"))
  15479. X          sprintf (_address, "^[ \t]*%s", matches +
  15480. X               (!strncmp (matches, ".*", 2) ? 2 : 0));
  15481. X        else
  15482. X          strcpy (_address, address),
  15483. X          strcpy (_line, line);
  15484. X        if (address [0] != EOS && re_strcmp (_address, _line, NULL) > 0) {
  15485. X          /* User found; remove him */
  15486. X          char _address [MAX_LINE];
  15487. X          BOOLEAN removed = FALSE;
  15488. X
  15489. X          fclose (subscribers);
  15490. X          sprintf (_address, "^[\t ]*%s ", address);
  15491. X          if (cp (subscribersf, OLD_SUBSCRIBERS))
  15492. X        exit (16);
  15493. X          REMOVE_ADDRESS (_address, OLD_SUBSCRIBERS, NEW_SUBSCRIBERS,
  15494. X                  removed_usersf);
  15495. X# ifdef bsd
  15496. X          sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15497. X# elif defined (svr4) || defined (svr3)
  15498. X          sighold (SIGINT);
  15499. X          sighold (SIGTERM);
  15500. X# endif
  15501. X          if (mv (NEW_SUBSCRIBERS, subscribersf))
  15502. X        exit (16);
  15503. X# ifdef bsd
  15504. X          sigsetmask (sig_mask);
  15505. X# elif defined (svr4) || defined (svr3)
  15506. X          sigrelse (SIGINT);
  15507. X          sigrelse (SIGTERM);
  15508. X# endif
  15509. X          OPEN_FILE (subscribers, subscribersf, "r", "process_message");
  15510. X          if (cp (aliasesf, OLD_ALIASES))
  15511. X        exit (16);
  15512. X          REMOVE_ADDRESS (_address, OLD_ALIASES, NEW_ALIASES,
  15513. X                  removed_aliasesf);
  15514. X# ifdef bsd
  15515. X          sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15516. X# elif defined (svr4) || defined (svr3)
  15517. X          sighold (SIGINT);
  15518. X          sighold (SIGTERM);
  15519. X# endif
  15520. X          if (mv (NEW_ALIASES, aliasesf))
  15521. X        exit (16);
  15522. X# ifdef bsd
  15523. X          sigsetmask (sig_mask);
  15524. X# elif defined (svr4) || defined (svr3)
  15525. X          sigrelse (SIGINT);
  15526. X          sigrelse (SIGTERM);
  15527. X# endif
  15528. X          if (cp (ALIASESF, OLD_ALIASES))
  15529. X        exit (16);
  15530. X          REMOVE_ADDRESS (_address, OLD_ALIASES, NEW_ALIASES, "/dev/null");
  15531. X# ifdef bsd
  15532. X          sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15533. X# elif defined (svr4) || defined (svr3)
  15534. X          sighold (SIGINT);
  15535. X          sighold (SIGTERM);
  15536. X# endif
  15537. X          if (mv (NEW_ALIASES, ALIASESF))
  15538. X        exit (16);
  15539. X# ifdef bsd
  15540. X          sigsetmask (sig_mask);
  15541. X# elif defined (svr4) || defined (svr3)
  15542. X          sigrelse (SIGINT);
  15543. X          sigrelse (SIGTERM);
  15544. X# endif
  15545. X          sprintf (_address, " %s[\t ]*$", address);
  15546. X          if (cp (aliasesf, OLD_ALIASES))
  15547. X        exit (16);
  15548. X          REMOVE_ADDRESS (_address, OLD_ALIASES, NEW_ALIASES, 
  15549. X                  removed_aliasesf);
  15550. X# ifdef bsd
  15551. X          sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15552. X# elif defined (svr4) || defined (svr3)
  15553. X          sighold (SIGINT);
  15554. X          sighold (SIGTERM);
  15555. X# endif
  15556. X          if (mv (NEW_ALIASES, aliasesf))
  15557. X        exit (16);
  15558. X# ifdef bsd
  15559. X          sigsetmask (sig_mask);
  15560. X# elif defined (svr4) || defined (svr3)
  15561. X          sigrelse (SIGINT);
  15562. X          sigrelse (SIGTERM);
  15563. X# endif
  15564. X          if (cp (ALIASESF, OLD_ALIASES))
  15565. X        exit (16);
  15566. X          REMOVE_ADDRESS (_address, OLD_ALIASES, NEW_ALIASES, "/dev/null");
  15567. X# ifdef bsd
  15568. X          sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15569. X# elif defined (svr4) || defined (svr3)
  15570. X          sighold (SIGINT);
  15571. X          sighold (SIGTERM);
  15572. X# endif
  15573. X          if (mv (NEW_ALIASES, ALIASESF))
  15574. X        exit (16);
  15575. X# ifdef bsd
  15576. X          sigsetmask (sig_mask);
  15577. X# elif defined (svr4) || defined (svr3)
  15578. X          sigrelse (SIGINT);
  15579. X          sigrelse (SIGTERM);
  15580. X# endif
  15581. X          unlink (OLD_SUBSCRIBERS);
  15582. X          unlink (OLD_ALIASES);
  15583. X          if (removed)
  15584. X        fprintf (forwardmail, "Automatic removal: user %s\n\
  15585. X  (possibly mentioned below) will be removed from the system files.\n", address);
  15586. X          else {
  15587. X        fprintf (forwardmail, "Automatic removal of user %s\n  failed.\n",
  15588. X             address_copy);
  15589. X        break;
  15590. X          }
  15591. X        }
  15592. X      }
  15593. X    } 
  15594. X
  15595. X    strcpy (matches, ".*\\1");
  15596. X    if (re_strcmp (warnings, line, matches) > 0) {
  15597. X      FILE *inerrors, *outerrors;
  15598. X      BOOLEAN found = FALSE;
  15599. X      char _line [1024], address [MAX_LINE], _address [MAX_LINE], *sp;
  15600. X      long int stime;
  15601. X
  15602. X      mv (errorsf, errors2f);
  15603. X      inerrors = fopen (errors2f, "r");
  15604. X      OPEN_FILE (outerrors, errorsf, "w", "process_message");
  15605. X      while (inerrors && !feof (inerrors)) {
  15606. X        RESET (_line);
  15607. X        fgets (_line, 1023, inerrors);
  15608. X        sscanf (_line, "%ld", &stime);
  15609. X        if ((sp = strchr (_line, ' ')))
  15610. X          ++sp;
  15611. X        else
  15612. X          sp = _line;
  15613. X        upcase (sp);
  15614. X        if (!strcmp (line, sp)) { /* Match */
  15615. X          found = TRUE;
  15616. X          if ((long int) time (0) < (long int) (stime + GRACE_PERIOD))
  15617. X        /* No action */
  15618. X        fputs (_line, outerrors);
  15619. X          else {    /* Look for matches in the subscribers file and */
  15620. X        char mode [MAX_LINE], address_copy [MAX_LINE], *p;
  15621. X
  15622. X        rewind (subscribers); /* change mail mode to POSTPONE */
  15623. X        while (!feof (subscribers)) {
  15624. X          mode [0] = address [0] = RESET (_line);
  15625. X          fgets (_line, MAX_LINE - 2, subscribers);
  15626. X          sscanf (_line, "%s %s", address, mode);
  15627. X          if (!strcmp (mode, POSTPONE))
  15628. X            continue;
  15629. X          upcase (_line);
  15630. X          upcase (address);
  15631. X          strcpy (address_copy, address);
  15632. X          escape_re (address);
  15633. X# if (ERROR_MAIL_ANALYSIS == 9)
  15634. X          if (strcmp (matches, ".*") && strcmp (matches, ".*\\1"))
  15635. X            sprintf (_address, "^[ \t]*%s", matches + 2);
  15636. X          else
  15637. X# endif
  15638. X            strcpy (_address, address),
  15639. X            strcpy (_line, line);
  15640. X          if (p = strchr (_address, '<'))
  15641. X            sprintf (p, "%s", p + 1); /* Remove '<' */
  15642. X          if (p = strchr (_address, '>'))
  15643. X            sprintf (p, "%s", p + 1);  /* Remove '>' */
  15644. X          if (address [0] != EOS && re_strcmp (_address, _line, NULL) >
  15645. X              0) {
  15646. X            /* User found; change mode */
  15647. X            char _address [MAX_LINE];
  15648. X            BOOLEAN suspended = FALSE;
  15649. X
  15650. X            fclose (subscribers);
  15651. X            sprintf (_address, "^[\t ]*%s ", address);
  15652. X            if (cp (subscribersf, OLD_SUBSCRIBERS))
  15653. X              exit (16);
  15654. X            SUSPEND_ADDRESS (_address, OLD_SUBSCRIBERS, NEW_SUBSCRIBERS);
  15655. X# ifdef bsd
  15656. X            sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  15657. X# elif defined (svr4) || defined (svr3)
  15658. X            sighold (SIGINT);
  15659. X            sighold (SIGTERM);
  15660. X# endif
  15661. X            if (mv (NEW_SUBSCRIBERS, subscribersf))
  15662. X              exit (16);
  15663. X# ifdef bsd
  15664. X            sigsetmask (sig_mask);
  15665. X# elif defined (svr4) || defined (svr3)
  15666. X            sigrelse (SIGINT);
  15667. X            sigrelse (SIGTERM);
  15668. X# endif
  15669. X            OPEN_FILE (subscribers, subscribersf, "r", "process_message");
  15670. X            if (suspended)
  15671. X              fprintf (forwardmail, "Subscription subspension: user \
  15672. X%s\n  (possibly mentioned below) will have his mail mode reset to POSTPONE.\n",
  15673. X                   address_copy);
  15674. X            else {
  15675. X              fprintf (forwardmail, "Attempt to suspend subscription \
  15676. Xof user %s\n  failed.\n", address_copy);
  15677. X              break;
  15678. X            }
  15679. X          }
  15680. X        }
  15681. X              }
  15682. X        }
  15683. X        else if ((long int) time (0) < (long int) (stime + ONE_MONTH))
  15684. X          /* discard if older > 1 mo */
  15685. X          fputs (_line, outerrors); /* No match; copy error line as is */
  15686. X      }
  15687. X      if (!found)    /* Save new error message */
  15688. X        fprintf (outerrors, "%ld %s", time (0), line),
  15689. X        fprintf (forwardmail, "Recorded new error message: %s", line);
  15690. X      fclose (outerrors);
  15691. X      if (inerrors)
  15692. X        fclose (inerrors);
  15693. X      unlink (errors2f);
  15694. X    }
  15695. X      }
  15696. X    }
  15697. X#endif
  15698. X
  15699. X    fprintf (forwardmail, "-----------------------------------------------\
  15700. X--------------------------------\n");
  15701. X    rewind (msg);
  15702. X    while (!feof (msg))  /* Copy actual message */
  15703. X      RESET (line),
  15704. X      fgets (line, MAX_LINE - 2, msg),
  15705. X      fprintf (forwardmail, "%s", line);
  15706. X    COMPLETE_TELNET (forwardmail);
  15707. X    fclose (forwardmail);
  15708. X    fclose (msg);
  15709. X    /* Form UNIX sendmail command */
  15710. X    if (sender_subscribed != PEER && sender_subscribed != NEWS)
  15711. X      if (sys.options & USE_SYSMAIL)
  15712. X    sysmail (mailforwardf);
  15713. X      else
  15714. X    syscom ("%s '%s' < %s", sys.mail.method,
  15715. X        (((sys.options & USE_TELNET) == 0) ?
  15716. X         ((mailer_daemon || susp_subject || errors_to_owner) ?
  15717. X          sys.lists[listid].owner : locase (sender)) : ""),
  15718. X        mailforwardf);
  15719. X    return;
  15720. X  }
  15721. X  if (is_moderated) /* USER CONTRIBUTED CODE: Warren Burstein */
  15722. X    if (owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  15723. X      /* 
  15724. X     Sender is owner, look for MESSAGE SEPARATOR, subject and sender,
  15725. X     and blank lines and set lines_to_skip (# of lines till 
  15726. X     MESSAGE_SEPARATOR + one for Subject: + one for Sender: + blank lines)
  15727. X      */
  15728. X      FILE *msg;
  15729. X      long int line_no = 0;
  15730. X
  15731. X      OPEN_FILE (msg, msgf, "r", "process_message");
  15732. X      while (!feof (msg)) {
  15733. X    RESET (line);
  15734. X    fgets (line, MAX_LINE - 2, msg);
  15735. X    if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  15736. X      line [strlen (line) - 1] = EOS;
  15737. X    line_no++;
  15738. X
  15739. X    if (!strcmp (line, MESSAGE_SEPARATOR)) {
  15740. X      lines_to_skip = line_no;
  15741. X      break;
  15742. X    }
  15743. X      }
  15744. X
  15745. X      if (lines_to_skip) {
  15746. X    /* Look for Subject: and Sender:, skip blank lines */
  15747. X    char match [MAX_LINE];
  15748. X    while (!feof (msg)) {
  15749. X      RESET (line);
  15750. X      fgets (line, MAX_LINE - 2, msg);
  15751. X      if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  15752. X        line [strlen (line) - 1] = EOS;
  15753. X
  15754. X      strcpy (match, "\\1");
  15755. X      if (re_strcmp (SUBJECT, line, match) > 0)
  15756. X        strcpy (senders_subject, line + strlen (match)),
  15757. X        strcpy (subject_copy, senders_subject),
  15758. X        lines_to_skip++;
  15759. X      else if (re_strcmp (SENDER, line, match) > 0)
  15760. X        strcpy (original_sender, line + strlen (match)),
  15761. X        lines_to_skip++;
  15762. X      else if (line[0] == EOS) {
  15763. X        lines_to_skip++;    /* [Tasos: ???] */
  15764. X        break;
  15765. X      }
  15766. X      else
  15767. X        break;
  15768. X        }
  15769. X        while (!feof (msg)) {
  15770. X      RESET (line);
  15771. X      fgets (line, MAX_LINE - 2, msg);
  15772. X      if (strcmp (line, "\n"))
  15773. X        break;
  15774. X      lines_to_skip++;
  15775. X        }
  15776. X      }
  15777. X
  15778. X      fclose (msg);
  15779. X    }
  15780. X    else { /* Sender isn't owner, send message to owner */
  15781. X      int i;
  15782. X
  15783. X      report_progress (report, tsprintf ("Public message #%04d. Forwarding to \
  15784. Xmoderator", ++public_msg), TRUE);
  15785. X      OPEN_FILE (msg_no, msg_nof, "w", "process_message");
  15786. X      fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
  15787. X      fclose (msg_no);
  15788. X
  15789. X      create_header (&forwardmail, mailforwardf, original_sender,
  15790. X             originator, sys.lists[listid].owner, senders_subject,
  15791. X             FALSE, TRUE, FALSE);
  15792. X
  15793. X      sprintf (line, "This message was submitted by %s to list %s.",
  15794. X           original_sender, sys.lists[listid].address);
  15795. X      fill_text (forwardmail, line);
  15796. X      for (i = 0; msgs[i]; i++)
  15797. X    fill_text (forwardmail, msgs[i]);
  15798. X      fprintf (forwardmail, "%s\n", MESSAGE_SEPARATOR);
  15799. X
  15800. X      /* Send these two under the line for extraction when the moderator
  15801. X     forwards the message back */
  15802. X      fprintf (forwardmail, "Sender: %s\nSubject: %s\n\n",
  15803. X           original_sender, senders_subject);
  15804. X      if (copy_msg (forwardmail, msgf, FALSE, original_sender, 0, TRUE))
  15805. X        sendmail (sys.lists[listid].owner, FALSE, FALSE, 0, 0, mailforwardf);
  15806. X      already_sent = message_forwarded = TRUE;
  15807. X    }
  15808. X  fclose (msg);
  15809. X  
  15810. X  if (!already_sent) {
  15811. X    report_progress (report,
  15812. X             tsprintf ("Public message #%04d%s. Distributing to all \
  15813. Xsubscribers%s.\n%s",
  15814. X                   ++public_msg,
  15815. X                   (sender_subscribed == NEWS ? " (news)" : 
  15816. X                (sender_subscribed == PEER ? " (peer)" : "")), 
  15817. X                   (sender_subscribed == SUBSCRIBED ? 
  15818. X                ", news groups and peers" : 
  15819. X                (sender_subscribed == NEWS ? ", peers" : 
  15820. X                 ", news groups")),
  15821. X                   sender), TRUE);
  15822. X    if (fake_mail && at)
  15823. X      report_progress (report,
  15824. X               tsprintf ("*** Possible fake mail: Host %s in user \
  15825. Xaddress does\nnot match any of the domains in the Received: header lines.\n",
  15826. X                 at + 1), FALSE);
  15827. X    OPEN_FILE (msg_no, msg_nof, "w", "process_message");
  15828. X    fprintf (msg_no, "%d %d\n", public_msg, returned_msg);
  15829. X    fclose (msg_no);
  15830. X    distributions (sender_subscribed, headerf, msgf, FALSE, sender,
  15831. X           original_sender, senders_subject, subject_copy, originator,
  15832. X           lines_to_skip, is_moderated);
  15833. X
  15834. X    if (append_to_digest && !message_rejected) {
  15835. X      long int line_no = 0, digest_toc_lines, digest_lines, total;
  15836. X      FILE *fp, *msg;
  15837. X
  15838. X      OPEN_FILE (fp, digest_tocf, "a", "process_message");
  15839. X      fprintf (fp, "%s (%s)\n", senders_subject, original_sender);
  15840. X      fclose (fp);
  15841. X
  15842. X      OPEN_FILE (fp, digest_msgf, "a", "process_message");
  15843. X      if (sent_date[0] != EOS)
  15844. X    fprintf (fp, "\nDate: %s", sent_date);
  15845. X      fprintf (fp, "\nFrom: %s\nSubject: %s\n\n", original_sender,
  15846. X           senders_subject);
  15847. X
  15848. X      OPEN_FILE (msg, msgf, "r", "process_message");
  15849. X      while (!feof (msg)) { /* Copy actual message */
  15850. X    RESET (line);
  15851. X    fgets (line, MAX_LINE - 2, msg);
  15852. X    line_no++;
  15853. X
  15854. X    if (line_no > lines_to_skip)
  15855. X      fprintf (fp, "%s", line);
  15856. X      }
  15857. X      fclose(msg);
  15858. X
  15859. X      fprintf (fp, "\n------------------------------\n");
  15860. X      fclose(fp);
  15861. X
  15862. X      digest_toc_lines = count_lines_in_file (fp = fopen (digest_tocf, "r"));
  15863. X      if (fp) fclose(fp);
  15864. X      digest_lines = count_lines_in_file (fp = fopen (digest_msgf, "r"));
  15865. X      if (fp) fclose(fp);
  15866. X
  15867. X      report_progress (report, tsprintf ("Adding to digest, which now has \
  15868. X%d token + %d message = %d lines",
  15869. X               digest_toc_lines, digest_lines,
  15870. X               (total = digest_toc_lines + digest_lines)), TRUE);
  15871. X
  15872. X      if (total >= sys.lists[listid].digest_lines) { /* Max lines exceeded */
  15873. X    BOOLEAN fd = force_digest;
  15874. X
  15875. X    force_digest = TRUE;
  15876. X        digest_make (TRUE);
  15877. X        digest_distribute ();
  15878. X    force_digest = fd;
  15879. X      }
  15880. X    }
  15881. X  }
  15882. X
  15883. X  update_unprocessed_messages (unprocessed_messages);
  15884. X  unlink (unprocessed_tmp);
  15885. X
  15886. X  if (!message_rejected && !message_forwarded) { /* New message is archived */
  15887. X    cat_append (headerf, archivef);
  15888. X    OPEN_FILE (in, msgf, "r", "process_message");
  15889. X    OPEN_FILE (out, archivef, "a", "process_message");
  15890. X    if (is_moderated) { /* Skip message lines before appending */
  15891. X      long int offset = ftell (in); /* Store current position */
  15892. X      while (!feof (in)) {
  15893. X    RESET (line);
  15894. X    fgets (line, MAX_LINE - 2, in);
  15895. X    if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  15896. X      line [strlen (line) - 1] = EOS;
  15897. X    if (!strcmp (line, MESSAGE_SEPARATOR))
  15898. X      break;
  15899. X      }
  15900. X      if (feof (in))    /* No message separator, so archive the whole msg */
  15901. X    (void) fseek (in, offset, SEEK_SET);
  15902. X    }
  15903. X    while (!feof (in))
  15904. X      RESET (line),
  15905. X      fgets (line, MAX_LINE - 2, in),
  15906. X      fputs (line, out);
  15907. X    fclose (in);
  15908. X    fclose (out);
  15909. X    unlink (headerf);
  15910. X    if (is_moderated) /* Save the original author's address */
  15911. X      extract_address (original_sender),
  15912. X      upcase (original_sender),
  15913. X      fprintf (headers, "%s\n", original_sender);
  15914. X    else
  15915. X      fprintf (headers, "%s\n", sender);
  15916. X    fflush (headers);
  15917. X  }
  15918. X
  15919. X  if (message_id[0] != EOS && !message_rejected && !message_forwarded) {
  15920. X    if ((message_ids = fopen (message_idsf, "a")) == NULL)
  15921. X      report_progress (report,
  15922. X               tsprintf ("\nprocess_message(): Could not open %s",
  15923. X                 message_idsf), TRUE),
  15924. X      gexit (1);
  15925. X    fprintf (message_ids, "%s %s\n", message_id, sender); /* Save new id */
  15926. X    fclose (message_ids);
  15927. X  }
  15928. X}
  15929. X
  15930. X/*
  15931. X  Check to see if there are subscribers/newsgroups/peers that did not
  15932. X  receive any mail because of a previous interrupted distribution.
  15933. X*/
  15934. X
  15935. XBOOLEAN unprocessed_users (char *unprocessed, char *s, FILE *report)
  15936. X{
  15937. X  struct stat stat_buf;
  15938. X
  15939. X  if (!stat (unprocessed, &stat_buf)) { /* There is undelivered mail */
  15940. X    if (stat_buf.st_size > 0)
  15941. X      report_progress (report,
  15942. X               tsprintf ("Resuming delivery of interrupted mail to %s",
  15943. X                 s), TRUE);
  15944. X    return TRUE;
  15945. X  }
  15946. X  return FALSE;
  15947. X}
  15948. X
  15949. X/*
  15950. X  Distribute a message, either to regular subscribers, or to DIGEST
  15951. X  subscribers if is_digest is TRUE.
  15952. X  Write an archive file if is_digest == sys.lists[listid].options & ARCHIVE_DIGEST
  15953. X*/
  15954. X
  15955. Xvoid distributions (BOOLEAN subscribed, char *header_file,
  15956. X            char *message_file, BOOLEAN is_digest,
  15957. X            char *sender, char *original_sender, char *senders_subject,
  15958. X            char *subject_copy, char *originator,
  15959. X            long int lines_to_skip, BOOLEAN is_moderated)
  15960. X{
  15961. X  BOOLEAN sremnants, nremnants, premnants;
  15962. X
  15963. X  if (!(sremnants = unprocessed_users (unprocessed_subscribersf,
  15964. X                       "subscribers", report)))
  15965. X    echo ("0", unprocessed_subscribersf);
  15966. X  if (!(nremnants = unprocessed_users (unprocessed_newsf, "news", report)))
  15967. X    echo ("0", unprocessed_newsf);
  15968. X  if (!(premnants = unprocessed_users (unprocessed_peersf, "peers", report)))
  15969. X    echo ("0", unprocessed_peersf);
  15970. X
  15971. X  do_distribute (message_file, subscribers, subscribersf, sremnants,
  15972. X         unprocessed_subscribersf, send_to_subscribers, sender,
  15973. X         original_sender, senders_subject, subject_copy, originator,
  15974. X         report, FALSE, multi_recip, lines_to_skip, is_digest, TRUE,
  15975. X         subscribed);
  15976. X  unlink (unprocessed_subscribersf);
  15977. X
  15978. X  if ((subscribed == SUBSCRIBED || subscribed == PEER) && !is_digest)
  15979. X    /* Send to news also */
  15980. X    do_distribute (message_file, news, newsf, nremnants, unprocessed_newsf,
  15981. X           TRUE, sender, original_sender, senders_subject,
  15982. X           subject_copy, originator, report, TRUE, FALSE,
  15983. X           lines_to_skip, is_digest, FALSE, subscribed);
  15984. X  unlink (unprocessed_newsf);
  15985. X
  15986. X  if ((subscribed == SUBSCRIBED || subscribed == NEWS) && !is_digest)
  15987. X    /* Send to peers also */
  15988. X    do_distribute (message_file, peers, peersf, premnants,
  15989. X           unprocessed_peersf, TRUE, sender, original_sender, 
  15990. X           senders_subject, subject_copy, originator, 
  15991. X           report, FALSE, FALSE, lines_to_skip, is_digest, FALSE,
  15992. X           subscribed);
  15993. X  unlink (unprocessed_peersf);
  15994. X
  15995. X  if (((sys.lists[listid].options & ARCHIVE_LIST) &&
  15996. X       !(sys.lists[listid].options & ARCHIVE_DIGEST) && !is_digest) ||
  15997. X      (is_digest & sys.lists[listid].options & ARCHIVE_DIGEST))
  15998. X    do_archive (header_file, message_file, subject_copy, is_moderated);
  15999. X}
  16000. X
  16001. X/*
  16002. X  Do the distribution of the message to the specified list of subscribers.
  16003. X  The BOOLEAN argument 'posting' should be TRUE when posting AND gating to
  16004. X  news, and FALSE otherwise.
  16005. X
  16006. X  Undelivered mail has higher priority.
  16007. X*/
  16008. X
  16009. Xvoid do_distribute (char *message_file,
  16010. X            FILE *recipient_list, char *file, BOOLEAN mail_remnants,
  16011. X            char *unprocessed, BOOLEAN send_to_subscribers, 
  16012. X            char *sender, char *original_sender, char *senders_subject,
  16013. X            char *subject_copy, char *originator, FILE *report,
  16014. X            BOOLEAN posting, BOOLEAN multi_recip,
  16015. X            long int lines_to_skip, BOOLEAN is_digest,
  16016. X            BOOLEAN is_subscribers, BOOLEAN subscribed)
  16017. X{
  16018. X  char name [MAX_LINE];            /* holds each subscribers name */
  16019. X  char mailmode [MAX_LINE];        /* send message back to sender or not */
  16020. X  char subscriber [MAX_LINE];      /* holds each subscriber's address */
  16021. X  char recipient_file [MAX_LINE];  /* file of subscribers to use when -r */
  16022. X  char restricted_subscriber [MAX_LINE]; /* name of subscriber in RESTRICTED */
  16023. X  char line [MAX_LINE];
  16024. X  FILE *forwardmail, *f;
  16025. X  BOOLEAN alternate_file = FALSE;
  16026. X  int  nrecipients = 0, offset = -1;
  16027. X
  16028. X  /* Check if there is previously undelivered mail */
  16029. X  if (mail_remnants) { /* There is undelivered mail; move to offset */
  16030. X    OPEN_FILE (f, unprocessed, "r", "do_distribute");
  16031. X    fscanf (f, "%d", &offset);
  16032. X    fclose (f);
  16033. X    if (offset < 0) /* Empty unprocessed file, go to eof */
  16034. X      while (!feof (recipient_list))
  16035. X    fgets (line, MAX_LINE - 2, recipient_list);
  16036. X    else /* Skip 'offset' subscribers, check for DIGEST subscribers */
  16037. X      while (!feof (recipient_list) && offset) {
  16038. X    if (!is_digest &&
  16039. X        read_recipient (recipient_list, subscriber, mailmode, name,
  16040. X                is_subscribers) && !strcmp (mailmode, DIGEST))
  16041. X      append_to_digest = TRUE;
  16042. X    --offset;
  16043. X      }
  16044. X  }
  16045. X  else {
  16046. X    if (!send_to_subscribers) {  /* -r: Check if restricted mail has arrived */
  16047. X      rewind (restricted);
  16048. X      while (!feof (restricted)) {
  16049. X        alternate_file = TRUE;
  16050. X        restricted_subscriber[0] = RESET (recipient_file);
  16051. X        fscanf (restricted, "%s %s", restricted_subscriber, recipient_file);
  16052. X        upcase (restricted_subscriber);
  16053. X        if (!strcmp (restricted_subscriber, sender)) {
  16054. X        if (!strcmp (recipient_file, NO_RECIPIENT_FILE)) {
  16055. X        /* Do not forward to anyone */
  16056. X        report_progress (report, "No alternate recipient file specified. \
  16057. XMessage ignored.\n", FALSE);
  16058. X        return;
  16059. X      }
  16060. X      /* Restricted mail; forward message only to the people listed
  16061. X         in recipient_file */
  16062. X      OPEN_FILE (recipient_list, recipient_file, "r", "do_distribute");
  16063. X      report_progress (report, tsprintf ("Restricted mail. Distributing \
  16064. Xonly to individuals listed in %s", recipient_file), TRUE);
  16065. X      break;
  16066. X        }
  16067. X      }
  16068. X    }
  16069. X  }
  16070. X  if (!mail_remnants)
  16071. X    rewind (recipient_list);
  16072. X  while (!feof (recipient_list)) { /* Send to all of them */
  16073. X
  16074. X    if (!read_recipient (recipient_list, subscriber, mailmode, name,
  16075. X             is_subscribers))
  16076. X      continue;
  16077. X
  16078. X    if (is_digest) {
  16079. X      if (strcmp (mailmode, DIGEST))
  16080. X    continue;
  16081. X    }
  16082. X    else if (!strcmp (mailmode, DIGEST)) {
  16083. X      append_to_digest = TRUE;
  16084. X      continue;
  16085. X    }
  16086. X    else if (!strcmp (mailmode, NOACK)) {
  16087. X      upcase (subscriber);
  16088. X      if (!strcmp (subscriber, sender) || !strcmp (subscriber, originator))
  16089. X    continue;
  16090. X    }
  16091. X    else if (!strcmp (mailmode, POSTPONE))  /* No email to this subscriber */
  16092. X      continue;
  16093. X    else if (mailmode[0] != EOS && strcmp (mailmode, ACK)) {
  16094. X      syscom ("echo Unrecognized mail mode %s for recipient %s in %s | \
  16095. Xrmail %s %s",
  16096. X          mailmode, subscriber, file, sys.manager, sys.lists[listid].owner);
  16097. X      report_progress (report, tsprintf ("\ndo_distribute(): Unrecognized mail \
  16098. Xmode %s in %s", mailmode, file), TRUE);
  16099. X      continue;
  16100. X    }
  16101. X    RESET (senders_subject);
  16102. X    strcpy (senders_subject, subject_copy);
  16103. X    if (multi_recip) {
  16104. X      if ((multi_recipients[nrecipients] =
  16105. X       (char *) malloc ((strlen (subscriber) + 1) * sizeof (char)))
  16106. X      == NULL)
  16107. X        report_progress (report, "\ndo_distribute(): malloc() failed", TRUE),
  16108. X    gexit (11);
  16109. X      strcpy (multi_recipients[nrecipients++], locase (subscriber));
  16110. X    }
  16111. X    /* Prepare header */
  16112. X    if (posting) {
  16113. X      if (sys.options & POST_MAIL) /* Post to news group */
  16114. X    create_news_header (&forwardmail, mailforwardf, original_sender,
  16115. X                originator, name, senders_subject);
  16116. X      else if (sys.options & GATE_MAIL) /* Gate to news gateway */
  16117. X    create_gate_header (&forwardmail, mailforwardf, original_sender,
  16118. X                originator, subscriber, name, senders_subject),
  16119. X    posting = FALSE;
  16120. X      if (!copy_msg (forwardmail, message_file, posting, original_sender,
  16121. X             lines_to_skip, subscribed))
  16122. X    return;
  16123. X    }
  16124. X    else { /* Regular mail */
  16125. X      if (multi_recip) { /* Multi recipient header */
  16126. X    if (nrecipients == maxrecipients) {
  16127. X      create_multi_recipient_header (&forwardmail, mailforwardf,
  16128. X                     original_sender, originator,
  16129. X                     tsprintf ("Multiple recipients of \
  16130. Xlist <%s>", sys.lists[listid].address),
  16131. X                     senders_subject, nrecipients);
  16132. X      if (!copy_msg (forwardmail, message_file, posting, original_sender,
  16133. X             lines_to_skip, subscribed))
  16134. X        return;
  16135. X    }
  16136. X      }
  16137. X      else { /* Single recipient header */
  16138. X    create_header (&forwardmail, mailforwardf, original_sender, originator,
  16139. X               subscriber, senders_subject, FALSE, FALSE, FALSE);
  16140. X    if (!copy_msg (forwardmail, message_file, posting, original_sender,
  16141. X               lines_to_skip, subscribed))
  16142. X      return;
  16143. X      }
  16144. X    }
  16145. X    sendmail (subscriber, posting, multi_recip, nrecipients, maxrecipients,
  16146. X          mailforwardf);
  16147. X    update_unprocessed (unprocessed, posting, multi_recip, nrecipients);
  16148. X    if (nrecipients == maxrecipients)
  16149. X      nrecipients = 0;
  16150. X  }
  16151. X  if (alternate_file)  /* Close alternate recipient file */
  16152. X    fclose (recipient_list);
  16153. X
  16154. X  if (multi_recip && (nrecipients != 0)) { /* Left overs */
  16155. X    create_multi_recipient_header (&forwardmail, mailforwardf,
  16156. X                   original_sender, originator,
  16157. X                   tsprintf ("Multiple recipients of list <%s>",
  16158. X                         sys.lists[listid].address),
  16159. X                   senders_subject, nrecipients);
  16160. X    if (copy_msg (forwardmail, message_file, posting, original_sender,
  16161. X          lines_to_skip, subscribed))
  16162. X      sendmail (subscriber, posting, multi_recip, nrecipients, nrecipients, 
  16163. X            mailforwardf),
  16164. X      update_unprocessed (unprocessed, posting, multi_recip, nrecipients);
  16165. X  }
  16166. X}
  16167. X
  16168. X/*
  16169. X  Increment count of number of recipients that have received the current
  16170. X  message.
  16171. X*/
  16172. X
  16173. Xvoid update_unprocessed (char *unprocessed, BOOLEAN posting,
  16174. X             BOOLEAN multi_recip, int nrecipients)
  16175. X{
  16176. X  int nproc = 1, offset;
  16177. X  FILE *f;
  16178. X  struct stat stat_buf;
  16179. X
  16180. X  if (stat (unprocessed, &stat_buf) || stat_buf.st_size <= 0)
  16181. X    return;
  16182. X  if (multi_recip && !posting)
  16183. X    nproc = nrecipients;
  16184. X  OPEN_FILE (f, unprocessed, "r", "update_unprocessed");
  16185. X  fscanf (f, "%d", &offset);
  16186. X  fclose (f);
  16187. X  OPEN_FILE (f, unprocessed, "w", "update_unprocessed");
  16188. X  fprintf (f, "%d\n", offset + nproc);
  16189. X  fclose (f);
  16190. X}
  16191. X
  16192. X/*
  16193. X  Remove the message that was just delivered to everybody from the
  16194. X  unprocessed file.
  16195. X*/
  16196. X
  16197. Xvoid update_unprocessed_messages (char *unprocessed)
  16198. X{
  16199. X  FILE *in, *out;
  16200. X  char line [MAX_LINE];
  16201. X
  16202. X  OPEN_FILE (in, unprocessed, "r", "update_unprocessed_messages");
  16203. X  OPEN_FILE (out, unprocessed_tmp, "w", "update_unprocessed_messages");
  16204. X  if (!feof (in))
  16205. X    fgets (line, MAX_LINE - 2, in); /* Skip first "From " */
  16206. X  RESET (line);
  16207. X  while (!feof (in) &&
  16208. X         (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE))))
  16209. X    fgets (line, MAX_LINE - 2, in);
  16210. X  while (!feof (in)) /* Copy rest of messages */
  16211. X    fputs (line, out),
  16212. X    RESET (line),
  16213. X    fgets (line, MAX_LINE - 2, in);
  16214. X  fclose (in);
  16215. X  fclose (out);
  16216. X  mv (unprocessed_tmp, unprocessed);
  16217. X}
  16218. X
  16219. X/*
  16220. X  Copy the original message from message_file to the outgoing message.
  16221. X  Skip first "skip" lines. Reject it if it messages have a certain
  16222. X  limit, and that limit is exceeded (only when not distributing a digest).
  16223. X*/
  16224. X
  16225. XBOOLEAN copy_msg (FILE *forwardmail, char *message_file, BOOLEAN posting,
  16226. X          char *sender, long int lines_to_skip, BOOLEAN subscribed)
  16227. X{
  16228. X  FILE *msg;
  16229. X  char line [MAX_LINE];
  16230. X  long int count = 0, line_no = 0;
  16231. X
  16232. X  OPEN_FILE (msg, message_file, "r", "copy_msg");
  16233. X  while (!feof (msg)) { /* Copy actual message */
  16234. X    RESET (line);
  16235. X    fgets (line, MAX_LINE - 2, msg);
  16236. X    line_no++;
  16237. X
  16238. X    if (line_no > lines_to_skip)
  16239. X      fprintf (forwardmail, "%s", line);
  16240. X
  16241. X    count += strlen (line);
  16242. X    message_rejected = FALSE;
  16243. X    if ((sys.options & LIMIT_MSG) && (count > sys.limits.msg) &&
  16244. X    subscribed != FALSE && subscribed != PEER && subscribed != NEWS) {
  16245. X      fclose (forwardmail);
  16246. X      rewind (msg);
  16247. X      create_header (&forwardmail, mailforwardf, sys.lists[listid].address, 
  16248. X             sys.lists[listid].address, sender, "Posting rejected",
  16249. X             COPY_OWNER (ccerrors), FALSE, TRUE);
  16250. X      fprintf (forwardmail, "Your posting to list %s was rejected.\n\
  16251. XReason: message size limit exceeded (maximum allowed: %ld bytes)\n\
  16252. XThe first few lines of your message are included herein for reference:\n\n",
  16253. X           sys.lists[listid].alias, sys.limits.msg);
  16254. X      report_progress (report, "Message rejected: maximum size exceeded",
  16255. X               TRUE);
  16256. X      message_rejected = TRUE;
  16257. X      count = 0;
  16258. X      while (!feof (msg) && count < 10)
  16259. X    RESET (line),
  16260. X    fgets (line, MAX_LINE - 2, msg),
  16261. X    fprintf (forwardmail, "%s", line),
  16262. X    ++count;
  16263. X      COMPLETE_TELNET (forwardmail);
  16264. X      fclose (forwardmail);
  16265. X      fclose (msg);
  16266. X      sendmail (sender, FALSE, FALSE, 0, 0, mailforwardf);
  16267. X      return FALSE;
  16268. X    }
  16269. X  }
  16270. X  if (!posting && (sys.options & USE_TELNET))
  16271. X    COMPLETE_FILE (forwardmail);
  16272. X  fclose (forwardmail);
  16273. X  fclose (msg);
  16274. X  return TRUE;
  16275. X}
  16276. X
  16277. X/*
  16278. X  Send email (to subscribers/news/gateways/peers). It may send one single
  16279. X  copy to one recipient, or one copy to multiple recipients.
  16280. X*/
  16281. X
  16282. Xvoid sendmail (char *subscriber, BOOLEAN posting, BOOLEAN multi_recip,
  16283. X           int nrecipients, int maxrecipients, char *mailforwardf)
  16284. X{
  16285. X  char *buf;
  16286. X  int size, i;
  16287. X
  16288. X  /* Form UNIX sendmail command */
  16289. X  if (posting && (sys.options & POST_MAIL)) { /* Post to news */
  16290. X    if (syscom ("%s -h < %s > %s 2> %s", INEWS, mailforwardf, INEWS_REPLY,
  16291. X        INEWS_REPLY)) {
  16292. X      FILE *f = fopen (mailforwardf, "r");
  16293. X      char line [MAX_LINE], match [MAX_LINE];
  16294. X      while (f && !feof (f)) {
  16295. X    RESET (line);
  16296. X    fgets (line, MAX_LINE - 2, f);
  16297. X    strcpy (match, "\\1");
  16298. X    if (re_strcmp (FROM, line, match) > 0) {
  16299. X      sprintf (line, "%s", line + strlen (match)); /* Save From: */
  16300. X      line [strlen (line) - 1] = EOS; /* \n -> \0 */
  16301. X      extract_address (line);
  16302. X      break;
  16303. X    }
  16304. X      }
  16305. X      if (f)
  16306. X    fclose (f);
  16307. X      syscom ("%s -s \"Posting to `grep '^Newsgroups:' %s | \
  16308. Xawk '{ print $2 }'` failed: \" %s %s < %s",
  16309. X          UCB_MAIL, mailforwardf, line, sys.lists[listid].owner,
  16310. X          INEWS_REPLY);
  16311. X      unlink (INEWS_REPLY);
  16312. X    }
  16313. X  }
  16314. X  else { /* Send email */
  16315. X    if (multi_recip) { 
  16316. X      if (nrecipients == maxrecipients) {
  16317. X    if ((sys.options & USE_TELNET) == 0) { /* Line up recipients */
  16318. X      size = strlen (multi_recipients[0]) + 1;
  16319. X      if ((buf = (char *) malloc (size * sizeof (char))) == NULL)
  16320. X        report_progress (report, "\nsendmail(): malloc() failed", TRUE),
  16321. X        gexit (11);
  16322. X      strcpy (buf, multi_recipients[0]);
  16323. X      for (i = 1; i < nrecipients; i++)
  16324. X        size += strlen (multi_recipients[i]) + 2,
  16325. X        buf = (char *) realloc (buf, size * sizeof (char)),
  16326. X        sprintf (buf + strlen (buf), " %s", multi_recipients[i]);
  16327. X      if ((int) strlen (buf) > 10000)
  16328. X        report_progress (report, "Too many multiple recipients", TRUE),
  16329. X        gexit (9);
  16330. X      syscom ("%s '%s' < %s", sys.mail.method, buf, mailforwardf);
  16331. X      free ((char *) buf);
  16332. X    }
  16333. X    else if (sys.options & USE_SYSMAIL)
  16334. X      sysmail (mailforwardf);
  16335. X    else /* telnet */
  16336. X      syscom ("%s < %s", sys.mail.method, mailforwardf);
  16337. X      }
  16338. X    }
  16339. X    else  /* Single recipient */
  16340. X      if (sys.options & USE_SYSMAIL)
  16341. X    sysmail (mailforwardf);
  16342. X      else
  16343. X    extract_address (locase (subscriber)),
  16344. X        syscom ("%s '%s' < %s", sys.mail.method,
  16345. X                (((sys.options & USE_TELNET) == 0) ? subscriber : ""),
  16346. X                mailforwardf);
  16347. X  }
  16348. X}
  16349. X
  16350. Xvoid usage ()
  16351. X{
  16352. X  fprintf (stderr, "Usage: list <-L LIST_ALIAS> [-r] [-m #] [-1] [-f] [-e] \
  16353. X[-s] [-p] [-P] [-v] [-M] [-d] [-i address] [-D]\n\
  16354. X-L: Process LIST_ALIAS (LIST_ALIAS has to be all in capital letters).\n\
  16355. X-r: Restricted mail.\n\
  16356. X-m: Specify number of multiple recipients in one outgoing message.\n\
  16357. X-1: Execute only once.\n\
  16358. X-f: Forward rejected messages to the list's owner.\n\
  16359. X-e: Echo reports to the screen.\n\
  16360. X-s: Do not check for subscriptions.\n\
  16361. X-p: Replies to posted (to news) messages will go to the author.\n\
  16362. X-P: Replies to distributed messages will go to the author.\n\
  16363. X-v: Version number.\n\
  16364. X-M: Moderated list.\n\
  16365. X-d: Distribute digest.\n\
  16366. X-i: Send partial digest to 'address'.\n\
  16367. X-D: Turn debug on.\n");
  16368. X  exit (3);
  16369. X}
  16370. X
  16371. Xvoid list_config (char *alias)
  16372. X{
  16373. X  if (!alias)
  16374. X    return;
  16375. X  setup_string (subscribersf, alias, SUBSCRIBERS);
  16376. X  setup_string (headersf, alias, HEADERS);
  16377. X  setup_string (restrictedf, alias, RESTRICTED);
  16378. X  setup_string (newsf, alias, NEWSF);
  16379. X  setup_string (peersf, alias, PEERS);
  16380. X  setup_string (aliasesf, alias, ALIASES);
  16381. X  setup_string (ignoredf, alias, IGNORED);
  16382. X  setup_string (list_mail_f, alias, LIST_MAIL_FILE);
  16383. X  setup_string (list_moderated_f, alias, LIST_MODERATED_F);
  16384. X  setup_string (mboxf, alias, MBOX);
  16385. X  setup_string (msg_nof, alias, MSG_NO);
  16386. X  setup_string (mailforwardf, alias, MAILFORWARD);
  16387. X  setup_string (msgf, alias, MSG);
  16388. X  setup_string (archivef, alias, ARCHIVE);
  16389. X  setup_string (digest_nof, alias, DIGEST_NO);
  16390. X  setup_string (digest_tocf, alias, DIGEST_TOC);
  16391. X  setup_string (digest_msgf, alias, DIGEST_MSG);
  16392. X  setup_string (digest_timef, alias, DIGEST_TIME);
  16393. X  setup_string (headerf, alias, HEADER);
  16394. X  setup_string (mail_copyf, alias, MAIL_COPY);
  16395. X  setup_string (report_listf, alias, REPORT_LIST);
  16396. X  setup_string (message_idsf, alias, MESSAGE_IDS_F);
  16397. X  setup_string (unprocessed_digestf, alias, UNPROC_DIGEST);
  16398. X  setup_string (unprocessed_subscribersf, alias, UNPROC_SUBSCRIBERS);
  16399. X  setup_string (unprocessed_peersf, alias, UNPROC_PEERS);
  16400. X  setup_string (unprocessed_newsf, alias, UNPROC_NEWS);
  16401. X  setup_string (unprocessed_messages, alias, UNPROC_MESSAGES);
  16402. X  setup_string (unprocessed_tmp, alias, UNPROC_TMP);
  16403. X  setup_string (removed_usersf, alias, REMOVED_USERS);
  16404. X  setup_string (removed_aliasesf, alias, REMOVED_ALIASES);
  16405. X  setup_string (limitsf, alias, LIST_LIMITS);
  16406. X  setup_string (errorsf, alias, ERRORSF);
  16407. X  setup_string (errors2f, alias, ERRORS2F);
  16408. X}
  16409. X
  16410. Xvoid version ()
  16411. X{
  16412. X  fprintf (stderr, "%s\n", VERSION);
  16413. X  exit (0);
  16414. X}
  16415. X
  16416. X/*
  16417. X  Graceful exit. Remove pid file.
  16418. X*/
  16419. X
  16420. Xint gexit (int exitcode)
  16421. X{
  16422. X  unlink (PID_LIST);
  16423. X#ifndef NO_LOCKS
  16424. X  unlock_file (lfd);
  16425. X#endif
  16426. X  exit (exitcode);
  16427. X}
  16428. X
  16429. X/*
  16430. X  Write the text to fp, filling to 80 characters. Writing a null string
  16431. X  flushes the paragraph.
  16432. X
  16433. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16434. X*/
  16435. X
  16436. X#define LEN 79            /* to avoid wrapping on some terminals */
  16437. X
  16438. Xvoid fill_text (FILE *fp, char *s)
  16439. X{
  16440. X  static char buf [LEN + 1];
  16441. X  static int pos = 0;
  16442. X  char word [LEN + 1], *p;
  16443. X
  16444. X  if (*s == EOS) { /* Flush buffer */
  16445. X    if (pos)
  16446. X      fprintf (fp, "%s\n", buf),
  16447. X      pos = 0;
  16448. X    fprintf (fp, "\n");
  16449. X  }
  16450. X  else
  16451. X    while (*s) { /* Get a word */
  16452. X      for (p = word; (*s != EOS) && !isspace (*s); s++, p++)
  16453. X    *p = *s;
  16454. X      *p = EOS;
  16455. X
  16456. X      /* Flush line if it won't fit */
  16457. X      if ((pos + strlen (word) + (pos != 0)) > LEN)
  16458. X    fprintf (fp, "%s\n", buf),
  16459. X    pos = 0;
  16460. X
  16461. X      /* Add word to line, precede with space if not first word */
  16462. X      if (pos)
  16463. X    buf[pos++] = ' ';
  16464. X      strcpy (&buf[pos], word);
  16465. X      pos += (int) strlen (word);
  16466. X      buf[pos] = EOS;
  16467. X
  16468. X      /* Skip trailing spaces */
  16469. X      while (isspace(*s))
  16470. X    s++;
  16471. X    }
  16472. X}
  16473. X
  16474. X/*
  16475. X  Read a line from the recipients file, fill subscriber, mailmode and name.
  16476. X  Return TRUE if it's OK, FALSE if no subscriber found.
  16477. X*/
  16478. X
  16479. XBOOLEAN read_recipient (FILE *fp, char *subscriber, char *mailmode, char *name,
  16480. X            BOOLEAN is_subscribers)
  16481. X{
  16482. X  char othermode [MAX_LINE];
  16483. X  int i;
  16484. X  FILE *f;
  16485. X
  16486. X  othermode[0] = mailmode[0] = name[0] = RESET (subscriber);
  16487. X  if (!extract_subscriber (fp, subscriber, FALSE)) {
  16488. X    fgets (othermode, MAX_LINE - 2, fp); /* Skip to eoln */
  16489. X    NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS(subscriber, "read_recipient", FALSE);
  16490. X    return FALSE;
  16491. X  }
  16492. X  if (subscriber[0] == EOS)
  16493. X    return FALSE;
  16494. X  fscanf (fp, "%s ", mailmode);
  16495. X
  16496. X  if (is_subscribers)
  16497. X    for (i = 1; i < (MAX_SET_OPTIONS - 1); i++) /* Skip unused options */
  16498. X      fscanf (fp, "%s ", othermode);
  16499. X  fgets (name, MAX_LINE - 2, fp);
  16500. X  if (name [0] != EOS && name [strlen (name) - 1] == '\n')
  16501. X    name [strlen (name) - 1] = EOS;
  16502. X  upcase (mailmode);
  16503. X
  16504. X  return TRUE;
  16505. X}
  16506. X
  16507. X/*
  16508. X  Count the number of lines in a file.
  16509. X
  16510. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16511. X*/
  16512. X
  16513. Xlong int count_lines_in_file (FILE *fp)
  16514. X{
  16515. X  long int lines = 0;
  16516. X  char line [MAX_LINE];
  16517. X
  16518. X  if (fp)
  16519. X    while (!feof (fp)) {
  16520. X      RESET (line);
  16521. X      fgets (line, MAX_LINE - 2, fp);
  16522. X      if (line[0] != EOS)
  16523. X    ++lines;
  16524. X    }
  16525. X
  16526. X  return lines;
  16527. X}
  16528. X
  16529. X/*
  16530. X  Put the digest_toc and digest_msg files together to make a digest
  16531. X  in unprocessed_digestf.
  16532. X
  16533. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16534. X*/
  16535. X
  16536. Xvoid digest_make (BOOLEAN to_everyone)
  16537. X{
  16538. X  FILE *ofp, *ifp;
  16539. X  char line [MAX_LINE];
  16540. X
  16541. X  OPEN_FILE (ofp, (to_everyone ? unprocessed_digestf : msgf), "w",
  16542. X         "digest_make");
  16543. X  fprintf (ofp, "Contents:\n");
  16544. X
  16545. X  OPEN_FILE (ifp, digest_tocf, "r", "digest_make");
  16546. X  while (!feof (ifp)) {
  16547. X    RESET (line);
  16548. X    fgets (line, MAX_LINE - 2, ifp);
  16549. X    if (line[0] != EOS)
  16550. X      fputs (line, ofp);
  16551. X  }
  16552. X  fclose (ifp);
  16553. X
  16554. X  fprintf (ofp, "\n------------------------------------------\
  16555. X----------------------------\n");
  16556. X
  16557. X  OPEN_FILE (ifp, digest_msgf, "r", "digest_make");
  16558. X  while (!feof (ifp)) {
  16559. X    RESET (line);
  16560. X    fgets (line, MAX_LINE - 2, ifp);
  16561. X    if (line[0] != EOS)
  16562. X      fputs (line, ofp);
  16563. X  }
  16564. X  fclose (ifp);
  16565. X
  16566. X  fprintf (ofp, "End of Digest\n************************\n");
  16567. X  fclose (ofp);
  16568. X
  16569. X  if (to_everyone) {
  16570. X    unlink (digest_tocf);
  16571. X    unlink (digest_msgf);
  16572. X    OPEN_FILE (ofp, digest_timef, "w", "digest_make");
  16573. X    fprintf (ofp, "%ld\n", time (0));
  16574. X    fclose (ofp);
  16575. X  }
  16576. X
  16577. X  report_progress (report,
  16578. X           tsprintf ("%sDistributing %sdigest #%04d.", DIGEST_TIME_,
  16579. X                 (to_everyone ? "" : "partial "), ++digest_msg),
  16580. X           TRUE);
  16581. X
  16582. X  if (to_everyone) {
  16583. X    OPEN_FILE (digest_no, digest_nof, "w", "digest_make");
  16584. X    fprintf (digest_no, "%d\n", digest_msg);
  16585. X    fclose (digest_no);
  16586. X  }
  16587. X}
  16588. X
  16589. X/*
  16590. X  Distribute a digest.
  16591. X
  16592. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16593. X*/
  16594. X
  16595. Xvoid digest_distribute (void)
  16596. X{
  16597. X  char subject1[MAX_LINE], subject2[MAX_LINE];
  16598. X  struct stat stat_buf;
  16599. X
  16600. X  sprintf (subject1, "%s digest %d", sys.lists[listid].alias, digest_msg);
  16601. X  strcpy (subject2, subject1);
  16602. X
  16603. X  if (!stat (unprocessed_digestf, &stat_buf) && stat_buf.st_size > 0)
  16604. X    distributions (SUBSCRIBED, NULL, unprocessed_digestf, ARCHIVE_DIGEST,
  16605. X           sys.lists[listid].address,
  16606. X           sys.lists[listid].address, subject1, subject2,
  16607. X           sys.lists[listid].address, 0, FALSE);
  16608. X  unlink (unprocessed_digestf);
  16609. X}
  16610. X
  16611. X/*
  16612. X  Copy message_file to a file in arch_dir, whose name is specified
  16613. X  by arch_spec.
  16614. X  arch_spec is interpreted like a printf format string.  The following
  16615. X  formats are recognized:
  16616. X  %m month        01 - 12
  16617. X  %d day of month    01 - 31
  16618. X  %y year               00 - 99
  16619. X  %j julian date    001 - 366
  16620. X  %h month name    Jan - Dec
  16621. X  %a contents of Archive-Name header line (cannot be used if arching digests)
  16622. X  %# digest number (only use this if archiving digests)
  16623. X  %1 first non-blank line of file
  16624. X  %v volume number (extracted from Volume # Number # line)
  16625. X  %n issue number (extracted from Volume # Number # line)
  16626. X  %% the character %
  16627. X  any other characters are entered into the name of the file
  16628. X  example: arch.%y%m%d
  16629. X  If there already is a file by that name, add additional characters
  16630. X  to make a unique file.
  16631. X
  16632. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16633. X*/
  16634. X
  16635. Xvoid do_archive (char *header_file, char *message_file, char *subject,
  16636. X         BOOLEAN is_moderated)
  16637. X{
  16638. X  FILE *fp;
  16639. X  char fullpath [MAX_LINE], line [MAX_LINE], dirname [MAX_LINE],
  16640. X    report_msg [MAX_LINE], *src, *dst, *p, *filep;
  16641. X  int i, volume_num = -1, issue_num = -1;
  16642. X  BOOLEAN done_volume = FALSE;
  16643. X  long int time_is = 0;
  16644. X  struct tm *t;
  16645. X  struct stat stat_buf;
  16646. X
  16647. X  time (&time_is);
  16648. X  t = localtime (&time_is);
  16649. X
  16650. X  strcpy (fullpath, sys.lists[listid].arch_dir);
  16651. X  dst = fullpath + strlen (fullpath);
  16652. X  *dst++ = '/';
  16653. X  filep = dst;        /* start of file name */
  16654. X
  16655. X  for (src = sys.lists[listid].arch_spec; *src != EOS; src++) {
  16656. X    if (*src == '%') {
  16657. X      /* found a %, if next char is a known format specifier, print the
  16658. X     appropriate value.  Otherwise just print the character, so %% prints
  16659. X     one %. */
  16660. X      switch (*++src) {
  16661. X      case 'm':        /* month number */
  16662. X    sprintf (dst, "%02d", t->tm_mon + 1);
  16663. X    dst += 2;
  16664. X    break;
  16665. X      case 'd':        /* day of month */
  16666. X    sprintf (dst, "%02d", t->tm_mday);
  16667. X    dst += 2;
  16668. X    break;
  16669. X      case 'y':        /* 2 digits of year */
  16670. X    sprintf (dst, "%02d", t->tm_year % 100);
  16671. X    dst += 2;
  16672. X    break;
  16673. X      case 'j':        /* julian date */
  16674. X    sprintf (dst, "%03d", t->tm_yday + 1);
  16675. X    dst += 3;
  16676. X    break;
  16677. X      case 'h':        /* short name of month */
  16678. X    strcpy (dst, mname[t->tm_mon]);
  16679. X    dst += 3;
  16680. X    break;
  16681. X      case 'a':        /* contents of Archive-Name: header line */
  16682. X    if (archive_name[0] == EOS)
  16683. X      if (!get_archive_name (message_file, archive_name)) {
  16684. X        reject_archive ("Archive-Name: name missing", subject);
  16685. X        return;
  16686. X      }
  16687. X    strcpy (dst, archive_name);
  16688. X    dst += strlen (archive_name);
  16689. X    break;
  16690. X      case '#':        /* digest number */
  16691. X    sprintf (dst, "%d", digest_msg);
  16692. X    dst += strlen (dst);
  16693. X    break;
  16694. X      case '1':        /* 1st word of 1st nonblank line of message */
  16695. X    OPEN_FILE (fp, message_file, "r", "do_archive");
  16696. X    while (!feof (fp)) {
  16697. X      RESET (line);
  16698. X      fgets (line, MAX_LINE - 2, fp);
  16699. X      if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  16700. X        line [strlen (line) - 1] = EOS;
  16701. X      /* Skip leading blanks, truncate string at blank. */
  16702. X      for (p = line; *p && isspace (*p); p++);
  16703. X      if (*p) {
  16704. X        strcpy (archive_name, p);
  16705. X        for (p = archive_name; *p != EOS && !isspace (*p); p++);
  16706. X        *p = EOS;
  16707. X        break;
  16708. X      }
  16709. X      locase (archive_name);
  16710. X    }
  16711. X    fclose (fp);        
  16712. X    strcpy (dst, archive_name);
  16713. X    dst += strlen (archive_name);
  16714. X    break;
  16715. X      case 'v':
  16716. X    if (!done_volume) {
  16717. X      if (!get_volume (message_file, &volume_num, &issue_num)) {
  16718. X        reject_archive ("Volume number missing", subject);
  16719. X        return;
  16720. X      }
  16721. X      done_volume = TRUE;
  16722. X    }
  16723. X    sprintf (dst, "%d", volume_num);
  16724. X    dst += strlen (dst);
  16725. X    break;
  16726. X      case 'n':
  16727. X    if (!done_volume) {
  16728. X      if (!get_volume (message_file, &volume_num, &issue_num)) {
  16729. X        reject_archive ("Issue number missing", subject);
  16730. X        return;
  16731. X      }
  16732. X      done_volume = TRUE;
  16733. X    }
  16734. X
  16735. X    sprintf (dst, "%d", issue_num);
  16736. X    dst += strlen(dst);
  16737. X    break;
  16738. X      default:
  16739. X    *dst++ = *src;
  16740. X      }
  16741. X    }
  16742. X    else
  16743. X      *dst++ = *src;
  16744. X  }
  16745. X  *dst = EOS;
  16746. X
  16747. X  if (filep == dst) { /* No name to archive */
  16748. X    reject_archive ("Archive name is blank", subject);
  16749. X    return;
  16750. X  }
  16751. X
  16752. X  if (re_strcmp ("/*\\.\\./", fullpath, NULL) > 0) {
  16753. X    /* Someone is trying to write an archive into a parent dir. */
  16754. X    reject_archive (tsprintf ("Archive file %s contains ..", fullpath),
  16755. X            subject);
  16756. X    return;
  16757. X  }
  16758. X  if (re_strcmp ("/", archive_name, NULL)) {
  16759. X    reject_archive (tsprintf ("Archive file %s contains directory", archive_name),
  16760. X            subject);
  16761. X    return;
  16762. X  }
  16763. X  for (i = 0; i < strlen (fullpath); i++)
  16764. X    if (!isalnum (fullpath[i]) && fullpath[i] != '.' && fullpath[i] != '/' &&
  16765. X    fullpath[i] != '@' && fullpath[i] != '#' && fullpath[i] != '%' &&
  16766. X    fullpath[i] != '-') {
  16767. X      reject_archive (tsprintf ("Archive file %s contains invalid character '%c'",
  16768. X           fullpath, fullpath[i]), subject);
  16769. X      return;
  16770. X    }
  16771. X
  16772. X  /* Create archive dir if needed.  Can't use arch_dir, there might be
  16773. X     /'s in %1 or %a or arch_spec. */
  16774. X  strcpy (dirname, fullpath);
  16775. X  if (p = strrchr (dirname, '/'))
  16776. X    *p = EOS;
  16777. X  if (!mkdir1 (dirname, report_msg, mask)) {
  16778. X    reject_archive (report_msg, subject);
  16779. X    return;
  16780. X  }
  16781. X
  16782. X/*
  16783. X  If the file already exists, append .1, .2 and so on.
  16784. X  for (i = 1; access (fullpath, 0) == 0; i++)
  16785. X    sprintf (dst, ".%d", i);
  16786. X*/
  16787. X
  16788. X  report_progress (report, tsprintf ("Archiving in %s", fullpath), TRUE);
  16789. X
  16790. X  if (stat (fullpath, &stat_buf))    /* Compress previous archive files */
  16791. X    syscom ("compress %s/* > /dev/null 2>&1 < /dev/null", dirname),
  16792. X    syscom ("uncompress %s/%s.Z %s/%s.Z > /dev/null 2>&1 < /dev/null", dirname,
  16793. X        DIRF, dirname, INDEX);
  16794. X  if (is_moderated) { /* Skip message lines before appending */
  16795. X    char line [MAX_LINE];
  16796. X    FILE *in, *out;
  16797. X    if (header_file)
  16798. X      cat_append (header_file, fullpath);
  16799. X    OPEN_FILE (in, message_file, "r", "do_archive");
  16800. X    OPEN_FILE (out, fullpath, "a", "do_archive");
  16801. X    while (!feof (in)) {
  16802. X      RESET (line);
  16803. X      fgets (line, MAX_LINE - 2, in);
  16804. X      if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  16805. X    line [strlen (line) - 1] = EOS;
  16806. X      if (!strcmp (line, MESSAGE_SEPARATOR))
  16807. X    break;
  16808. X    }
  16809. X    if (feof (in))    /* No message separator, so archive the whole msg */
  16810. X      rewind (in);
  16811. X    while (!feof (in))
  16812. X      RESET (line),
  16813. X      fgets (line, MAX_LINE - 2, in),
  16814. X      fputs (line, out);
  16815. X    fclose (in);
  16816. X    fclose (out);
  16817. X  }
  16818. X  else {
  16819. X    if (header_file)
  16820. X      cat_append (header_file, fullpath);
  16821. X    cat_append (message_file, fullpath);
  16822. X  }
  16823. X  chmod (fullpath, 0644 & (0644 ^ otoi (mask)));
  16824. X
  16825. X  if (*sys.lists[listid].farch_dir != EOS)
  16826. X    farch (sys.lists[listid].arch_dir, sys.lists[listid].farch_dir,
  16827. X       sys.lists[listid].arch_pass, fullpath, filep, subject);
  16828. X}
  16829. X
  16830. X/*
  16831. X  Add the archive file to the DIR in farch_dir.
  16832. X
  16833. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16834. X*/
  16835. X
  16836. Xvoid farch (char *arch_dir, char *farch_dir, char *password, char *fullpath,
  16837. X        char *file_part, char *subject)
  16838. X{
  16839. X  FILE *fin, *fout;
  16840. X  long int dummy;
  16841. X  char dir [MAX_LINE], file [MAX_LINE], dirf [MAX_LINE],
  16842. X  full_arch_dir [MAX_LINE], full_farch_dir [MAX_LINE], error [MAX_LINE],
  16843. X  desc [MAX_LINE], _file [MAX_LINE];
  16844. X  char *p;
  16845. X  struct stat stat_buf;
  16846. X  BOOLEAN continued = FALSE, found;
  16847. X
  16848. X  /* If file_part contains a directory, extract that into dir to append
  16849. X     to farch_dir and to arch_dir. */
  16850. X  strcpy (dir, file_part);
  16851. X  if (p = strrchr(dir, '/'))
  16852. X    strcpy (file, p + 1),
  16853. X    *p = EOS,
  16854. X    sprintf (full_arch_dir, "%s/%s", arch_dir, dir),
  16855. X    sprintf (full_farch_dir, "%s/%s", farch_dir, dir);
  16856. X  else
  16857. X    RESET (dir),
  16858. X    strcpy(file, file_part),
  16859. X    strcpy (full_arch_dir, arch_dir),
  16860. X    strcpy (full_farch_dir, farch_dir);
  16861. X  sprintf (dirf, "%s/%s/%s", ARCHIVE_DIR, full_farch_dir, DIRF);
  16862. X  if (!make_indexes (dirf, full_farch_dir, password, error, mask)) {
  16863. X    reject_archive (error, subject);
  16864. X    return;
  16865. X  }
  16866. X
  16867. X  sprintf (error, "%s.old", dirf);
  16868. X  mv (dirf, error);
  16869. X  OPEN_FILE (fin, error, "r", "farch");
  16870. X  OPEN_FILE (fout, dirf, "w", "farch");
  16871. X  stat (fullpath, &stat_buf);
  16872. X  found = FALSE;
  16873. X  while (!feof (fin)) { /* Get location and file-count of file */
  16874. X    RESET (_file);
  16875. X    fscanf (fin, "%s", _file);
  16876. X    if (_file[0] != EOS) {
  16877. X      locase (_file);
  16878. X      if (!strcmp (_file, file)) {
  16879. X    fprintf (fout, "%s 1 %ld", file, stat_buf.st_size);
  16880. X    fscanf (fin, "%d %d", &dummy, &dummy);
  16881. X    found = TRUE;
  16882. X    do { /* Get file description */
  16883. X      RESET (desc);
  16884. X      fgets (desc, MAX_LINE - 2, fin);
  16885. X      fputs (desc, fout);
  16886. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\n')
  16887. X        desc[strlen (desc) - 1] = EOS;
  16888. X      continued = FALSE;
  16889. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  16890. X        continued = TRUE;
  16891. X    } while (continued);
  16892. X      }
  16893. X      else {
  16894. X    fprintf (fout, "%s", _file);
  16895. X    do { /* Get file description */
  16896. X      RESET (desc);
  16897. X      fgets (desc, MAX_LINE - 2, fin);
  16898. X      fputs (desc, fout);
  16899. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\n')
  16900. X        desc[strlen (desc) - 1] = EOS;
  16901. X      continued = FALSE;
  16902. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  16903. X        continued = TRUE;
  16904. X    } while (continued);
  16905. X      }
  16906. X    }
  16907. X  }
  16908. X  if (!found)
  16909. X    fprintf (fout, "%s 1 %ld %s %s\n", file, stat_buf.st_size, full_arch_dir,
  16910. X         subject);
  16911. X  fclose (fin);
  16912. X  fclose (fout);
  16913. X  unlink (error);
  16914. X  chmod (dirf, 0644 & (0644 ^ otoi (mask)));
  16915. X}
  16916. X
  16917. X/*
  16918. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16919. X*/
  16920. X
  16921. Xvoid reject_archive (char *msg, char *subject)
  16922. X{
  16923. X  FILE *forwardmail = NULL;
  16924. X  char report_msg [MAX_LINE];
  16925. X
  16926. X  sprintf (report_msg, "Cannot archive: %s", msg);
  16927. X  report_progress (report, report_msg, TRUE);
  16928. X
  16929. X  create_header (&forwardmail, mailforwardf, sys.lists[listid].address,
  16930. X         sys.lists[listid].address, sys.lists[listid].owner,
  16931. X         subject, FALSE, TRUE, TRUE);
  16932. X  fprintf (forwardmail, "Cannot archive: %s\n", msg);
  16933. X  fprintf (forwardmail, "arch_dir: %s\n", sys.lists[listid].arch_dir);
  16934. X  fprintf (forwardmail, "arch_spec: %s\n", sys.lists[listid].arch_spec);
  16935. X  fprintf (forwardmail, "Here is the message that was not archived:\n\
  16936. X------------------------------------------------------------------------------\
  16937. X\n\n");
  16938. X
  16939. X  if (copy_msg (forwardmail, msgf, FALSE, sys.lists[listid].address, 0, FALSE))
  16940. X    sendmail (sys.lists[listid].owner, FALSE, FALSE, 0, 0,
  16941. X          mailforwardf);
  16942. X}
  16943. X
  16944. X/*
  16945. X  Look for a line like "volume <number> number <number>" and store
  16946. X  numbers in volume_num and issue_num.
  16947. X
  16948. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  16949. X*/
  16950. X
  16951. XBOOLEAN get_volume (char *message_file, int *volume_num, int *issue_num)
  16952. X{
  16953. X  FILE *fp;
  16954. X  char line [MAX_LINE], *p;
  16955. X  BOOLEAN found = FALSE;
  16956. X
  16957. X  OPEN_FILE (fp, message_file, "r", "get_volume");
  16958. X  while (!feof (fp) && !found) {
  16959. X    RESET (line);
  16960. X    fgets (line, MAX_LINE - 2, fp);
  16961. X    if (line [0] != EOS && line [strlen (line) - 1] == '\n')
  16962. X      line [strlen (line) - 1] = EOS;
  16963. X
  16964. X    locase (line);
  16965. X
  16966. X    for (p = line; *p != EOS && isspace (*p); p++);
  16967. X    if (strncmp (p, "volume", strlen ("volume")))
  16968. X      continue;
  16969. X
  16970. X    for (p += strlen ("volume"); *p != EOS && isspace (*p); p++);
  16971. X    if (!isdigit (*p))
  16972. X      continue;
  16973. X
  16974. X    *volume_num = atoi (p);
  16975. X    for (; *p != EOS && isdigit (*p); p++);
  16976. X
  16977. X    for (; *p != EOS && isspace (*p); p++);
  16978. X    if (strncmp (p, "number", strlen ("number")))
  16979. X      continue;
  16980. X
  16981. X    for (p += strlen ("number"); *p != EOS && isspace (*p); p++);
  16982. X    if (!isdigit (*p))
  16983. X      continue;
  16984. X
  16985. X    *issue_num = atoi (p);
  16986. X    found = TRUE;
  16987. X  }
  16988. X
  16989. X  fclose (fp);
  16990. X  return found;
  16991. X}
  16992. X
  16993. X/*
  16994. X  Get the Archive-Name: if any.
  16995. X*/
  16996. X
  16997. XBOOLEAN get_archive_name (char *message_file, char *archive_name)
  16998. X{
  16999. X  FILE *fp;
  17000. X  char error [MAX_LINE], line[MAX_LINE];
  17001. X
  17002. X  OPEN_FILE (fp, message_file, "r", "get_archive_name");
  17003. X  while (!feof (fp)) {
  17004. X    RESET (line);
  17005. X    fgets (line, MAX_LINE - 2, fp);
  17006. X    locase (line);
  17007. X    clean_request (line);
  17008. X    if (re_strcmp (ARCHIVE_NAME, line, NULL) > 0) {
  17009. X      sscanf (line, "%s %s", error, archive_name);
  17010. X      fclose (fp);
  17011. X      return TRUE;
  17012. X    }
  17013. X  }
  17014. X  fclose (fp);
  17015. X  return FALSE;
  17016. X}
  17017. X
  17018. X/*
  17019. X  Check if the daily limit of messages posted has been exceeded and return
  17020. X  immediately; otherwise, distribute no more than the limit minus messages
  17021. X  already posted and update the limits file.
  17022. X*/
  17023. X
  17024. XBOOLEAN limit_exceeded (char *limitsf, char *list_mail_f, char *mail_copyf)
  17025. X{
  17026. X  FILE *fin, *fout;
  17027. X  long int nmessages, mon, day, year, time_is;
  17028. X  struct tm *t;
  17029. X  char line [MAX_LINE];
  17030. X  char *tmprest;
  17031. X
  17032. X  nmessages = mon = day = year = 0;
  17033. X  if ((fin = fopen (limitsf, "r")))
  17034. X    fscanf (fin, "%d %d %d %d", &nmessages, &mon, &day, &year),
  17035. X    fclose (fin);
  17036. X  if (nmessages > sys.lists[listid].max_messages)
  17037. X    return TRUE;
  17038. X  OPEN_FILE (fin, list_mail_f, "r", "limit_exceeded");
  17039. X  OPEN_FILE (fout, mail_copyf, "w", "limit_exceeded");
  17040. X  while (!feof (fin) && nmessages < sys.lists[listid].max_messages) {
  17041. X    ++nmessages;
  17042. X    RESET (line);
  17043. X    fgets (line, MAX_LINE - 2, fin);
  17044. X    do {
  17045. X      fputs (line, fout);
  17046. X      RESET (line);
  17047. X      fgets (line, MAX_LINE - 2, fin);
  17048. X    } while (!feof (fin) &&
  17049. X         (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE))));
  17050. X    if (!strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))
  17051. X      fseek (fin, -strlen (line), SEEK_CUR); /* Move back to beginning */
  17052. X  }
  17053. X  fclose (fout);
  17054. X  OPEN_FILE (fout, (tmprest = mystrdup (tmpnam (NULL))), "w", "limit_exceeded");
  17055. X  RESET (line);
  17056. X  while (!feof (fin))
  17057. X    RESET (line),
  17058. X    fgets (line, MAX_LINE - 2, fin),
  17059. X    fputs (line, fout);
  17060. X  fclose (fin);
  17061. X  fclose (fout);
  17062. X  mv (tmprest, list_mail_f);
  17063. X  free ((char *) tmprest);
  17064. X  time (&time_is);
  17065. X  t = localtime (&time_is);
  17066. X  echo (tsprintf ("%d %d %d %d", nmessages, t->tm_mon + 1, t->tm_mday,
  17067. X          t->tm_year), limitsf);
  17068. X  return FALSE;
  17069. X}
  17070. *-*-END-of-src/list.c-*-*
  17071. echo x - src/listserv.c
  17072. sed 's/^X//' >src/listserv.c <<'*-*-END-of-src/listserv.c-*-*'
  17073. X/*
  17074. X  ----------------------------------------------------------------------------
  17075. X  |                         MAILING LIST SERVER                              |
  17076. X  |                                         |
  17077. X  |                             Version 6.0                     |
  17078. X  |                                                                          |
  17079. X  |                (or, when Computer Science gets to you)                   |
  17080. X  |                                                                          |
  17081. X  |                    Written by Anastasios Kotsikonas                      |
  17082. X  |                           (tasos@cs.bu.edu)                              |
  17083. X  |                                                                          |
  17084. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  17085. X  | whole and not in parts, as long as you do not remove or alter the author |
  17086. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  17087. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  17088. X  | provided for your personal use, you you may not alter the functions      |
  17089. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  17090. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  17091. X  | any changes you may have made. No part of the source code bearing a         |
  17092. X  | copyright notice can be included in commercial software systems without  |
  17093. X  | written permission by the author.                         |
  17094. X  | By using this software you are bound by this agreement.             |
  17095. X  | This software comes with no warranties and cannot be sold for profit.    |
  17096. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  17097. X  | files when distributing this software.                                   |
  17098. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  17099. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  17100. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  17101. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  17102. X  | (ii).                                                                    |
  17103. X  ----------------------------------------------------------------------------
  17104. X
  17105. X  This is the system's server. People send requests to ListServer for
  17106. X  subscription, removal of subscription, general information request, etc.
  17107. X  In addition, list owners issue administrative requests.
  17108. X
  17109. X  The recognized user-commands are as follows:
  17110. X    help [command]
  17111. X    set <list> [<option> <arg[s]>]    option: mail, password, address, conceal
  17112. X                    arg: ack, noack, postpone, digest
  17113. X                    args: current-password new-password
  17114. X                    args: current-password new-address
  17115. X                    arg: yes, no
  17116. X    subscribe <list> <name>
  17117. X    unsubscribe <list> (alias signoff)
  17118. X    recipients <list> (alias review)
  17119. X    information <list>
  17120. X    statistics <list> {[subscriber email address(es)] | [-all]}
  17121. X    lists
  17122. X    which
  17123. X    index [archive | path-to-archive] [/password] [-all]
  17124. X    get <archive | path-to-archive> <filename> [/password] [parts]
  17125. X    search <archive | path-to-archive> [/password] [-all] <pattern>
  17126. X    fax <fax-number> <archive | path-to-archive> <filename> [/password] [parts]
  17127. X    run <list> [<password> cmd [args]]
  17128. X    release
  17129. X
  17130. X  List administration commands:
  17131. X    system <list> <password> <user-address> #<user-request>
  17132. X    reports <list> <password>
  17133. X    edit <list> <password> <file>
  17134. X    put <list> <password> <keyword> [args]
  17135. X    approve <list> <password> <tag>
  17136. X    discard <list> <password> <tag>
  17137. X
  17138. X  Manager oriented commands:
  17139. X    shutdown <password>
  17140. X    restart <password>
  17141. X    execute <password> #<prog> [args]
  17142. X
  17143. X  Above, <user-request> is any of the recognized user requests.
  17144. X
  17145. X  Commands are sent to ListServer one on each line of the message. The user
  17146. X  is notified of the first invalid request; all subsequent commands
  17147. X  are ignored -- imagine someone sending an entire book!! For each 
  17148. X  successfully completed command, a confirmation is sent back to the sender.
  17149. X  Commands/requests may be abbreviated.
  17150. X
  17151. X  USER ORIENTED REQUESTS:
  17152. X  -----------------------
  17153. X
  17154. X  The user may request help in general, or on a specific command; he can
  17155. X  'set list mail ack' in which case his/her messages to the list will be
  17156. X  echoed back to him/her, and 'set list mail noack' (the opposite);
  17157. X  A 'set list mail postpone' request will not send any messages to the
  17158. X  subscriber until he resets it to one of the other options (used to suppress
  17159. X  sending email temporarily). 'set list mail digest' will only send messages
  17160. X  periodically as digests. 'set list' with no arguments returns the current
  17161. X  values for all options. The user may reset his/her password with the
  17162. X  'set list password current-password new-password' request, and use this
  17163. X  password to alter the address he/she is subscribed with: 'set list address
  17164. X  current-password new-address'; he may hide his identity by issuing a
  17165. X  'set list conceal yes' request.
  17166. X
  17167. X  To subscribe to the list, a user has to give his/her full name; 
  17168. X  he/she may leave the list by issuing an 'unsubscribe' request;
  17169. X  a list of the current subscribers is obtained through a 'recipients' request;
  17170. X  a copy of the sender's message is also sent to peer lists in this case.
  17171. X  Moreover, general information is available by means of an 'information'
  17172. X  request, and finally 'statistics' compiles a count of messages sent by
  17173. X  each subscriber (unless specific subscriber address are given) as well as
  17174. X  a total count of messages on file; again, a copy of the message will be
  17175. X  forwarded to all peer lists. Private lists do not allow non-members to
  17176. X  execute 'recipients' and 'statistics' requests.
  17177. X
  17178. X  A list of all mailing lists served by this server can be obtained by
  17179. X  a 'lists' request.
  17180. X
  17181. X  A listing of all lists a person is subscribed in is available via a
  17182. X  'which' request.
  17183. X
  17184. X  Information on the current release of this server can be obtained by
  17185. X  a 'release' request.
  17186. X
  17187. X  Subscribers of a list may also run a set of UNIX commands as defined by the
  17188. X  system's manager via the 'run' request. Each command may have a different
  17189. X  password and may take arguments. Users receive the output from stdout and/or
  17190. X  stderr.
  17191. X
  17192. X  The system includes a means for users to obtain files. The files
  17193. X  can be placed anywhere in the system and are archived under
  17194. X              HOMEDIR/archives/*
  17195. X  Each of these archives has an index of subarchives and a directory
  17196. X  of files that can be obtained from that archive; there is a master
  17197. X  archive in archives/listserver: the file INDEX contains names and full paths
  17198. X  to all of the archives (including listserver); the file DIR is a directory 
  17199. X  of files that are archived under listserver. A user
  17200. X  may obtain a list of all the archives and their files by sending an
  17201. X  'index' request. That request followed by a specific archive will
  17202. X  send a list of files for that archive and all of its subsrchives.
  17203. X  The format of the INDEX file is as follows: one line per archive
  17204. X  with the following:
  17205. X
  17206. X     archive-name full-path-to-its-directory [password]
  17207. X
  17208. X  When listing subarchives in INDEX the following rule has to be followed:
  17209. X  the first entry is the archive itself; all first level subarchives follow
  17210. X  (let's say A, B and C), then all second level subarchives (starting with
  17211. X  A's subarchives, then listing B's and last C's), then all third level
  17212. X  subarchives, etc. No sibling archives may have the same name.
  17213. X
  17214. X  An archive is made private by putting a password after its full
  17215. X  path specification. This password has to be present in all parent
  17216. X  archives and is required for obtaining an index of that archive,
  17217. X  as well as any files from that archive.
  17218. X
  17219. X  A file can be obtained via a 'get' request, specifying the archive and
  17220. X  the file to get. It is possible that a file has been split in various
  17221. X  parts, in which case multiple emails with the various subparts will
  17222. X  be sent to the user. Note that only the master index is used in this
  17223. X  case for locating the archive. Individual parts of the split file may
  17224. X  be obtained by specifying them as arguments.
  17225. X
  17226. X  An archive's files may be searched for a pattern via the 'search' request.
  17227. X  The pattern is an egrep(1)-style regular expression with the additional
  17228. X  `&` (AND) and '~' (OR) loginal operators.
  17229. X
  17230. X  A file may be archived with the farch utility, or manually by
  17231. X  editing the DIR file of the target archive. The format is as follows:
  17232. X  one line per file containing the following information:
  17233. X
  17234. X  filename number-of-subparts size-of-each-part dir-where-found [Comments]
  17235. X
  17236. X  The restriction is that the actual disk file should be all in lower case.
  17237. X  Private archives require a password for obtaining files.
  17238. X
  17239. X  A new archive may be created by creating a subdirectory under
  17240. X  HOMEDIR/archives (the new directory may not be all in lower-case letters),
  17241. X  updating the master INDEX (archives/listserver/INDEX) and all lower-level
  17242. X  indeces (if any), creating a new INDEX file in the new directory with one
  17243. X  entry (the new archive itself), and creating an empty DIR file in the
  17244. X  same new directory.
  17245. X
  17246. X  The hierarchical structure is only logical and directory hierarchy does
  17247. X  not matter. All archives though have to be placed under HOMEDIR/archives.
  17248. X
  17249. X  All commands may be abbreviated except 'shutdown' and 'restart'.
  17250. X
  17251. X  LIST OWNER ORIENTED REQUESTS:
  17252. X  -----------------------------
  17253. X
  17254. X  The system includes support for list owners. These are list administrators
  17255. X  with special privileges on the system. They may issue requests on users'
  17256. X  behalf overriding any restriction set on regular users (these include
  17257. X  disabled commands also). The following requests are available to
  17258. X  list owners:
  17259. X
  17260. X    system <list> <password> <user-address> #<user-request>
  17261. X
  17262. X  This request overrides all system restrictions and executes <user-request>
  17263. X  on behalf of <user-address>; the address has to appear as listsed in the
  17264. X  .subscribers file, where applicable. The most frequent use of the 'system'
  17265. X  request is to subscribe a user to a private list. ListServer will send
  17266. X  a message to the owner igiving him the exact address and request to
  17267. X  issue back. For example:
  17268. X
  17269. X    system herc herc1 user1@foo.com #subscribe herc Foo Bar
  17270. X
  17271. X  As another example, to remove a user from a list, the owner issues:
  17272. X
  17273. X    system herc herc1 user1@foo.com #unsubscribe herc
  17274. X
  17275. X  Keep in mind that if the owner makes a syntax error in <user-request>,
  17276. X  <user-address> will be notified as if they issued the incorrect
  17277. X  request.
  17278. X
  17279. X  A list owner may obtain all reports pertinent to the list he is maintaining
  17280. X  by issuing the following request:
  17281. X
  17282. X    reports <list> <password>
  17283. X
  17284. X  This will send two mail messages: one with the current report and one with
  17285. X  the previously archived ones.
  17286. X
  17287. X  An owner may also obtain other files pertinent to his list via the
  17288. X  following request:
  17289. X
  17290. X    edit <list> <password> <file>
  17291. X
  17292. X  This will send a message containing the specified file.
  17293. X
  17294. X  A list owner may also add aliases to the .aliases file, add users to the
  17295. X  .ignored file, change the welcoming message in .welcome, change
  17296. X  the informative message in .info, change the .subscribers/.peers/.news etc
  17297. X  by way of the 'put' request:
  17298. X
  17299. X    put <list> <password> <keyword> [args]
  17300. X
  17301. X  The keyword defines the action to be taken; valid keywords are: alias,
  17302. X  ignore, welcome, info. To add an alias, the following request may be
  17303. X  issued:
  17304. X
  17305. X    put <list> <password> alias <new-alias> <address-as-subscribed>
  17306. X
  17307. X  Refer to the man pages for explanation on aliases. To add to the .ignored
  17308. X  file:
  17309. X
  17310. X    put <list> <password> ignore <address-as-subscribed-or-aliased>
  17311. X
  17312. X  To create new .welcome/.info/.aliases/.ignored/.subscribers/.news/.peers
  17313. X  files the following requests may be issued:
  17314. X
  17315. X    put <list> <password> welcome
  17316. X    put <list> <password> info
  17317. X    put <list> <password> aliases
  17318. X    put <list> <password> ignored
  17319. X    put <list> <password> subscribers
  17320. X    put <list> <password> news
  17321. X    put <list> <password> peers
  17322. X
  17323. X  After the request, all text that follows is assumed to be the message
  17324. X  to be copied until the end of this message. Thus no more requests can
  17325. X  be made in the same mail message (they are treated as regular text).
  17326. X
  17327. X  As a final note, list owners are authenticated by checking their
  17328. X  addresses in HOMEDIR/owners (a file containing all owners' addresses),
  17329. X  and verifying their passwords. There is no provision for adding restricted
  17330. X  users, adding new peers and connecting with news groups. These cases
  17331. X  have to be handled by the system's manager.
  17332. X
  17333. X  A list owner may also approve messages for posting to his moderated
  17334. X  list via an 'approve' request. ListServer forwards every new message
  17335. X  to the owner providing him with the message's tag number. The
  17336. X  owner then replies with:
  17337. X
  17338. X    approve <list> <password> <tag>
  17339. X
  17340. X  ListServer then finds the message with the provided tag and prepares
  17341. X  it for posting. To discard a message, the owner sends the following
  17342. X  request:
  17343. X
  17344. X    discard <list> <password> <tag>
  17345. X
  17346. X  MANAGER ORIENTED REQUESTS:
  17347. X  --------------------------
  17348. X
  17349. X  The entire system may be remotely shut down by way of a 'shutdown' request;
  17350. X  this request must be followed by a password that must match the one defined
  17351. X  in config. Note that this may result in requests being queued with the
  17352. X  'shutdown' one not being serviced; note thought that a copy of the original
  17353. X  requests can be found in MAIL_COPY as defined in listserv.h.
  17354. X  Likewise, the system may be remotely restarted by issuing a 'restart'
  17355. X  request with the proper password. Note that a 'restart' request has no
  17356. X  effect after a 'shutdown' (because the server is not running), and that
  17357. X  any requests queued with the 'restart' will be serviced (the system will
  17358. X  not restart until all requests are serviced).
  17359. X
  17360. X  ListServer lets the manager execute a command remotely via the 'execute'
  17361. X  request, and sends him the output from stdout and stderr in two separate
  17362. X  messages.
  17363. X
  17364. X  COMMAND LINE OPTIONS:
  17365. X    -1: Same as for the list program.
  17366. X    -r: This option may be repeated an infinite number of times and is
  17367. X        always followed by a valid ListServer command (as outlined above).
  17368. X        This forces a restriction to be placed on the specified command;
  17369. X        whenever a user makes such a request, the request will be rejected
  17370. X        if the number of users currently on the system is greater than
  17371. X        the threshold specified in listserv.h. This option was added due
  17372. X        to the fact that the 'statistics' request may take up a lot of
  17373. X        resources to complete.
  17374. X    -e: Echo reports to the screen.
  17375. X    -n: Do not notify peer servers.
  17376. X    -d: Disable a ListServer command. This makes totally unknown to the server.
  17377. X        However, help is still available for the particular request.
  17378. X    -a: Usually, subscriptions are automatic. This option turns automatic
  17379. X    subscription off for the specified list. Such requests will be
  17380. X    forwarded to manager for approval.
  17381. X    -b: The command that follows will be executed in batch mode.
  17382. X    -B: Process the batch queue.
  17383. X    -i: Go to interactive mode. No mail is sent out and the text saved
  17384. X    in MAILFORWARD will be read by serverd.
  17385. X    -D: Turn debug on. A transaction of the last email sent out is kept
  17386. X        in the files HOMEDIR/sent and HOMEDIR/received. This assumes
  17387. X    use of the 'system' mail method.
  17388. X
  17389. X  EXIT CODES:
  17390. X    0: OK
  17391. X    1: Could not open or lock file
  17392. X    2: SIGINT signal
  17393. X    3: Command line option error
  17394. X    4: Syntax error in file
  17395. X    5: Could not spawn
  17396. X    6: Shutdown request
  17397. X    7: Restart request
  17398. X    8: Received system signal
  17399. X    9: Too many multiple recipients
  17400. X   10: Could not deliver mail
  17401. X   11: Malloc failed
  17402. X   12: Cannot fork
  17403. X   13: Socket connection problem
  17404. X   14: Semaphore error
  17405. X   15: Cannot setuid, setgid
  17406. X   16: Internal error
  17407. X
  17408. X  Approximate algorithm:
  17409. X  {
  17410. X    Place a lock so that no other programs will access the same files.
  17411. X    Lock SERVER_MAIL_FILE or BATCH_FILE so catmail can't append to it
  17412. X    Read the SERVER_MAIL_FILE or BATCH_FILE
  17413. X    Unlock the file
  17414. X
  17415. X    if new messages have arrived then {
  17416. X      For each message do {
  17417. X        If the message is sent by MAILER-DAEMON forward it to MANAGER
  17418. X        else {
  17419. X      if the person in not in the IGNORED file, then
  17420. X          scan each line of the body of the message and treat it as a
  17421. X          command with possible arguments. Reply to the sender for each such
  17422. X          request. If a request cannot be processed, send an error message to
  17423. X          the sender and ignore all subsequent requests.
  17424. X        }
  17425. X      }
  17426. X    }
  17427. X  }
  17428. X
  17429. X  Required files:
  17430. X    SUBSCRIBERS       <-- The list of subscribed people (diff. for each list)
  17431. X    ALIASES          <-- Aliases of email addresses of subscribers, news &
  17432. X                  peers.
  17433. X    PEERS          <-- A list of peers for a particular list (where appl.)
  17434. X    IGNORED           <-- The list of undesired people (one for the server
  17435. X              and one for each list)
  17436. X    SERVER_LOCK_FILE  <-- Lock file
  17437. X
  17438. X  Input files:
  17439. X    HEADERS           <-- Used for the 'statistics' request (see list.c)
  17440. X    SERVER_MAIL_FILE  <-- Where new messages go
  17441. X    BATCH_FILE          <-- Where requests are batched
  17442. X    MAIL_COPY         <-- Copy of this file (actual work file)
  17443. X    MSG_NO            <-- Read last message count
  17444. X    SUBSCRIBERS
  17445. X    IGNORED     
  17446. X
  17447. X  Output files:
  17448. X    SERVER_MBOX       <-- A log of all messages sent
  17449. X    SUBSCRIBERS       <-- After updating
  17450. X    OLD_SUBSCRIBERS   <-- Temporary
  17451. X    MSG_NO            <-- Write last message count
  17452. X    REPORT_SERVER     <-- Progress report
  17453. X    MAILFORWARD       <-- Completed message (with header and the
  17454. X                          the body of the message) to be forwarded
  17455. X
  17456. X  Format of the SUBSCRIBERS, PEERS and IGNORED files:
  17457. X    See comments for list.c
  17458. X
  17459. X*/
  17460. X
  17461. X#include <stdio.h>
  17462. X#include <sys/types.h>
  17463. X#ifdef SYSLOG
  17464. X# ifdef ultrix
  17465. X#  include <sys/syslog.h>
  17466. X# else
  17467. X#  include <syslog.h>
  17468. X# endif
  17469. X#endif
  17470. X#include <ctype.h>
  17471. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  17472. X  && !defined (sequent) && !defined (unknown_port)
  17473. X# include <malloc.h>
  17474. X#endif
  17475. X#include <string.h>
  17476. X#ifndef unknown_port
  17477. X# ifndef __NeXT__
  17478. X#  include <unistd.h>
  17479. X# else
  17480. X#  include <libc.h>
  17481. X# endif
  17482. X#endif
  17483. X#include <sys/stat.h>
  17484. X#include <fcntl.h>
  17485. X#include <signal.h>
  17486. X#include <math.h>
  17487. X#if !defined (stellar) && !defined (unknown_port)
  17488. X# include <time.h>
  17489. X#endif
  17490. X#include <sys/time.h>
  17491. X#if !defined (sequent) && !defined (__NeXT__) && !defined (__convex__) && \
  17492. X !defined (apollo) && !defined (i386) && !defined (unknown_port)
  17493. X# include <sys/termio.h>
  17494. X#endif
  17495. X#ifndef sun
  17496. X# include <sys/ioctl.h>
  17497. X#endif
  17498. X#include <errno.h>
  17499. X#ifdef unknown_port
  17500. Xextern int errno;
  17501. X#endif
  17502. X#include "defs.h"
  17503. X#include "listserv.h"
  17504. X#include "struct.h"
  17505. X#include "global.h"
  17506. X#include "iulp.h"
  17507. X#if defined (__NeXT__) || defined (unknown_port)
  17508. X# include "next.h"
  17509. X#endif
  17510. X
  17511. X#ifdef TCP_IP
  17512. X# include <sys/socket.h>
  17513. X# include <netdb.h>
  17514. X# include <netinet/in.h>
  17515. Xstruct     in_addr localaddr;
  17516. X#else
  17517. Xchar     *localaddr;
  17518. X#endif
  17519. X
  17520. X/* 
  17521. X  Function prototypes:
  17522. X*/
  17523. X
  17524. X#ifdef __STDC__
  17525. X# include "ansi/misc.h"
  17526. X# include <stdarg.h>
  17527. Xextern int  syscom (char *, ...);
  17528. Xextern int  siul (char *, int, char *, char *, int, char *, char *, ...);
  17529. Xextern char *tsprintf (char *, ...);
  17530. X#else
  17531. X# include "nonansi/misc.h"
  17532. X# include <varargs.h>
  17533. Xextern int  syscom ();
  17534. Xextern int  siul ();
  17535. Xextern char *tsprintf ();
  17536. X#endif
  17537. Xextern int  sys_config (FILE *, SYS *);
  17538. Xextern void report_progress (FILE *, char *, int);
  17539. Xextern void init_signals (void);
  17540. Xextern void catch_signals (void);
  17541. Xextern void setup_string (char *, char *, char *);
  17542. Xextern char *upcase (char *);
  17543. Xextern char *locase (char *);
  17544. Xextern void distribute (FILE *, void (*)(char *, char *, BOOLEAN),
  17545. X            FILE *, char *, char *, char *, char *);
  17546. Xextern char *clean_name (char *);
  17547. Xextern void clean_request (char *);
  17548. Xextern int  _getopt (int, char **, char *);
  17549. Xextern void get_list_name (char *, char *);
  17550. Xextern int  get_list_id (char *, SYS *, int);
  17551. Xextern void shrink (char *);
  17552. Xextern void free_remote (REMOTE **);
  17553. Xextern void check_aliases (char *, char *);
  17554. Xextern void shadow_password (char *);
  17555. Xextern void read_params (char *, char *, char *, FILE *, FILE *);
  17556. Xextern BOOLEAN extract_subscriber (FILE *, char *, BOOLEAN);
  17557. Xextern BOOLEAN extract_sender (char *);
  17558. Xextern BOOLEAN sysmail (char *);
  17559. Xextern BOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
  17560. Xextern BOOLEAN strinstr (char *, char *);
  17561. Xextern BOOLEAN ignore_sender (FILE *, char *, FILE *, BOOLEAN);
  17562. Xextern BOOLEAN requested_part (char *, int);
  17563. Xextern BOOLEAN owner_listed (char *, char *, char *, FILE *);
  17564. Xextern BOOLEAN remove_msg (char *, int, FILE *);
  17565. Xextern int  lock_file (char *, int, int, BOOLEAN);
  17566. Xextern void unlock_file (int);
  17567. Xextern void escape_address (char *);
  17568. Xextern int  otoi (char *);
  17569. Xextern int  insert_word (char *, char **, int, int, int);
  17570. Xextern char *_strstr (char *, char *);
  17571. Xextern int  re_strcmp (char *, char *, char *);
  17572. Xextern char *mystrdup (char *);
  17573. Xextern int echo (char *, char *);
  17574. Xextern int echo_append (char *, char *);
  17575. Xextern int mv (char *, char *);
  17576. Xextern int cp (char *, char *);
  17577. Xextern int cat_append (char *, char *);
  17578. Xextern int touch (char *);
  17579. Xextern int ucb_strftime (char *, int, char *, struct tm *);
  17580. Xextern long int write_to_fd (int, char *, long int);
  17581. X
  17582. Xvoid   main (int, char **, char **);
  17583. Xvoid   process_message (char *, char *, BOOLEAN);
  17584. Xvoid   action (char *, char *, char *, BOOLEAN);
  17585. Xvoid   reply_code (int);
  17586. Xvoid   create_header (FILE **, char *, char *, char *, char *, BOOLEAN, int,
  17587. X              BOOLEAN, BOOLEAN);
  17588. Xvoid   reject_mail (char *, char *, char *, int, int);
  17589. Xvoid   System (char *, char *, char *);
  17590. Xvoid   get_sys_files (char *, char *, char *);
  17591. Xvoid   put (char *, char *, char *);
  17592. Xvoid   help (char *, char *, char *);
  17593. Xvoid   unsubscribe (char *, char *, char *);
  17594. Xvoid   subscribe (char *, char *, char *, BOOLEAN);
  17595. Xvoid   which (char *, char *, char *);
  17596. Xvoid   set (char *, char *, char *);
  17597. Xvoid   recipients (char *, char *, char *);
  17598. Xvoid   info (char *, char *, char *);
  17599. Xvoid   stats (char *, char *, char *);
  17600. Xvoid   Shutdown (char *, char *, char *);
  17601. Xvoid   restart (char *, char *, char *);
  17602. Xvoid   lists (char *, char *, char *);
  17603. Xvoid   Index (char *, char *, char *);
  17604. Xvoid   get (char *, char *, char *);
  17605. Xvoid   search (char *, char *, char *);
  17606. Xvoid   release (char *, char *, char *);
  17607. Xvoid   notify (char *, char *, char *);
  17608. Xvoid   approve (char *, char *, char *);
  17609. Xvoid   discard (char *, char *, char *);
  17610. Xvoid   notify_peer_servers (char *, char *, char *, char *);
  17611. Xvoid   execute (char *, char *, char *);
  17612. Xvoid   unix_cmd (char *, char *, char *);
  17613. Xvoid   init_commands (void);
  17614. Xvoid   usage (void);
  17615. Xvoid   server_config (char *);
  17616. Xint    gexit (int);
  17617. X
  17618. X/*
  17619. X  The control structure of the server. Check if mail has arrived.
  17620. X  If so, copy it to MAIL_COPY and proceed to lower level.
  17621. X  First, the command line options are analyzed (for restrictions, etc.).
  17622. X*/
  17623. X
  17624. Xvoid main (int argc, char **argv, char **envp)
  17625. X{
  17626. X  struct stat stat_buf;
  17627. X  char *options = "1r:d:enDa:b:c:Bi", *mask;
  17628. X  int c;
  17629. X  BOOLEAN execute_once = FALSE, notok;
  17630. X  int i, j, k, rlfd = 2;
  17631. X  FILE *f;
  17632. X  extern char *optarg, *getenv();
  17633. X  extern int optopt;
  17634. X#ifdef TCP_IP
  17635. X  struct hostent *lhost;
  17636. X#endif
  17637. X
  17638. X  prog = argv[0];
  17639. X  init_commands();
  17640. X#ifdef SYSLOG
  17641. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  17642. X# ifndef i386
  17643. X       |LOG_NOWAIT
  17644. X# endif
  17645. X       , SYSLOG);
  17646. X# ifndef ultrix
  17647. X  setlogmask (LOG_UPTO (LOG_INFO));
  17648. X# endif
  17649. X#else
  17650. X  if ((report = fopen (REPORT_SERVER, "a")) == NULL)
  17651. X    fprintf (stderr, "listserv: Unable to open %s\n", REPORT_SERVER),
  17652. X    exit (1);
  17653. X  chmod (REPORT_SERVER, 384); /* 600 */
  17654. X#endif
  17655. X  nlists = sys_config (report, &sys);
  17656. X  while ((c = _getopt (argc, argv, options)) != EOF)
  17657. X    switch ((char) c) {
  17658. X      case '1': execute_once = TRUE; break;
  17659. X      case 'e': tty_echo = TRUE; break;
  17660. X      case 'i': interactive = TRUE;
  17661. X      case 'n': do_not_notify_peer_server = TRUE; break;
  17662. X      case 'a':
  17663. X      case 'c':
  17664. X    if ((listid = get_list_id (upcase (optarg), &sys, nlists)) < 0)
  17665. X      fprintf (stderr, "\nlistserv: Unknown list %s for -%c option\n",
  17666. X           optarg, c),
  17667. X      exit (3);
  17668. X    if (c == 'a')
  17669. X      sys.lists[listid].options |= NON_AUTO_SUB;
  17670. X    else if (c == 'c')
  17671. X      sys.lists[listid].options |= CONCEAL_LIST;
  17672. X    break;
  17673. X      case 'B': process_batch = TRUE; break;
  17674. X      case 'D': debug = TRUE; break;
  17675. X      case 'b':
  17676. X      case 'r':
  17677. X      case 'd':
  17678. X        notok = TRUE;
  17679. X        k = 0;
  17680. X        upcase (optarg);
  17681. X        for (i = 0; i < MAX_COMMANDS; ++i) {
  17682. X          notok &= (((j = strncmp (optarg, commands[i].name, strlen (optarg)))
  17683. X                    != 0) ? 1 : 0);
  17684. X          if (!j) {
  17685. X            ++k;
  17686. X        if (c == 'r')
  17687. X              restricted_commands |= commands[i].mask;
  17688. X        else if (c == 'd')
  17689. X          disabled_commands |= commands[i].mask;
  17690. X        else if (c == 'b')
  17691. X          batched_commands |= commands[i].mask;
  17692. X      }
  17693. X    }
  17694. X        if (notok)
  17695. X          fprintf (stderr, "listserv: Unrecognized request '%s'\n", optarg),
  17696. X          exit (3);
  17697. X        if (k > 1) /* ambiguous command */
  17698. X          fprintf (stderr, "listserv: Ambiguous request '%s'\n", optarg),
  17699. X          exit (3);
  17700. X        break;
  17701. X      case ':':
  17702. X          fprintf (stderr, "listserv: Option '%c' requires an argument.\n",
  17703. X           optopt);
  17704. X          exit (3);
  17705. X      case '?':
  17706. X      default:
  17707. X        usage ();
  17708. X    }
  17709. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  17710. X    umask (otoi (mask));
  17711. X  else
  17712. X    mask = "066",
  17713. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  17714. X#ifndef NO_LOCKS
  17715. X  if ((lfd = lock_file (SERVER_LOCK_FILE, O_RDWR, 0, FALSE)) < 0)
  17716. X    fprintf (stderr, "listserv: Unable to lock %s. Aborting.\n", 
  17717. X             SERVER_LOCK_FILE),
  17718. X    exit (1);
  17719. X#endif
  17720. X  if (!execute_once)
  17721. X    printf ("%s", COPYRIGHT);
  17722. X  init_signals();
  17723. X  catch_signals();
  17724. X  if (sys.options & USE_ENV_VAR) {
  17725. X    if ((sys.mail.method = (char *) malloc (256 * sizeof (char))) == NULL)
  17726. X      report_progress (report, "\nmain(): malloc() failed", TRUE),
  17727. X      gexit (11);
  17728. X    sprintf (sys.mail.method, "env - %s=%s %s ", sys.mail.env_var,
  17729. X         sys.server.address, sys.mail.mail_prog);
  17730. X   }
  17731. X  if ((msg_no = fopen (MSG_NO, "r")) != NULL)
  17732. X    fscanf (msg_no, "%d\n", &request_no),
  17733. X    fclose (msg_no);
  17734. X#if defined (TIOCNOTTY) && defined (SIGTTOU) && defined (SIGTTIN)
  17735. X  if (!tty_echo)
  17736. X    if ((i = open ("/dev/tty", 2)) >=0)
  17737. X      ioctl (i, TIOCNOTTY, 0),
  17738. X      close (i);
  17739. X#endif
  17740. X    
  17741. X  if ((f = fopen (PID_SERVER, "w")) != NULL)
  17742. X    fprintf (f, "%d", getpid()),
  17743. X    fclose (f);
  17744. X  signal (SIGINT, (void (*) ()) gexit);
  17745. X  signal (SIGALRM, SIG_IGN);
  17746. X#ifdef TCP_IP
  17747. X  gethostname (hostname, sizeof (hostname));
  17748. X  lhost = gethostbyname (hostname);
  17749. X  memcpy ((char *) &localaddr, (char *) lhost->h_addr, lhost->h_length);
  17750. X#else
  17751. X  strcpy (localaddr, LOCAL_ADDR);
  17752. X  strcpy (hostname, HOSTNAME);
  17753. X#endif
  17754. X
  17755. X  if (process_batch) /* Select file to process: batch or requests */
  17756. X    strcpy (requests_file, BATCH_FILE);
  17757. X  else if (!interactive)
  17758. X    strcpy (requests_file, SERVER_MAIL_FILE);
  17759. X  else
  17760. X    strcpy (requests_file, LIVE_REQUESTS_F);
  17761. X
  17762. X  do {
  17763. X    if (!stat (requests_file, &stat_buf) && stat_buf.st_size > 0) {
  17764. X#ifndef NO_LOCKS
  17765. X      if ((rlfd = lock_file (requests_file, O_RDWR, 0, FALSE)) < 0)
  17766. X    break; /* Cannot lock file, so exit, regardless of execute_once */
  17767. X#endif
  17768. X      cp (requests_file, MAIL_COPY);
  17769. X      if (!process_batch)
  17770. X        cat_append (MAIL_COPY, SERVER_MBOX),
  17771. X        echo_append ("", SERVER_MBOX);
  17772. X      if (!unlink (requests_file)) {
  17773. X    touch (requests_file); /* rewrite file */
  17774. X    if (process_batch)
  17775. X      chmod (requests_file, /*384*/ 0666 & (0666 ^ otoi (mask)));
  17776. X    else
  17777. X      chmod (requests_file, /*416*/ 0666 & (0666 ^ otoi (mask)));
  17778. X      }
  17779. X#ifndef NO_LOCKS
  17780. X      unlock_file (rlfd);
  17781. X#endif
  17782. X      OPEN_FILE (mail, MAIL_COPY, "r", "main");
  17783. X      if (process_batch)
  17784. X    report_progress (report, PROCESSING_BATCH, FALSE);
  17785. X      else
  17786. X        report_progress (report, NEW_ARRIVAL, FALSE);
  17787. X      distribute (mail, (void (*)(char *, char *, BOOLEAN)) process_message,
  17788. X          report, NULL, NULL, NULL, NULL);
  17789. X      fclose (mail);  /* Done */
  17790. X      shrink (message_idsf);
  17791. X      unlink (MAIL_COPY);  /* Done delivering */
  17792. X    }
  17793. X    else if (!execute_once) /* No mail to deliver */
  17794. X      if (sys.frequency > 0)
  17795. X        sleep (sys.frequency);
  17796. X  } while (!execute_once);
  17797. X#ifdef SYSLOG
  17798. X  closelog ();
  17799. X#else
  17800. X  fclose (report);
  17801. X#endif
  17802. X  free_remote (&rlists);
  17803. X  if (restart_sys)
  17804. X    gexit (7); /* Exit status of 7 signifies a restart request */
  17805. X  gexit (0);
  17806. X}
  17807. X
  17808. X/*
  17809. X  Process each message. Isolate each command and pass it to action().
  17810. X  Before that, check if the message is from MAILER_DAEMON, in which case
  17811. X  forward the message to MANAGER. Any messages from people listed in the
  17812. X  IGNORED file are not processed.
  17813. X  Note: Please look at the documentation for list.c for the definition of a
  17814. X  mailer daemon.
  17815. X*/
  17816. X
  17817. Xvoid process_message (char *sender, char *linecopy, BOOLEAN address_ok)
  17818. X{
  17819. X  char line [MAX_LINE];          /* ... from the current message */
  17820. X  char request [MAX_LINE];       /* holds each command */
  17821. X  char sender_copy [MAX_LINE];
  17822. X  char senders_subject [MAX_LINE];
  17823. X  char id_copy [MAX_LINE];
  17824. X  char original_sender [MAX_LINE];
  17825. X  char received [MAX_LINE];
  17826. X  char match [MAX_LINE];
  17827. X  char error [MAX_LINE];
  17828. X  char *at = NULL;
  17829. X  FILE *f;
  17830. X  BOOLEAN loop = FALSE;
  17831. X  BOOLEAN did_action;
  17832. X  BOOLEAN done;
  17833. X  BOOLEAN fake_mail = TRUE;
  17834. X  BOOLEAN mailer_daemon;
  17835. X  BOOLEAN susp_subject;
  17836. X
  17837. X  listid = -1;
  17838. X  peer_server_request = FALSE;
  17839. X  line[0] = message_id[0] = id_copy[0] = RESET (sender_copy);
  17840. X  strcpy (sender_copy, sender);  /* We do not like converting the actual */
  17841. X  upcase (sender_copy);          /* address to upper case */
  17842. X  report_progress (report, tsprintf ("Request #%04d:%s\n", ++request_no,
  17843. X    (*sender != EOS ? sender : "\"\"")), FALSE);
  17844. X  OPEN_FILE (msg_no, MSG_NO, "w", "process_message");
  17845. X  fprintf (msg_no, "%d\n", request_no);
  17846. X  fclose (msg_no);
  17847. X
  17848. X  received[0] = RESET (senders_subject);
  17849. X  while (!feof (mail) && line[0] != '\n') { /* Skip to beginning of message */
  17850. X    strcpy (match, "\\1");
  17851. X    if (re_strcmp (SUBJECT, line, match) > 0) {
  17852. X      strcpy (senders_subject, line + strlen (match));
  17853. X      sprintf (line, "%s", line + strlen (match));
  17854. X      strcpy (match, "\\1");
  17855. X      if (re_strcmp (PEER_SERVER_REQUEST, line, match) > 0)
  17856. X    strcpy (psr_string, match),
  17857. X    peer_server_request = TRUE;
  17858. X    }
  17859. X    else if (re_strcmp (FROM, line, match) > 0)
  17860. X      strcpy (original_sender, line + strlen (match)), /* Save From: */
  17861. X      original_sender [strlen (original_sender) - 1] = EOS; /* \n -> \0 */
  17862. X    else if (re_strcmp (RECEIVED, line, match) > 0) { /* Check for fake mail */
  17863. X      strcpy (received, line + strlen (match));
  17864. X      received [strlen (received) - 1] = EOS;
  17865. X      sscanf (received, "%s %s", error, received); /* Get host after "from" */
  17866. X      upcase (received);  /* Relay host */
  17867. X      if (fake_mail && (at = strchr (sender_copy, '@')))
  17868. X    if (re_strcmp (at + 1, received, NULL) > 0)
  17869. X      fake_mail = FALSE;
  17870. X    }
  17871. X    else if (re_strcmp (MESSAGE_ID1, line, NULL) > 0 ||
  17872. X         re_strcmp (MESSAGE_ID2, line, NULL) > 0 ||
  17873. X         re_strcmp (MESSAGE_ID3, line, NULL) > 0)
  17874. X      strcpy (message_id, line + strlen ("Message-") + 4),
  17875. X      message_id [strlen (message_id) - 1] = EOS, /* \n -> \0 */
  17876. X      strcpy (id_copy, message_id);
  17877. X      upcase (id_copy);
  17878. X    RESET (line);
  17879. X    fgets (line, MAX_LINE - 2, mail);
  17880. X  }
  17881. X
  17882. X  if (message_id[0] != EOS) { /* Check for mail loop using Message-Id: */
  17883. X    SETUP_MESSAGE_IDSF;
  17884. X    if (message_ids = fopen (message_idsf, "r")) {
  17885. X      if (ignore_sender (message_ids, id_copy, report, TRUE))
  17886. X        loop = TRUE;
  17887. X      fclose (message_ids);
  17888. X    }
  17889. X    if (!loop) {
  17890. X      OPEN_FILE (message_ids, message_idsf, "a", "process_message");
  17891. X      fprintf (message_ids, "%s %s\n", message_id, sender); /* Save new id */
  17892. X      fclose (message_ids);
  17893. X    }
  17894. X  }
  17895. X
  17896. X  if (!address_ok) {
  17897. X    RESET (request);
  17898. X    NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS (sender);
  17899. X    one_rejection = TRUE;
  17900. X  }
  17901. X
  17902. X  mailer_daemon = strinstr (MAILER_DAEMON, sender_copy) ||
  17903. X    (original_sender[0] != EOS && strinstr (MAILER_DAEMON, original_sender)) ||
  17904. X    *sender == EOS;
  17905. X  susp_subject = (senders_subject[0] != EOS &&
  17906. X          strinstr (SUSP_SUBJECT, senders_subject));
  17907. X  if (mailer_daemon || susp_subject) {
  17908. X    /* Send message to MANAGER */
  17909. X    create_header (&f, MAILFORWARD, sys.server.address, sys.manager,
  17910. X           senders_subject, FALSE, INVALID_REQ, TRUE, TRUE);
  17911. X    fprintf (f, "\nRejected message: sent to %s by %s follows.\n\
  17912. XReason for rejection: %s.\n--------------------------------------\
  17913. X-----------------------------------------\n", sys.server.address,
  17914. X         (*sender != EOS ? sender : "\"\""),
  17915. X         (mailer_daemon ? "suspicious address" :
  17916. X          (susp_subject ? "suspicious subject" : "???")));
  17917. X    RESET (line);
  17918. X    while (!feof (mail) && 
  17919. X           (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {
  17920. X      fprintf (f, "%s", line);
  17921. X      RESET (line);
  17922. X      fgets (line, MAX_LINE - 2, mail);
  17923. X    }
  17924. X    COMPLETE_TELNET (f);
  17925. X    fclose (f);
  17926. X    DELIVER_MAIL (sys.manager, FALSE);
  17927. X    report_progress (report,
  17928. X             tsprintf ("Forwarding message to %s (%s)\n", sys.manager,
  17929. X                   (mailer_daemon ? "suspicious address" :
  17930. X                (susp_subject ? "suspicious subject" : "???"))),
  17931. X             FALSE);
  17932. X    did_action = TRUE;
  17933. X  }
  17934. X  else { /* Isolate request and call action() */
  17935. X    check_aliases (ALIASESF, sender);
  17936. X    done = did_action = FALSE;
  17937. X    if (!interactive && fake_mail && at && !one_rejection && !loop)
  17938. X      report_progress (report,
  17939. X               tsprintf ("*** Possible fake mail: Host %s in user \
  17940. Xaddress does\nnot match any of the domains in the Received: header lines.\n",
  17941. X                 at + 1), FALSE);
  17942. X    while (!feof (mail) && 
  17943. X           (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))) {
  17944. X      clean_request (line);
  17945. X      RESET (request);
  17946. X      sscanf (line, "%s ", request);
  17947. X      upcase (request);
  17948. X      if (!strcmp (request, START_OF_SIGNATURE) || strinstr (THANKS, request))
  17949. X    done = TRUE; /* End of requests, start of .signature */
  17950. X      else if (request[0] != EOS && !one_rejection && !loop && !done)
  17951. X    if (!re_strcmp ("OFFICE[ \t]+MEMO|Subject|:.$|^\\>|^\\]|^\\||^#|^%|^\\}",
  17952. X        line, NULL))
  17953. X          action (line, request, sender, FALSE),
  17954. X      did_action = TRUE;
  17955. X      RESET (line);
  17956. X      fgets (line, MAX_LINE - 2, mail);
  17957. X    }
  17958. X  }
  17959. X  if (!did_action && !one_rejection && !loop) {
  17960. X    create_header (&f, MAILFORWARD, sys.server.address, sender,
  17961. X           "No requests found", FALSE, INVALID_REQ, FALSE, FALSE);
  17962. X    fprintf (f, "No requests found in your message. Requests should be \
  17963. Xincluded in the\nbody of the mail message.\n");
  17964. X    COMPLETE_TELNET (f);
  17965. X    fclose (f);
  17966. X    DELIVER_MAIL (sender, FALSE);
  17967. X  }
  17968. X  strcpy (linecopy, line);
  17969. X  one_rejection = FALSE;
  17970. X  report_progress (report, "", -TRUE); /* -TRUE for no leading newline */
  17971. X}
  17972. X
  17973. X/*
  17974. X  Recognize the 'request' and call the appropriate routine, or reject the
  17975. X  message if the request is not recognized. Isolate any parameters.
  17976. X  If a restriction is in force for the recognized request, then get
  17977. X  the number of users currently on the system and reject the request if
  17978. X  this number is greater that the predetermined threshold.
  17979. X  A request may be batched if we are not processing the batch queue and
  17980. X  the specified request is indeed to be batched according to the command
  17981. X  line options.
  17982. X*/
  17983. X
  17984. Xvoid action (char *line, char *request, char *sender, BOOLEAN override)
  17985. X{
  17986. X  char params [MAX_LINE];
  17987. X  char error [MAX_LINE];
  17988. X  char list_name [MAX_LINE];
  17989. X  char *users_file;
  17990. X  int i, nusers;
  17991. X  FILE *f, *ignored;
  17992. X  long int time_is = 0;
  17993. X  struct tm *t;
  17994. X
  17995. X  report_progress (report, line, FALSE);
  17996. X  listid = -1;
  17997. X  RESET (error);
  17998. X  SETUP_IGNOREDF;
  17999. X  if ((ignored = fopen (server_ignoredf, "r"))) { /* No file for remote list */
  18000. X    if (ignore_sender (ignored, sender, report, FALSE))
  18001. X      goto abort;
  18002. X    fclose (ignored);
  18003. X  }
  18004. X  upcase (sender);
  18005. X  original_params[0] = RESET (params);
  18006. X  read_params (line, params, request, mail, report);
  18007. X  strcpy (original_params, params); /* Preserve case */
  18008. X  upcase (params);
  18009. X  for (i = 0; i < MAX_COMMANDS; i++) /* Walk through the valid requests */
  18010. X    if (! strncmp (request, commands[i].name, strlen (request)) &&
  18011. X    strlen (request) > 2 && ! (disabled_commands & commands[i].mask)) {
  18012. X      if (strncmp (request, "SHUTDOWN", strlen (request)) &&
  18013. X          strncmp (request, "RESTART", strlen (request)) &&
  18014. X          strncmp (request, "LISTS", strlen (request)) &&
  18015. X      strncmp (request, "INDEX", strlen (request)) &&
  18016. X      strncmp (request, "GET", strlen (request)) &&
  18017. X      strncmp (request, "FAX", strlen (request)) &&
  18018. X      strncmp (request, "SEARCH", strlen (request)) &&
  18019. X      strncmp (request, "RELEASE", strlen (request)) &&
  18020. X      strncmp (request, "WHICH", strlen (request)) &&
  18021. X      strncmp (request, "NOTIFY", strlen (request)) &&
  18022. X      strncmp (request, "EXECUTE", strlen (request)) &&
  18023. X          strncmp (request, "HELP", strlen (request))) {
  18024. X        get_list_name (params, list_name);
  18025. X        listid = get_list_id (list_name, &sys, nlists);
  18026. X        server_config (list_name);
  18027. X        if (listid < 0) {
  18028. X          if (list_name[0] == EOS)
  18029. X            sprintf (error, "%s: Missing list name\n\n\
  18030. XSyntax: %s <list> [...]\n", request, request);
  18031. X          else
  18032. X            sprintf (error, "%s: Unknown list name %s\n", request, list_name);
  18033. X          reject_mail (sender, line, error, SYNTAX_ERROR, REJECT_LIST);
  18034. X          return;
  18035. X        }
  18036. X        if ((ignored = fopen (ignoredf, "r"))) { /* No file for remote list */
  18037. X          if (ignore_sender (ignored, sender, report, FALSE)) {
  18038. X        fclose (ignored);
  18039. X            goto abort;
  18040. X      }
  18041. X      fclose (ignored);
  18042. X    }
  18043. X        if (commands[i].mask & sys.lists[listid].disabled_commands &&
  18044. X        !override) {
  18045. X      reject_mail (sender, line,
  18046. X               tsprintf ("%s requests for list %s are disabled\n",
  18047. X                 request, sys.lists[listid].alias),
  18048. X               INVALID_REQ, 0);
  18049. X      goto abort;
  18050. X    }
  18051. X      }
  18052. X      if (restricted_commands & commands[i].mask && !override) {
  18053. X    /* Restriction set */
  18054. X#ifdef _AIX
  18055. X        syscom ("%s | %s -F, '{ print $2 }' > %s", UPTIME, AWK, 
  18056. X        (users_file = mystrdup (tmpnam (NULL))));
  18057. X#else
  18058. X        syscom ("%s | %s -F, '{ print $3 }' > %s", UPTIME, AWK,
  18059. X        (users_file = mystrdup (tmpnam (NULL))));
  18060. X#endif
  18061. X    OPEN_FILE (f, users_file, "r", "action");
  18062. X        fscanf (f, "%d", &nusers);
  18063. X        fclose (f);
  18064. X        unlink (users_file);
  18065. X    free ((char *) users_file);
  18066. X        if (nusers > sys.users) {
  18067. X          create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  18068. X             FALSE, RESTRICTED_REQ, FALSE, FALSE);
  18069. X          fprintf (f, "This request takes a considerable amount of resources \
  18070. Xand certain restrictions\nare currently in force. Please resubmit your \
  18071. Xrequest at a later time.\n");
  18072. X      COMPLETE_TELNET (f);
  18073. X          fclose (f);
  18074. X      DELIVER_MAIL (sender, FALSE);
  18075. X          strcat (request, ": restriction enforced\n");
  18076. X          report_progress (report, request, FALSE);
  18077. X          goto abort;
  18078. X        }
  18079. X      }
  18080. X      if (!process_batch && 
  18081. X      (batched_commands & commands[i].mask)) { /* Batch request */
  18082. X    time (&time_is);
  18083. X    t = localtime (&time_is);
  18084. X    if (t->tm_hour >= sys.batch.start &&
  18085. X        t->tm_hour <= (sys.batch.stop - 1)) { /* Between 8am and 8pm */
  18086. X      if (interactive) { /* Cannot batch a "live" request */
  18087. X        OPEN_FILE (f, MAILFORWARD, "w", "action");
  18088. X        fprintf (f, ">%s\nThe request cannot be processed at this time: \
  18089. Xbatch mode in effect.\nPlease send email.\n", line);
  18090. X        fclose (f);
  18091. X        goto abort;
  18092. X      }
  18093. X      OPEN_FILE (f, BATCH_FILE, "a", "action");
  18094. X      time_is = time (0);
  18095. X      fprintf (f, "From %s %s\n\n%s\n", sender, ctime (&time_is), line);
  18096. X      fclose (f);
  18097. X      report_progress (report, "(request placed in the batch queue)\n",
  18098. X               FALSE);
  18099. X      goto abort;
  18100. X    }
  18101. X      }
  18102. X      commands[i].func (request, params, sender, override); /* Call routine */
  18103. X      goto abort;
  18104. X    }
  18105. X  if (! (sys.options & IGNR_INVLD_RQSTS) || interactive)
  18106. X    reject_mail (sender, line, tsprintf ("Unrecognized request %s\n", request),
  18107. X         INVALID_REQ, REJECT_REQUEST);
  18108. X  else
  18109. X    report_progress (report, "[ignored]\n", FALSE);
  18110. X  abort: ;
  18111. X}
  18112. X
  18113. X/*
  18114. X  Produce the reply code during a live session.
  18115. X*/
  18116. X
  18117. Xvoid reply_code (int reply)
  18118. X{
  18119. X  FILE *f;
  18120. X
  18121. X  OPEN_FILE (f, ULISTSERVER_REPLY, "w", "reply_code");
  18122. X  fprintf (f, "%d\n", reply);
  18123. X  fclose (f);
  18124. X}
  18125. X
  18126. X/*
  18127. X  Create a message header addressed to 'sender' with the given 'subject'.
  18128. X  If this a reply to an invalid request, 'copy_owner' should be TRUE.
  18129. X*/
  18130. X
  18131. Xvoid create_header (FILE **f, char *filename, char *sender, char *recipient, 
  18132. X            char *subject, BOOLEAN copy_owner, int reply,
  18133. X            BOOLEAN preserve_msg_id, BOOLEAN error_condition)
  18134. X{
  18135. X#ifdef NEED_DATE
  18136. X  char date [80];
  18137. X  long int time_is;
  18138. X  struct tm *t;
  18139. X#endif
  18140. X
  18141. X  reply_code (reply);
  18142. X  OPEN_FILE (*f, filename, "w", "create_header");
  18143. X  locase (recipient);
  18144. X  if (subject [0] != EOS && subject [strlen (subject) - 1] == '\n')
  18145. X    subject [strlen (subject) - 1] = EOS;
  18146. X  if (interactive)
  18147. X    return;
  18148. X  if (!fax_it && sys.options & USE_TELNET) {
  18149. X    fprintf (*f, "HELO %s\nMAIL From: <%s>\nRCPT To: <%s>\n",
  18150. X#ifdef ZMAILER
  18151. X/*
  18152. X# ifdef TCP_IP
  18153. X         (char *) inet_ntoa (localaddr),
  18154. X# else
  18155. X         localaddr,
  18156. X# endif
  18157. X    Use either the local address or the host name.
  18158. X*/
  18159. X         hostname,
  18160. X#else
  18161. X         "",
  18162. X#endif
  18163. X         sender, recipient);
  18164. X    if (copy_owner)
  18165. X      fprintf (*f, "RCPT To: <%s>\n",
  18166. X           (listid >= 0 ? sys.lists[listid].owner : sys.manager));
  18167. X    fprintf (*f, "DATA\n");
  18168. X  }
  18169. X  if (preserve_msg_id && message_id[0] != EOS)
  18170. X    fprintf (*f, "Message-Id: %s\n", message_id);
  18171. X#ifdef NEED_DATE
  18172. X  time (&time_is);
  18173. X  t = localtime (&time_is);
  18174. X  ucb_strftime (date, 1024, "%a, %e %b %Y %T %Z", t);
  18175. X  fprintf (*f, "Date: %s\n", date);
  18176. X#endif
  18177. X#ifndef NO_ERRORS_TO
  18178. X  fprintf (*f, "Errors-To: %s\n",((listid < 0 || listid == nlists) ?
  18179. X                  sys.manager : sys.lists[listid].owner));
  18180. X#endif
  18181. X  fprintf (*f, "Reply-To: %s\nSender: %s\nFrom: %s\nTo: %s\n",
  18182. X       sender, sender, sender, recipient);
  18183. X  if (copy_owner && !fax_it)
  18184. X    fprintf (*f, "Cc: %s\n",
  18185. X         ((listid >= 0 && listid < nlists) ?
  18186. X          sys.lists[listid].owner : sys.manager));
  18187. X  fprintf (*f, "Subject: %s%s\nX-Listserver-Version: %s\n", 
  18188. X       (error_condition ? ERROR_CONDITION : ""), subject, VERSION);
  18189. X  if (sys.server.comment[0] != EOS)
  18190. X    fprintf (*f, "X-Comment: %s\n\n", sys.server.comment);
  18191. X  else
  18192. X    fprintf (*f, "\n");
  18193. X}
  18194. X
  18195. X/*
  18196. X  Send a message to 'sender' indicating an invalid request. The body of
  18197. X  the message is given in 'text'. Only one such mail is sent to the user
  18198. X  for each of his/her invalid requests. All subsequent requests are ignored.
  18199. X*/
  18200. X
  18201. Xvoid reject_mail (char *sender, char *request, char *text, int reply, int why)
  18202. X{
  18203. X  FILE *f;
  18204. X  char *newline;
  18205. X  if (one_rejection)
  18206. X    return;
  18207. X  one_rejection = TRUE;
  18208. X  create_header (&f, MAILFORWARD, sys.server.address, sender, 
  18209. X         "Invalid request", COPY_OWNER (ccerrors), reply, FALSE, TRUE);
  18210. X  fprintf (f, ">%s\n%s\n", request, text);
  18211. X  if ((newline = strchr (text, '\n')))
  18212. X    *(newline + 1) = EOS;
  18213. X  report_progress (report, text, FALSE);
  18214. X  if (interactive) {
  18215. X    fclose (f);
  18216. X    return;
  18217. X  }
  18218. X  fprintf (f, "Report any problems to '%s'.\nFor a list of the \
  18219. Xavailable requests send a message to %s\nwith a body consisting of nothing \
  18220. Xbut the word HELP\n\nPS: Any subsequent requests that you might have \
  18221. Xsubmitted have been ignored.\n",
  18222. X       ((listid < 0 || listid == nlists) ?
  18223. X        sys.manager : sys.lists[listid].owner),
  18224. X       sys.server.address);
  18225. X  COMPLETE_TELNET (f);
  18226. X  fclose (f);
  18227. X  DELIVER_MAIL (sender, COPY_OWNER (ccerrors));
  18228. X}
  18229. X
  18230. X/*
  18231. X  Execute a system request. This is usually a request issued by the
  18232. X  list's owner. System requests are valid only for the list the password
  18233. X  is given for.
  18234. X*/
  18235. X
  18236. Xvoid System (char *request, char *params, char *sender)
  18237. X{
  18238. X  char password [MAX_LINE];
  18239. X  char newrequest [MAX_LINE];
  18240. X  char newsender [MAX_LINE];
  18241. X  char list [MAX_LINE];
  18242. X  char *comment, *c;
  18243. X  int target_listid;
  18244. X  FILE *f;
  18245. X
  18246. X  newsender[0] = newrequest[0] = list[0] = RESET (password);
  18247. X  sscanf (params, "%s ", password);
  18248. X  if ((c = _strstr (params, password))) {
  18249. X    while (*c != EOS && !isspace (*c))  /* Get to the end of password */
  18250. X      ++c;
  18251. X    while (*c != EOS && isspace (*c))   /* Get to new sender address */
  18252. X      ++c;
  18253. X    sprintf (newsender, "From %s", c);
  18254. X    if (!extract_sender (newsender)) {  /* Error in address scanning */
  18255. X      shadow_password (params);
  18256. X      sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18257. X           params);
  18258. X      NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS (newsender);
  18259. X      return;
  18260. X    }
  18261. X  }
  18262. X  shadow_password (params);
  18263. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18264. X           params);
  18265. X  if (!owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  18266. X    NOT_LIST_OWNER; /* Hacker attack */
  18267. X    return;
  18268. X  }
  18269. X  if (password[0] == EOS) {
  18270. X    reject_mail (sender, request, "Missing password for SYSTEM request\n\n\
  18271. XSyntax: system <list> <password> <address> #<user-request>\n",
  18272. X         SYNTAX_ERROR, 0);
  18273. X    return;
  18274. X  }
  18275. X  if (password[0] == '#' || strcmp (password, sys.lists[listid].password)) {
  18276. X    reject_mail (sender, request, "Invalid password for SYSTEM request\n",
  18277. X         SYNTAX_ERROR, 0);
  18278. X    return;
  18279. X  }
  18280. X  if (newsender[0] == EOS || newsender[0] == '#') {
  18281. X    reject_mail (sender, request, "Missing user address for SYSTEM request\n\n\
  18282. XSyntax: system <list> <password> <address> #<user-request>\n",
  18283. X         SYNTAX_ERROR, 0);
  18284. X    return;
  18285. X  }
  18286. X  if (!(comment = strchr (params, '#'))) { /* No actual request */
  18287. X    reject_mail (sender, request, "Missing '#': no system request specified\n\n\
  18288. XSyntax: system <list> <password> <address> #<user-request>\n",
  18289. X         SYNTAX_ERROR, 0);
  18290. X    return;
  18291. X  }
  18292. X  sprintf (params, "%s", comment + 1); /* Remove password + sender address */
  18293. X  clean_request (params); /* Now we have the actual request */
  18294. X  sscanf (params, "%s %s", newrequest, list);
  18295. X  if (strlen (newrequest) < 3) {
  18296. X    reject_mail (sender, request, tsprintf ("Ambiguous request %s\n",
  18297. X                        newrequest), SYNTAX_ERROR, 0);
  18298. X    return;
  18299. X  }
  18300. X  if (strncmp (newrequest, "SHUTDOWN", strlen (request)) &&
  18301. X      strncmp (newrequest, "RESTART", strlen (request)) &&
  18302. X      strncmp (newrequest, "LISTS", strlen (request)) &&
  18303. X      strncmp (newrequest, "SEARCH", strlen (request)) &&
  18304. X      strncmp (newrequest, "INDEX", strlen (request)) &&
  18305. X      strncmp (newrequest, "GET", strlen (request)) &&
  18306. X      strncmp (newrequest, "FAX", strlen (request)) &&
  18307. X      strncmp (newrequest, "RELEASE", strlen (request)) &&
  18308. X      strncmp (newrequest, "WHICH", strlen (request)) &&
  18309. X      strncmp (newrequest, "NOTIFY", strlen (request)) &&
  18310. X      strncmp (newrequest, "EXECUTE", strlen (request)) &&
  18311. X      strncmp (newrequest, "HELP", strlen (request)) &&
  18312. X      list[0] != EOS) { /* Check target list validity */
  18313. X    if ((target_listid = get_list_id (list, &sys, nlists)) < 0) {
  18314. X      reject_mail (sender, request, tsprintf ("Unknown list %s\n", list),
  18315. X           SYNTAX_ERROR, 0);
  18316. X      return;
  18317. X    }
  18318. X    if (listid != target_listid) { /* Owner is cheating */
  18319. X      reject_mail (sender, request,
  18320. X           tsprintf ("Invalid request for list %s; SYSTEM requests \
  18321. Xshould be made only\nfor list %s.\n",
  18322. X                 list, sys.lists[listid].alias), INVALID_REQ, 0);
  18323. X      return;
  18324. X    }
  18325. X  }
  18326. X  action (params, newrequest, newsender, TRUE);
  18327. X}
  18328. X
  18329. X/*
  18330. X  Provide the list owner with the requested files. The accumulated
  18331. X  report file is then shrunk. When a file is edited, the last modification
  18332. X  time is saved to prevent a subsequent put in case the file got modified
  18333. X  in the meantime.
  18334. X*/
  18335. X
  18336. Xvoid get_sys_files (char *request, char *params, char *sender)
  18337. X{
  18338. X  char password [MAX_LINE];
  18339. X  char req [MAX_LINE];
  18340. X  char file [MAX_LINE];
  18341. X  char extra [MAX_LINE];
  18342. X  FILE *f;
  18343. X  struct stat stat_buf;
  18344. X
  18345. X  req[0] = extra[0] = file[0] = RESET (password);
  18346. X  strcpy (req, request);
  18347. X  sscanf (params, "%s %s %s", password, file, extra);
  18348. X  shadow_password (params);
  18349. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18350. X       params);
  18351. X  if (!owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  18352. X    NOT_LIST_OWNER; /* Hacker attack */
  18353. X    return;
  18354. X  }
  18355. X  if (password[0] == EOS) {
  18356. X    reject_mail (sender, request,
  18357. X         tsprintf ("Missing password for %s request\n\n%s\n", req,
  18358. X               (!strncmp (req, "EDIT", strlen (req)) ?
  18359. X                "Syntax: edit <list> <password> <file>\n\
  18360. X\tfile: subscribers/aliases/ignored/\
  18361. Xnews/peers/info/welcome" : "Syntax: reports <list> <password>")),
  18362. X         SYNTAX_ERROR, 0);
  18363. X    return;
  18364. X  }
  18365. X  if (strcmp (password, sys.lists[listid].password)) {
  18366. X    reject_mail (sender, request,
  18367. X         tsprintf ("Invalid password for %s request\n", req),
  18368. X         SYNTAX_ERROR, 0);
  18369. X    return;
  18370. X  }
  18371. X  if (!strncmp (req, "REPORTS", strlen (req))) { /* Send reports */
  18372. X    if (file[0] != EOS) {
  18373. X      reject_mail (sender, request,
  18374. X           tsprintf ("Too many arguments to REPORTS ... : %s\n\n\
  18375. XSyntax: reports <list> <password>\n", file), SYNTAX_ERROR, 0);
  18376. X      return;
  18377. X    }
  18378. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  18379. X           OK, FALSE, TRUE);
  18380. X#ifndef SYSLOG
  18381. X    fprintf (f, "*** Here is the latest report file:\n\n");
  18382. X#else
  18383. X    fprintf (f, "Sorry, this system is using syslog(3) and no reports are \
  18384. Xavailable.\n");
  18385. X#endif
  18386. X    fclose (f);
  18387. X#ifndef SYSLOG
  18388. X    setup_string (report_listf, sys.lists[listid].alias, REPORT_LIST);
  18389. X    cat_append (report_listf, MAILFORWARD);
  18390. X#endif
  18391. X    APPEND_TELNET ("get_sys_files");
  18392. X    DELIVER_MAIL (sender, FALSE);
  18393. X#ifndef SYSLOG
  18394. X    if (!interactive)
  18395. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  18396. X             FALSE, OK, FALSE, FALSE);
  18397. X    else
  18398. X      OPEN_FILE (f, MAILFORWARD, "a", "get_sys_files");
  18399. X    fprintf (f, "*** Here is the accumulated report file; this file was shrunk \
  18400. Xafter it was sent\nto you, so you may wish to save it:\n\n");
  18401. X    fclose (f);
  18402. X    setup_string (report_listf, sys.lists[listid].alias, REPORT_LIST_ACC);
  18403. X    cat_append (report_listf, MAILFORWARD);
  18404. X    APPEND_TELNET ("get_sys_files");
  18405. X    DELIVER_MAIL (sender, FALSE);
  18406. X    shrink (report_listf);
  18407. X#endif
  18408. X  }
  18409. X  else { /* Request is EDIT */
  18410. X    if (extra[0] != EOS) {
  18411. X      reject_mail (sender, request,
  18412. X           tsprintf ("Too many arguments to EDIT ... %s: %s\n\n\
  18413. XSyntax: edit <list> <password> <file>\n\
  18414. X\tfile: subscribers/aliases/ignored/\
  18415. Xnews/peers/info/welcome\n", file, extra), SYNTAX_ERROR, 0);
  18416. X      return;
  18417. X    }
  18418. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  18419. X           OK, FALSE, FALSE);
  18420. X    if (!strcmp (file, "ALIASES")) { /* Send .aliases */
  18421. X      fprintf (f, "*** Here is the aliases file:\n\n");
  18422. X      fclose (f);
  18423. X      cat_append (aliasesf, MAILFORWARD);
  18424. X      APPEND_TELNET ("get_sys_files");
  18425. X      DELIVER_MAIL (sender, FALSE);
  18426. X      PUT_TIMESTAMP (aliasesf, aliases_timestampf);
  18427. X    }
  18428. X    else if (!strcmp (file, "IGNORED")) { /* Send .ignored */
  18429. X      fprintf (f, "*** Here is the ignored file:\n\n");
  18430. X      fclose (f);
  18431. X      cat_append (ignoredf, MAILFORWARD);
  18432. X      APPEND_TELNET ("get_sys_files");
  18433. X      DELIVER_MAIL (sender, FALSE);
  18434. X      PUT_TIMESTAMP (ignoredf, ignored_timestampf);
  18435. X    }
  18436. X    else if (!strcmp (file, "INFO")) { /* Send .info */
  18437. X      fprintf (f, "*** Here is the info file:\n\n");
  18438. X      fclose (f);
  18439. X      cat_append (infof, MAILFORWARD);
  18440. X      APPEND_TELNET ("get_sys_files");
  18441. X      DELIVER_MAIL (sender, FALSE);
  18442. X      PUT_TIMESTAMP (infof, info_timestampf);
  18443. X    }
  18444. X    else if (!strcmp (file, "SUBSCRIBERS")) { /* Send .subscribers */
  18445. X      fprintf (f, "*** Here is the subscribers file:\n\n");
  18446. X      fclose (f);
  18447. X      cat_append (subscribersf, MAILFORWARD);
  18448. X      APPEND_TELNET ("get_sys_files");
  18449. X      DELIVER_MAIL (sender, FALSE);
  18450. X      PUT_TIMESTAMP (subscribersf, subscribers_timestampf);
  18451. X    }
  18452. X    else if (!strcmp (file, "WELCOME")) { /* Send .welcome */
  18453. X      fprintf (f, "*** Here is the welcome file:\n\n");
  18454. X      fclose (f);
  18455. X      cat_append (welcomef, MAILFORWARD);
  18456. X      APPEND_TELNET ("get_sys_files");
  18457. X      DELIVER_MAIL (sender, FALSE);
  18458. X      PUT_TIMESTAMP (welcomef, welcome_timestampf);
  18459. X    }
  18460. X    else if (!strcmp (file, "NEWS")) { /* Send .news */
  18461. X      fprintf (f, "*** Here is the news file:\n\n");
  18462. X      fclose (f);
  18463. X      cat_append (newsf, MAILFORWARD);
  18464. X      APPEND_TELNET ("get_sys_files");
  18465. X      DELIVER_MAIL (sender, FALSE);
  18466. X      PUT_TIMESTAMP (newsf, news_timestampf);
  18467. X    }
  18468. X    else if (!strcmp (file, "PEERS")) { /* Get .peers */
  18469. X      fprintf (f, "*** Here is the peers file:\n\n");
  18470. X      fclose (f);
  18471. X      cat_append (peersf, MAILFORWARD);
  18472. X      APPEND_TELNET ("get_sys_files");
  18473. X      DELIVER_MAIL (sender, FALSE);
  18474. X      PUT_TIMESTAMP (peersf, peers_timestampf);
  18475. X    }
  18476. X    else {
  18477. X      fprintf (f, "%s: No such file.\nFiles that can be obtained: \
  18478. Xsubscribers/aliases/ignored/news/peers/info/welcome\n", file);
  18479. X      COMPLETE_TELNET (f);
  18480. X      fclose (f);
  18481. X      DELIVER_MAIL (sender, FALSE);
  18482. X    }
  18483. X  }
  18484. X}
  18485. X
  18486. X/*
  18487. X  Perform various list owner requests: put user addresses in files, or
  18488. X  put new files in the list's directory. The owner may put new aliases
  18489. X  in the .aliases file, new users to be ignored in the .ignored file,
  18490. X  change the welcome message in .welcome, and change the informative
  18491. X  message in .info.
  18492. X*/
  18493. X
  18494. Xvoid put (char *request, char *params, char *sender)
  18495. X{
  18496. X  char password [MAX_LINE];
  18497. X  char keyword [MAX_LINE];
  18498. X  char arg1 [MAX_LINE];
  18499. X  char arg2 [MAX_LINE];
  18500. X  char arg3 [MAX_LINE];
  18501. X  char line [MAX_LINE];
  18502. X  char sign [MAX_LINE];
  18503. X  char params_copy [MAX_LINE];
  18504. X  BOOLEAN signature;
  18505. X  FILE *f;
  18506. X  struct stat stat_buf;
  18507. X  time_t timestamp;
  18508. X  long int sig_mask;
  18509. X
  18510. X  arg1[0] = arg2[0] = arg3[0] = keyword[0] = params_copy[0] = RESET (password);
  18511. X  sscanf (original_params, "%s %s %s %s %s %s", password, password, keyword,
  18512. X      arg1, arg2, arg3);    /* Actually only interested in arg[1-3] */
  18513. X  sscanf (params, "%s %s", password, keyword);
  18514. X  strcpy (params_copy, params);
  18515. X  shadow_password (params);
  18516. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18517. X       params);
  18518. X  if (!owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  18519. X    NOT_LIST_OWNER; /* Hacker attack */
  18520. X    return;
  18521. X  }
  18522. X  if (password[0] == EOS) {
  18523. X    reject_mail (sender, request, "Missing password for PUT request\n\n\
  18524. XSyntax: put <list> <password> <keyword> [args]\n\
  18525. X\tkeyword:alias/ignore/subscribers/aliases/news/peers/ignored/info/welcome\n\
  18526. X\targs:email address for alias/ignore\n",
  18527. X         SYNTAX_ERROR, 0);
  18528. X    return;
  18529. X  }
  18530. X  if (strcmp (password, sys.lists[listid].password)) {
  18531. X    reject_mail (sender, request, "Invalid password for PUT request\n",
  18532. X         SYNTAX_ERROR, 0);
  18533. X    return;
  18534. X  }
  18535. X  if (!strcmp (keyword, "ALIAS")) { /* Add to list's, system's aliases files */
  18536. X    if (arg1[0] == EOS || arg2[0] == EOS || arg3[0] != EOS) {
  18537. X      reject_mail (sender, request, "Wrong number of arguments to \
  18538. XPUT ... ALIAS\n\n\
  18539. XSyntax: put <list> <password> alias <alias-address> <address-as-subscribed | \
  18540. Xregex>\n", SYNTAX_ERROR, 0);
  18541. X      return;
  18542. X    }
  18543. X    echo_append (tsprintf ("%s %s", arg1, arg2), aliasesf);
  18544. X    echo_append (tsprintf ("%s %s", arg1, arg2), ALIASESF);
  18545. X  }
  18546. X  else if (!strcmp (keyword, "IGNORE")) { /* Add to list's ignore file */
  18547. X    if (arg1[0] == EOS || arg2[0] != EOS) {
  18548. X      reject_mail (sender, request, "Wrong number of arguments to \
  18549. XPUT ... IGNORE\n\n\
  18550. XSyntax: put <list> <password> ignore <address>\n", SYNTAX_ERROR, 0);
  18551. X      return;
  18552. X    }
  18553. X    echo_append (tsprintf ("%s", arg1), ignoredf);
  18554. X  }
  18555. X  else if (!strcmp (keyword, "WELCOME") || !strcmp (keyword, "INFO") ||
  18556. X       !strcmp (keyword, "ALIASES") || !strcmp (keyword, "IGNORED") ||
  18557. X       !strcmp (keyword, "SUBSCRIBERS") || !strcmp (keyword, "NEWS") ||
  18558. X       !strcmp (keyword, "PEERS")) {
  18559. X    if (arg1[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  18560. X      reject_mail (sender, request,
  18561. X           tsprintf ("Too many arguments to PUT ... %s: %s\n\n\
  18562. XSyntax: put <list> <password> <file>\n\
  18563. X\tfile: subscribers/aliases/news/peers/ignored/info/welcome\n", keyword, arg1),
  18564. X           SYNTAX_ERROR, 0);
  18565. X      return;
  18566. X    }
  18567. X    if (!strcmp (keyword, "WELCOME")) { /* Write to .welcome */
  18568. X      CHECK_TIMESTAMP (welcome_timestampf, welcomef);
  18569. X      OPEN_FILE (f, welcomef, "w", "put");
  18570. X      unlink (welcome_timestampf);
  18571. X    }
  18572. X    else if (!strcmp (keyword, "INFO")) { /* Write to .info */
  18573. X      CHECK_TIMESTAMP (info_timestampf, infof);
  18574. X      OPEN_FILE (f, infof, "w", "put");
  18575. X      unlink (info_timestampf);
  18576. X    }
  18577. X    else if (!strcmp (keyword, "ALIASES")) { /* Write to .aliases */
  18578. X      CHECK_TIMESTAMP (aliases_timestampf, aliasesf);
  18579. X      OPEN_FILE (f, aliasesf, "w", "put");
  18580. X      unlink (aliases_timestampf);
  18581. X    }
  18582. X    else if (!strcmp (keyword, "IGNORED")) { /* Wite to .ignored */
  18583. X      CHECK_TIMESTAMP (ignored_timestampf, ignoredf);
  18584. X      OPEN_FILE (f, ignoredf, "w", "put");
  18585. X      unlink (ignored_timestampf);
  18586. X    }
  18587. X    else if (!strcmp (keyword, "SUBSCRIBERS")) { /* Write to .subscribers */
  18588. X      CHECK_TIMESTAMP (subscribers_timestampf, subscribersf);
  18589. X      OPEN_FILE (f, subscribersf, "w", "put");
  18590. X      unlink (subscribers_timestampf);
  18591. X    }
  18592. X    else if (!strcmp (keyword, "NEWS")) { /* Write to .news */
  18593. X      CHECK_TIMESTAMP (news_timestampf, newsf);
  18594. X      OPEN_FILE (f, newsf, "w", "put");
  18595. X      unlink (news_timestampf);
  18596. X    }
  18597. X    else { /* Write to .peers */
  18598. X      CHECK_TIMESTAMP (peers_timestampf, peersf);
  18599. X      OPEN_FILE (f, peersf, "w", "put");
  18600. X      unlink (peers_timestampf);
  18601. X    }
  18602. X#ifdef bsd
  18603. X    sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18604. X#elif defined (svr4) || defined (svr3)
  18605. X    sighold (SIGINT);
  18606. X    sighold (SIGTERM);
  18607. X#endif
  18608. X    COPY_MESSAGE;
  18609. X    fclose (f);
  18610. X#ifdef bsd
  18611. X    sigsetmask (sig_mask);
  18612. X#elif defined (svr4) || defined (svr3)
  18613. X    sigrelse (SIGINT);
  18614. X    sigrelse (SIGTERM);
  18615. X#endif
  18616. X    fclose (f);
  18617. X  }
  18618. X  else {
  18619. X    reject_mail (sender, request, "Invalid or missing keyword for PUT \
  18620. Xrequest\n\n\
  18621. XSyntax: put <list> <password> <keyword> [args]\n\
  18622. X\tkeyword:alias/ignore/subscribers/aliases/news/peers/ignored/info/welcome\n\
  18623. X\targs:email address for alias/ignore\n", SYNTAX_ERROR, 0);
  18624. X    return;
  18625. X  }
  18626. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  18627. X         OK, FALSE, FALSE);
  18628. X  fprintf (f, "Your request was successfully completed.\n");
  18629. X  COMPLETE_TELNET (f);
  18630. X  fclose (f);
  18631. X  DELIVER_MAIL (sender, FALSE);
  18632. X}
  18633. X
  18634. X/*
  18635. X  Provide help on the specified topic to 'sender'.
  18636. X*/
  18637. X
  18638. Xvoid help (char *request, char *params, char *sender)
  18639. X{
  18640. X  FILE *f, *index;
  18641. X  char param [MAX_LINE];
  18642. X  char moreparams [MAX_LINE];
  18643. X  char topic [MAX_LINE];
  18644. X  char file [MAX_LINE];
  18645. X  char shell [MAX_LINE];
  18646. X  BOOLEAN found;
  18647. X  struct stat stat_buf;
  18648. X  int ntopics;
  18649. X
  18650. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  18651. X  param[0] = RESET (moreparams);
  18652. X  sscanf (params, "%s %s\n", param, moreparams);
  18653. X  if (moreparams[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  18654. X    reject_mail (sender, request, tsprintf ("Too many HELP topics: %s\n\n\
  18655. XSyntax: help [topic | request]\n", moreparams),
  18656. X         SYNTAX_ERROR, 0);
  18657. X    return;
  18658. X  }
  18659. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  18660. X         COPY_OWNER (cchelp), OK, FALSE, FALSE);
  18661. X  if (param[0] == EOS)
  18662. X    strcpy (param, "GENERAL");
  18663. X  found = FALSE;
  18664. X  if ((index = fopen (HELP_TOPICS, "r")) == NULL)
  18665. X    fprintf (f, "Sorry, no help index found.\n");
  18666. X  else {  /* Check index for help topic, get filename */
  18667. X    while (!feof (index)) {
  18668. X      topic[0] = RESET (file);
  18669. X      fscanf (index, "%s %s\n", topic, file);
  18670. X      upcase (topic);
  18671. X      if (topic[0] != EOS)
  18672. X    if (!strncmp (param, topic, strlen (param))) { /* A match */
  18673. X      found = TRUE;
  18674. X      break;
  18675. X    }
  18676. X    }
  18677. X    if (!found) {
  18678. X      fprintf (f, "Sorry, no help on topic '%s' currently available.\n\n\
  18679. XHelp is available on the following topics:\n\n", param);
  18680. X      rewind (index);
  18681. X      ntopics = 0;
  18682. X      while (!feof (index)) {
  18683. X    topic[0] = RESET (file);
  18684. X    fscanf (index, "%s %s\n", topic, file);
  18685. X    fprintf (f, "%s ", topic);
  18686. X    if ((++ntopics) > 9)
  18687. X      ntopics = 0,
  18688. X      fprintf (f, "\n");
  18689. X      }
  18690. X      fprintf (f, "\n");
  18691. X    }
  18692. X    else if (stat (file, &stat_buf))
  18693. X      fprintf (f, "Sorry, unable to stat file %s for topic '%s'.\n", file,
  18694. X           param),
  18695. X      found = FALSE;
  18696. X    fclose (index);
  18697. X  }
  18698. X  fclose (f);
  18699. X  if (found) {
  18700. X    strcpy (shell, "cat");
  18701. X    if ((f = fopen (file, "r"))) {
  18702. X      fgets (shell, 3, f);
  18703. X      if (!strncmp (shell, "#!", 2)) {
  18704. X    fgets (shell, MAX_LINE - 2, f);
  18705. X    if (shell [strlen (shell) - 1] == '\n')
  18706. X      shell [strlen (shell) - 1] = EOS;
  18707. X      }
  18708. X      else
  18709. X    strcpy (shell, "cat");
  18710. X      fclose (f);
  18711. X    }
  18712. X    syscom ("%s %s >> %s", shell, file, MAILFORWARD);
  18713. X  }
  18714. X  APPEND_TELNET ("help");
  18715. X  DELIVER_MAIL (sender, COPY_OWNER (cchelp));
  18716. X}
  18717. X
  18718. X/*
  18719. X  Unsubscribe a member if he/she is listed in SUBSCRIBERS. If the list
  18720. X  is remote, the request is forwarded.
  18721. X*/
  18722. X
  18723. Xvoid unsubscribe (char *request, char *params, char *sender)
  18724. X{
  18725. X  FILE *f;
  18726. X  char error [10240];
  18727. X  char param [MAX_LINE];
  18728. X  char address [MAX_LINE];
  18729. X  BOOLEAN status, ok_to_reset_address = FALSE;
  18730. X  long int sig_mask;
  18731. X  int i;
  18732. X  
  18733. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18734. X           params); /* Used as a subject */
  18735. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  18736. X    NOTIFY_OF_REQUEST_FORWARDING;
  18737. X    FORWARD_REQUEST;
  18738. X    return;
  18739. X  }
  18740. X  error[0] = RESET (param);
  18741. X  sscanf (params, "%s", param);
  18742. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  18743. X    reject_mail (sender, request, tsprintf ("Invalid UNSUBSCRIBE option%s\n\
  18744. XSyntax: unsubscribe <list> (or signoff <list>)\n", params),
  18745. X         SYNTAX_ERROR, 0);
  18746. X    return;
  18747. X  }
  18748. X  if (!(status = subscribed (report, sender, subscribersf, newsf, peersf,
  18749. X                 aliasesf))) {
  18750. X    if ((sys.lists[listid].defaults.set_values[0][0] == EOS &&
  18751. X     !strcmp (default_values [0], "VARIABLE")) ||
  18752. X    (!strcmp (sys.lists[listid].defaults.set_values[0], "VARIABLE")))
  18753. X      ok_to_reset_address = TRUE;
  18754. X    sprintf (error, "%s: You are not subscribed to %s\n", sender,
  18755. X             sys.lists[listid].address);
  18756. X    if (alternate_addresses) {
  18757. X      sprintf (error + strlen (error),
  18758. X           "\nIn addition, the system found the following \
  18759. Xaddress(es) that resemble yours.\nIf one of these is you, please resend your \
  18760. Xmessage from that one%s:\n\n",
  18761. X           (ok_to_reset_address ?
  18762. X        ", or use the\n'set <list> address' request to change the \
  18763. Xaddress you are subscribed with" :
  18764. X        ""));
  18765. X      for (i = 0; alternate_addresses[i]; ++i)
  18766. X    sprintf (error + strlen (error), "%s\n", alternate_addresses[i]),
  18767. X    free ((char *) alternate_addresses[i]);
  18768. X      free ((char **) alternate_addresses);
  18769. X      alternate_addresses = NULL;
  18770. X      strcat (error, "\n");
  18771. X    }
  18772. X    reject_mail (sender, request, error, INVALID_REQ, 0);
  18773. X    return;
  18774. X  }
  18775. X  else if (status > SUBSCRIBED) { /* Notify manager */
  18776. X    NOTIFY_MANAGER ("Attempt to unsubscribe news or peer");
  18777. X    return;
  18778. X  }
  18779. X  /* Now move the current list of subscribers to a temporary file; then
  18780. X     copy each entry of this file to SUBSCRIBERS excluding the
  18781. X     user to be removed. */
  18782. X  sprintf (address, "^[\t ]*%s ", sender);
  18783. X  upcase (address);
  18784. X  if (cp (subscribersf, OLD_SUBSCRIBERS))
  18785. X    exit (16);
  18786. X  REMOVE_ADDRESS (address, OLD_SUBSCRIBERS, NEW_SUBSCRIBERS);
  18787. X#ifdef bsd
  18788. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18789. X#elif defined (svr4) || defined (svr3)
  18790. X  sighold (SIGINT);
  18791. X  sighold (SIGTERM);
  18792. X#endif
  18793. X  if (mv (NEW_SUBSCRIBERS, subscribersf))
  18794. X    exit (16);
  18795. X#ifdef bsd
  18796. X  sigsetmask (sig_mask);
  18797. X#elif defined (svr4) || defined (svr3)
  18798. X  sigrelse (SIGINT);
  18799. X  sigrelse (SIGTERM);
  18800. X#endif
  18801. X  if (cp (aliasesf, OLD_ALIASES))
  18802. X    exit (16);
  18803. X  REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  18804. X#ifdef bsd
  18805. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18806. X#elif defined (svr4) || defined (svr3)
  18807. X  sighold (SIGINT);
  18808. X  sighold (SIGTERM);
  18809. X#endif
  18810. X  if (mv (NEW_ALIASES, aliasesf))
  18811. X    exit (16);
  18812. X#ifdef bsd
  18813. X  sigsetmask (sig_mask);
  18814. X#elif defined (svr4) || defined (svr3)
  18815. X  sigrelse (SIGINT);
  18816. X  sigrelse (SIGTERM);
  18817. X#endif
  18818. X  if (cp (ALIASESF, OLD_ALIASES))
  18819. X    exit (16);
  18820. X  REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  18821. X#ifdef bsd
  18822. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18823. X#elif defined (svr4) || defined (svr3)
  18824. X  sighold (SIGINT);
  18825. X  sighold (SIGTERM);
  18826. X#endif
  18827. X  if (mv (NEW_ALIASES, ALIASESF))
  18828. X#ifdef bsd
  18829. X  sigsetmask (sig_mask);
  18830. X#elif defined (svr4) || defined (svr3)
  18831. X  sigrelse (SIGINT);
  18832. X  sigrelse (SIGTERM);
  18833. X#endif
  18834. X  sprintf (address, " %s[\t ]*$", sender);
  18835. X  upcase (address);
  18836. X  if (cp (aliasesf, OLD_ALIASES))
  18837. X    exit (16);
  18838. X  REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  18839. X#ifdef bsd
  18840. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18841. X#elif defined (svr4) || defined (svr3)
  18842. X  sighold (SIGINT);
  18843. X  sighold (SIGTERM);
  18844. X#endif
  18845. X  if (mv (NEW_ALIASES, aliasesf))
  18846. X    exit (16);
  18847. X#ifdef bsd
  18848. X  sigsetmask (sig_mask);
  18849. X#elif defined (svr4) || defined (svr3)
  18850. X  sigrelse (SIGINT);
  18851. X  sigrelse (SIGTERM);
  18852. X#endif
  18853. X  if (cp (ALIASESF, OLD_ALIASES))
  18854. X    exit (16);
  18855. X  REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  18856. X#ifdef bsd
  18857. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18858. X#elif defined (svr4) || defined (svr3)
  18859. X  sighold (SIGINT);
  18860. X  sighold (SIGTERM);
  18861. X#endif
  18862. X  if (mv (NEW_ALIASES, ALIASESF))
  18863. X    exit (16);
  18864. X#ifdef bsd
  18865. X  sigsetmask (sig_mask);
  18866. X#elif defined (svr4) || defined (svr3)
  18867. X  sigrelse (SIGINT);
  18868. X  sigrelse (SIGTERM);
  18869. X#endif
  18870. X  unlink (OLD_SUBSCRIBERS);
  18871. X  unlink (OLD_ALIASES);
  18872. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  18873. X         COPY_OWNER (ccunsub), OK, FALSE, FALSE);
  18874. X  fprintf (f, "You have been removed from list %s.\n\
  18875. XThanks for being with us.\n", sys.lists[listid].address);
  18876. X  COMPLETE_TELNET (f);
  18877. X  fclose (f);
  18878. X  DELIVER_MAIL (sender, COPY_OWNER (ccunsub));
  18879. X}
  18880. X
  18881. X/*
  18882. X  Subscribe a new user if he/she is not already subscribed. If the list
  18883. X  is remote, the request is forwarded. If the list is private, a message
  18884. X  is sent to the sender, and another one to the list owner requesting his
  18885. X  approval.
  18886. X*/
  18887. X
  18888. Xvoid subscribe (char *request, char *params, char *sender, BOOLEAN override)
  18889. X{
  18890. X  FILE *f;
  18891. X  char name [MAX_LINE];
  18892. X  char password [MAX_LINE];
  18893. X  char shell [MAX_LINE];
  18894. X  long int sig_mask;
  18895. X  int i;
  18896. X  BOOLEAN status;
  18897. X  BOOLEAN live;
  18898. X  BOOLEAN chaddr;
  18899. X
  18900. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  18901. X           params); /* Used as a subject */
  18902. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  18903. X    NOTIFY_OF_REQUEST_FORWARDING;
  18904. X    FORWARD_REQUEST;
  18905. X    return;
  18906. X  }
  18907. X  RESET (name);
  18908. X  clean_name (params); /* Remove extraneous characters */
  18909. X  sscanf (params, "%s\n", name);
  18910. X  if (name[0] == EOS) {  /* No user's name */
  18911. X    reject_mail (sender, request, "No name given to SUBSCRIBE\n\n\
  18912. XSyntax: subscribe <list> <Your Name>\n", SYNTAX_ERROR,
  18913. X         REJECT_NAME);
  18914. X    return;
  18915. X  }
  18916. X  if ((status = subscribed (report, sender, subscribersf, newsf, peersf,
  18917. X                aliasesf)) == SUBSCRIBED) {
  18918. X    reject_mail (sender, request,
  18919. X         tsprintf ("%s: You are already subscribed to %s\n", sender, 
  18920. X               sys.lists[listid].address), INVALID_REQ, 0);
  18921. X    return;
  18922. X  }
  18923. X  else if (status > SUBSCRIBED) { /* Notify manager */
  18924. X    NOTIFY_MANAGER ("Attempt to subscribe news or peer");
  18925. X    return;
  18926. X  }
  18927. X  if ((sys.lists[listid].options & NON_AUTO_SUB) &&
  18928. X      !owner_listed (OWNERSF, sender, sys.lists[listid].alias, report) &&
  18929. X      !override) { /* Notify sender/owner */
  18930. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  18931. X           RESTRICTED_REQ, FALSE, FALSE);
  18932. X    fprintf (f, "Subscription requests are not automatic for this list. \
  18933. XYour request has\nbeen forwarded to %s for approval.\n",
  18934. X         sys.lists[listid].owner);
  18935. X    COMPLETE_TELNET (f);
  18936. X    fclose (f);
  18937. X    DELIVER_MAIL (sender, FALSE);
  18938. X    create_header (&f, MAILFORWARD, sys.server.address, sys.lists[listid].owner,
  18939. X           "Subscription approval request", FALSE, OK, FALSE, FALSE);
  18940. X    fprintf (f, "User %s has requested subscription to list %s\n\
  18941. XIf you approve, send the following request to %s:\n\n\
  18942. Xsystem %s <password> %s #%s\n\n\
  18943. Xwhere 'password' is the list's password, as given to you by the manager of\n\
  18944. Xthis system.\n",
  18945. X         sender, sys.lists[listid].alias, sys.server.address,
  18946. X         sys.lists[listid].alias, sender, request);
  18947. X    COMPLETE_TELNET (f);
  18948. X    fclose (f);
  18949. X    DELIVER_MAIL (sys.lists[listid].owner, FALSE);
  18950. X    return;
  18951. X  }
  18952. X#ifdef bsd
  18953. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  18954. X#elif defined (svr4) || defined (svr3)
  18955. X  sighold (SIGINT);
  18956. X  sighold (SIGTERM);
  18957. X#endif
  18958. X  OPEN_FILE (f, subscribersf, "a", "subscribe"); /* Automatic subscription */
  18959. X  fprintf (f, "%s ", sender);
  18960. X  for (i = 1; i < MAX_SET_OPTIONS; i++)  /* Copy all options */
  18961. X    if (sys.lists[listid].defaults.set_values[i][0] != EOS) {
  18962. X      if (i == 2)
  18963. X    strcpy (password, sys.lists[listid].defaults.set_values[i]);
  18964. X      fprintf (f, "%s ", sys.lists[listid].defaults.set_values[i]);
  18965. X    }
  18966. X    else if (i != 2)    /* Not a password */
  18967. X      fprintf (f, "%s ", default_values[i]);
  18968. X    else
  18969. X      sprintf (password, "%d", time (0)),
  18970. X      fprintf (f, "%s ", password);
  18971. X  clean_request (params); /* Remove leading blanks from name */
  18972. X  fprintf (f, "%s\n", params);
  18973. X  fclose (f);
  18974. X  REARRANGE_SUBSCRIBERS;
  18975. X#ifdef bsd
  18976. X  sigsetmask (sig_mask);
  18977. X#elif defined (svr4) || defined (svr3)
  18978. X  sigrelse (SIGINT);
  18979. X  sigrelse (SIGTERM);
  18980. X#endif
  18981. X  live = (_strstr (sys.serverd_cmdoptions, "-i") != NULL);
  18982. X  chaddr = (sys.lists[listid].defaults.set_values[0][0] == EOS &&
  18983. X        !strcmp (default_values [0], "VARIABLE")) ||
  18984. X          (!strcmp (sys.lists[listid].defaults.set_values[0], "VARIABLE"));
  18985. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  18986. X         COPY_OWNER (ccsub), OK, FALSE, FALSE);
  18987. X  fprintf (f, "You have been added to list %s. The system has recorded\nyour \
  18988. Xaddress as %s and in order for your messages to get posted,\nyou will have to \
  18989. Xsend them from this address. If a message is ever rejected,\nplease contact \
  18990. Xthe list's owner: %s\n\n",
  18991. X       sys.lists[listid].address, sender, sys.lists[listid].owner);
  18992. X  if (live || chaddr)  {
  18993. X    fprintf (f, "Your initial password is %s. Please change it as soon as you \
  18994. Xcan\nby issuing the following request to %s:\n\n\
  18995. X\t\tset %s password %s new-password\n\n",
  18996. X         password, sys.server.address, sys.lists[listid].alias, password);
  18997. X    if (live)
  18998. X      fprintf (f, "This system may accept Internet TCP/IP connections for \
  18999. Xprocessing of live\nrequests, and the password will be used to give you \
  19000. Xsubscriber privileges.\nFor more information, send a 'help live' request to \
  19001. X%s.\n\n", sys.server.address);
  19002. X    if (chaddr)
  19003. X      fprintf (f, "You may change the address you \
  19004. Xare subscribed with (currently %s)\nwith the following request:\n\n\
  19005. X\t\tset %s address %s new-address\n\nassuming that you keep the same \
  19006. Xpassword.\n\n", sender, sys.lists[listid].alias, password);
  19007. X  }
  19008. X  fprintf (f, "All requests should be addressed to %s.\n", sys.server.address);
  19009. X  fclose (f);
  19010. X  strcpy (shell, "cat");
  19011. X  if ((f = fopen (welcomef, "r"))) {
  19012. X    fgets (shell, 3, f);
  19013. X    if (!strncmp (shell, "#!", 2)) {
  19014. X      fgets (shell, MAX_LINE - 2, f);
  19015. X      if (shell [strlen (shell) - 1] == '\n')
  19016. X    shell [strlen (shell) - 1] = EOS;
  19017. X    }
  19018. X    else
  19019. X      strcpy (shell, "cat");
  19020. X    fclose (f);
  19021. X  }
  19022. X  syscom ("%s %s >> %s", shell, welcomef, MAILFORWARD);
  19023. X  APPEND_TELNET ("subscribe");
  19024. X  DELIVER_MAIL (sender, COPY_OWNER (ccsub));
  19025. X}
  19026. X
  19027. X/*
  19028. X  Tell 'sender' what list(s) he/she is subscribed in.
  19029. X*/
  19030. X
  19031. Xvoid which (char *request, char *params, char *sender)
  19032. X{
  19033. X  char subscribersf [MAX_LINE];
  19034. X  char aliasesf [MAX_LINE];
  19035. X  char param [MAX_LINE];
  19036. X  FILE *f;
  19037. X  int i;
  19038. X
  19039. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  19040. X  RESET (param);
  19041. X  sscanf (params, "%s", param);
  19042. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  19043. X    reject_mail (sender, request, tsprintf ("Invalid WHICH option%s\n\
  19044. XSyntax: which\n", params), SYNTAX_ERROR, 0);
  19045. X    return;
  19046. X  }
  19047. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  19048. X         OK, FALSE, FALSE);
  19049. X  fprintf (f, "%s: You are subscribed to the following lists;\nif none appear, \
  19050. Xyou are not subscribed to any:\n", sender);
  19051. X  for (i = 0; i < nlists; ++i) {
  19052. X    setup_string (subscribersf, sys.lists[i].alias, SUBSCRIBERS);
  19053. X    setup_string (aliasesf, sys.lists[i].alias, ALIASES);
  19054. X    if (subscribed (report, sender, subscribersf, NULL, NULL, aliasesf) ==
  19055. X    SUBSCRIBED)
  19056. X      fprintf (f, "%s\n", sys.lists[i].alias);
  19057. X  }
  19058. X  COMPLETE_TELNET (f);
  19059. X  fclose (f);
  19060. X  DELIVER_MAIL (sender, FALSE);
  19061. X}
  19062. X
  19063. X/*
  19064. X  Set options for user if he/she is subscribed. If the list is remote,
  19065. X  the request is forwarded. If resetting MAIL ACK/NOACK/POSTPONE from
  19066. X  DIGEST, send a partial digest.
  19067. X  Adding more SET options:
  19068. X  - In defs.h, define the new MAX_SET_OPTIONS.
  19069. X  - In global.h, define the new option in options[], the valid
  19070. X    values in values[] and the default_values[].
  19071. X  - the MAIL option should be second in the list; this assumption is made by
  19072. X    list and listserv.
  19073. X*/
  19074. X
  19075. Xvoid set (char *request, char *params, char *sender)
  19076. X{
  19077. X  FILE *f, *from, *to;
  19078. X  char error [10240];
  19079. X  char option [MAX_LINE];
  19080. X  char subscriber [MAX_LINE];
  19081. X  char oldmodes [MAX_SET_OPTIONS] [MAX_LINE];
  19082. X  char newmode [MAX_LINE];
  19083. X  char moreparams [MAX_LINE];
  19084. X  char name [MAX_LINE];
  19085. X  char address [MAX_LINE];
  19086. X  char *blank;
  19087. X  int  i, j, index;
  19088. X  long int sig_mask;
  19089. X  BOOLEAN status, ok_to_reset_address = FALSE;
  19090. X
  19091. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  19092. X           params); /* Used as a subject */
  19093. X  error[0] = option[0] = moreparams[0] = RESET (newmode);
  19094. X  sscanf (params, "%s %s %s\n", option, newmode, moreparams); /* Get params */
  19095. X  upcase (option);
  19096. X  upcase (newmode);
  19097. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  19098. X    NOTIFY_OF_REQUEST_FORWARDING;
  19099. X    FORWARD_REQUEST;
  19100. X    return;
  19101. X  }
  19102. X  if ((sys.lists[listid].defaults.set_values[0][0] == EOS &&
  19103. X       !strcmp (default_values [0], "VARIABLE")) ||
  19104. X      (!strcmp (sys.lists[listid].defaults.set_values[0], "VARIABLE")))
  19105. X    ok_to_reset_address = TRUE;
  19106. X  if (!(status = subscribed (report, sender, subscribersf, newsf, peersf,
  19107. X                 aliasesf))) {
  19108. X    sprintf (error, "%s: You are not subscribed to %s\n", sender,
  19109. X             sys.lists[listid].address);
  19110. X    if (alternate_addresses) {
  19111. X      sprintf (error + strlen (error),
  19112. X           "\nIn addition, the system found the following \
  19113. Xaddress(es) that resemble yours.\nIf one of these is you, please resend your \
  19114. Xmessage from that one%s:\n\n",
  19115. X           (ok_to_reset_address ?
  19116. X        ", or use the\n'set <list> address' request to change the \
  19117. Xaddress you are subscribed with" :
  19118. X        ""));
  19119. X      for (i = 0; alternate_addresses[i]; ++i)
  19120. X    sprintf (error + strlen (error), "%s\n", alternate_addresses[i]),
  19121. X    free ((char *) alternate_addresses[i]);
  19122. X      free ((char **) alternate_addresses);
  19123. X      alternate_addresses = NULL;
  19124. X      strcat (error, "\n");
  19125. X    }
  19126. X    reject_mail (sender, request, error, INVALID_REQ, 0);
  19127. X    return;
  19128. X  }
  19129. X  else if (status > SUBSCRIBED) { /* Notify manager */
  19130. X    NOTIFY_MANAGER ("Attempt to set mode for news or peer");
  19131. X    return;
  19132. X  }
  19133. X  if (option[0] != EOS) {
  19134. X    for (index = 0; index < MAX_SET_OPTIONS; index++)
  19135. X      if (! strcmp (option, options[index]))
  19136. X    break;
  19137. X    if (index == MAX_SET_OPTIONS) {
  19138. X      reject_mail (sender, request, tsprintf ("Invalid SET option %s\n\n\
  19139. XSyntax: set <list> [<option> <arg[s]>]\n\
  19140. X\toption: mail, password, address, conceal\n\
  19141. X\targ for 'mail': ack/noack/postpone/digest\n\
  19142. X\targs for 'password': <current-password> <new-password>\n\
  19143. X\targs for 'address': <current-password> <new-address>\n\
  19144. X\targ for 'conceal': yes/no\n", option), SYNTAX_ERROR, 0);
  19145. X      return;
  19146. X    }
  19147. X    if (newmode[0] == EOS ||
  19148. X    (!strcmp (option, options[0]) && moreparams[0] == EOS) ||
  19149. X    (!strcmp (option, options[2]) && moreparams[0] == EOS)) {
  19150. X      reject_mail (sender, request, tsprintf ("Missing SET %s value\n\n\
  19151. XSyntax: set <list> [<option> <arg[s]>]\n\
  19152. X\toption: mail, password, address, conceal\n\
  19153. X\targ for 'mail': ack/noack/postpone/digest\n\
  19154. X\targs for 'password': <current-password> <new-password>\n\
  19155. X\targs for 'address': <current-password> <new-address>\n\
  19156. X\targ for 'conceal': yes/no\n", options[index]), SYNTAX_ERROR, 0);
  19157. X      return;
  19158. X    }
  19159. X    if (index > 0 &&
  19160. X    !strinstr (values[index], (index == 1 || index == 3 ?
  19161. X                   newmode : moreparams))) {
  19162. X      reject_mail (sender, request, tsprintf ("Invalid SET %s value %s\n\n\
  19163. XSyntax: set <list> [<option> <arg[s]>]\n\
  19164. X\toption: mail, password, address, conceal\n\
  19165. X\targ for 'mail': ack/noack/postpone/digest\n\
  19166. X\targs for 'password': <current-password> <new-password>\n\
  19167. X\targs for 'address': <current-password> <new-address>\n\
  19168. X\targ for 'conceal': yes/no\n", options[index], newmode), SYNTAX_ERROR, 0);
  19169. X      return;
  19170. X    }
  19171. X  }
  19172. X  if (moreparams[0] != EOS && strcmp (option, options[0]) &&
  19173. X      strcmp (option, options[2]) && !(sys.options & RELAXED_SYNTAX)) {
  19174. X    reject_mail (sender, request, tsprintf ("Too many SET parameters: %s\n\n\
  19175. XSyntax: set <list> [<option> <arg[s]>]\n\
  19176. X\toption: mail, password, address, conceal\n\
  19177. X\targ for 'mail': ack/noack/postpone/digest\n\
  19178. X\targs for 'password': <current-password> <new-password>\n\
  19179. X\targs for 'address': <current-password> <new-address>\n\
  19180. X\targ for 'conceal': yes/no\n", moreparams), SYNTAX_ERROR, 0);
  19181. X    return;
  19182. X  }
  19183. X  if (option[0] == EOS) { /* Status inquiry */
  19184. X#if defined (__NeXT__) || defined (unknown_port)
  19185. X    syscom ("grep -i '^[ \t]*%s ' %s | \
  19186. X%s '{ printf \"%%s\", $1; for (i = 1; i <= %d; ++i) printf \" %%s\", $i; \
  19187. Xprintf \"\\n\" }' > %s",
  19188. X        sender, subscribersf, AWK, MAX_SET_OPTIONS, OLD_SUBSCRIBERS);
  19189. X#else
  19190. X    syscom ("grep -i '^[ \t]*%s ' %s | %s -d' ' -f1-%d > %s", sender,
  19191. X        subscribersf, CUT, MAX_SET_OPTIONS, OLD_SUBSCRIBERS);
  19192. X#endif
  19193. X    if (! one_rejection) {
  19194. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19195. X             COPY_OWNER (ccset), OK, FALSE, FALSE);
  19196. X      fprintf (f, "Current settings are:\n\n");
  19197. X      OPEN_FILE (from, OLD_SUBSCRIBERS, "r", "set");
  19198. X      for (i = 0; i < MAX_SET_OPTIONS; i++)
  19199. X    RESET (newmode),
  19200. X    fscanf (from, "%s ", newmode),
  19201. X    fprintf (f, "%s = %s\n", options[i], newmode);
  19202. X      fflush (f);
  19203. X      fclose (from);
  19204. X      COMPLETE_TELNET (f);
  19205. X      fclose (f);
  19206. X      DELIVER_MAIL (sender, COPY_OWNER (ccset));
  19207. X      unlink (OLD_SUBSCRIBERS);
  19208. X      return;
  19209. X    }
  19210. X  }
  19211. X  /* Change of mode */
  19212. X  if (cp (subscribersf, OLD_SUBSCRIBERS))
  19213. X    exit (16);
  19214. X  OPEN_FILE (from, OLD_SUBSCRIBERS, "r", "set");
  19215. X  OPEN_FILE (to, NEW_SUBSCRIBERS, "w", "set");
  19216. X  while (!feof (from)) {
  19217. X    subscriber[0] = RESET (name);
  19218. X    if (!extract_subscriber (from, subscriber, FALSE)) {
  19219. X      NOTIFY_MANAGER_OF_INVALID_USER_ADDRESS (subscriber);
  19220. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19221. X             COPY_OWNER (ccset), OK, FALSE, FALSE);
  19222. X      fprintf (f, "Sorry, a system error has occured. Try again later.\n");
  19223. X      COMPLETE_TELNET (f);
  19224. X      fclose (f);
  19225. X      DELIVER_MAIL (sender, COPY_OWNER (ccset));
  19226. X      fclose (from);
  19227. X      fclose (to);
  19228. X      unlink (OLD_SUBSCRIBERS);
  19229. X      unlink (NEW_SUBSCRIBERS);
  19230. X      return;
  19231. X    }
  19232. X    strcpy (oldmodes[0], subscriber);
  19233. X    for (i = 1; i < MAX_SET_OPTIONS; i++)
  19234. X      RESET (oldmodes[i]),
  19235. X      fscanf (from, "%s ", oldmodes[i]);
  19236. X    fgets (name, MAX_LINE - 2, from);
  19237. X    upcase (subscriber);
  19238. X    if (!feof (from)) {
  19239. X      if (! strcmp (sender, subscriber))
  19240. X    for (i = 0; i < MAX_SET_OPTIONS; i++) {
  19241. X      if (i == 0) {
  19242. X        if (!strcmp (option, options[0]))
  19243. X          if (!ok_to_reset_address)
  19244. X        fprintf (to, "%s ", subscriber),
  19245. X        reject_mail (sender, request, "Changing of address is not \
  19246. Xallowed for this list.\n", RESTRICTED_REQ, 0);
  19247. X          else
  19248. X        if (strcmp (newmode, oldmodes[2])) /* Invalid password */
  19249. X          fprintf (to, "%s ", subscriber),
  19250. X          reject_mail (sender, request,
  19251. X                   tsprintf ("Password verification failure: %s\n",
  19252. X                     newmode), SYNTAX_ERROR, 0);
  19253. X        else {
  19254. X          sprintf (address, "From %s", moreparams);
  19255. X          if (!extract_sender (address))
  19256. X            fprintf (to, "%s ", subscriber),
  19257. X            reject_mail (sender, request,
  19258. X                 tsprintf ("Invalid address: %s\n", moreparams),
  19259. X                 SYNTAX_ERROR, 0);
  19260. X          else {
  19261. X            sprintf (address, "^[\t ]*%s ", sender);
  19262. X            if (cp (aliasesf, OLD_ALIASES))
  19263. X              exit (16);
  19264. X            REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  19265. X#ifdef bsd
  19266. X            sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  19267. X#elif defined (svr4) || defined (svr3)
  19268. X            sighold (SIGINT);
  19269. X            sighold (SIGTERM);
  19270. X#endif
  19271. X            if (mv (NEW_ALIASES, aliasesf))
  19272. X              exit (16);
  19273. X#ifdef bsd
  19274. X            sigsetmask (sig_mask);
  19275. X#elif defined (svr4) || defined (svr3)
  19276. X            sigrelse (SIGINT);
  19277. X            sigrelse (SIGTERM);
  19278. X#endif
  19279. X            if (cp (ALIASESF, OLD_ALIASES))
  19280. X              exit (16);
  19281. X            REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  19282. X#ifdef bsd
  19283. X            sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  19284. X#elif defined (svr4) || defined (svr3)
  19285. X            sighold (SIGINT);
  19286. X            sighold (SIGTERM);
  19287. X#endif
  19288. X            if (mv (NEW_ALIASES, ALIASESF))
  19289. X              exit (16);
  19290. X#ifdef bsd
  19291. X    sigsetmask (sig_mask);
  19292. X#elif defined (svr4) || defined (svr3)
  19293. X    sigrelse (SIGINT);
  19294. X    sigrelse (SIGTERM);
  19295. X#endif
  19296. X            sprintf (address, " %s[\t ]*$", sender);
  19297. X            if (cp (aliasesf, OLD_ALIASES))
  19298. X              exit (16);
  19299. X            REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  19300. X#ifdef bsd
  19301. X            sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  19302. X#elif defined (svr4) || defined (svr3)
  19303. X            sighold (SIGINT);
  19304. X            sighold (SIGTERM);
  19305. X#endif
  19306. X            if (mv (NEW_ALIASES, aliasesf))
  19307. X              exit (16);
  19308. X#ifdef bsd
  19309. X            sigsetmask (sig_mask);
  19310. X#elif defined (svr4) || defined (svr3)
  19311. X            sigrelse (SIGINT);
  19312. X            sigrelse (SIGTERM);
  19313. X#endif
  19314. X            if (cp (ALIASESF, OLD_ALIASES))
  19315. X              exit (16);
  19316. X            REMOVE_ADDRESS (address, OLD_ALIASES, NEW_ALIASES);
  19317. X#ifdef bsd
  19318. X            sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  19319. X#elif defined (svr4) || defined (svr3)
  19320. X            sighold (SIGINT);
  19321. X            sighold (SIGTERM);
  19322. X#endif
  19323. X            if (mv (NEW_ALIASES, ALIASESF))
  19324. X              exit (16);
  19325. X#ifdef bsd
  19326. X            sigsetmask (sig_mask);
  19327. X#elif defined (svr4) || defined (svr3)
  19328. X            sigrelse (SIGINT);
  19329. X            sigrelse (SIGTERM);
  19330. X#endif
  19331. X            unlink (OLD_ALIASES);
  19332. X            if (echo_append (tsprintf ("%s %s", subscriber,
  19333. X                           moreparams), aliasesf))
  19334. X              exit (16);
  19335. X            if (echo_append (tsprintf ("%s %s", subscriber,
  19336. X                           moreparams), ALIASESF))
  19337. X              exit (16);
  19338. X            fprintf (to, "%s ", moreparams); /* Put new address */
  19339. X          }
  19340. X        }
  19341. X        else
  19342. X          fprintf (to, "%s ", subscriber);
  19343. X      }
  19344. X      else if (i == 2 && !strcmp (option, options[2]) &&
  19345. X           strcmp (newmode, oldmodes[i])) /* Invalid old password */
  19346. X        fprintf (to, "%s ", oldmodes[i]),
  19347. X        reject_mail (sender, request,
  19348. X             tsprintf ("Password verification failure: %s\n", newmode),
  19349. X             SYNTAX_ERROR, 0);
  19350. X      else
  19351. X        fprintf (to, "%s ", (i == index ? 
  19352. X             (strcmp (option, options[2]) ? newmode : moreparams) :
  19353. X             oldmodes[i]));
  19354. X      if (strcmp (newmode, DIGEST) && strcmp (newmode, POSTPONE) &&
  19355. X          !strcmp (oldmodes[i], DIGEST))
  19356. X        /* Turned off DIGEST, send a partial digest */
  19357. X        syscom ("%s %s -i%s %s", LIST, sys.lists[listid].alias,
  19358. X           sender, sys.lists[i].cmdoptions);
  19359. X    }
  19360. X      else
  19361. X    for (i = 0; i < MAX_SET_OPTIONS; i++)
  19362. X      fprintf (to, "%s ", oldmodes[i]);
  19363. X      clean_request (name); /* Remove leading blanks */
  19364. X      fprintf (to, "%s", name);
  19365. X    }
  19366. X  }
  19367. X  fclose (from);
  19368. X  fclose (to);
  19369. X#ifdef bsd
  19370. X    sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  19371. X#elif defined (svr4) || defined (svr3)
  19372. X    sighold (SIGINT);
  19373. X    sighold (SIGTERM);
  19374. X#endif
  19375. X  if (mv (NEW_SUBSCRIBERS, subscribersf))
  19376. X    exit (16);
  19377. X#ifdef bsd
  19378. X    sigsetmask (sig_mask);
  19379. X#elif defined (svr4) || defined (svr3)
  19380. X    sigrelse (SIGINT);
  19381. X    sigrelse (SIGTERM);
  19382. X#endif
  19383. X  unlink (OLD_SUBSCRIBERS);
  19384. X  if (! one_rejection) {
  19385. X    blank = request;
  19386. X    (index == 0 ? (j = 3) : (j = 4));
  19387. X    for (i = 0; i < j; i++)
  19388. X      blank = strchr (blank + 1, ' ');
  19389. X    ++blank;
  19390. X    shadow_password (blank);
  19391. X    create_header (&f, MAILFORWARD, sys.server.address, 
  19392. X           (index == 0 ? moreparams : sender), request,
  19393. X           COPY_OWNER (ccset), OK, FALSE, FALSE);
  19394. X    fprintf (f, "%s mode reset to %s\n", options[index],
  19395. X         (index == 0 || index == 2 ? moreparams : newmode));
  19396. X    COMPLETE_TELNET (f);
  19397. X    fclose (f);
  19398. X    if (!index) {
  19399. X      DELIVER_MAIL (moreparams, COPY_OWNER (ccset));
  19400. X    }
  19401. X    else
  19402. X      DELIVER_MAIL (sender, COPY_OWNER (ccset));
  19403. X  }
  19404. X}
  19405. X
  19406. X/*
  19407. X  Provide user with the current list of subscribers. Peer servers are
  19408. X  also notified and they send their own compilations. If the list is
  19409. X  remote, the request is forwarded.
  19410. X  For private lists, only members may make this request.
  19411. X*/
  19412. X
  19413. Xvoid recipients (char *request, char *params, char *sender)
  19414. X{
  19415. X  char param [MAX_LINE];
  19416. X  FILE *f;
  19417. X
  19418. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  19419. X           params); /* Used as a subject */
  19420. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  19421. X    NOTIFY_OF_REQUEST_FORWARDING;
  19422. X    FORWARD_REQUEST;
  19423. X    return;
  19424. X  }
  19425. X  RESET (param);
  19426. X  sscanf (params, "%s", param);
  19427. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  19428. X    reject_mail (sender, request, tsprintf ("Invalid RECIPIENTS option%s\n\
  19429. XSyntax: recipients <list> (or review <list>)\n", params), SYNTAX_ERROR, 0);
  19430. X    return;
  19431. X  }
  19432. X  if (sys.lists[listid].options & NON_AUTO_SUB) { /* Private list */
  19433. X    if (subscribed (report, sender, subscribersf, NULL, NULL, aliasesf) ==
  19434. X    NOTSUBSCRIBED) {
  19435. X      MEMBERS_ONLY;
  19436. X      return;
  19437. X    }
  19438. X  }
  19439. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19440. X         COPY_OWNER (ccrec), OK, FALSE, FALSE);
  19441. X  fprintf (f, "Here is the current list of non-concealed subscribers:\n\n");
  19442. X  fclose (f);
  19443. X#if defined (__NeXT__) || defined (unknown_port)
  19444. X  syscom ("%s '{ printf \"%%s\", $1; for (i = %d; i <= %d; ++i) \
  19445. Xprintf \" %%s\", $i; printf \"\\n\" }' %s | grep -i ' NO ' | \
  19446. X%s '{ printf \"%%s\", $1; for (i = 3; i <= %d; ++i) printf \" %%s\", $i; \
  19447. Xprintf \"\\n\" }' > %s",
  19448. X      AWK, MAX_SET_OPTIONS, MAX_SET_OPTIONS + 5, subscribersf, AWK,
  19449. X      MAX_SET_OPTIONS + 4, recipf);
  19450. X#else
  19451. X  syscom ("%s -d\" \" -f1,%d-%d %s | grep -i ' NO ' | %s -d\" \" -f1,3-%d \
  19452. X> %s", CUT, MAX_SET_OPTIONS, MAX_SET_OPTIONS + 5, subscribersf, CUT,
  19453. X      MAX_SET_OPTIONS + 4, recipf);
  19454. X#endif
  19455. X  syscom ("%s -f %s %s >> %s", AWK, AWK_PROG, recipf, MAILFORWARD);
  19456. X  syscom ("echo Total number of subscribers: `cat %s | wc -l` \
  19457. X\"(`cat %s | wc -l | tr -d ' '` shown here)\" >> %s", subscribersf, recipf,
  19458. X      MAILFORWARD);
  19459. X  unlink (recipf);
  19460. X  APPEND_TELNET ("recipients");
  19461. X  DELIVER_MAIL (sender, COPY_OWNER (ccrec));
  19462. X  notify_peer_servers (peersf, "review", params, sender);
  19463. X}
  19464. X
  19465. X/*
  19466. X  Provide user with general information about the list. A reminder, the
  19467. X  actual text is in the INFO_FILE. If the list is remote, the request
  19468. X  is forwarded.
  19469. X*/
  19470. X
  19471. Xvoid info (char *request, char *params, char *sender)
  19472. X{
  19473. X  char param [MAX_LINE];
  19474. X  char shell [MAX_LINE];
  19475. X  FILE *f;
  19476. X
  19477. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  19478. X           params); /* Used as a subject */
  19479. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  19480. X    NOTIFY_OF_REQUEST_FORWARDING;
  19481. X    FORWARD_REQUEST;
  19482. X    return;
  19483. X  }
  19484. X  RESET (param);
  19485. X  sscanf (params, "%s", param);
  19486. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  19487. X    reject_mail (sender, request, tsprintf ("Invalid INFORMATION option%s\n\
  19488. XSyntax: information <list>\n", params), SYNTAX_ERROR, 0);
  19489. X    return;
  19490. X  }
  19491. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19492. X         COPY_OWNER (ccinfo), OK, FALSE, FALSE);
  19493. X  fclose (f);
  19494. X  strcpy (shell, "cat");
  19495. X  if ((f = fopen (infof, "r"))) {
  19496. X    fgets (shell, 3, f);
  19497. X    if (!strncmp (shell, "#!", 2)) {
  19498. X      fgets (shell, MAX_LINE - 2, f);
  19499. X      if (shell [strlen (shell) - 1] == '\n')
  19500. X    shell [strlen (shell) - 1] = EOS;
  19501. X    }
  19502. X    else
  19503. X      strcpy (shell, "cat");
  19504. X    fclose (f);
  19505. X  }
  19506. X  syscom ("%s %s >> %s", shell, infof, MAILFORWARD);
  19507. X  APPEND_TELNET ("info");
  19508. X  DELIVER_MAIL (sender, COPY_OWNER (ccinfo));
  19509. X}
  19510. X
  19511. X/*
  19512. X  Collect and send statistics about all subscribers, by grepping through
  19513. X  HEADERS. If a user has selected particular names (asterisks are OK) then
  19514. X  give statistics about these people only. Also include a total count
  19515. X  of messages on file. Peer servers are also notified and they send their
  19516. X  own compilations. If the list is remote, the request is forwarded.
  19517. X  For private lists, only members may make this request.
  19518. X*/
  19519. X
  19520. Xvoid stats (char *request, char *params, char *sender)
  19521. X{
  19522. X  FILE *f;
  19523. X  char junk [MAX_LINE];
  19524. X  struct stat stat_buf;
  19525. X
  19526. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  19527. X           params); /* Used as a subject */
  19528. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  19529. X    NOTIFY_OF_REQUEST_FORWARDING;
  19530. X    FORWARD_REQUEST;
  19531. X    return;
  19532. X  }
  19533. X  if (sys.lists[listid].options & NON_AUTO_SUB) { /* Private list */
  19534. X    if (subscribed (report, sender, subscribersf, NULL, NULL, aliasesf) ==
  19535. X    NOTSUBSCRIBED) {
  19536. X      MEMBERS_ONLY;
  19537. X      return;
  19538. X    }
  19539. X  }
  19540. X  params [strlen (params) - 1] = EOS; /* Remove \n */
  19541. X  RESET (junk);
  19542. X  sscanf (params, "%s", junk);
  19543. X  if (junk[0] == EOS) /* No specific subscribers to report on */
  19544. X    RESET (params);
  19545. X  if (stat (headersf, &stat_buf)) {
  19546. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, no mail archive found.\n", NULL, OK);
  19547. X    return;
  19548. X  }
  19549. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19550. X         COPY_OWNER (ccstat), OK, FALSE, FALSE);
  19551. X  fprintf (f, "Here are the number of messages per non-concealed subscriber:\
  19552. X\n\n");
  19553. X  fclose (f);
  19554. X  EXEC_STATS;
  19555. X  APPEND_TELNET ("stats");
  19556. X  DELIVER_MAIL (sender, COPY_OWNER (ccstat));
  19557. X  notify_peer_servers (peersf, "stat", params, sender);
  19558. X}
  19559. X
  19560. X/*
  19561. X  Exit with a shutdown status if the correct password is provided.
  19562. X*/
  19563. X
  19564. Xvoid Shutdown (char *request, char *params, char *sender)
  19565. X{
  19566. X  char passwd [MAX_LINE];
  19567. X
  19568. X  sscanf (params, "%s\n", passwd);
  19569. X  if (!strcmp (sys.server.password, passwd))
  19570. X    report_progress (report, "SHUTDOWN request accepted", TRUE),
  19571. X    gexit (6); /* Exit status of 6 signifies a shutdown request */
  19572. X  reject_mail (sender, request, tsprintf ("Unrecognized request %s\n", request),
  19573. X           INVALID_REQ, 0);
  19574. X}
  19575. X
  19576. X/*
  19577. X  Set the global variable 'restart_sys' to TRUE if the correct password
  19578. X  is given.
  19579. X*/
  19580. X
  19581. Xvoid restart (char *request, char *params, char *sender)
  19582. X{
  19583. X  char passwd [MAX_LINE];
  19584. X
  19585. X  sscanf (params, "%s\n", passwd);
  19586. X  if (!strcmp (sys.server.password, passwd)) { 
  19587. X    report_progress (report, "RESTART request accepted\n", FALSE);
  19588. X    restart_sys = TRUE;
  19589. X    return;
  19590. X  }
  19591. X  reject_mail (sender, request, tsprintf ("Unrecognized request %s\n", request),
  19592. X           INVALID_REQ, 0);
  19593. X}
  19594. X
  19595. X/*
  19596. X  Provide 'sender' with a list of all mailing lists served by this server,
  19597. X  as well as any remote lists known to this server.
  19598. X*/
  19599. X
  19600. Xvoid lists (char *request, char *params, char *sender)
  19601. X{
  19602. X  char param [MAX_LINE];
  19603. X  FILE *f;
  19604. X  int i, alslen, lstlen, adrlen, len, _nlists;
  19605. X  REMOTE *r = rlists, *s = rlists;
  19606. X
  19607. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  19608. X  RESET (param);
  19609. X  sscanf (params, "%s", param);
  19610. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  19611. X    reject_mail (sender, request, tsprintf ("Invalid LISTS option%s\n\
  19612. XSyntax: lists\n", params), SYNTAX_ERROR, 0);
  19613. X    return;
  19614. X  }
  19615. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19616. X         COPY_OWNER (cclists), OK, FALSE, FALSE);
  19617. X  adrlen = -99;
  19618. X  for (i = 0, _nlists = 0; i < nlists; ++i) /* Get longest address */
  19619. X    if (!(sys.lists[i].options & CONCEAL_LIST)) {
  19620. X      ++_nlists;
  19621. X      if ((len = strlen (sys.lists[i].address)) > adrlen)
  19622. X    adrlen = len;
  19623. X    }
  19624. X  fprintf (f, "Here is the current active list of the %d mailing lists \
  19625. Xserved by this server:\n\n", _nlists);
  19626. X  for (i = 0; i < nlists; ++i)
  19627. X    if (!(sys.lists[i].options & CONCEAL_LIST))
  19628. X      fprintf (f, "%-*s  %s\n", adrlen, sys.lists[i].address,
  19629. X           sys.lists[i].comment);
  19630. X
  19631. X  if (rlists) { /* List all remote lists */
  19632. X    i = 0;
  19633. X    fprintf (f, "\nIn addition, the following remote lists are known to this \
  19634. Xserver:\n\n");
  19635. X    alslen = strlen ("ALIAS");
  19636. X    adrlen = strlen ("FULL ADDRESS");
  19637. X    lstlen = strlen ("LISTSERVER ADDRESS");
  19638. X    while (s) {
  19639. X      if ((len = strlen (s->alias)) > alslen)
  19640. X    alslen = len;
  19641. X      if ((len = strlen (s->address)) > adrlen)
  19642. X        adrlen = len;
  19643. X      if ((len = strlen (s->listserv)) > lstlen)
  19644. X        lstlen = len;
  19645. X      s = s->next;
  19646. X    }
  19647. X    fprintf (f, "%-*s %-*s %-*s COMMENT\n%-*s %-*s %-*s -------\n",
  19648. X       alslen, "ALIAS", adrlen, "FULL ADDRESS", lstlen, "LISTSERVER ADDRESS",
  19649. X       alslen, "-----", adrlen, "------------", lstlen, "------------------");
  19650. X    while (r)
  19651. X      ++i,
  19652. X      fprintf (f, "%-*s %-*s %-*s %s\n", alslen, r->alias, adrlen,
  19653. X           r->address, lstlen, r->listserv, r->comment),
  19654. X      r = r->next;
  19655. X    fprintf (f, "\nTotal number of remote lists: %d. Requests sent to \
  19656. Xthis server for these\nremote lists will be forwarded to the servers \
  19657. Xserving these lists.\n", i);
  19658. X  }
  19659. X  COMPLETE_TELNET (f);
  19660. X  fclose (f);
  19661. X  DELIVER_MAIL (sender, COPY_OWNER (cclists));
  19662. X}
  19663. X
  19664. X/*
  19665. X  Get an index of files for the specified archive, or the master archive
  19666. X  if none specified. Private archives require a password to list their
  19667. X  files.
  19668. X
  19669. X  Adapted USER CONTRIBUTED FUNCTION: Stefan Schroer.
  19670. X*/
  19671. X
  19672. Xvoid Index (char *request, char *params, char *sender)
  19673. X{
  19674. X  FILE *f, *index, *dir, *master;
  19675. X  char archive [MAX_LINE];
  19676. X  char arch [MAX_LINE];
  19677. X  char cur_archive [MAX_LINE];
  19678. X  char line [MAX_LINE];
  19679. X  char file [MAX_LINE];
  19680. X  char fullpath [MAX_LINE];
  19681. X  char moreparams [MAX_LINE];
  19682. X  char fullname [MAX_LINE];
  19683. X  char desc [MAX_LINE];
  19684. X  char junk [MAX_LINE];
  19685. X  char user_password [MAX_LINE];
  19686. X  char sys_password [MAX_LINE];
  19687. X  char *slash;
  19688. X  BOOLEAN found, continued, header_printed, all = FALSE;
  19689. X  int count, parts, i;
  19690. X  long int *filesizes;
  19691. X
  19692. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  19693. X  archive[0] = fullpath[0] = fullname[0] = 
  19694. X  cur_archive[0] = RESET (moreparams);
  19695. X  sscanf (params, "%s %s %s", archive, user_password, moreparams);
  19696. X  if (archive[0] == '/') /* No archive given, just password */
  19697. X    strcpy (user_password, archive),
  19698. X    RESET (archive);
  19699. X  else if (!strcmp (archive, "-ALL"))
  19700. X    all = TRUE,
  19701. X    RESET (archive);
  19702. X  if (user_password[0] == '/') /* Remove leading '/' */
  19703. X    sprintf (user_password, "%s", user_password + 1);
  19704. X  else if (!strcmp (user_password, "-ALL"))
  19705. X    RESET (user_password),
  19706. X    all = TRUE;
  19707. X  locase (archive);
  19708. X  if (moreparams[0] != EOS)
  19709. X    if (strcmp (moreparams, "-ALL")) {
  19710. X      if (!(sys.options & RELAXED_SYNTAX)) {
  19711. X    reject_mail (sender, request,
  19712. X             tsprintf ("Too many arguments to INDEX: %s\n\n\
  19713. XSyntax: index [archive | path-to-archive] [/password]\n", moreparams),
  19714. X             SYNTAX_ERROR, 0);
  19715. X    return;
  19716. X      }
  19717. X    }
  19718. X    else
  19719. X      all = TRUE;
  19720. X  if (archive[0] == EOS) /* Get archive */
  19721. X    strcpy (archive, DEFAULT_ARCHIVE);
  19722. X  sprintf (fullpath, "%s/%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE, INDEX);
  19723. X  strcpy (cur_archive, archive);
  19724. X  if ((slash = strchr (cur_archive, '/')))
  19725. X    *slash = EOS;
  19726. X  while (archive[0] != EOS) { /* Check all archives specified */
  19727. X    if ((master = fopen (fullpath, "r")) == NULL) {
  19728. X      NOTIFY_OF_BAD_ARCHIVE ("%s: Sorry, no index found.\n", cur_archive,
  19729. X                 BAD_ARCHIVE);
  19730. X      return;
  19731. X    }
  19732. X    found = FALSE;
  19733. X    while (!feof (master)) { /* Look at the current index for fullpath */
  19734. X      fullpath[0] = arch[0] = RESET (line);
  19735. X      fgets (line, MAX_LINE - 2, master);
  19736. X      if (line[0] != EOS) {
  19737. X        sscanf (line, "%s %s\n", arch, fullpath);
  19738. X        locase (arch);
  19739. X        if (!strcmp (arch, cur_archive)) {
  19740. X       found = TRUE;
  19741. X      break;
  19742. X        }
  19743. X      }
  19744. X    }
  19745. X    fclose (master);
  19746. X    if (!found) {
  19747. X      NOTIFY_OF_BAD_ARCHIVE ("%s: not a valid archive or path.\n", cur_archive,
  19748. X                 SYNTAX_ERROR);
  19749. X      return;
  19750. X    }
  19751. X    if ((slash = strchr (archive, '/')))
  19752. X      sprintf (archive, "%s", slash + 1); /* Move down the path */
  19753. X    else
  19754. X      sprintf (archive, "%s", archive + strlen (cur_archive));
  19755. X    strcpy (cur_archive, archive);
  19756. X    if ((slash = strchr (cur_archive, '/')))
  19757. X      *slash = EOS;
  19758. X    if (cur_archive[0] != EOS)
  19759. X      sprintf (fullpath, "%s/%s", fullpath, INDEX);
  19760. X  }
  19761. X  sscanf (params, "%s", archive);
  19762. X  sprintf (fullname, "%s/%s", fullpath, INDEX);
  19763. X  if ((index = fopen (fullname, "r")) == NULL) { /* Open index */
  19764. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, no index found in archive %s.\n", archive,
  19765. X               BAD_ARCHIVE);
  19766. X    return;
  19767. X  }
  19768. X  slash = request;
  19769. X  while ((slash = strchr (slash + 1, '/')) && !isspace (*(slash - 1)));
  19770. X  if (slash)
  19771. X    shadow_password (slash + 1);
  19772. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  19773. X         COPY_OWNER (ccindex), OK, FALSE, FALSE);
  19774. X  count = 0;
  19775. X  while (!feof (index)) { /* Echo archive; goto archive and get DIR file */
  19776. X    fullpath[0] = archive[0] = sys_password[0] = RESET (line);
  19777. X    fgets (line, MAX_LINE - 2, index);
  19778. X    if (line[0] != EOS) {
  19779. X      sscanf (line, "%s %s %s\n", archive, fullpath, sys_password);
  19780. X      upcase (sys_password);
  19781. X      fprintf (f, "\n%s: %s ", (!count ?  "Archive" : "Subarchive"), archive);
  19782. X      if (!strncmp (fullpath, ARCHIVE_DIR, strlen (ARCHIVE_DIR)))
  19783. X    fprintf (f, "(path: %s) ", fullpath + strlen (ARCHIVE_DIR) + 1);
  19784. X      if (!count || all) { /* List files for the top level archive only */
  19785. X    fprintf (f, "-- Files:\n");
  19786. X    if (sys_password[0] != EOS && strcmp (user_password, sys_password)) {
  19787. X      reply_code (RESTRICTED_REQ);
  19788. X      fprintf (f, "This archive requires special privileges for access.\n");
  19789. X      continue;
  19790. X    }
  19791. X    if (chdir (fullpath))
  19792. X      fprintf (f, "%s: Sorry, archive out of date.\n", archive);
  19793. X    else { /* Open DIR and get file names */
  19794. X      if ((dir = fopen (DIRF, "r")) == NULL)
  19795. X        reply_code (BAD_ARCHIVE),
  19796. X        fprintf (f, "Cannot obtain directory information.\n");
  19797. X      else {
  19798. X        while (!feof (dir)) {
  19799. X          line[0] = junk[0] = RESET (file);
  19800. X          fscanf (dir, "%s %d ", file, &parts);
  19801. X          if (file[0] != EOS) {
  19802. X        if (! (filesizes = (long int *) malloc (abs (parts) * sizeof (long int))))
  19803. X          report_progress (report, "\nIndex(): malloc() failed", TRUE),
  19804. X          gexit (11);
  19805. X        for (i = 0; i < abs (parts); i++)
  19806. X          fscanf (dir, "%ld ", filesizes + i);
  19807. X        fscanf (dir, "%s", junk);
  19808. X        header_printed = FALSE;
  19809. X        do { /* Get file description */
  19810. X          RESET (desc);
  19811. X          fgets (desc, MAX_LINE - 2, dir);
  19812. X          if (desc [0] != EOS && desc[strlen (desc) - 1] == '\n')
  19813. X            desc[strlen (desc) - 1] = EOS;
  19814. X          continued = FALSE;
  19815. X          if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  19816. X            desc[strlen (desc) - 1] = EOS,
  19817. X            continued = TRUE;
  19818. X          if (file[0] != EOS) {
  19819. X            if (!header_printed) {
  19820. X              fprintf (f, "  %s (%d part%s", file, abs (parts),
  19821. X                   (abs (parts) > 1 ? "s" : ""));
  19822. X              for (i = 0; i < abs (parts); i++)
  19823. X            fprintf (f, ", %ld", *(filesizes + i));
  19824. X              fprintf (f, " bytes) %s", ((desc[0] != EOS) ? "--" : ""));
  19825. X              free ((long int *) filesizes);
  19826. X              header_printed = TRUE;
  19827. X            }
  19828. X            fprintf (f, "%s\n", desc);
  19829. X          }
  19830. X        } while (continued);
  19831. X          }
  19832. X        }
  19833. X        fclose (dir);
  19834. X      }
  19835. X    }
  19836. X      }
  19837. X      else
  19838. X    fprintf (f, "\n");
  19839. X    }
  19840. X    ++count;
  19841. X  }
  19842. X  fclose (index);
  19843. X  COMPLETE_TELNET (f);
  19844. X  fclose (f);
  19845. X  DELIVER_MAIL (sender, COPY_OWNER (ccindex));
  19846. X}
  19847. X
  19848. X/*
  19849. X  Send the requested file from the specified archive. The file may have been
  19850. X  split in subparts, and in this case several emails will be sent -- one
  19851. X  for each part. The user may also obtain certain parts. A password is
  19852. X  required for obtaining files from a private archive.
  19853. X
  19854. X  Adapted USER CONTRIBUTED FUNCTION: Stefan Schroer.
  19855. X*/
  19856. X
  19857. Xvoid get (char *request, char *params, char *sender)
  19858. X{
  19859. X  FILE *f, *dir, *master;
  19860. X  char archive [MAX_LINE];
  19861. X  char arch [MAX_LINE];
  19862. X  char cur_archive [MAX_LINE];
  19863. X  char archive_orig [MAX_LINE];
  19864. X  char fullpath [MAX_LINE];
  19865. X  char moreparams [MAX_LINE];
  19866. X  char filename [MAX_LINE];
  19867. X  char fullname [MAX_LINE];
  19868. X  char dirpath [MAX_LINE];
  19869. X  char file [MAX_LINE];
  19870. X  char line [MAX_LINE];
  19871. X  char copy [MAX_LINE];
  19872. X  char sys_password [MAX_LINE];
  19873. X  char user_password [MAX_LINE];
  19874. X  char desc [MAX_LINE];
  19875. X  char subject [MAX_LINE];
  19876. X  char req [MAX_LINE];
  19877. X  char *slash, *uue_file = NULL;
  19878. X  struct stat stat_buf;
  19879. X  int i, count = 0;
  19880. X  long int *filesizes;
  19881. X  BOOLEAN found, continued, compressed_source;
  19882. X
  19883. X  strcpy (req, request);
  19884. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  19885. X  archive[0] = fullpath[0] = fullname[0] = dirpath[0] =
  19886. X  filename[0] = cur_archive[0] = archive_orig[0] = sys.fax.fax_no [0] =
  19887. X    RESET (moreparams);
  19888. X  params [strlen (params) - 1] = EOS; /* Remove \n */
  19889. X  if (!strcmp (req, "FAX"))
  19890. X    fax_it = TRUE,
  19891. X    sscanf (params, "%s %s %s %s", sys.fax.fax_no, archive, filename,
  19892. X        moreparams);
  19893. X  else
  19894. X    fax_it = FALSE,
  19895. X    sscanf (params, "%s %s %s", archive, filename, moreparams);
  19896. X  strcpy (archive_orig, archive);
  19897. X  locase (archive);
  19898. X  locase (filename);
  19899. X  if (archive[0] == EOS || filename[0] == EOS ||
  19900. X      (fax_it && sys.fax.fax_no[0] == EOS)) { /* Missing args */
  19901. X    reject_mail (sender, request, tsprintf ("%s: missing arguments\n\n\
  19902. XSyntax: %s %s<archive | path-to-archive> <file> [/password] [parts]\n", req,
  19903. X         req, (fax_it ? "<fax-number> " : "")), SYNTAX_ERROR, 0);
  19904. X    fax_it = FALSE;
  19905. X    return;
  19906. X  }
  19907. X  if (moreparams[0] != EOS) { /* Specified password and/or parts to get */
  19908. X    if (moreparams[0] == '/') { /* Get password and any parts */
  19909. X      strcpy (user_password, moreparams);
  19910. X      strcpy (copy, user_password);
  19911. X      upcase (copy);
  19912. X      do {
  19913. X        sprintf (params, "%s", params + 1);
  19914. X      } while (strncmp (params, copy, strlen (copy)));
  19915. X      sprintf (params, "%s", params + strlen (copy));
  19916. X      RESET (moreparams);
  19917. X      sscanf (params, "%s", moreparams); /* Get parts */
  19918. X      if (moreparams[0] != EOS)
  19919. X        sprintf (params, "%s", strchr (params, moreparams[0]));
  19920. X      if (user_password[0] == '/') /* Remove leading '/' */
  19921. X        sprintf (user_password, "%s", user_password + 1);
  19922. X    }
  19923. X    else { /* No password given just parts */
  19924. X      strcpy (copy, filename);
  19925. X      upcase (copy);
  19926. X      do {
  19927. X        sprintf (params, "%s", params + 1);
  19928. X      } while (strncmp (params, copy, strlen (copy)));
  19929. X      sprintf (params, "%s", params + strlen (copy));
  19930. X      sprintf (params, "%s", strchr (params, moreparams[0]));
  19931. X    }
  19932. X  }
  19933. X  sprintf (fullpath, "%s/%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE, INDEX);
  19934. X  strcpy (cur_archive, archive);
  19935. X  if ((slash = strchr (cur_archive, '/')))
  19936. X    *slash = EOS;
  19937. X  while (archive[0] != EOS) { /* Check all archives specified */
  19938. X    if ((master = fopen (fullpath, "r")) == NULL) {
  19939. X      NOTIFY_OF_BAD_ARCHIVE ("%s: Sorry, no index found.\n", cur_archive,
  19940. X                 BAD_ARCHIVE);
  19941. X      fax_it = FALSE;
  19942. X      return;
  19943. X    }
  19944. X    found = FALSE;
  19945. X    while (!feof (master)) { /* Look at the current index for fullpath */
  19946. X      fullpath[0] = arch[0] = sys_password[0] = RESET (line);
  19947. X      fgets (line, MAX_LINE - 2, master);
  19948. X      if (line[0] != EOS) {
  19949. X        sscanf (line, "%s %s %s\n", arch, fullpath, sys_password);
  19950. X        locase (arch);
  19951. X    upcase (sys_password);
  19952. X        if (!strcmp (arch, cur_archive)) {
  19953. X          found = TRUE;
  19954. X          break;
  19955. X        }
  19956. X      }
  19957. X    }
  19958. X    fclose (master);
  19959. X    if (!found) {
  19960. X      NOTIFY_OF_BAD_ARCHIVE ("%s: not a valid archive or path.\n", cur_archive,
  19961. X                 SYNTAX_ERROR);
  19962. X      fax_it = FALSE;
  19963. X      return;
  19964. X    }
  19965. X    if ((slash = strchr (archive, '/')))
  19966. X      sprintf (archive, "%s", slash + 1); /* Move down the path */
  19967. X    else
  19968. X      sprintf (archive, "%s", archive + strlen (cur_archive));
  19969. X    strcpy (cur_archive, archive);
  19970. X    if ((slash = strchr (cur_archive, '/')))
  19971. X      *slash = EOS;
  19972. X    if (cur_archive[0] != EOS)
  19973. X      sprintf (fullpath, "%s/%s", fullpath, INDEX);
  19974. X  }
  19975. X
  19976. X
  19977. X  if (sys_password[0] != EOS && strcmp (user_password, sys_password)) {
  19978. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, archive %s requires special privileges \
  19979. Xfor obtaining files.\n", archive_orig, RESTRICTED_REQ);
  19980. X    fax_it = FALSE;
  19981. X    return;
  19982. X  }
  19983. X  sprintf (dirpath, "%s/%s", fullpath, DIRF);
  19984. X  if ((dir = fopen (dirpath, "r")) == NULL) { /* Dir archive */
  19985. X    NOTIFY_OF_BAD_ARCHIVE ("Unable to dir archive %s\n", archive_orig,
  19986. X               BAD_ARCHIVE);
  19987. X    fax_it = FALSE;
  19988. X    return;
  19989. X  }
  19990. X  found = FALSE;
  19991. X  while (!feof (dir)) { /* Get location and file-count of file to send */
  19992. X    file[0] = RESET (fullpath);
  19993. X    fscanf (dir, "%s %d ", file, &count);
  19994. X    if (! (filesizes = (long int *) malloc (abs (count) * sizeof (long int))))
  19995. X      report_progress (report, "\nget(): malloc() failed", TRUE),
  19996. X      gexit (11);
  19997. X    for (i = 0; i < abs (count); i++)
  19998. X      fscanf (dir, "%ld ", filesizes + i);
  19999. X    fscanf (dir, "%s", fullpath);
  20000. X    do { /* Get file description */
  20001. X      RESET (desc);
  20002. X      fgets (desc, MAX_LINE - 2, dir);
  20003. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\n')
  20004. X        desc[strlen (desc) - 1] = EOS;
  20005. X      continued = FALSE;
  20006. X      if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  20007. X        desc[strlen (desc) - 1] = EOS,
  20008. X        continued = TRUE;
  20009. X    } while (continued);
  20010. X    if (file[0] != EOS) {
  20011. X      locase (file);
  20012. X      if (!strcmp (filename, file)) {
  20013. X    found = TRUE;
  20014. X    break;
  20015. X      }
  20016. X    }
  20017. X  }
  20018. X  fclose (dir);
  20019. X  if (!found) {
  20020. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, file %s not found in specified archive.\n",
  20021. X               filename, SYNTAX_ERROR);
  20022. X    fax_it = FALSE;
  20023. X    return;
  20024. X  }
  20025. X  if (interactive) /* Empty out file */
  20026. X    create_header (&f, MAILFORWARD, sys.server.address, sender, subject,
  20027. X           COPY_OWNER (ccget), OK, FALSE, FALSE),
  20028. X    fclose (f);
  20029. X  for (i = 1; i <= abs (count); i++) { /* Send all parts of the file */
  20030. X    RESET (fullname);
  20031. X    if (abs (count) > 1)
  20032. X      sprintf (fullname, "%s/%s%d", fullpath, filename, i);
  20033. X    else
  20034. X      sprintf (fullname, "%s/%s", fullpath, filename);
  20035. X    if (moreparams[0] != EOS && !requested_part (params, i))
  20036. X      continue;
  20037. X    compressed_source = FALSE;
  20038. X    if (stat (fullname, &stat_buf)) {
  20039. X      strcat (fullname, ".Z"); /* Check for compressed file */
  20040. X      if (stat (fullname, &stat_buf)) {
  20041. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, file %s not found in specified \
  20042. Xarchive.\n", filename, BAD_ARCHIVE);
  20043. X    fax_it = FALSE;
  20044. X    return;
  20045. X      }
  20046. X      compressed_source = TRUE;
  20047. X    }
  20048. X    if (request [strlen (request) - 1] == '\n')
  20049. X      request [strlen (request) - 1] = EOS;
  20050. X    sprintf (subject, "%s (%d/%d)", request, i, abs (count));
  20051. X    if (!interactive) {
  20052. X      if (count < 0)
  20053. X    syscom ("%s %s | uuencode %s > %s",
  20054. X        (compressed_source ? "zcat" : "cat"), fullname, filename,
  20055. X        (uue_file = mystrdup (tmpnam (NULL)))),
  20056. X    compressed_source = FALSE,
  20057. X    strcpy (fullname, uue_file),
  20058. X    stat (fullname, &stat_buf),
  20059. X    *(filesizes + i - 1) = stat_buf.st_size;
  20060. X      slash = subject;
  20061. X      while ((slash = strchr (slash + 1, '/')) && !isspace (*(slash - 1)));
  20062. X      if (slash)
  20063. X    shadow_password (slash + 1);
  20064. X      {
  20065. X    long int offset = 0, cnt = 0, nbytes, nsubparts;
  20066. X    char _subject[MAX_LINE], _count[32], *part_copy = NULL;
  20067. X    FILE *file = NULL;
  20068. X    struct stat stat_buf;
  20069. X
  20070. X    if (sys.options & LIMIT_FILES) {
  20071. X      if (compressed_source)
  20072. X        part_copy = mystrdup (tmpnam (NULL)),
  20073. X        syscom ("zcat %s > %s", fullname, part_copy);
  20074. X      OPEN_FILE (file, (compressed_source ? part_copy : fullname), "r",
  20075. X             "get");
  20076. X      fstat (fileno (file), &stat_buf);
  20077. X    }
  20078. X    while (offset < *(filesizes + i - 1)) {
  20079. X      strcpy (_subject, subject);
  20080. X      if (sys.options & LIMIT_FILES &&
  20081. X          *(filesizes + i - 1) > sys.limits.files)
  20082. X         /* nsubparts could be inaccurate if during the process of looking
  20083. X        for the nearest newlines not beyond the limit, the total number
  20084. X        of bytes backtracked is an integer multiple of the limit; that
  20085. X        can be very frequent if the limit is too small */
  20086. X        nsubparts = (long int)
  20087. X          ceil ((float) *(filesizes + i - 1) / (float) sys.limits.files),
  20088. X        sprintf (_subject + strlen (_subject), " [%ld/%ld]", (++cnt),
  20089. X             nsubparts),
  20090. X        sprintf (_count, " (subpart %ld/%ld)", cnt, nsubparts);
  20091. X      create_header (&f, MAILFORWARD, sys.server.address, sender, _subject,
  20092. X             COPY_OWNER (ccget), OK, FALSE, FALSE);
  20093. X      fprintf (f, "Archive %s, file %s.\nPart %d/%d%s, \
  20094. Xtotal size %ld bytes:\n\n",
  20095. X           archive_orig, filename, i, abs (count), (cnt ? _count : ""),
  20096. X           *(filesizes + i - 1));
  20097. X      fprintf (f, "------------------------------ Cut here \
  20098. X------------------------------\n");
  20099. X      fclose (f);
  20100. X      if (sys.options & LIMIT_FILES) { /* Calculate nearest newline */
  20101. X        if (*(filesizes + i - 1) > sys.limits.files) {
  20102. X          nbytes = sys.limits.files;
  20103. X          fseek (file, (offset + nbytes - 1 < stat_buf.st_size ?
  20104. X                offset + nbytes - 1 : stat_buf.st_size - 1),
  20105. X             SEEK_SET);
  20106. X          while (fgetc (file) != '\n' && nbytes > 1)
  20107. X        --nbytes,
  20108. X        fseek (file, -2L, SEEK_CUR);
  20109. X          if (nbytes == 1)
  20110. X        nbytes = sys.limits.files;
  20111. X        }
  20112. X        else
  20113. X          nbytes = *(filesizes + i - 1);
  20114. X      }
  20115. X      else
  20116. X        nbytes = *(filesizes + i - 1);
  20117. X      CAT_FILE;
  20118. X      offset += nbytes;
  20119. X      echo_append ("------------------------------ Cut here \
  20120. X------------------------------", MAILFORWARD);
  20121. X      APPEND_TELNET ("get");
  20122. X      DELIVER_MAIL (sender, COPY_OWNER (ccget));
  20123. X    }
  20124. X    if (file) {
  20125. X      fclose (file);
  20126. X      if (part_copy)
  20127. X        unlink (part_copy),
  20128. X        free ((char *) part_copy);
  20129. X    }
  20130. X      }
  20131. X    }
  20132. X    else { /* Interactive */
  20133. X      if (fax_it)
  20134. X    syscom ("%s < %s %s > /dev/null &", sys.fax.prog,
  20135. X        MAILFORWARD, sys.fax.fax_no),
  20136. X    reply_code (OK);
  20137. X      else
  20138. X    reply_code (WRITE_TO_FILE_ASC), /* Other modes possible */
  20139. X    syscom ("%s %s >> %s", (compressed_source ? "zcat" : "cat"), fullname,
  20140. X        MAILFORWARD);
  20141. X    }
  20142. X    if (uue_file)
  20143. X      unlink (uue_file),
  20144. X      free ((char *) uue_file),
  20145. X      uue_file = NULL;
  20146. X  }
  20147. X  free ((long int *) filesizes);
  20148. X  fax_it = FALSE;
  20149. X}
  20150. X
  20151. X/*
  20152. X  Search the specified archive for matches of the supplied extended regular
  20153. X  expression.
  20154. X*/
  20155. X
  20156. Xvoid search (char *request, char *params, char *sender)
  20157. X{
  20158. X  FILE *f, *index, *dir, *master, *fp;
  20159. X  char archive [MAX_LINE];
  20160. X  char arch [MAX_LINE];
  20161. X  char cur_archive [MAX_LINE];
  20162. X  char line [MAX_LINE];
  20163. X  char file [MAX_LINE];
  20164. X  char _line [MAX_LINE];
  20165. X  char _line_copy [MAX_LINE];
  20166. X  char fullpath [MAX_LINE];
  20167. X  char regex [MAX_LINE];
  20168. X  char fullname [MAX_LINE];
  20169. X  char desc [MAX_LINE];
  20170. X  char junk [MAX_LINE];
  20171. X  char user_password [MAX_LINE];
  20172. X  char sys_password [MAX_LINE];
  20173. X  char arch_dir [MAX_LINE];
  20174. X  char *slash, *part_copy = NULL, *quote;
  20175. X  BOOLEAN continued, compressed_source, all, header_printed, found = FALSE;
  20176. X  int count, parts, i;
  20177. X  long int filesize;
  20178. X  struct stat stat_buf;
  20179. X
  20180. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  20181. X  archive[0] = fullpath[0] = fullname[0] = 
  20182. X  cur_archive[0] = RESET (regex);
  20183. X  sscanf (params, "%s %s", archive, user_password);
  20184. X  sscanf (original_params, "%s %s %s", junk, junk, regex);
  20185. X  if (archive[0] == EOS) {
  20186. X    reject_mail (sender, request, "SEARCH: missing arguments\n\n\
  20187. XSyntax: search <archive | path-to-archive> [/password] [-all] \
  20188. X<pattern>\n", SYNTAX_ERROR, 0);
  20189. X    fax_it = FALSE;
  20190. X    return;
  20191. X  }
  20192. X  locase (archive);
  20193. X  if (user_password[0] == '/') /* Remove leading '/' */
  20194. X    sprintf (user_password, "%s", user_password + 1);
  20195. X  else if (!strcmp (user_password, "-ALL"))
  20196. X    RESET (user_password),
  20197. X    all = TRUE,
  20198. X    sscanf (original_params, "%s %s %[^\n]", junk, junk, regex);
  20199. X  else
  20200. X    sscanf (original_params, "%s %[^\n]", junk, regex),
  20201. X    RESET (user_password);
  20202. X  if (regex[0] != EOS) {
  20203. X    part_copy = mystrdup (regex);
  20204. X    upcase (part_copy);
  20205. X    if (!strcmp (part_copy, "-ALL"))
  20206. X      all = TRUE,
  20207. X      sscanf (original_params, "%s %s %s %[^\n]", junk, junk, junk, regex);
  20208. X    else if (user_password[0] != EOS)
  20209. X      sscanf (original_params, "%s %s %[^\n]", junk, junk, regex);
  20210. X    free ((char *) part_copy);
  20211. X    part_copy = NULL;
  20212. X  }
  20213. X  else {
  20214. X    reject_mail (sender, request,
  20215. X         tsprintf ("Too few arguments to SEARCH\n\n\
  20216. XSyntax: search <archive | path-to-archive> [/password] [-all] <pattern>\n"),
  20217. X         SYNTAX_ERROR, 0);
  20218. X    return;
  20219. X  }
  20220. X  clean_request (regex);
  20221. X  if (regex[0] == '\'') {
  20222. X    sprintf (regex, "%s", regex + 1);
  20223. X    if (regex[0] == EOS || !re_strcmp ("'[ \t]*$", regex, NULL)) {
  20224. X      reject_mail (sender, request, "Mismatched or misplaced quotes\n",
  20225. X           SYNTAX_ERROR, 0);
  20226. X      return;
  20227. X    }
  20228. X    quote = strrchr (regex, '\'');
  20229. X    *quote = EOS;
  20230. X  }
  20231. X  else if (regex[0] == '\"') {
  20232. X    sprintf (regex, "%s", regex + 1);
  20233. X    if (regex[0] == EOS || !re_strcmp ("\"[ \t]*$", regex, NULL)) {
  20234. X      reject_mail (sender, request, "Mismatched or misplaced quotes\n",
  20235. X           SYNTAX_ERROR, 0);
  20236. X      return;
  20237. X    }
  20238. X    quote = strrchr (regex, '"');
  20239. X    *quote = EOS;
  20240. X  }
  20241. X  if (regex[0] == EOS) {
  20242. X    reject_mail (sender, request, "Empty regular expression\n", SYNTAX_ERROR, 0);
  20243. X    return;
  20244. X  }
  20245. X  if (re_strcmp (regex, "", NULL) < 0) {
  20246. X    reject_mail (sender, request, "Malformed regular expression\n",
  20247. X         SYNTAX_ERROR, 0);
  20248. X    return;
  20249. X  }
  20250. X  sprintf (fullpath, "%s/%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE, INDEX);
  20251. X  strcpy (cur_archive, archive);
  20252. X  if ((slash = strchr (cur_archive, '/')))
  20253. X    *slash = EOS;
  20254. X  while (archive[0] != EOS) { /* Check all archives specified */
  20255. X    if ((master = fopen (fullpath, "r")) == NULL) {
  20256. X      NOTIFY_OF_BAD_ARCHIVE ("%s: Sorry, no index found.\n", cur_archive,
  20257. X                 BAD_ARCHIVE);
  20258. X      return;
  20259. X    }
  20260. X    while (!feof (master)) { /* Look at the current index for fullpath */
  20261. X      fullpath[0] = arch[0] = RESET (line);
  20262. X      fgets (line, MAX_LINE - 2, master);
  20263. X      if (line[0] != EOS) {
  20264. X        sscanf (line, "%s %s\n", arch, fullpath);
  20265. X        locase (arch);
  20266. X        if (!strcmp (arch, cur_archive)) {
  20267. X       found = TRUE;
  20268. X      break;
  20269. X        }
  20270. X      }
  20271. X    }
  20272. X    fclose (master);
  20273. X    if (!found) {
  20274. X      NOTIFY_OF_BAD_ARCHIVE ("%s: not a valid archive or path.\n", cur_archive,
  20275. X                 SYNTAX_ERROR);
  20276. X      return;
  20277. X    }
  20278. X    if ((slash = strchr (archive, '/')))
  20279. X      sprintf (archive, "%s", slash + 1); /* Move down the path */
  20280. X    else
  20281. X      sprintf (archive, "%s", archive + strlen (cur_archive));
  20282. X    strcpy (cur_archive, archive);
  20283. X    if ((slash = strchr (cur_archive, '/')))
  20284. X      *slash = EOS;
  20285. X    if (cur_archive[0] != EOS)
  20286. X      sprintf (fullpath, "%s/%s", fullpath, INDEX);
  20287. X  }
  20288. X  sscanf (params, "%s", archive);
  20289. X  sprintf (fullname, "%s/%s", fullpath, INDEX);
  20290. X  if ((index = fopen (fullname, "r")) == NULL) { /* Open index */
  20291. X    NOTIFY_OF_BAD_ARCHIVE ("Sorry, no index found in archive %s.\n", archive,
  20292. X               BAD_ARCHIVE);
  20293. X    return;
  20294. X  }
  20295. X  slash = request;
  20296. X  while ((slash = strchr (slash + 1, '/')) && !isspace (*(slash - 1)));
  20297. X  if (slash)
  20298. X    shadow_password (slash + 1);
  20299. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20300. X         COPY_OWNER (ccindex), OK, FALSE, FALSE);
  20301. X  fprintf (f, "Matches for pattern %s ...\n", regex);
  20302. X  locase (regex);
  20303. X  count = 0;
  20304. X  while (!feof (index)) { /* Echo archive; goto archive and get DIR file */
  20305. X    fullpath[0] = archive[0] = sys_password[0] = RESET (line);
  20306. X    fgets (line, MAX_LINE - 2, index);
  20307. X    if (line[0] != EOS) {
  20308. X      sscanf (line, "%s %s %s\n", archive, fullpath, sys_password);
  20309. X      upcase (sys_password);
  20310. X      if (!count || all) { /* Search files of the top level archive only */
  20311. X    fprintf (f, "\n%s: %s ", (!count ?  "--- Archive" : "--- Subarchive"),
  20312. X         archive);
  20313. X    if (!strncmp (fullpath, ARCHIVE_DIR, strlen (ARCHIVE_DIR)))
  20314. X      fprintf (f, "(path: %s) ", fullpath + strlen (ARCHIVE_DIR) + 1);
  20315. X    fprintf (f, "\n");
  20316. X    if (sys_password[0] != EOS && strcmp (user_password, sys_password)) {
  20317. X      reply_code (RESTRICTED_REQ);
  20318. X      fprintf (f, "This archive requires special privileges for access.\n");
  20319. X      continue;
  20320. X    }
  20321. X    if (chdir (fullpath))
  20322. X      fprintf (f, "%s: Sorry, archive out of date.\n", archive);
  20323. X    else { /* Open DIR and get file names */
  20324. X      if ((dir = fopen (DIRF, "r")) == NULL)
  20325. X        reply_code (BAD_ARCHIVE),
  20326. X        fprintf (f, "Cannot obtain directory information.\n");
  20327. X      else {
  20328. X        while (!feof (dir)) {
  20329. X          line[0] = junk[0] = RESET (file);
  20330. X          fscanf (dir, "%s %d ", file, &parts);
  20331. X          if (file[0] != EOS) {
  20332. X        for (i = 0; i < abs (parts); i++)
  20333. X          fscanf (dir, "%ld ", &filesize);
  20334. X        fscanf (dir, "%s", arch_dir);
  20335. X        do { /* Get file description */
  20336. X          RESET (desc);
  20337. X          fgets (desc, MAX_LINE - 2, dir);
  20338. X          if (desc [0] != EOS && desc[strlen (desc) - 1] == '\n')
  20339. X            desc[strlen (desc) - 1] = EOS;
  20340. X          continued = FALSE;
  20341. X          if (desc[0] != EOS && desc[strlen (desc) - 1] == '\\')
  20342. X            desc[strlen (desc) - 1] = EOS,
  20343. X            continued = TRUE;
  20344. X        } while (continued);
  20345. X        if (parts > 0) { /* Binaries are not searched */
  20346. X          for (i = 0; i < parts; i++) {
  20347. X            RESET (fullname);
  20348. X            if (parts > 1)
  20349. X              sprintf (fullname, "%s/%s%d", arch_dir, file, i);
  20350. X            else
  20351. X              sprintf (fullname, "%s/%s", arch_dir, file);
  20352. X            compressed_source = FALSE;
  20353. X            if (stat (fullname, &stat_buf)) {
  20354. X              strcat (fullname, ".Z"); /* Check for compressed file */
  20355. X              if (stat (fullname, &stat_buf))
  20356. X            continue; /* Error in archive */
  20357. X              compressed_source = TRUE;
  20358. X            }
  20359. X            if (compressed_source)
  20360. X              part_copy = mystrdup (tmpnam (NULL)),
  20361. X              syscom ("zcat %s > %s", fullname, part_copy);
  20362. X            OPEN_FILE (fp, (compressed_source ? part_copy :
  20363. X                    fullname), "r", "search");
  20364. X            header_printed = FALSE;
  20365. X            while (!feof (fp)) {
  20366. X              RESET (_line);
  20367. X              fgets (_line, MAX_LINE - 2, fp);
  20368. X              strcpy (_line_copy, _line);
  20369. X              if (_line_copy[0] != EOS &&
  20370. X              _line_copy[strlen (_line_copy) - 1] == '\n')
  20371. X            _line_copy[strlen (_line_copy) - 1] = EOS;
  20372. X              locase (_line);
  20373. X              if (_line[0] != EOS &&
  20374. X              re_strcmp (regex, _line, NULL) > 0) {
  20375. X            if (!header_printed)
  20376. X              if (parts > 1)
  20377. X                fprintf (f, "\n>>> File %s, part %d:\n", file, i);
  20378. X              else
  20379. X                fprintf (f, "\n>>> File %s:\n", file);
  20380. X            fprintf (f, "%s\n", _line_copy);
  20381. X            header_printed = TRUE;
  20382. X              }
  20383. X            }
  20384. X            if (header_printed)
  20385. X              fprintf (f, "<<< End of matches in file %s\n", file);
  20386. X            fclose (fp);
  20387. X            if (part_copy)
  20388. X              unlink (part_copy),
  20389. X              free ((char *) part_copy),
  20390. X              part_copy = NULL;
  20391. X          }
  20392. X        }
  20393. X          }
  20394. X        }
  20395. X        fclose (dir);
  20396. X      }
  20397. X    }
  20398. X      }
  20399. X    }
  20400. X    ++count;
  20401. X  }
  20402. X  fclose (index);
  20403. X  COMPLETE_TELNET (f);
  20404. X  fclose (f);
  20405. X  DELIVER_MAIL (sender, COPY_OWNER (ccindex));
  20406. X}
  20407. X
  20408. X/*
  20409. X  Give specific information about this release.
  20410. X*/
  20411. X
  20412. Xvoid release (char *request, char *params, char *sender)
  20413. X{
  20414. X  char param [MAX_LINE];
  20415. X  FILE *f;
  20416. X
  20417. X  sprintf (request + strlen (request), "%s", params); /* Used as a subject */
  20418. X  RESET (param);
  20419. X  sscanf (params, "%s", param);
  20420. X  if (param[0] != EOS && !(sys.options & RELAXED_SYNTAX)) {
  20421. X    reject_mail (sender, request, tsprintf ("Invalid RELEASE option%s\n\
  20422. XSyntax: release\n", params), SYNTAX_ERROR, 0);
  20423. X    return;
  20424. X  }
  20425. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20426. X         COPY_OWNER (ccrelease), OK, FALSE, FALSE);
  20427. X  fprintf (f, "UNIX ListServer, version %s\n", VERSION);
  20428. X  fprintf (f, "Last update: %s\nManager: %s\nListServer address: %s\n",
  20429. X       UPDATE_DATE, sys.manager, sys.server.address);
  20430. X  COMPLETE_TELNET (f);
  20431. X  fclose (f);
  20432. X  DELIVER_MAIL (sender, COPY_OWNER (ccrelease));
  20433. X}
  20434. X
  20435. X/*
  20436. X  Forward a 'request' to all servers handling peer lists.
  20437. X*/
  20438. X
  20439. Xvoid notify_peer_servers (char *file, char *request, char *params, char *sender)
  20440. X{
  20441. X  FILE *f, *mail;
  20442. X  char *mail_method;
  20443. X  char email [MAX_LINE];
  20444. X  char mode [MAX_LINE];
  20445. X  char alias [MAX_LINE];
  20446. X  char listserv [MAX_LINE];
  20447. X  char servers [MAX_LINE];
  20448. X  char subject [MAX_LINE];
  20449. X
  20450. X  if (peer_server_request || do_not_notify_peer_server)
  20451. X    return;
  20452. X  OPEN_FILE (f, file, "r", "notify_peer_servers");
  20453. X  sprintf (subject, "%s%s", psr_string, sys.server.address);
  20454. X  RESET (servers);
  20455. X  if (sys.options & USE_ENV_VAR) {
  20456. X    if ((mail_method = (char *) malloc ((10 + strlen (sys.mail.env_var) +
  20457. X                     strlen (sender) +
  20458. X                     strlen (sys.mail.mail_prog))
  20459. X                    * sizeof (char))) == NULL)
  20460. X      report_progress (report, "\nnotify_peer_servers(): malloc() failed",
  20461. X               TRUE),
  20462. X      gexit (11);
  20463. X    sprintf (mail_method, "env - %s=%s %s ", sys.mail.env_var,
  20464. X         sender, sys.mail.mail_prog);
  20465. X  }
  20466. X  else {
  20467. X    if ((mail_method = (char *) malloc ((strlen (sys.mail.method) + 1) 
  20468. X                    * sizeof (char))) == NULL)
  20469. X      report_progress (report, "\nnotify_peer_servers(): malloc() failed",
  20470. X               TRUE),
  20471. X      gexit (11);
  20472. X    strcpy (mail_method, sys.mail.method);
  20473. X  }
  20474. X  while (!feof (f)) {
  20475. X    email[0] = mode[0] = alias[0] = RESET (listserv);
  20476. X    fscanf (f, "%s %s %s %s\n", email, mode, alias, listserv);
  20477. X    if (email[0] != EOS) { /* Send mail to peer server */
  20478. X      sprintf (servers + strlen (servers), "%s\n", listserv);
  20479. X      create_header (&mail, MAILFORWARD, sender, listserv, 
  20480. X             subject, FALSE, OK, FALSE, FALSE);
  20481. X      fprintf (mail, "%s %s %s\n", request, alias, params);
  20482. X      COMPLETE_TELNET (mail);
  20483. X      fclose (mail);
  20484. X      if (sys.options & USE_SYSMAIL)
  20485. X    sysmail (MAILFORWARD);
  20486. X      else
  20487. X    syscom ("%s %s < %s", mail_method,
  20488. X        (((sys.options & USE_TELNET) == 0) ? locase (listserv) : ""),
  20489. X        MAILFORWARD);
  20490. X    }
  20491. X  }
  20492. X  if (servers[0] != EOS) { /* Notify sender as well */
  20493. X    create_header (&mail, MAILFORWARD, sys.server.address, sender, 
  20494. X           tsprintf ("Notification from %s", sys.server.address),
  20495. X           FALSE, OK, FALSE, FALSE);
  20496. X    fprintf (mail, "%s: Your request has been forwarded to the following peer \
  20497. Xservers,\nwho will forward you with a copy of their own results:\n\n%s", 
  20498. Xupcase (request), servers);
  20499. X    COMPLETE_TELNET (mail);
  20500. X    fclose (mail);
  20501. X    if (sys.options & USE_SYSMAIL)
  20502. X      sysmail (MAILFORWARD);
  20503. X    else
  20504. X      syscom ("%s %s < %s", mail_method,
  20505. X          (((sys.options & USE_TELNET) == 0) ? locase (sender) : ""),
  20506. X          MAILFORWARD);
  20507. X  }
  20508. X  free ((char *) mail_method);
  20509. X  fclose (f);
  20510. X}
  20511. X
  20512. X/*
  20513. X  Internal request generated by catmail; the text that follows is sent
  20514. X  to 'sender'. This request is generated only for moderated lists.
  20515. X*/
  20516. X
  20517. Xvoid notify (char *request, char *params, char *sender)
  20518. X{
  20519. X  FILE *f;
  20520. X  char line [MAX_LINE];
  20521. X
  20522. X  create_header (&f, MAILFORWARD, sys.server.address, sender, "Notification",
  20523. X         FALSE, OK, FALSE, FALSE);
  20524. X  RESET (line);
  20525. X  while (!feof (mail) && /* Copy till eof or next message */
  20526. X     (strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE))))
  20527. X    fputs (line, f),
  20528. X    RESET (line),
  20529. X    fgets (line, MAX_LINE - 2, mail);
  20530. X  COMPLETE_TELNET (f);
  20531. X  fclose (f);
  20532. X  DELIVER_MAIL (sender, FALSE);
  20533. X  if (!strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))
  20534. X    fseek (mail, -strlen (line), SEEK_CUR); /* Move back to beginning */
  20535. X}
  20536. X
  20537. X/*
  20538. X  Approve a message for a moderated list. The owner has supplied message
  20539. X  a tag for a message approved, so look for it in the moderated file,
  20540. X  and append it to the mail file, then remove it from the moderated file.
  20541. X*/
  20542. X
  20543. Xvoid approve (char *request, char *params, char *sender)
  20544. X{
  20545. X  char password [MAX_LINE];
  20546. X  char req [MAX_LINE];
  20547. X  char line [MAX_LINE];
  20548. X  char prev_line [MAX_LINE];
  20549. X  char moreparams [MAX_LINE];
  20550. X  char match [MAX_LINE];
  20551. X  FILE *f, *moderated, *mail;
  20552. X  int lfd = 2, lfd2 = 2, tag, tag_to_approve = 0;
  20553. X  long int sig_mask;
  20554. X  BOOLEAN copy = FALSE;
  20555. X
  20556. X  moreparams[0] = req[0] = RESET (password);
  20557. X  strcpy (req, request);
  20558. X  sscanf (params, "%s %d %s", password, &tag_to_approve, moreparams);
  20559. X  shadow_password (params);
  20560. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  20561. X       params);
  20562. X  if (!owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  20563. X    NOT_LIST_OWNER; /* Hacker attack */
  20564. X    return;
  20565. X  }
  20566. X  if (password[0] == EOS) {
  20567. X    reject_mail (sender, request,
  20568. X         tsprintf ("Missing password for %s request\n\n\
  20569. XSyntax: approve <list> <password> <tag>\n", req), SYNTAX_ERROR, 0);
  20570. X    return;
  20571. X  }
  20572. X  if (strcmp (password, sys.lists[listid].password)) {
  20573. X    reject_mail (sender, request,
  20574. X         tsprintf ("Invalid password for %s request\n", req),
  20575. X         SYNTAX_ERROR, 0);
  20576. X    return;
  20577. X  }
  20578. X  if (tag_to_approve == 0) {
  20579. X    reject_mail (sender, request,
  20580. X         tsprintf ("Invalid or missing tag number for %s request\n\n\
  20581. XSyntax: approve <list> <password> <tag>\n", req), SYNTAX_ERROR, 0);
  20582. X    return;
  20583. X  }
  20584. X  if (moreparams[0] != EOS) {
  20585. X    reject_mail (sender, request,
  20586. X         tsprintf ("Too many tag numbers to %s request\n\n\
  20587. XSyntax: approve <list> <password> <tag>\n", req), SYNTAX_ERROR, 0);
  20588. X    return;
  20589. X  }
  20590. X#ifndef NO_LOCKS
  20591. X  if ((lfd = lock_file (list_mail_f, O_RDWR | O_CREAT, 416, TRUE)) < 0)
  20592. X    switch (lfd) {
  20593. X    case CANT_OPEN:
  20594. X      report_progress (report, 
  20595. X               tsprintf ("\nCould not stat file %s", list_mail_f),
  20596. X               TRUE);
  20597. X      gexit (1);
  20598. X    case CANT_LOCK:
  20599. X      CANNOT_LOCK_FILE (list_mail_f);
  20600. X      return;
  20601. X    }
  20602. X  if ((lfd2 = lock_file (list_moderated_f, O_RDWR | O_CREAT, 416, TRUE)) < 0)
  20603. X    switch (lfd2) {
  20604. X    case CANT_OPEN:
  20605. X      report_progress (report,
  20606. X               tsprintf ("\nCould not stat file %s", list_moderated_f),
  20607. X               TRUE);
  20608. X      gexit (1);
  20609. X    case CANT_LOCK:
  20610. X      unlock_file (lfd);
  20611. X      CANNOT_LOCK_FILE (list_moderated_f);
  20612. X      return;
  20613. X    }
  20614. X#endif
  20615. X#ifdef bsd
  20616. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  20617. X#elif defined (svr4) || defined (svr3)
  20618. X  sighold (SIGINT);
  20619. X  sighold (SIGTERM);
  20620. X#endif
  20621. X  OPEN_FILE (moderated, list_moderated_f, "r", "approve");
  20622. X  OPEN_FILE (mail, list_mail_f, "a", "approve");
  20623. X  prev_line[0] = RESET (line);
  20624. X  while (!feof (moderated)) {
  20625. X    if (!strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)) &&
  20626. X    copy)
  20627. X      break; /* We are at the beginning of another message; stop copying */
  20628. X    strcpy (match, "\\1");
  20629. X    if (re_strcmp (MESSAGE_TAG, line, match) > 0)  { /* Get tag # */
  20630. X      sprintf (line, "%s", line + strlen (match));
  20631. X      sscanf (line, "%d", &tag);
  20632. X      RESET (line); /* Blow away Message-Tag: */
  20633. X      if (tag_to_approve == tag)
  20634. X    copy = TRUE;
  20635. X    }
  20636. X    if (copy && prev_line[0] != EOS)
  20637. X      fprintf (mail, "%s", prev_line);
  20638. X    strcpy (prev_line, line);
  20639. X    RESET (line);
  20640. X    fgets (line, MAX_LINE - 2, moderated);
  20641. X  }
  20642. X  if (copy && prev_line[0] != EOS)
  20643. X    fprintf (mail, "%s", prev_line);
  20644. X  fclose (moderated);
  20645. X  fclose (mail);
  20646. X  if (!copy) { /* Message to be approved not found */
  20647. X    NO_SUCH_MESSAGE_TAG (tag_to_approve);
  20648. X    goto abort;
  20649. X  }
  20650. X  remove_msg (list_moderated_f, tag_to_approve, report);
  20651. X#ifdef bsd
  20652. X  sigsetmask (sig_mask);
  20653. X#elif defined (svr4) || defined (svr3)
  20654. X  sigrelse (SIGINT);
  20655. X  sigrelse (SIGTERM);
  20656. X#endif
  20657. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  20658. X         OK, FALSE, FALSE);
  20659. X  fprintf (f, "Your request was successfully completed.\n");
  20660. X  COMPLETE_TELNET (f);
  20661. X  fclose (f);
  20662. X  DELIVER_MAIL (sender, FALSE);
  20663. X  abort: ;
  20664. X#ifndef NO_LOCKS
  20665. X  unlock_file (lfd);
  20666. X  unlock_file (lfd2);
  20667. X#endif
  20668. X}
  20669. X
  20670. X/*
  20671. X  Discard a message from a moderated list.
  20672. X*/
  20673. X
  20674. Xvoid discard (char *request, char *params, char *sender)
  20675. X{
  20676. X  char password [MAX_LINE];
  20677. X  char req [MAX_LINE];
  20678. X  char moreparams [MAX_LINE];
  20679. X  FILE *f;
  20680. X  int tag_to_discard = 0, lfd = 2;
  20681. X  long int sig_mask;
  20682. X
  20683. X  moreparams[0] = req[0] = RESET (password);
  20684. X  strcpy (req, request);
  20685. X  sscanf (params, "%s %d %s", password, &tag_to_discard, moreparams);
  20686. X  shadow_password (params);
  20687. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  20688. X           params);
  20689. X  if (!owner_listed (OWNERSF, sender, sys.lists[listid].alias, report)) {
  20690. X    NOT_LIST_OWNER; /* Hacker attack */
  20691. X    return;
  20692. X  }
  20693. X  if (password[0] == EOS) {
  20694. X    reject_mail (sender, request, tsprintf ("Missing password for %s request\n\n\
  20695. XSyntax: discard <list> <password> <tag>\n", req), SYNTAX_ERROR, 0);
  20696. X    return;
  20697. X  }
  20698. X  if (strcmp (password, sys.lists[listid].password)) {
  20699. X    reject_mail (sender, request,
  20700. X         tsprintf ("Invalid password for %s request\n", req),
  20701. X         SYNTAX_ERROR, 0);
  20702. X    return;
  20703. X  }
  20704. X  if (tag_to_discard == 0) {
  20705. X    reject_mail (sender, request,
  20706. X         tsprintf ("Invalid or missing tag number for %s request\n\n\
  20707. XSyntax: discard <list> <password> <tag>\n", req),
  20708. X         SYNTAX_ERROR, 0);
  20709. X    return;
  20710. X  }
  20711. X  if (moreparams[0] != EOS) {
  20712. X    reject_mail (sender, request,
  20713. X         tsprintf ("Too many tag numbers to %s request\n\n\
  20714. XSyntax: discard <list> <password> <tag>\n", req), SYNTAX_ERROR, 0);
  20715. X    return;
  20716. X  }
  20717. X#ifndef NO_LOCKS
  20718. X  if ((lfd = lock_file (list_moderated_f, O_RDWR | O_CREAT, 416, TRUE)) < 0)
  20719. X    switch (lfd) {
  20720. X    case CANT_OPEN:
  20721. X      report_progress (report,
  20722. X               tsprintf ("\nCould not stat file %s", list_moderated_f),
  20723. X               TRUE);
  20724. X      gexit (1);
  20725. X    case CANT_LOCK:
  20726. X      CANNOT_LOCK_FILE (list_moderated_f);
  20727. X      return;
  20728. X    }
  20729. X#endif
  20730. X#ifdef bsd
  20731. X  sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  20732. X#elif defined (svr4) || defined (svr3)
  20733. X  sighold (SIGINT);
  20734. X  sighold (SIGTERM);
  20735. X#endif
  20736. X  if (!remove_msg (list_moderated_f, tag_to_discard, report)) {
  20737. X#ifdef bsd
  20738. X    sigsetmask (sig_mask);
  20739. X#elif defined (svr4) || defined (svr3)
  20740. X    sigrelse (SIGINT);
  20741. X    sigrelse (SIGTERM);
  20742. X#endif
  20743. X    NO_SUCH_MESSAGE_TAG (tag_to_discard);
  20744. X    goto abort;
  20745. X  }
  20746. X#ifdef bsd
  20747. X  sigsetmask (sig_mask);
  20748. X#elif defined (svr4) || defined (svr3)
  20749. X  sigrelse (SIGINT);
  20750. X  sigrelse (SIGTERM);
  20751. X#endif
  20752. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  20753. X         OK, FALSE, FALSE);
  20754. X  fprintf (f, "Your request was successfully completed.\n");
  20755. X  COMPLETE_TELNET (f);
  20756. X  fclose (f);
  20757. X  DELIVER_MAIL (sender, FALSE);
  20758. X  abort: ;
  20759. X#ifndef NO_LOCKS
  20760. X  unlock_file (lfd);
  20761. X#endif
  20762. X}
  20763. X
  20764. X/*
  20765. X  Execute a program and reply with the output from stdout and stderr.
  20766. X*/
  20767. X
  20768. Xvoid execute (char *request, char *params, char *sender)
  20769. X{
  20770. X  char password [MAX_LINE];
  20771. X  char req [MAX_LINE];
  20772. X  char *prog = NULL;
  20773. X  FILE *f;
  20774. X  struct stat stat_buf;
  20775. X
  20776. X  req[0] = RESET (password);
  20777. X  strcpy (req, request);
  20778. X  sscanf (params, "%s ", password);
  20779. X  shadow_password (original_params);
  20780. X  sprintf (request + strlen (request), "%s", original_params);
  20781. X  if (password[0] == EOS) {
  20782. X    reject_mail (sender, request,
  20783. X         tsprintf ("Missing password for %s request\n\n\
  20784. XSyntax: execute <password> #<prog> [args]\n", req), SYNTAX_ERROR, 0);
  20785. X    return;
  20786. X  }
  20787. X  if (strcmp (password, sys.server.password)) {
  20788. X    reject_mail (sender, request, tsprintf ("Invalid password for %s request\n",
  20789. X                        req), SYNTAX_ERROR, 0);
  20790. X    return;
  20791. X  }
  20792. X  if ((prog = strchr (original_params, '#')) == NULL) {
  20793. X    reject_mail (sender, request,
  20794. X         tsprintf ("Missing '#' for %s request\n\n\
  20795. XSyntax: execute <password> #<prog> [args]\n", req), SYNTAX_ERROR, 0);
  20796. X    return;
  20797. X  }
  20798. X  original_params [strlen (original_params) - 1] = EOS; /* Remove \n */
  20799. X  syscom ("%s > %s 2> %s", prog + 1, STDOUT, STDERR);
  20800. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  20801. X         OK, FALSE, FALSE);
  20802. X  if (!stat (STDOUT, &stat_buf) && stat_buf.st_size > 0) {
  20803. X    fprintf (f, "Output from stdout:\n");
  20804. X    fclose (f);
  20805. X    cat_append (STDOUT, MAILFORWARD);
  20806. X    APPEND_TELNET ("execute");
  20807. X    DELIVER_MAIL (sender, FALSE);
  20808. X  }
  20809. X  if (!stat (STDERR, &stat_buf) && stat_buf.st_size > 0) {
  20810. X    if (interactive) /* In case execute is ever allowed for live connections */
  20811. X      if (stat (STDOUT, &stat_buf))
  20812. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20813. X               FALSE, OK, FALSE, FALSE);
  20814. X      else
  20815. X    f = fopen (MAILFORWARD, "a");
  20816. X    else
  20817. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20818. X             FALSE, OK, FALSE, FALSE);
  20819. X    fprintf (f, "Output from stderr:\n");
  20820. X    fclose (f);
  20821. X    cat_append (STDERR, MAILFORWARD);
  20822. X    APPEND_TELNET ("execute");
  20823. X    DELIVER_MAIL (sender, FALSE);
  20824. X  }
  20825. X  unlink (STDOUT);
  20826. X  unlink (STDERR);
  20827. X}
  20828. X
  20829. X/*
  20830. X  Execute a UNIX command allowed for the specified list by members of the list,
  20831. X  and receive the output from stdout and/or stderr.
  20832. X*/
  20833. X
  20834. Xvoid unix_cmd (char *request, char *params, char *sender)
  20835. X{
  20836. X  char password [MAX_LINE];
  20837. X  char req [MAX_LINE];
  20838. X  char prog [10240], *_prog, *args [10], *blank;
  20839. X  FILE *f;
  20840. X  struct stat stat_buf;
  20841. X  UNIX_CMDS *unix_cmd = sys.lists[listid].unix_cmds;
  20842. X  int nargs;
  20843. X  long int sig_mask;
  20844. X
  20845. X  if (matched_rlists) { /* Request for a remote list; notify sender */
  20846. X    NOTIFY_OF_REQUEST_FORWARDING;
  20847. X    FORWARD_REQUEST;
  20848. X    return;
  20849. X  }
  20850. X  req[0] = RESET (password);
  20851. X  strcpy (req, request);
  20852. X  sscanf (params, "%s ", password);
  20853. X  _prog = original_params;
  20854. X  while (*_prog != EOS && isspace (*_prog))    /* Skip over list */
  20855. X    ++_prog;
  20856. X  while (*_prog != EOS && !isspace (*_prog))    /* Get to password */
  20857. X    ++_prog;
  20858. X  shadow_password (_prog);
  20859. X  sprintf (request + strlen (request), " %s%s", sys.lists[listid].alias,
  20860. X           _prog);
  20861. X  if (subscribed (report, sender, subscribersf, NULL, NULL,
  20862. X          aliasesf) == NOTSUBSCRIBED) {
  20863. X    MEMBERS_ONLY;
  20864. X    return;
  20865. X  }
  20866. X  if (password[0] == EOS) {
  20867. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  20868. X           OK, FALSE, FALSE);
  20869. X    fprintf (f, "You may run the following commands:\n\n");
  20870. X    while (unix_cmd)
  20871. X      fprintf (f, "%s (%s)\n", unix_cmd->name, unix_cmd->comment),
  20872. X      unix_cmd = unix_cmd->next;
  20873. X    COMPLETE_TELNET (f);
  20874. X    fclose (f);
  20875. X    DELIVER_MAIL (sender, FALSE);
  20876. X    return;
  20877. X  }
  20878. X  if (!sys.lists[listid].unix_cmds) {
  20879. X    reject_mail (sender, request, tsprintf ("No commands to execute for %s \
  20880. Xrequest\n", req), SYNTAX_ERROR, 0);
  20881. X    return;
  20882. X  }
  20883. X  if (strcmp (password, sys.lists[listid].unix_cmds->password)) {
  20884. X    reject_mail (sender, request, tsprintf ("Invalid password for %s request\n",
  20885. X                        req), SYNTAX_ERROR, 0);
  20886. X    return;
  20887. X  }
  20888. X  if ((blank = strchr (original_params, '`')) ||
  20889. X      (blank = strchr (original_params, '|')) ||
  20890. X      (blank = strchr (original_params, '<')) ||
  20891. X      (blank = strchr (original_params, '>')) ||
  20892. X      (blank = strchr (original_params, ':'))) {
  20893. X    reject_mail (sender, request,
  20894. X         tsprintf ("Invalid character %c in request.\n", *blank),
  20895. X         SYNTAX_ERROR, 0);
  20896. X    return;
  20897. X  }
  20898. X  clean_request (_prog); /* Skip leading blanks */
  20899. X  while (*_prog != EOS && *_prog == 'X') ++_prog;
  20900. X  clean_request (_prog); /* Skip leading blanks */
  20901. X  if (*_prog == EOS) {
  20902. X    reject_mail (sender, request, tsprintf ("Missing command to run for %s \
  20903. Xrequest\n\n\
  20904. XSyntax: run <list> [<password> <cmd> [args]]\n", req), SYNTAX_ERROR, 0);
  20905. X    return;
  20906. X  }
  20907. X  sscanf (_prog, "%s ", prog);
  20908. X  upcase (prog);
  20909. X  while (unix_cmd) {
  20910. X    if (!strcmp (unix_cmd->name, prog)) {
  20911. X      strcpy (prog, unix_cmd->cmd);
  20912. X      break;
  20913. X    }
  20914. X    unix_cmd = unix_cmd->next;
  20915. X  }
  20916. X  if (!unix_cmd) {
  20917. X    reject_mail (sender, request, tsprintf ("Unknown command %s\n", prog),
  20918. X         SYNTAX_ERROR, 0);
  20919. X    return;
  20920. X  }
  20921. X  original_params [strlen (original_params) - 1] = EOS; /* Remove \n */
  20922. X  while (*_prog != EOS && isspace (*_prog))    /* Skip over cmd */
  20923. X    ++_prog;
  20924. X  while (*_prog != EOS && !isspace (*_prog))    /* Get to arguments */
  20925. X    ++_prog;
  20926. X  while (*_prog != EOS && isspace (*_prog))
  20927. X    ++_prog;
  20928. X  nargs = 0;
  20929. X  while (*_prog != EOS && nargs < 9) {
  20930. X    if (!(args[nargs] = (char *) malloc ((strlen (_prog) + 1) * sizeof (char))))
  20931. X      report_progress (report, "\nunix_cmd(): malloc() failed", TRUE),
  20932. X      gexit (11);
  20933. X    strcpy (args[nargs], _prog);
  20934. X    if ((blank = strchr (args[nargs++], ' ')))
  20935. X      *blank = EOS;
  20936. X    while (*_prog != EOS && !isspace (*_prog))
  20937. X      ++_prog;
  20938. X    while (*_prog != EOS && isspace (*_prog))    /* Get to next arg */
  20939. X      ++_prog;
  20940. X  }
  20941. X  _prog = prog;
  20942. X  while (*_prog != EOS && (_prog = strchr (_prog, '$')))
  20943. X    if (*(_prog + 1) == '*')     /* Insert all user arguments */
  20944. X      if (nargs)
  20945. X    _prog += insert_word (_prog, args, nargs, 0, 2);
  20946. X      else
  20947. X    *_prog = ' ',
  20948. X    *(_prog + 1) = ' ',
  20949. X    _prog += 2;
  20950. X    else if (isdigit (*(_prog + 1)) && *(_prog + 1) > '0')
  20951. X      if (nargs && ((int) *(_prog + 1) - '0') <= nargs)
  20952. X    _prog += insert_word (_prog, args, 1, (int) *(_prog + 1) - '0' - 1, 2);
  20953. X      else
  20954. X    *_prog = ' ',
  20955. X    *(_prog + 1) = ' ',
  20956. X    _prog += 2;
  20957. X    else
  20958. X      ++_prog;
  20959. X  while (nargs)
  20960. X    free ((char *) args[--nargs]);
  20961. X#ifdef bsd
  20962. X    sig_mask = sigblock (sigmask (SIGINT) | sigmask (SIGTERM));
  20963. X#elif defined (svr4) || defined (svr3)
  20964. X    sighold (SIGINT);
  20965. X    sighold (SIGTERM);
  20966. X#endif
  20967. X  syscom ("%s > %s 2> %s", prog, STDOUT, STDERR);
  20968. X#ifdef bsd
  20969. X    sigsetmask (sig_mask);
  20970. X#elif defined (svr4) || defined (svr3)
  20971. X    sigrelse (SIGINT);
  20972. X    sigrelse (SIGTERM);
  20973. X#endif
  20974. X  create_header (&f, MAILFORWARD, sys.server.address, sender, request, FALSE,
  20975. X         OK, FALSE, FALSE);
  20976. X  if (!stat (STDOUT, &stat_buf) && stat_buf.st_size > 0) {
  20977. X    fprintf (f, "Output from stdout:\n");
  20978. X    fclose (f);
  20979. X    cat_append (STDOUT, MAILFORWARD);
  20980. X    APPEND_TELNET ("execute");
  20981. X    DELIVER_MAIL (sender, FALSE);
  20982. X  }
  20983. X  if (!stat (STDERR, &stat_buf) && stat_buf.st_size > 0) {
  20984. X    if (interactive)
  20985. X      if (stat (STDOUT, &stat_buf))
  20986. X    create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20987. X               FALSE, OK, FALSE, FALSE);
  20988. X      else
  20989. X    f = fopen (MAILFORWARD, "a");
  20990. X    else
  20991. X      create_header (&f, MAILFORWARD, sys.server.address, sender, request,
  20992. X             FALSE, OK, FALSE, FALSE);
  20993. X    fprintf (f, "Output from stderr:\n");
  20994. X    fclose (f);
  20995. X    cat_append (STDERR, MAILFORWARD);
  20996. X    APPEND_TELNET ("execute");
  20997. X    DELIVER_MAIL (sender, FALSE);
  20998. X  }
  20999. X  unlink (STDOUT);
  21000. X  unlink (STDERR);
  21001. X}
  21002. X
  21003. X/*
  21004. X  Initialize the commands[].
  21005. X*/
  21006. X
  21007. Xvoid init_commands ()
  21008. X{
  21009. X  COMMAND (0, "HELP", 0x1, help);
  21010. X  COMMAND (1, "SET", 0x2, set);
  21011. X  COMMAND (2, "SUBSCRIBE", 0x4, subscribe);
  21012. X  COMMAND (3, "UNSUBSCRIBE", 0x8, unsubscribe);
  21013. X  COMMAND (4, "SIGNOFF", 0x8, unsubscribe);
  21014. X  COMMAND (5, "RECIPIENTS", 0x10, recipients);
  21015. X  COMMAND (6, "REVIEW", 0x10, recipients);
  21016. X  COMMAND (7, "INFORMATION", 0x20, info);
  21017. X  COMMAND (8, "STATISTICS", 0x40, stats);
  21018. X  COMMAND (9, "SHUTDOWN", 0x80, Shutdown);
  21019. X  COMMAND (10, "RESTART", 0x100, restart);
  21020. X  COMMAND (11, "LISTS", 0x200, lists);
  21021. X  COMMAND (12, "INDEX", 0x400, Index);
  21022. X  COMMAND (13, "GET", 0x800, get);
  21023. X  COMMAND (14, "RELEASE", 0x1000, release);
  21024. X  COMMAND (15, "WHICH", 0x2000, which);
  21025. X  COMMAND (16, "SYSTEM", 0x4000, System);
  21026. X  COMMAND (17, "REPORTS", 0x8000, get_sys_files);
  21027. X  COMMAND (18, "EDIT", 0x10000, get_sys_files);
  21028. X  COMMAND (19, "PUT", 0x20000, put);
  21029. X  COMMAND (20, "NOTIFY", 0x40000, notify);
  21030. X  COMMAND (21, "APPROVE", 0x80000, approve);
  21031. X  COMMAND (22, "DISCARD", 0x100000, discard);
  21032. X  COMMAND (23, "EXECUTE", 0x200000, execute);
  21033. X  COMMAND (24, "RUN", 0x400000, unix_cmd);
  21034. X  COMMAND (25, "FAX", 0x800000, get);
  21035. X  COMMAND (26, "SEARCH", 0x1000000, search);
  21036. X}
  21037. X
  21038. Xvoid usage ()
  21039. X{
  21040. X  fprintf (stderr, "Usage: listserv [-1] [-e] [-i] [-n] [-a <LIST_ALIAS>] \
  21041. X[-c <LIST_ALIAS>] {[-r <request>]}* {[-d <request>]}* {[-b <request>]}* [-B] \
  21042. X[-D]\n\
  21043. X-1: Execute only once.\n\
  21044. X-e: Echo reports to the screen.\n\
  21045. X-i: Interactive mode (do not send mail).\n\
  21046. X-n: Do not notify peer servers.\n\
  21047. X-a: Turn off automatic subscription for the specified list.\n\
  21048. X-c: Conceal the specified list from LISTS requests.\n\
  21049. X-r: Set restriction on 'request'.\n\
  21050. X-d: Disable 'request'.\n\
  21051. X-b: Batch 'request'.\n\
  21052. X-B: Process the batch queue.\n\
  21053. X-D: Turn debug on.\n");
  21054. X  exit (3);
  21055. X}
  21056. X
  21057. Xvoid server_config (char *alias)
  21058. X{
  21059. X  setup_string (list_mail_f, alias, LIST_MAIL_FILE);
  21060. X  setup_string (list_moderated_f, alias, LIST_MODERATED_F);
  21061. X  setup_string (infof, alias, INFO_FILE);
  21062. X  setup_string (recipf, alias, RECIP_FILE);
  21063. X  setup_string (welcomef, alias, WELCOME_FILE);
  21064. X  setup_string (subscribersf, alias, SUBSCRIBERS);
  21065. X  setup_string (aliasesf, alias, ALIASES);
  21066. X  setup_string (newsf, alias, NEWSF);
  21067. X  setup_string (peersf, alias, PEERS);
  21068. X  setup_string (headersf, alias, HEADERS);
  21069. X  setup_string (ignoredf, alias, IGNORED);
  21070. X  setup_string (aliases_timestampf, alias, ALIASES_TIMESTAMPF);
  21071. X  setup_string (ignored_timestampf, alias, IGNORED_TIMESTAMPF);
  21072. X  setup_string (info_timestampf, alias, INFO_TIMESTAMPF);
  21073. X  setup_string (subscribers_timestampf, alias, SUBSCRIBERS_TIMESTAMPF);
  21074. X  setup_string (welcome_timestampf, alias, WELCOME_TIMESTAMPF);
  21075. X  setup_string (news_timestampf, alias, NEWS_TIMESTAMPF);
  21076. X  setup_string (peers_timestampf, alias, PEERS_TIMESTAMPF);
  21077. X}
  21078. X
  21079. X/*
  21080. X  Graceful exit. Remove pid file.
  21081. X*/
  21082. X
  21083. Xint gexit (int exitcode)
  21084. X{
  21085. X  unlink (PID_SERVER);
  21086. X#ifndef NO_LOCKS
  21087. X  unlock_file (lfd);
  21088. X#endif
  21089. X  exit (exitcode);
  21090. X}
  21091. *-*-END-of-src/listserv.c-*-*
  21092. echo x - src/misc.c
  21093. sed 's/^X//' >src/misc.c <<'*-*-END-of-src/misc.c-*-*'
  21094. X/*
  21095. X  ----------------------------------------------------------------------------
  21096. X  |                      GENERAL PURPOSE FUNCTIONS                           |
  21097. X  |                                                                          |
  21098. X  |                             Version 3.0                                  |
  21099. X  |                                                                          |
  21100. X  |                (or, when Computer Science gets to you)                   |
  21101. X  |                                                                          |
  21102. X  |                    Written by Anastasios Kotsikonas                      |
  21103. X  |                           (tasos@cs.bu.edu)                              |
  21104. X  |                                                                          |
  21105. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  21106. X  | whole and not in parts, as long as you do not remove or alter the author |
  21107. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  21108. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  21109. X  | provided for your personal use, you you may not alter the functions      |
  21110. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  21111. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  21112. X  | any changes you may have made. No part of the source code bearing a         |
  21113. X  | copyright notice can be included in commercial software systems without  |
  21114. X  | written permission by the author.                         |
  21115. X  | By using this software you are bound by this agreement.                  |
  21116. X  | This software comes with no warranties and cannot be sold for profit.    |
  21117. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  21118. X  | files when distributing this software.                                   |
  21119. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  21120. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  21121. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  21122. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  21123. X  | (ii).                                                                    |
  21124. X  ----------------------------------------------------------------------------
  21125. X*/
  21126. X
  21127. X#include <stdio.h>
  21128. X#include <sys/types.h>
  21129. X#ifdef SYSLOG
  21130. X# ifdef ultrix
  21131. X#  include <sys/syslog.h>
  21132. X# else
  21133. X#  include <syslog.h>
  21134. X# endif
  21135. X#endif
  21136. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  21137. X  && !defined (sequent) && !defined (unknown_port)
  21138. X# include <malloc.h>
  21139. X#endif
  21140. X#include <time.h>
  21141. X#include <string.h>
  21142. X#include <signal.h>
  21143. X#include <ctype.h>
  21144. X#ifndef unknown_port
  21145. X# ifndef __NeXT__
  21146. X#  include <unistd.h>
  21147. X# else
  21148. X#  include <libc.h>
  21149. X# endif
  21150. X#endif
  21151. X#include <sys/stat.h>
  21152. X#include <fcntl.h>
  21153. X#include <errno.h>
  21154. X#ifdef unknown_port
  21155. Xextern int errno;
  21156. X#endif
  21157. X#include <signal.h>
  21158. X#include <sys/wait.h>
  21159. X#include <math.h>
  21160. X#include "defs.h"
  21161. X#include "struct.h"
  21162. X
  21163. X#ifndef WAIT3_NEEDS_UNION
  21164. X# if defined (sequent) || defined (unknown_port)
  21165. X#  ifdef WEXITSTATUS
  21166. X#   undef WEXITSTATUS
  21167. X#  endif
  21168. X# endif
  21169. X#endif
  21170. X
  21171. X#ifndef WEXITSTATUS
  21172. X# define  WEXITSTATUS(stat)    ((int)(((stat)>>8)&0377))
  21173. X#endif
  21174. X
  21175. Xextern  COMMANDS commands[MAX_COMMANDS];
  21176. Xextern  REMOTE *rlists, *matched_rlists;
  21177. Xextern  BOOLEAN extract_sender (char *);
  21178. Xextern  char *options [MAX_SET_OPTIONS];
  21179. Xextern  char *values [MAX_SET_OPTIONS];
  21180. X
  21181. X#if !defined (__NeXT__) && !defined (__osf__) && !defined (_AIX)
  21182. Xextern long int atoi (char *);
  21183. X#else
  21184. Xextern int atoi (const char *);
  21185. X#endif
  21186. Xextern BOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
  21187. Xextern void process_message (char *, char *, BOOLEAN, BOOLEAN);
  21188. Xextern int re_strcmp (char *, char *, char *);
  21189. Xextern int gexit (int);
  21190. Xextern int mv (char *, char *);
  21191. X
  21192. X#ifdef __STDC__
  21193. X# include "ansi/misc.h"
  21194. X# include <stdarg.h>
  21195. Xint     syscom (char *, ...);
  21196. Xextern  char *tsprintf (char *, ...);
  21197. X#else
  21198. X# include "nonansi/misc.h"
  21199. X# include <varargs.h>
  21200. Xint     syscom ();
  21201. Xextern  char *tsprintf ();
  21202. X#endif
  21203. Xint    sys_config (FILE *, SYS *);
  21204. Xvoid    config_owner_prefs (SYS *, int, FILE *);
  21205. Xchar    *locase (char *);
  21206. Xchar    *upcase (char *);
  21207. Xvoid    shadow_password (char *);
  21208. Xvoid    report_progress (FILE *, char *, int);
  21209. Xvoid    distribute (FILE *, void (*)(char *, char *, BOOLEAN, BOOLEAN), FILE *,
  21210. X            char *, char *, char *, char *);
  21211. XBOOLEAN strinstr (char *, char *);
  21212. Xchar    *extract_filename (char *);
  21213. Xint     _getopt (int, char **, char *);
  21214. Xchar    *clean_name (char *);
  21215. Xvoid    clean_request (char *);
  21216. Xvoid    get_list_name (char *, char *);
  21217. Xvoid    free_remote_matched (REMOTE **);
  21218. Xint    get_list_id (char *, SYS *, int);
  21219. XREMOTE  *check_remote (REMOTE *, char *);
  21220. Xvoid    setup_string (char *, char *, char *);
  21221. Xchar    *_strstr (char *, char *);
  21222. Xvoid    shrink (char *);
  21223. XBOOLEAN requested_part (char *, int);
  21224. Xvoid    free_remote (REMOTE **);
  21225. Xint    my_system (char *);
  21226. XBOOLEAN remove_msg (char *, int, FILE *);
  21227. Xvoid    read_params (char *, char *, char *, FILE *, FILE *);
  21228. Xint    lock_file (char *, int, int, BOOLEAN);
  21229. Xvoid    unlock_file (int);
  21230. Xlong int write_to_fd (int, char *, long int);
  21231. XBOOLEAN mkdir1 (char *, char *, char *);
  21232. Xint    otoi (char *);
  21233. XBOOLEAN get_field (char **, char, char *);
  21234. XBOOLEAN make_indexes (char *, char *, char *, char *, char *);
  21235. Xint    insert_word (char *, char **, int, int, int);
  21236. Xchar    *skip_to_word (char *, int);
  21237. Xchar    *mystrdup (char *);
  21238. X
  21239. X/*
  21240. X  Execute a system request.
  21241. X*/
  21242. X
  21243. X#ifdef __STDC__
  21244. Xint syscom (char *control, ...)
  21245. X#else
  21246. Xint syscom (control, va_alist)
  21247. Xchar *control;
  21248. Xva_dcl
  21249. X#endif
  21250. X{
  21251. X  char command [10240], *ambersand;
  21252. X  int mask;
  21253. X  extern SYS sys;
  21254. X  extern BOOLEAN tty_echo;
  21255. X  va_list ap;
  21256. X  int status;
  21257. X  FILE *f;
  21258. X  long int time_is = 0;
  21259. X  struct tm *t;
  21260. X
  21261. X#ifdef __STDC__
  21262. X  va_start (ap, control);
  21263. X#else
  21264. X  va_start (ap);
  21265. X#endif
  21266. X  RESET (command);
  21267. X  vsprintf (command, control, ap);
  21268. X  va_end (ap);
  21269. X  if (!_strstr (command, " 2>")) {
  21270. X    sprintf (command + strlen (command), " 2>> %s", WARNING);
  21271. X    if ((ambersand = _strstr (command, " &")))
  21272. X      *(ambersand + 1) = ' ',
  21273. X      strcat (command, " &");
  21274. X  }
  21275. X#ifdef GO_INTERACTIVE
  21276. X# if defined (bsd)
  21277. X#  ifdef SIGCLD
  21278. X      mask = sigblock (sigmask (SIGCLD));
  21279. X#  elif defined (SIGCHLD)
  21280. X      mask = sigblock (sigmask (SIGCHLD));
  21281. X#  endif
  21282. X# elif (defined (svr4) || defined (svr3)) && !defined (stellar) && \
  21283. X  !defined (M_UNIX) && !defined (M_XENIX) && !defined (sco) && \
  21284. X  !defined (unknown_port)
  21285. X#  ifdef SIGCLD
  21286. X      sighold (SIGCLD);
  21287. X#  elif defined (SIGCHLD)
  21288. X      sighold (SIGCHLD);
  21289. X#  endif
  21290. X# endif
  21291. X#endif
  21292. X  if ((sys.options & USE_MY_SYSTEM) == 0)
  21293. X    status = system (command);
  21294. X  else
  21295. X    status = my_system (command);
  21296. X#ifdef GO_INTERACTIVE
  21297. X# if defined (bsd) && (defined (SIGCLD) || defined (SIGCHLD))
  21298. X    sigsetmask (mask);
  21299. X# elif (defined (svr3) || defined (svr4)) && !defined (stellar) && \
  21300. X  !defined (M_UNIX) && !defined (M_XENIX) && !defined (sco) && \
  21301. X  !defined (unknown_port)
  21302. X# ifdef SIGCLD
  21303. X    sigrelse (SIGCLD);
  21304. X#  elif defined (SIGCHLD)
  21305. X    sigrelse (SIGCHLD);
  21306. X#  endif
  21307. X# endif
  21308. X#endif
  21309. X  if (status > 0) {
  21310. X    if ((f = fopen (WARNING, "a")) != NULL)
  21311. X      fprintf (f, "\nWARNING: System call exit status %d: %s\n",
  21312. X           WEXITSTATUS (status), command),
  21313. X      time (&time_is),
  21314. X      t = localtime (&time_is),
  21315. X      fprintf (f, "Time/Date: %2d:%.2d:%.2d, %2d/%.2d/%2d\n",
  21316. X               t->tm_hour, t->tm_min, t->tm_sec, t->tm_mon + 1, t->tm_mday,
  21317. X               t->tm_year),
  21318. X      fclose (f);
  21319. X    if (tty_echo)
  21320. X      printf ("\nWARNING: System call exit status %d: %s\n",
  21321. X          WEXITSTATUS (status), command);
  21322. X  }
  21323. X  return status;
  21324. X}
  21325. X
  21326. X/*
  21327. X  Initialize the 'sys' structure from the CONFIG file. It returns the number
  21328. X  of lists in the system.
  21329. X*/
  21330. X
  21331. Xint sys_config (FILE *report, SYS *sys)
  21332. X{
  21333. X  FILE *config;
  21334. X  char cmd [MAX_LINE];
  21335. X  char args [MAX_LINE];
  21336. X  char arg [MAX_LINE];
  21337. X  char line [MAX_LINE];
  21338. X  char *comment, *cmdarg, *start, *end;
  21339. X  int nlists = 0, i, j, k, id;
  21340. X  BOOLEAN notok, found;
  21341. X  REMOTE *remote;
  21342. X  PRECIOUS_HEADER *header;
  21343. X  UNIX_CMDS *unix_cmd;
  21344. X
  21345. X  for (i = 0; i < MAX_LISTS; i++)
  21346. X    sys->lists[i].digest_lines = 1000,
  21347. X    sys->lists[i].digest_hours = 24,
  21348. X    sys->lists[i].disabled_commands = 0,
  21349. X    sys->lists[i].owner_prefs = 0,
  21350. X    sys->lists[i].header = NULL,
  21351. X    sys->lists[i].unix_cmds = NULL,
  21352. X    sys->lists[i].options = 0,
  21353. X    sys->lists[i].max_messages = 0,
  21354. X    RESET (sys->lists[i].alias),
  21355. X    RESET (sys->lists[i].address),
  21356. X    RESET (sys->lists[i].password),
  21357. X    RESET (sys->lists[i].owner),
  21358. X    RESET (sys->lists[i].comment),
  21359. X    RESET (sys->lists[i].cmdoptions),
  21360. X    RESET (sys->lists[i].arch_dir),
  21361. X    RESET (sys->lists[i].farch_dir),
  21362. X    RESET (sys->lists[i].arch_pass),
  21363. X    RESET (sys->lists[i].arch_spec);
  21364. X  RESET (sys->server.address), RESET (sys->server.cmdoptions),
  21365. X  RESET (sys->server.comment), RESET (sys->serverd_cmdoptions),
  21366. X  RESET (sys->server.password), RESET (sys->arg), RESET (sys->manager),
  21367. X  RESET (sys->organization), RESET (sys->fax.prog);
  21368. X  sys->limits.msg = sys->limits.files = 100000;
  21369. X  sys->server.manager_prefs = 0;
  21370. X  strcpy (sys->server.address, DEFAULT_SERVER_ADDRESS);
  21371. X  strcpy (sys->server.cmdoptions, DEFAULT_SERVER_CMDOPTIONS);
  21372. X  strcpy (sys->server.comment, DEFAULT_SERVER_COMMENT);
  21373. X  strcpy (sys->manager, DEFAULT_MANAGER);
  21374. X  sys->mail.method = BINMAIL;
  21375. X  strcpy (sys->mail.precedence, DEFAULT_PRECEDENCE);
  21376. X  sys->options = 0;
  21377. X  sys->users = 100;
  21378. X  sys->frequency = 5;
  21379. X  sys->batch.start = 8; /* 8 am */
  21380. X  sys->batch.stop = 20; /* 8 pm */
  21381. X  OPEN_FILE (config, CONFIG, "r", "sys_config");
  21382. X  chmod (CONFIG, 384);
  21383. X  while (! feof (config)) {
  21384. X    line [0] = args [0] = RESET (cmd);
  21385. X    fgets (line, MAX_LINE - 2, config);
  21386. X    sscanf (line, "%s", cmd);
  21387. X    if (cmd[0] == EOS)
  21388. X      continue;
  21389. X/*    fgets (args, MAX_LINE - 2, config);*/
  21390. X    read_params (line, args, cmd, config, NULL);
  21391. X    if (args [strlen (args) - 1] == '\n')
  21392. X      args [strlen (args) - 1] = EOS;
  21393. X    if (cmd[0] == '#')
  21394. X      continue;
  21395. X    if (!strcmp (locase (cmd), "list")) {
  21396. X      if (nlists >= MAX_LISTS) {
  21397. X    report_progress (report,
  21398. X             tsprintf ("\nsys_config(): List %s ignored: too many \
  21399. Xlists\n",
  21400. X                   args), FALSE);
  21401. X    continue;
  21402. X      }
  21403. X      comment = strchr (args, '#');
  21404. X      if (comment)
  21405. X    *comment = EOS;
  21406. X      sscanf (args, "%s %s %s %s", sys->lists [nlists].alias,
  21407. X          sys->lists [nlists].address, sys->lists [nlists].owner,
  21408. X          sys->lists [nlists].password);
  21409. X      if (get_list_id (sys->lists [nlists].alias, sys, nlists) >= 0 &&
  21410. X      nlists > 0)
  21411. X    report_progress (report,
  21412. X             tsprintf ("\nsys_config(): Duplicate list %s in %s",
  21413. X                   sys->lists [nlists].alias, CONFIG), TRUE),
  21414. X    exit (4);
  21415. X      cmdarg = _strstr (args, " -");
  21416. X      if (!cmdarg)
  21417. X    cmdarg = _strstr (args, "\t-");
  21418. X      if (cmdarg)
  21419. X    strcat (sys->lists [nlists].cmdoptions, cmdarg);
  21420. X      upcase (sys->lists [nlists].alias);
  21421. X      locase (sys->lists [nlists].address);
  21422. X      locase (sys->lists [nlists].owner);
  21423. X      upcase (sys->lists [nlists].password);
  21424. X      ++nlists;
  21425. X    }
  21426. X    else if (!strcmp (cmd, "server")) {
  21427. X      comment = strchr (args, '#');
  21428. X      if (comment)
  21429. X        *comment = EOS;
  21430. X      sscanf (args, "%s", sys->server.address);
  21431. X      cmdarg = _strstr (args, " -");
  21432. X      if (!cmdarg)
  21433. X    cmdarg = _strstr (args, "\t-");
  21434. X      if (cmdarg)
  21435. X    strcat (sys->server.cmdoptions, cmdarg);
  21436. X      locase (sys->server.address);
  21437. X    }
  21438. X    else if (!strcmp (cmd, "remote")) {
  21439. X      if ((remote = (REMOTE *) malloc (sizeof (*remote))) == NULL)
  21440. X    report_progress (report,
  21441. X             tsprintf ("\nsys_config(): malloc() failed during \
  21442. X'remote' in %s",
  21443. X                   CONFIG), TRUE),
  21444. X    exit (11);
  21445. X      RESET (remote->inet_addr);
  21446. X      remote->port = 0;
  21447. X      sscanf (args, "%s %s %s %s %d", remote->alias, remote->address,
  21448. X          remote->listserv, remote->inet_addr, &remote->port);
  21449. X      upcase (remote->alias);
  21450. X      locase (remote->address);
  21451. X      locase (remote->listserv);
  21452. X      if (remote->inet_addr[0] == '#')
  21453. X    RESET (remote->inet_addr);
  21454. X      else if (remote->port == 0)
  21455. X    remote->port = DEFAULT_IUL_PORT;
  21456. X      comment = strchr (args, '#');
  21457. X      if (!comment)
  21458. X        report_progress (report,
  21459. X             tsprintf ("\nsys_config(): Missing # for 'remote' in %s",
  21460. X                   CONFIG), TRUE),
  21461. X        exit (4);
  21462. X      RESET (remote->comment);
  21463. X      strcat (remote->comment, comment + 1);
  21464. X      remote->next = rlists;  /* Link it to the existing list */
  21465. X      rlists = remote;
  21466. X    }
  21467. X    else if (!strcmp (cmd, "frequency")) {
  21468. X      sscanf (args, "%d", &sys->frequency);
  21469. X      if (sys->frequency < 0 || sys->frequency > 86400)
  21470. X    report_progress (report,
  21471. X             tsprintf ("\nsys_config(): Invalid 'frequency' \
  21472. Xargument %d in %s",
  21473. X                   sys->frequency, CONFIG), TRUE),
  21474. X    exit (4);
  21475. X    }
  21476. X    else if (!strcmp (cmd, "limit")) {
  21477. X      sscanf (args, "%s", sys->arg);
  21478. X      if (!strcmp (locase (sys->arg), "message"))
  21479. X    sys->options |= LIMIT_MSG,
  21480. X        sscanf (args, "%s %ld", sys->arg, &sys->limits.msg);
  21481. X      else if (!strcmp (sys->arg, "files"))
  21482. X    sys->options |= LIMIT_FILES,
  21483. X    sscanf (args, "%s %ld", sys->arg, &sys->limits.files);
  21484. X      else
  21485. X     report_progress (report,
  21486. X             tsprintf ("\nsys_config(): Invalid argument %s to \
  21487. X'limit' in %s",
  21488. X                   sys->arg, CONFIG), TRUE),
  21489. X    exit (4);
  21490. X    }
  21491. X    else if (!strcmp (cmd, "ceiling")) {
  21492. X      sscanf (args, "%s ", sys->arg);
  21493. X      upcase (sys->arg);
  21494. X      id = get_list_id (sys->arg, sys, nlists);
  21495. X      if (id < 0)
  21496. X        report_progress (report,
  21497. X             tsprintf ("\nsys_config(): Unrecognized list name %s \
  21498. Xfor 'ceiling' in %s", sys->arg, CONFIG), TRUE),
  21499. X        exit (4);
  21500. X      sscanf (args, "%s %d", sys->arg, &sys->lists[id].max_messages);
  21501. X    }
  21502. X    else if (!strcmp (cmd, "batch")) {
  21503. X      sscanf (args, "%u %u", &sys->batch.start, &sys->batch.stop);
  21504. X      sys->batch.start %= 24;
  21505. X      sys->batch.stop %= 24;
  21506. X      if (sys->batch.stop == 0)
  21507. X    sys->batch.stop = 24;
  21508. X      if (sys->batch.start >= sys->batch.stop ||
  21509. X      (sys->batch.start == 0 && sys->batch.stop == 24))
  21510. X    report_progress (report, tsprintf ("\nsys_config(): Invalid times to \
  21511. X'batch' in %s",
  21512. X                       CONFIG), TRUE),
  21513. X    exit (4);
  21514. X    }
  21515. X    else if (!strcmp (cmd, "option")) {
  21516. X      sscanf (args, "%s", sys->arg);
  21517. X      if (!strcmp (locase (sys->arg), "bsd_ps"))
  21518. X    sys->options |= BSD_PS;
  21519. X      else if (!strcmp (sys->arg, "sysv_ps"))
  21520. X    sys->options |= SYSV_PS;
  21521. X      else if (!strcmp (sys->arg, "bsd_mail"))
  21522. X    sys->options |= BSD_MAIL;
  21523. X      else if (!strcmp (sys->arg, "bad_telnet"))
  21524. X    sys->options |= USE_MY_SYSTEM;
  21525. X      else if (!strcmp (sys->arg, "post_mail"))
  21526. X    sys->options |= POST_MAIL;
  21527. X      else if (!strcmp (sys->arg, "gate_mail"))
  21528. X    sys->options |= GATE_MAIL;
  21529. X      else if (!strcmp (sys->arg, "ignore_invalid_requests"))
  21530. X    sys->options |= IGNR_INVLD_RQSTS;
  21531. X      else if (!strcmp (sys->arg, "relaxed_syntax"))
  21532. X    sys->options |= RELAXED_SYNTAX;
  21533. X      else
  21534. X    report_progress (report, tsprintf ("\nsys_config(): Invalid argument \
  21535. X%s to 'option' in %s",
  21536. X                       sys->arg, CONFIG), TRUE),
  21537. X    exit (4);
  21538. X    }
  21539. X    else if (!strcmp (cmd, "serverd")) {
  21540. X      comment = strchr (args, '#');
  21541. X      if (comment)
  21542. X        *comment = EOS;
  21543. X      cmdarg = strchr (args, '-');
  21544. X      if (cmdarg)
  21545. X    strcat (sys->serverd_cmdoptions, cmdarg);
  21546. X    }
  21547. X    else if (!strcmp (cmd, "organization")) {
  21548. X      comment = strchr (args, '#');
  21549. X      if (comment)
  21550. X        *comment = EOS;
  21551. X      strcpy (sys->organization, args + 1);
  21552. X    }
  21553. X    else if (!strcmp (cmd, "restriction"))
  21554. X      sscanf (args, "%d", &sys->users);
  21555. X    else if (!strcmp (cmd, "manager"))
  21556. X      sscanf (args, "%s", sys->manager);
  21557. X    else if (!strcmp (cmd, "password"))
  21558. X      sscanf (args, "%s", sys->server.password),
  21559. X      upcase (sys->server.password);
  21560. X    else if (!strcmp (cmd, "disable")) {
  21561. X      if (commands[0].name == NULL)  /* Array not initialized */
  21562. X    continue;
  21563. X      sscanf (args, "%s", sys->arg);
  21564. X      upcase (sys->arg);
  21565. X      id = get_list_id (sys->arg, sys, nlists);
  21566. X      if (id < 0)
  21567. X      report_progress (report, tsprintf ("\nsys_config(): Unrecognized \
  21568. Xlist name %s for 'disable' in %s", sys->arg, CONFIG), TRUE),
  21569. X      exit (4);
  21570. X      sscanf (args, "%s %s", sys->arg, sys->arg); /* Get request to disable */
  21571. X      upcase (sys->arg);
  21572. X      notok = FALSE;
  21573. X      k = 0;
  21574. X      for (i = 0; i < MAX_COMMANDS; ++i) {
  21575. X    notok &= (((j = strncmp (sys->arg, commands[i].name, strlen (sys->arg)))
  21576. X           != 0) ? 1 : 0);
  21577. X    if (!j)
  21578. X      ++k,
  21579. X      sys->lists[id].disabled_commands |= commands[i].mask;
  21580. X      }
  21581. X      if (notok)
  21582. X    report_progress (report,
  21583. X             tsprintf ("\nsys_config(): Unrecognized \
  21584. Xrequest %s to 'disable' for list %s in %s",
  21585. X                   sys->arg, sys->lists[id].alias, CONFIG),
  21586. X             TRUE),
  21587. X    exit (4);
  21588. X      if (k > 1)
  21589. X    report_progress (report, tsprintf ("\nsys_config(): Ambiguous request \
  21590. X%s to 'disable' for list %s in %s", sys->arg, sys->lists[id].alias, CONFIG),
  21591. X             TRUE),
  21592. X    exit (4);
  21593. X    }
  21594. X    else if (!strcmp (cmd, "comment")) {
  21595. X      sscanf (args, "%s", sys->arg);
  21596. X      if (!strcmp (locase (sys->arg), "server")) {
  21597. X    comment = strchr (args, '#');
  21598. X    if (!comment)
  21599. X          report_progress (report, tsprintf ("\nsys_config(): Missing # for \
  21600. X'comment' in %s",
  21601. X                         CONFIG), TRUE),
  21602. X          exit (4);
  21603. X    RESET (sys->server.comment);
  21604. X    strcat (sys->server.comment, comment + 1);
  21605. X      }
  21606. X      else {  /* Some list name was specified */
  21607. X    upcase (sys->arg);
  21608. X    id = get_list_id (sys->arg, sys, nlists);
  21609. X    if (id < 0)
  21610. X      report_progress (report, tsprintf ("\nsys_config(): Unrecognized \
  21611. Xlist name %s for 'comment' in %s", sys->arg, CONFIG), TRUE),
  21612. X      exit (4);
  21613. X    comment = strchr (args, '#');
  21614. X    if (!comment)
  21615. X      report_progress (report, tsprintf ("\nsys_config(): Missing # for \
  21616. Xcomment in %s", CONFIG), TRUE),
  21617. X      exit (4);
  21618. X    RESET (sys->lists[id].comment);
  21619. X    strcat (sys->lists[id].comment, comment + 1);
  21620. X      }
  21621. X    }
  21622. X    else if (!strcmp (cmd, "mailmethod")) {
  21623. X      sscanf (args, "%s", sys->arg);
  21624. X      if (!strcmp (locase (sys->arg), "telnet"))
  21625. X    sys->mail.method = TELNET,
  21626. X     sys->options |= USE_TELNET;
  21627. X      else if (!strcmp (locase (sys->arg), "system")) {
  21628. X#ifndef TCP_IP
  21629. X    report_progress (report, "\nsys_config(): No system support for \
  21630. X'system' mailmethod. Select another method.", TRUE);
  21631. X    exit (1);
  21632. X#endif
  21633. X    sys->options |= (USE_TELNET | USE_SYSMAIL);
  21634. X      }
  21635. X      else if (!strcmp (sys->arg, "sendmail") || !strcmp (sys->arg, "rmail")) {
  21636. X    if (!(sys->mail.method = (char *) malloc (256 * sizeof (char))))
  21637. X      report_progress (report, tsprintf ("\nsys_config(): malloc() failed \
  21638. Xduring 'mailmethod' in %s", CONFIG), TRUE),
  21639. X      exit (11);
  21640. X    sscanf (args, "%s %s", sys->arg, sys->mail.method);
  21641. X    locase (sys->mail.method);
  21642. X    strcat (sys->mail.method, " > /dev/null 2>&1");
  21643. X      }
  21644. X      else if (!strcmp (sys->arg, "binmail"))
  21645. X    sys->mail.method = BINMAIL;
  21646. X      else if (!strcmp (sys->arg, "env_var"))
  21647. X    sys->options |= USE_ENV_VAR,
  21648. X    sscanf (args, "%s %s %s", sys->arg, sys->mail.env_var,
  21649. X            sys->mail.mail_prog),
  21650. X    locase (sys->mail.mail_prog),
  21651. X    upcase (sys->mail.env_var);
  21652. X      else
  21653. X    report_progress (report, tsprintf ("\nsys_config(): Unrecognized mail \
  21654. Xmethod %s in %s",
  21655. X                       sys->arg, CONFIG), TRUE),
  21656. X    exit (4);
  21657. X    }
  21658. X    else if (!strcmp (cmd, "digest")) { /* "digest list lines hours" */
  21659. X      sscanf (args, "%s ", sys->arg);
  21660. X      upcase (sys->arg);
  21661. X      id = get_list_id (sys->arg, sys, nlists);
  21662. X      if (id < 0)
  21663. X        report_progress (report, tsprintf ("\nsys_config(): Unrecognized list \
  21664. Xname %s for 'digest' in %s", sys->arg, CONFIG), TRUE),
  21665. X        exit (4);
  21666. X      sscanf (args, "%s %d %d", sys->arg, &sys->lists[id].digest_lines,
  21667. X          &sys->lists[id].digest_hours);
  21668. X    }
  21669. X    else if (!strcmp (cmd, "header")) { /* Precious header lines to be saved */
  21670. X      sscanf (args, "%s ", sys->arg);
  21671. X      upcase (sys->arg);
  21672. X      id = get_list_id (sys->arg, sys, nlists);
  21673. X      if (id < 0)
  21674. X        report_progress (report, tsprintf ("\nsys_config(): Unrecognized list \
  21675. Xname %s for 'header' in %s", sys->arg, CONFIG), TRUE),
  21676. X        exit (4);
  21677. X      if (!(comment = strchr (args, '{')))
  21678. X    report_progress (report, tsprintf ("\nsys_config(): Missing '{' for \
  21679. X'header' in %s",
  21680. X                       CONFIG), TRUE),
  21681. X        exit (4);
  21682. X      RESET (sys->arg);
  21683. X      sys->lists[id].header = NULL;
  21684. X      while (!feof (config) && strcmp (sys->arg, "}")) {
  21685. X    RESET (sys->arg);
  21686. X    fscanf (config, "%s\n", sys->arg);
  21687. X    if (sys->arg[0] == '#') {
  21688. X      fgets (sys->arg, MAX_LINE - 2, config);
  21689. X      continue;
  21690. X    }
  21691. X    if (sys->arg[0] != EOS && strcmp (sys->arg, "}")) {
  21692. X      if (! (header =
  21693. X         (PRECIOUS_HEADER *) malloc (sizeof (PRECIOUS_HEADER))))
  21694. X        report_progress (report, tsprintf ("\nsys_config(): malloc() \
  21695. Xfailed during 'header' in %s", CONFIG), TRUE),
  21696. X        exit (11);
  21697. X      if (! (header->line =
  21698. X          (char *) malloc ((strlen (sys->arg) + 1) * sizeof (char))))
  21699. X        report_progress (report, tsprintf ("\nsys_config(): malloc() \
  21700. Xfailed during 'header' in %s", CONFIG), TRUE),
  21701. X        exit (11);
  21702. X      strcpy (header->line, sys->arg);
  21703. X      header->next = sys->lists[id].header;
  21704. X      sys->lists[id].header = header;
  21705. X    }
  21706. X      }
  21707. X      if (feof (config) && strcmp (sys->arg, "}"))
  21708. X    report_progress (report, tsprintf ("\nsys_config(): Missing '}' for \
  21709. X'header' for list %s in %s", sys->lists[id].alias, CONFIG), TRUE),
  21710. X    exit (4);
  21711. X    }
  21712. X    else if (!strcmp (cmd, "default")) { /* Default list values */
  21713. X      sscanf (args, "%s ", sys->arg);
  21714. X      upcase (sys->arg);
  21715. X      id = get_list_id (sys->arg, sys, nlists);
  21716. X      if (id < 0)
  21717. X    report_progress (report, tsprintf ("\nsys_config(): Unrecognized list \
  21718. Xname %s for 'default' in %s", sys->arg, CONFIG), TRUE),
  21719. X    exit (4);
  21720. X      if (!(comment = strchr (args, '{')))
  21721. X    report_progress (report, tsprintf ("\nsys_config(): Missing '{' for \
  21722. X'default' in %s",
  21723. X                       CONFIG), TRUE),
  21724. X    exit (4);
  21725. X      RESET (sys->arg);
  21726. X      while (!feof (config) && strcmp (sys->arg, "}")) {
  21727. X    RESET (sys->arg);
  21728. X    fscanf (config, "%s ", sys->arg);
  21729. X    upcase (sys->arg);
  21730. X    if (sys->arg[0] == '#') {
  21731. X      fgets (sys->arg, MAX_LINE - 2, config);
  21732. X      continue;
  21733. X    }
  21734. X    if (sys->arg[0] != EOS && strcmp (sys->arg, "}")) {
  21735. X      found = FALSE;
  21736. X      for (i = 0; i < MAX_SET_OPTIONS; i++)
  21737. X        if (!strcmp (sys->arg, options[i])) {
  21738. X          found = TRUE;
  21739. X          break;
  21740. X        }
  21741. X      if (!found)
  21742. X        report_progress (report, tsprintf ("\nsys_config(): Default value \
  21743. X%s not recognized in %s", sys->arg, CONFIG), TRUE),
  21744. X        exit (4);
  21745. X      fscanf (config, "%s %s\n", line, line);
  21746. X      if (!re_strcmp (values[i], upcase (line), NULL))
  21747. X        report_progress (report, tsprintf ("\nsys_config(): %s not a valid \
  21748. Xdefault value for %s in %s", line, options[i], CONFIG), TRUE),
  21749. X        exit (4);
  21750. X      strcpy (sys->lists[id].defaults.set_values[i], line);
  21751. X    }
  21752. X      }
  21753. X      if (feof (config) && strcmp (sys->arg, "}"))
  21754. X    report_progress (report, tsprintf ("\nsys_config(): Missing '}' for \
  21755. X'default'  for list %s in %s", sys->lists[id].alias, CONFIG), TRUE),
  21756. X    exit (4);
  21757. X    }
  21758. X    else if (!strcmp (cmd, "precedence"))
  21759. X      sscanf (args, "%s", sys->mail.precedence);
  21760. X    else if (!strcmp (cmd, "fax"))
  21761. X      strcpy (sys->fax.prog, args);
  21762. X    else if (!strcmp (cmd, "archive")) {
  21763. X      /* USER CONTRIBUTED CODE: Warren Burstein
  21764. X         "archive list dir spec [farch-dir] [password] [digest]"
  21765. X     
  21766. X         dir must be an absolute path
  21767. X       
  21768. X         farch-dir should be relative to HOMEDIR/archives
  21769. X         so we can create all the INDEX files
  21770. X       
  21771. X         if you don't want digests but do want farch-dir, set the field
  21772. X         to anything but digest, if you don't want farch-dir just omit it.
  21773. X      */
  21774. X      char digest [MAX_LINE];
  21775. X
  21776. X      RESET (digest);
  21777. X      sscanf (args, "%s ", sys->arg);
  21778. X      upcase (sys->arg);
  21779. X      id = get_list_id (sys->arg, sys, nlists);
  21780. X      if (id < 0)
  21781. X        report_progress (report, tsprintf ("\nsys_config(): Unrecognized list \
  21782. Xname %s for 'archive' in %s", sys->arg, CONFIG), TRUE),
  21783. X        exit (4);
  21784. X      sys->lists[id].options |= ARCHIVE_LIST;
  21785. X      sscanf (args, "%s %s %s %s %s %s",
  21786. X              sys->arg, sys->lists[id].arch_dir, sys->lists[id].arch_spec,
  21787. X              sys->lists[id].farch_dir, sys->lists[id].arch_pass, digest);
  21788. X
  21789. X      locase (sys->lists[id].arch_spec);
  21790. X      if (*sys->lists[id].arch_dir != '/') {
  21791. X        report_progress (report, tsprintf ("\nsys_config(): archive-dir for %s \
  21792. Xdoesn't start with /",
  21793. X                       sys->arg, CONFIG), TRUE),
  21794. X        exit (4);
  21795. X      }
  21796. X
  21797. X      if (*sys->lists[id].farch_dir == '/') {
  21798. X        report_progress (report, tsprintf ("\nsys_config(): farch-dir for %s \
  21799. Xstarts with /",
  21800. X                       sys->arg, CONFIG), TRUE),
  21801. X        exit (4);
  21802. X      }
  21803. X
  21804. X      if (*sys->lists[id].farch_dir == '-' || *sys->lists[id].farch_dir == EOS)
  21805. X    sprintf (sys->lists[id].farch_dir, DEFAULT_ARCHIVE);
  21806. X
  21807. X      if (!strcmp (sys->lists[id].arch_pass, "-"))
  21808. X    RESET (sys->lists[id].arch_pass);
  21809. X
  21810. X      if (!strcmp (locase (digest), "digest"))
  21811. X    sys->lists[id].options |= ARCHIVE_DIGEST;
  21812. X    }
  21813. X    else if (!strcmp (cmd, "unix_cmd")) {
  21814. X      sscanf (args, "%s", sys->arg);
  21815. X      upcase (sys->arg);
  21816. X      id = get_list_id (sys->arg, sys, nlists);
  21817. X      if (id < 0)
  21818. X    report_progress (report, tsprintf ("\nsys_config(): Unrecognized list \
  21819. Xname %s for 'unix_cmd' in %s", sys->arg, CONFIG), TRUE),
  21820. X    exit (4);
  21821. X      RESET (arg);
  21822. X      sscanf (args, "%s %s", sys->arg, arg);
  21823. X      if (arg[0] == EOS || arg[0] == '#' || arg[0] == '\'')
  21824. X    report_progress (report, tsprintf ("\nsys_config(): Missing or invalid \
  21825. Xpassword %s for 'unix_cmd' in %s", arg, CONFIG), TRUE),
  21826. X    exit (4);
  21827. X      if ((unix_cmd = (UNIX_CMDS *) malloc (sizeof (*unix_cmd))) == NULL)
  21828. X    report_progress (report, tsprintf ("\nsys_config(): malloc() failed \
  21829. Xduring 'unix_cmd' in %s", CONFIG), TRUE),
  21830. X    exit (11);
  21831. X      strcpy (unix_cmd->password, arg);
  21832. X      upcase (unix_cmd->password);
  21833. X      RESET (arg);
  21834. X      sscanf (args, "%s %s %s", sys->arg, sys->arg, arg);
  21835. X      if (arg[0] == EOS || arg[0] == '#' || arg[0] == '\'')
  21836. X    report_progress (report, tsprintf ("\nsys_config(): Missing or invalid \
  21837. Xcommand name %s for 'unix_cmd' in %s", arg, CONFIG), TRUE),
  21838. X    exit (4);
  21839. X      strcpy (unix_cmd->name, arg);
  21840. X      upcase (unix_cmd->name);
  21841. X      start = strchr (args, '\'');
  21842. X      end = strrchr (args, '\'');
  21843. X      if (!start || !end || start == end)
  21844. X    report_progress (report, tsprintf ("\nsys_config(): Missing ''' for \
  21845. X'unix_cmd' in %s",
  21846. X                       CONFIG), TRUE),
  21847. X    exit (4);
  21848. X      if (! (unix_cmd->cmd =
  21849. X      (char *) malloc ((abs (end - start - 1) + 1) * sizeof (char))))
  21850. X    report_progress (report, tsprintf ("\nsys_config(): malloc() failed \
  21851. Xduring 'unix_cmd' in %s", CONFIG), TRUE),
  21852. X    exit (11);
  21853. X      strncpy (unix_cmd->cmd, start + 1, abs (end - start - 1));
  21854. X      unix_cmd->cmd[abs (end - start - 1)] = EOS;
  21855. X      if (!(comment = strchr (args, '#')))
  21856. X    report_progress (report, tsprintf ("\nsys_config(): Missing '#' for \
  21857. X'unix_cmd' in %s",
  21858. X                       CONFIG), TRUE),
  21859. X    exit (4);
  21860. X      if (! (unix_cmd->comment =
  21861. X      (char *) malloc ((strlen (comment + 1) + 1) * sizeof (char))))
  21862. X    report_progress (report, tsprintf ("\nsys_config(): malloc() failed \
  21863. Xduring 'unix_cmd' in %s", CONFIG), TRUE),
  21864. X    exit (11);
  21865. X      strcpy (unix_cmd->comment, comment + 1);
  21866. X      unix_cmd->next = sys->lists[id].unix_cmds;
  21867. X      sys->lists[id].unix_cmds = unix_cmd;
  21868. X    }
  21869. X    else
  21870. X      report_progress (report, tsprintf ("\nsys_config(): Unrecognized \
  21871. Xdirective %s in %s", cmd, CONFIG), TRUE),
  21872. X      exit (4);
  21873. X  }
  21874. X  fclose (config);
  21875. X  config_owner_prefs (sys, nlists, report);
  21876. X  return nlists;
  21877. X}
  21878. X
  21879. X/*
  21880. X  Get owner and manager preferences from OWNERSF.
  21881. X
  21882. X  Enhanced by: Warren Burstein.
  21883. X*/
  21884. X
  21885. Xvoid config_owner_prefs (SYS *sys, int nlists, FILE *report)
  21886. X{
  21887. X  FILE *f;
  21888. X  char registered_owner [MAX_LINE];
  21889. X  char assigned_list [MAX_LINE];
  21890. X  char pref [MAX_OWNER_PREFS] [MAX_LINE];
  21891. X  char prefs [MAX_LINE];
  21892. X  int listid, i, *op;
  21893. X
  21894. X  OPEN_FILE (f, OWNERSF, "r", "config_owner_prefs");
  21895. X  while (!feof (f)) {
  21896. X    assigned_list[0] = RESET (prefs);
  21897. X    fscanf (f, "%s %s", registered_owner, assigned_list);
  21898. X    upcase (assigned_list);
  21899. X    fgets (prefs, MAX_LINE - 2, f);
  21900. X    if (assigned_list [0] != EOS && registered_owner[0] != '#') {
  21901. X      for (i = 0; i < MAX_OWNER_PREFS; i++)
  21902. X    RESET (pref [i]);
  21903. X      sscanf (prefs, "%s %s %s %s %s %s %s %s", pref [0], pref [1], pref [2],
  21904. X          pref [3], pref [4], pref [5], pref [6], pref [7]);
  21905. X      if (!strcmp (assigned_list, "SERVER"))
  21906. X    op = &(sys->server.manager_prefs);
  21907. X      else if ((listid = get_list_id (assigned_list, sys, nlists)) >= 0)
  21908. X    op = &(sys->lists[listid].owner_prefs);
  21909. X      else
  21910. X    report_progress (report, tsprintf ("\nconfig_owner_prefs(): Unknown \
  21911. Xlist %s in %s",
  21912. X                       assigned_list, OWNERSF), TRUE),
  21913. X    exit (4);
  21914. X      for (i = 0; i < MAX_OWNER_PREFS && pref [i][0] != EOS; i++) {
  21915. X    /* Undocumented: also support -CCxxx systax: keni@oasys.dt.navy.mil */
  21916. X    char *pi = pref[i];
  21917. X    int pil = strlen (pi);
  21918. X    int neg = 0;
  21919. X    if (pi[0] == '-')
  21920. X      neg = 1,
  21921. X      --pil,
  21922. X      ++pi,
  21923. X      *op = ~*op;
  21924. X    if (!strncmp (pi, CCALL, pil))
  21925. X      *op |= ccall;
  21926. X    else if (!strncmp (pi, CCERRORS, pil))
  21927. X      *op |= ccerrors;
  21928. X    else if (!strncmp (pi, CCSUB, pil))
  21929. X      *op |= ccsub;
  21930. X    else if (!strncmp (pi, CCUNSUB, pil))
  21931. X      *op |= ccunsub;
  21932. X    else if (!strncmp (pi, CCSET, pil))
  21933. X      *op |= ccset;
  21934. X    else if (!strncmp (pi, CCREC, pil))
  21935. X      *op |= ccrec;
  21936. X    else if (!strncmp (pi, CCINFO, pil))
  21937. X      *op |= ccinfo;
  21938. X    else if (!strncmp (pi, CCSTAT, pil))
  21939. X      *op |= ccstat;
  21940. X    else if (!strncmp (pi, CCGET, pil))
  21941. X      *op |= ccget;
  21942. X    else if (!strncmp (pi, CCINDEX, pil))
  21943. X      *op |= ccindex;
  21944. X    else if (!strncmp (pi, CCLISTS, pil))
  21945. X      *op |= cclists;
  21946. X    else if (!strncmp (pi, CCRELEASE, pil))
  21947. X      *op |= ccrelease;
  21948. X    else if (!strncmp (pi, CCHELP, pil))
  21949. X      *op |= cchelp;
  21950. X    else if (!strncmp (pi, CCPRIVATE, pil))
  21951. X      *op |= ccprivate;
  21952. X    else if (!strncmp (pi, CCRUN, pil))
  21953. X      *op |= ccrun;
  21954. X    else if (pref [i][0] != EOS)
  21955. X      report_progress (report, tsprintf ("\nconfig_owner_prefs(): Unknown \
  21956. Xpreference %s in %s",
  21957. X                         pref [i], OWNERSF), TRUE),
  21958. X      exit (4);
  21959. X    if (neg)
  21960. X      *op = ~*op;
  21961. X      }
  21962. X    }
  21963. X  }
  21964. X  fclose (f);
  21965. X}
  21966. X
  21967. X/*
  21968. X  Convert a string to lower case.
  21969. X*/
  21970. X
  21971. Xchar *locase (char *s)
  21972. X{
  21973. X  char *r = s;
  21974. X  while (*s != EOS) {
  21975. X    if (isupper (*s))
  21976. X      *s = (char) tolower (*s);
  21977. X    ++s;
  21978. X  }
  21979. X  return r;
  21980. X}
  21981. X
  21982. X/*
  21983. X  Convert a string to upper case.
  21984. X*/
  21985. X
  21986. Xchar *upcase (char *s)
  21987. X{
  21988. X  char *r = s;
  21989. X
  21990. X  while (*s != EOS) {
  21991. X    if (islower (*s))
  21992. X      *s = (char) toupper (*s);
  21993. X    ++s;
  21994. X  }
  21995. X  return r;
  21996. X}
  21997. X
  21998. X/*
  21999. X  Replace all characters of the first word in 's' with "X".
  22000. X*/
  22001. X
  22002. Xvoid shadow_password (char *s)
  22003. X{
  22004. X  while (*s != EOS && isspace (*s)) /* Get to first word */
  22005. X    ++s;
  22006. X  if (*s != EOS)
  22007. X    while (!isspace (*s))
  22008. X      *s = 'X',
  22009. X      ++s;
  22010. X}
  22011. X
  22012. X/*
  22013. X  Write messages and times to 'report' and stdout. If 'report_time'
  22014. X  is set to a negative value no leading newline is printed to 'report'.
  22015. X  NOTE: Use strftime(), if possible.
  22016. X*/
  22017. X
  22018. Xvoid report_progress (FILE *report, char *s, int report_time)
  22019. X{
  22020. X#ifdef SYSLOG
  22021. X  char *buf;
  22022. X  int i;
  22023. X
  22024. X  if (!(buf = (char *) malloc ((strlen (s) + 1) * sizeof (char))))
  22025. X    exit (11);
  22026. X  strcpy (buf, s);
  22027. X  for (i = 0; i < strlen (buf); i++)
  22028. X    if (buf[i] == '\n')
  22029. X      buf[i] = ' ';
  22030. X  syslog (LOG_INFO, buf);
  22031. X  free ((char *) buf);
  22032. X#else
  22033. X  extern BOOLEAN tty_echo;
  22034. X  long int time_is = 0;
  22035. X  struct tm *t;
  22036. X
  22037. X  if (report) {
  22038. X    fprintf (report, "%s", s);
  22039. X    if (report_time) {
  22040. X      time (&time_is);
  22041. X      t = localtime (&time_is);
  22042. X      if (report_time > 0)
  22043. X    fprintf (report, "\n");
  22044. X      fprintf (report, "Time/Date: %2d:%.2d:%.2d, %2d/%.2d/%2d\n",
  22045. X           t->tm_hour, t->tm_min, t->tm_sec, t->tm_mon + 1, t->tm_mday,
  22046. X           t->tm_year);
  22047. X    }
  22048. X    fflush (report);
  22049. X  }
  22050. X  if (tty_echo) {
  22051. X    printf ("%s", s);
  22052. X    if (report_time)
  22053. X      printf ("\n");
  22054. X    fflush (stdout);
  22055. X  }
  22056. X#endif
  22057. X}
  22058. X
  22059. X/*
  22060. X  Start distribution. Call lower level routines; the algorithm is such that
  22061. X  this routine always looks at the beginning of each message when reading
  22062. X  into 'first_line', i.e. 'first_line' is always assigned a string of the form:
  22063. X        'From emailaddress Date Time'
  22064. X  which is the universal convention for the start of every message. It calls
  22065. X  subscribed() to find out if the sender is subscribed and passes the
  22066. X  result to process_message(). Since the call to extract_sender() alters
  22067. X  'first_line' to contain only the sender's email address a 'linecopy' is used.
  22068. X  When returning from process_message() we have already advanced to the
  22069. X  beginning of the next message, and 'linecopy' contains a string of the 
  22070. X  above form; therefore we need to copy that back to 'first_line'.
  22071. X*/
  22072. X
  22073. Xvoid distribute (FILE *mail, void (*process_message)(), FILE *report,
  22074. X         char *Subscribersf, char *Newsf, char *Peersf, char *Aliasesf)
  22075. X{
  22076. X  char first_line[MAX_LINE], linecopy[MAX_LINE];
  22077. X  BOOLEAN address_status;
  22078. X
  22079. X  first_line[0] = RESET (linecopy);
  22080. X  while (!feof (mail))
  22081. X    if (first_line[0] != EOS)
  22082. X      address_status = extract_sender (first_line),
  22083. X      process_message ((char *) first_line, (char *) linecopy,
  22084. X               (BOOLEAN) address_status,
  22085. X               (BOOLEAN)
  22086. X                subscribed (report, first_line, Subscribersf, Newsf,
  22087. X                    Peersf, Aliasesf)),
  22088. X      strcpy (first_line, linecopy);
  22089. X    else /* Read the first line of the very first message */
  22090. X      fgets (first_line, MAX_LINE - 2, mail), /* 'From email Date Time' */
  22091. X      strcpy (linecopy, first_line);
  22092. X}
  22093. X
  22094. X/*
  22095. X  Look for occurence of 'string' in 'substr' and return either TRUE or FALSE.
  22096. X  Look at the comments for defs.h for the syntax of 'substr'. A 'substr' of
  22097. X  ".*" matches everything.
  22098. X*/
  22099. X
  22100. XBOOLEAN strinstr (char *substr, char *string)
  22101. X{
  22102. X  char *substrcopy, *stringcopy;
  22103. X  extern FILE *report;
  22104. X
  22105. X  substrcopy = (char *) malloc ((strlen (substr) + 1) * sizeof (char));
  22106. X  stringcopy = (char *) malloc ((strlen (string) + 1) * sizeof (char));
  22107. X  if (!substrcopy || !stringcopy)
  22108. X    report_progress (report, "\nstrinstr(): malloc() failed", TRUE),
  22109. X    exit (11);
  22110. X  strcpy (substrcopy, substr);
  22111. X  strcpy (stringcopy, string);
  22112. X  upcase (substrcopy);
  22113. X  upcase (stringcopy);
  22114. X  if (re_strcmp (substrcopy, stringcopy, NULL) > 0) {
  22115. X    free ((char *) substrcopy);
  22116. X    free ((char *) stringcopy);
  22117. X    return TRUE;
  22118. X  }
  22119. X  free ((char *) stringcopy);
  22120. X  free ((char *) substrcopy);
  22121. X  return FALSE;
  22122. X}
  22123. X
  22124. X/*
  22125. X  Given a file path, extract the file name. In the process, any command line
  22126. X  options or any characters separated from the filename are discarded.
  22127. X*/
  22128. X
  22129. Xchar *extract_filename (char *s)
  22130. X{
  22131. X  char *p, *r, *t = s, nchar = 0;
  22132. X  extern FILE *report;
  22133. X
  22134. X  while (*t != EOS && *t != ' ' && *t != '\t') /* Get to delimiting char */
  22135. X    ++t;
  22136. X  while (t != s && *t != '/') /* Go back till / or the beginning of s */
  22137. X    ++nchar,
  22138. X    --t;
  22139. X  if (t != s || (*t == '/' && *(t + 1) != EOS))
  22140. X    --nchar,
  22141. X    ++t;
  22142. X  if (! (r = p = (char *) malloc ((nchar + 1) * sizeof (char))))
  22143. X    report_progress (report, "\nextract_filename(): malloc() failed", TRUE),
  22144. X    exit (11);
  22145. X  *p = EOS;
  22146. X  while (*t != EOS && *t != ' ' && *t != '\t')
  22147. X    *(p++) = *(t++);
  22148. X  *p = EOS;
  22149. X  return r;
  22150. X}
  22151. X
  22152. X/*
  22153. X  Recognize the command line parameters. It returns '?' on an unrecognized
  22154. X  option, ':' if an option requires an argument and the argument is missing,
  22155. X  or the recognized character itself. This code is a copyright of AT&T.
  22156. X*/
  22157. X
  22158. X# define ERR(str, ch) if (opterr) \
  22159. X                        fprintf (stderr, "%s%s%c\n", argv[0], str, ch);
  22160. X
  22161. Xint _getopt (int argc, char **argv, char *opts)
  22162. X{
  22163. X  static int sp = 1;
  22164. X  register int c;
  22165. X  register char *cp;
  22166. X  extern int opterr, optind, optopt;
  22167. X  extern char *optarg;
  22168. X
  22169. X  if (sp == 1)
  22170. X    if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  22171. X      return EOF;
  22172. X    else if (!strcmp (argv[optind], "--")) {
  22173. X      optind++;
  22174. X      return EOF;
  22175. X    }
  22176. X    optopt = c = argv[optind][sp];
  22177. X    if (c == ':' || (cp = strchr (opts, c)) == NULL) {
  22178. X      ERR (": unknown option, -", c);
  22179. X      if (argv[optind][++sp] == '\0')
  22180. X        optind++,
  22181. X        sp = 1;
  22182. X      return '?';
  22183. X    }
  22184. X    if (*++cp == ':') {
  22185. X      if (argv[optind][sp+1] != '\0')
  22186. X        optarg = &argv[optind++][sp+1];
  22187. X      else if (++optind >= argc) {
  22188. X        ERR(": argument missing for -", c);
  22189. X        sp = 1;
  22190. X        return ':';
  22191. X      }
  22192. X      else
  22193. X        optarg = argv[optind++];
  22194. X      sp = 1;
  22195. X    }
  22196. X    else {
  22197. X      if (argv[optind][++sp] == '\0')
  22198. X        sp = 1,
  22199. X        optind++;
  22200. X      optarg = NULL;
  22201. X    }
  22202. X    return c;
  22203. X}
  22204. X
  22205. X/*
  22206. X  Remove any extraneous characters from a name and convert it to lower
  22207. X  case with the first character of each word capitalized [currently disbled].
  22208. X*/
  22209. X
  22210. Xchar *clean_name (char *s)
  22211. X{
  22212. X  char *tok, *copy, *sep = " ", *line;
  22213. X  int j, l;
  22214. X  extern FILE *report;
  22215. X
  22216. X  if (s [0] != EOS && s [strlen (s) - 1] == '\n')
  22217. X    s [strlen (s) - 1] = EOS;
  22218. X  if (! (line = (char *) malloc ((strlen (s) + 1) * sizeof (char))))
  22219. X    report_progress (report, "\nclean_name(): malloc() failed", TRUE),
  22220. X    exit (11);
  22221. X  strcpy (line, s);
  22222. X  *s = EOS;
  22223. X  tok = strtok (line, sep);
  22224. X  while (tok) {
  22225. X    copy = tok;
  22226. X    while (*copy != EOS) {  /* Remove extraneous characters */
  22227. X      if (! isalpha (*copy) && ! isspace (*copy) && ! isdigit (*copy) &&
  22228. X      *copy != '-' && *copy != '.' && *copy != '@') {
  22229. X        for (j = 0, l = strlen (copy); j < l; copy [j] = copy [j + 1], ++j);
  22230. X        continue;
  22231. X      }
  22232. X      ++copy;
  22233. X    }
  22234. X    locase (tok);
  22235. X    *tok = (char) toupper (*tok);
  22236. X    sprintf (s + strlen (s), " %s", tok);
  22237. X    tok = strtok (NULL, sep);
  22238. X  }
  22239. X  free ((char *) line);
  22240. X  return s;
  22241. X}
  22242. X
  22243. X/*
  22244. X  Remove leading blanks and extraneous characters from a request.
  22245. X*/
  22246. X
  22247. Xvoid clean_request (char *s)
  22248. X{
  22249. X  while (isspace (*s))
  22250. X    sprintf (s, "%s", s + 1);
  22251. X  while (*s != EOS) {
  22252. X    if (*s < ' ' && *s != '\t' && *s != '\n' && *s != '\r')
  22253. X      *s = EOS;
  22254. X    ++s;
  22255. X  }
  22256. X}
  22257. X
  22258. X/*
  22259. X  Identify the list that the request refers to. Before doing so, remove
  22260. X  any unnecessary blanks from the parameters. Also, check each parameter
  22261. X  for proper syntax.
  22262. X*/
  22263. X
  22264. Xvoid get_list_name (char *params, char *list_name)
  22265. X{
  22266. X  int i;
  22267. X  char *s, *r, *t;
  22268. X  char param [MAX_LINE];
  22269. X  extern FILE *report;
  22270. X
  22271. X  if (! (r = s = (char *) malloc ((strlen (params) + 1) * sizeof (char))))
  22272. X    report_progress (report, "\nget_list_name(): malloc() failed", TRUE),
  22273. X    exit (11);
  22274. X  strcpy (s, params);
  22275. X  param [0] = RESET (params);
  22276. X  for (i = 0; s[i] != EOS;)
  22277. X    if (isspace (s[i]) && isspace (s[i + 1]))
  22278. X      sprintf (s + i, "%s", s + i + 1);
  22279. X    else
  22280. X      i++;
  22281. X  do {
  22282. X    RESET (param);
  22283. X    sscanf (s, "%s", param);
  22284. X    s = s + strlen (param) + 1; /* Skip over space */
  22285. X    t = strpbrk (param, "*?/`");
  22286. X    if (t != NULL) {
  22287. X      if (t == param || (t != param && ! isalpha (*(t - 1)))) /* Invalid *,? */
  22288. X    *t = '#';
  22289. X      if (*t == '/') /* Invalid / */
  22290. X    *t = '%';
  22291. X      if (*t == '`') /* Invalid ` */
  22292. X    *t = '-';
  22293. X    }
  22294. X    sprintf (params + strlen (params), " %s", param);
  22295. X  } while (param[0] != EOS);
  22296. X  strcat (params, "\n");
  22297. X  free ((char *) r);
  22298. X  RESET (list_name);
  22299. X  sscanf (params, "%s", list_name);
  22300. X  upcase (list_name);
  22301. X  sprintf (params, "%s", params + strlen (list_name) + 1);
  22302. X}
  22303. X
  22304. X/*
  22305. X  Free the current list of matched remote lists.
  22306. X*/
  22307. X
  22308. Xvoid free_remote_matched (REMOTE **matched_rlists)
  22309. X{
  22310. X  REMOTE *next;
  22311. X
  22312. X  while (*matched_rlists)  /* Free old list */
  22313. X    next = (*matched_rlists)->next,
  22314. X    free ((REMOTE *) *matched_rlists),
  22315. X    *matched_rlists = next;
  22316. X}
  22317. X
  22318. X/*
  22319. X  Given a list name, return its index in the array of known lists. If the
  22320. X  list is a remote list, return nlists to signify this effect.
  22321. X*/
  22322. X
  22323. Xint get_list_id (char *list_name, SYS *sys, int nlists)
  22324. X{
  22325. X  int i;
  22326. X  char *p, address [MAX_LINE];;
  22327. X
  22328. X  free_remote_matched (&matched_rlists);
  22329. X  for (i = 0; i < nlists; i++) {
  22330. X    if (!strcmp (list_name, sys->lists[i].alias))
  22331. X      return i;
  22332. X    strcpy (address, sys->lists[i].address);
  22333. X    upcase (address);
  22334. X    if (!strcmp (list_name, address) && (p = strchr (list_name, '@'))) {
  22335. X      *p = EOS;
  22336. X      return i;
  22337. X    }
  22338. X  }
  22339. X  if (check_remote (rlists, list_name)) {
  22340. X    /* Store list name above all known lists */
  22341. X    strcpy (sys->lists[nlists].alias, list_name);
  22342. X    return nlists;
  22343. X  }
  22344. X  return -1;
  22345. X}
  22346. X
  22347. X/*
  22348. X  Check whether 'list_name' is a remote list. Return a linked list
  22349. X  of matched records, or NULL. The list is stored in the global variable
  22350. X  'matched_rlists'.
  22351. X*/
  22352. X
  22353. XREMOTE *check_remote (REMOTE *rlists, char *list_name)
  22354. X{
  22355. X  REMOTE *new;
  22356. X  char address [MAX_LINE];
  22357. X  extern FILE *report;
  22358. X
  22359. X  while (rlists) {
  22360. X    strcpy (address, rlists->address);
  22361. X    upcase (address);
  22362. X    if (!strcmp (list_name, rlists->alias) ||
  22363. X    !strcmp (list_name, address)) {
  22364. X      if ((new = (REMOTE *) malloc (sizeof (*new))) == NULL)
  22365. X    report_progress (report, "\ncheck_remote(): malloc() failed", TRUE),
  22366. X    exit (11);
  22367. X      memcpy ((char *) new, (char *) rlists, sizeof (*new));
  22368. X      new->next = matched_rlists;
  22369. X      matched_rlists = new;
  22370. X    }
  22371. X    rlists = rlists->next;
  22372. X  }
  22373. X  return matched_rlists;
  22374. X}
  22375. X
  22376. Xvoid setup_string (char *s, char *alias, char *filename)
  22377. X{
  22378. X  RESET (s);
  22379. X  SETUP_STRING;
  22380. X}
  22381. X
  22382. X/*
  22383. X  Return the first occurence of 'sub' in 'src', or NULL if not found.
  22384. X*/
  22385. X
  22386. Xchar *_strstr (char *src, char *sub)
  22387. X{
  22388. X  if (src == NULL || sub == NULL)
  22389. X    return NULL;
  22390. X  while (*src != EOS) {
  22391. X    if (!strncmp (src, sub, strlen (sub)))
  22392. X      return src;
  22393. X    ++src;
  22394. X  }
  22395. X  return NULL;
  22396. X}
  22397. X
  22398. X/*
  22399. X  Shrink a file so that it contains a maximum of MAX_FILE_LENGTH entries in it.
  22400. X*/
  22401. X
  22402. Xvoid shrink (char *s)
  22403. X{
  22404. X  struct stat buf;
  22405. X  char *tmpmsg;
  22406. X
  22407. X  if (s[0] == EOS || stat (s, &buf))
  22408. X    return;
  22409. X  syscom ("tail -%d %s > %s", MAX_FILE_LENGTH, s,
  22410. X      (tmpmsg = mystrdup (tmpnam (NULL))));
  22411. X  mv (tmpmsg, s);
  22412. X  free ((char *) tmpmsg);
  22413. X}
  22414. X
  22415. X/*
  22416. X  Verify that part 'i' (of a file split into different parts by farch)
  22417. X  is in 's'.
  22418. X*/
  22419. X
  22420. XBOOLEAN requested_part (char *s, int i)
  22421. X{
  22422. X  char buf [80];
  22423. X  char copy [MAX_LINE];
  22424. X
  22425. X  strncpy (copy, s, MAX_LINE - 1);
  22426. X  copy [MAX_LINE - 1] = EOS;
  22427. X  do {
  22428. X    RESET (buf);
  22429. X    sscanf (copy, "%s", buf);
  22430. X    sprintf (copy, "%s", strchr (copy, buf[0]) + strlen (buf));
  22431. X    if (atoi (buf) == i)
  22432. X      return TRUE;
  22433. X  } while (buf[0] != EOS);
  22434. X  return FALSE;
  22435. X}
  22436. X
  22437. X/*
  22438. X  Free the REMOTE linked list.
  22439. X*/
  22440. X
  22441. Xvoid free_remote (REMOTE **rlists)
  22442. X{
  22443. X  REMOTE *next;
  22444. X
  22445. X  while (*rlists)
  22446. X    next = (*rlists)->next,
  22447. X    free ((REMOTE *) *rlists),
  22448. X    *rlists = next;
  22449. X  *rlists = NULL;
  22450. X}
  22451. X
  22452. X/*
  22453. X  Use my_system() when either list and listserv use TELNET and there is
  22454. X  an indication that the sessions do not exit.
  22455. X*/
  22456. X
  22457. Xint my_system (char *s)
  22458. X{
  22459. X  FILE *f;
  22460. X  int pid, status;
  22461. X  char line [MAX_LINE], *r;
  22462. X  extern SYS sys;
  22463. X
  22464. X  if (strcmp ((r = extract_filename (s)), "telnet")) {
  22465. X    status = system (s);
  22466. X    free ((char *) r);
  22467. X    return status;
  22468. X  }
  22469. X  free ((char *) r);
  22470. X  strcat (s, " &"); /* Only telnet runs in the background */
  22471. X  status = system (s);
  22472. X  if (status > 127)
  22473. X    return status;
  22474. X  sleep (5);
  22475. X  if (sys.options & BSD_PS)
  22476. X    system ("ps -gx | grep telnet | grep -v \"grep telnet\" \
  22477. X        | grep -v telnetd > ./telnet");
  22478. X  else if (sys.options & SYSV_PS)
  22479. X    system ("ps -ef | grep telnet | grep -v \"grep telnet\" \
  22480. X        | grep -v telnetd > ./telnet");
  22481. X  if ((f = fopen ("./telnet", "r")) == NULL)
  22482. X    return -1;
  22483. X  while (! feof (f)) {
  22484. X    RESET (line);
  22485. X    fgets (line, MAX_LINE - 2, f);
  22486. X    if (line[0] != EOS)
  22487. X      sscanf (line, "%d", &pid),
  22488. X      sleep (15),
  22489. X      kill (pid, SIGHUP);
  22490. X  }
  22491. X  fclose (f);
  22492. X  unlink ("./telnet");
  22493. X  return status;
  22494. X}
  22495. X
  22496. X/* Change history (by Bob Boyd)
  22497. X21-Aug-1991   RLB     change parameter scanning for "list" lines in the
  22498. X                      config file so that "-" characters in the list-alias
  22499. X                      are ignored when looking for the beginning of the
  22500. X                      list parameters [tasos: I defined my own strstr()]
  22501. X*/
  22502. X
  22503. X/*
  22504. X  Remove the message identified as 'tag_to_remove' from the specified 'file'.
  22505. X  Return TRUE if successful, FALSE if the message was not located.
  22506. X*/
  22507. X
  22508. XBOOLEAN remove_msg (char *file, int tag_to_remove, FILE *report)
  22509. X{
  22510. X  FILE *in, *out;
  22511. X  char prev_line [MAX_LINE];
  22512. X  char line [MAX_LINE];
  22513. X  char match [MAX_LINE];
  22514. X  char *tmp_moderated_f;
  22515. X  BOOLEAN copy = FALSE, message_found = FALSE;
  22516. X  int tag;
  22517. X
  22518. X  mv (file, (tmp_moderated_f = mystrdup (tmpnam (NULL))));
  22519. X  chmod (tmp_moderated_f, 416); /* 640 */
  22520. X  OPEN_FILE (in, tmp_moderated_f, "r", "remove_msg");
  22521. X  OPEN_FILE (out, file, "w", "remove_msg");
  22522. X  prev_line[0] = RESET (line);
  22523. X  while (!feof (in)) {
  22524. X    if (!strncmp (line, START_OF_MESSAGE, strlen (START_OF_MESSAGE)) &&
  22525. X    !copy)
  22526. X      RESET (prev_line),
  22527. X      copy = TRUE;
  22528. X    strcpy (match, "\\1");
  22529. X    if (re_strcmp (MESSAGE_TAG, line, match) > 0) { /* Get tag # */
  22530. X      sprintf (line, "%s", line + strlen (match));
  22531. X      sscanf (line, "%d", &tag);
  22532. X      sprintf (line, "%s%d\n", match, tag);
  22533. X      if (tag_to_remove == tag)
  22534. X    message_found = TRUE,
  22535. X    copy = FALSE;
  22536. X    }
  22537. X    if (copy && prev_line[0] != EOS)
  22538. X      fprintf (out, "%s", prev_line);
  22539. X    strcpy (prev_line, line);
  22540. X    RESET (line);
  22541. X    fgets (line, MAX_LINE - 2, in);
  22542. X  }
  22543. X  if (copy && prev_line[0] != EOS)
  22544. X    fprintf (out, "%s", prev_line);
  22545. X  fclose (in);
  22546. X  fclose (out);
  22547. X  unlink (tmp_moderated_f);
  22548. X  free ((char *) tmp_moderated_f);
  22549. X  return message_found;
  22550. X}
  22551. X
  22552. X/*
  22553. X  Read the parameters from 'line' that follow 'request' in 'line',
  22554. X  and possibly from lines below in the 'mail' file, if 'line' ends
  22555. X  with &. Continuation lines should always end with '&' and no
  22556. X  trailing blanks or any other characters except new-line.
  22557. X  'params' should end with a \n.
  22558. X*/
  22559. X
  22560. Xvoid read_params (char *line, char *params, char *request, FILE *mail,
  22561. X          FILE *report)
  22562. X{
  22563. X  char l [MAX_LINE];
  22564. X
  22565. X  sprintf (params, "%s", line + strlen (request));
  22566. X  if (params [strlen (params) - 1] == '\n')
  22567. X    params [strlen (params) - 1] = EOS; /* Remove trailing \n */
  22568. X  RESET (l);
  22569. X  while (!feof (mail) &&
  22570. X     strncmp (l, START_OF_MESSAGE, strlen (START_OF_MESSAGE)) &&
  22571. X     params [0] != EOS && params [strlen (params) - 1] == '&') {
  22572. X    params [strlen (params) - 1] = EOS; /* Replace & */
  22573. X    RESET (l);
  22574. X    fgets (l, MAX_LINE - 2, mail);
  22575. X    if (l [0] != EOS &&
  22576. X    strncmp (l, START_OF_MESSAGE, strlen (START_OF_MESSAGE))) {
  22577. X      if (report)
  22578. X    report_progress (report, l, FALSE);
  22579. X      l [strlen (l) - 1] = EOS, /* Remove trailing \n */
  22580. X      strcat (params, l);
  22581. X    }
  22582. X  }
  22583. X  strcat (params, "\n");
  22584. X  if (!strncmp (l, START_OF_MESSAGE, strlen (START_OF_MESSAGE)))
  22585. X    fseek (mail, -strlen (l), SEEK_CUR); /* Move back to beginning of new msg */
  22586. X}
  22587. X
  22588. X/*
  22589. X  Open and lock file. It returns the opened file descriptor, or
  22590. X  CANT_OPEN or CANT_LOCK.
  22591. X
  22592. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  22593. X*/
  22594. X
  22595. Xint lock_file (char *file, int flag, int mode, BOOLEAN delay)
  22596. X{
  22597. X#ifdef NO_LOCKS
  22598. X  return 0;
  22599. X#else
  22600. X  int count, fd, lock;
  22601. X
  22602. X  if ((fd = open (file, flag, mode)) < 0)
  22603. X    return CANT_OPEN;
  22604. X  for (count = 0; (lock = lockf (fd, F_TLOCK, 0)) && (count < 180) && delay;
  22605. X       ++count, sleep (1));
  22606. X  if (lock) {
  22607. X    close (fd); 
  22608. X    return CANT_LOCK;
  22609. X  }
  22610. X  return fd;
  22611. X#endif
  22612. X}
  22613. X
  22614. X/*
  22615. X  Unlock and close the specified file descriptor.
  22616. X
  22617. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  22618. X*/
  22619. X
  22620. Xvoid unlock_file (int fd)
  22621. X{
  22622. X#ifndef NO_LOCKS
  22623. X  if (fd >= 0)
  22624. X    lockf (fd, F_ULOCK, 0),
  22625. X    close (fd);
  22626. X#endif
  22627. X}
  22628. X
  22629. X/*
  22630. X  Write to a non-blocking file descriptor.
  22631. X*/
  22632. X
  22633. Xlong int write_to_fd (int fd, char *buf, long int bytes_to_write)
  22634. X{
  22635. X  long int bytes_written, total_bytes = 0, bytes_requested = bytes_to_write;
  22636. X  extern FILE *report;
  22637. X
  22638. X  errno = 0;
  22639. X  while ((bytes_written = write (fd, buf, bytes_to_write)) < bytes_to_write) {
  22640. X    if (bytes_written < 0 && errno && errno != EWOULDBLOCK && errno != EAGAIN
  22641. X    && errno != EINTR
  22642. X#ifdef ERESTART
  22643. X    && errno != ERESTART
  22644. X#endif
  22645. X    ) {
  22646. X      char error [256];
  22647. X      sprintf (error, "\nwrite_to_fd(): ");
  22648. X      switch (errno) {
  22649. X    case EBADF: strcat (error, "Bad file number"); break;
  22650. X    case EFAULT: strcat (error, "Bad address"); break;
  22651. X    case EFBIG: strcat (error, "File limit reached"); break;
  22652. X    case EINVAL: strcat (error, "Negative seek pointer"); break;
  22653. X    case EIO: strcat (error, "I/O error"); break;
  22654. X    case ENOSPC: strcat (error, "No space left on device"); break;
  22655. X    case ENXIO: strcat (error, "No such device or address"); break;
  22656. X    case ERANGE: sprintf (error + strlen (error), "Bytes to write (%d) \
  22657. Xout of range", bytes_to_write); break;
  22658. X    case EPIPE: sprintf (error, "Client disappeared"); break;
  22659. X    default: sprintf (error + strlen (error), "Error number %d", errno);
  22660. X      }
  22661. X      report_progress (report, error, TRUE);
  22662. X      if (bytes_written > 0)
  22663. X    total_bytes += bytes_written;
  22664. X      return (total_bytes > 0 ? -total_bytes : -1);
  22665. X    }
  22666. X    if (bytes_written > 0)
  22667. X      bytes_to_write -= bytes_written,
  22668. X      total_bytes += bytes_written,
  22669. X      buf += bytes_written;
  22670. X    errno = 0;
  22671. X  }
  22672. X  return bytes_requested;
  22673. X}
  22674. X
  22675. X/*
  22676. X  Improved mkdir - builds all parents of full_path if needed.
  22677. X  If a mkdir fails, or a component of the directory exists but
  22678. X  is not a directory, return FALSE and store a description in report_msg.
  22679. X
  22680. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  22681. X*/
  22682. X
  22683. XBOOLEAN mkdir1 (char *full_path, char *report_msg, char *mask)
  22684. X{
  22685. X  BOOLEAN first = TRUE;
  22686. X  char *p = full_path, d[MAX_LINE], dir[MAX_LINE], head[MAX_LINE];
  22687. X  struct stat st;
  22688. X
  22689. X  RESET (head);
  22690. X  while (get_field (&p, '/', d)) {
  22691. X    if (first) {
  22692. X      first = FALSE;
  22693. X
  22694. X      if (d[0] == EOS) {
  22695. X    strcpy (head, "/");
  22696. X    continue;
  22697. X      }
  22698. X    }
  22699. X
  22700. X    sprintf (dir, "%s%s", head, d);
  22701. X    sprintf (head, "%s/", dir);
  22702. X
  22703. X    if (stat (dir, &st)) {
  22704. X      if (mkdir (dir, 0755 & (0755 ^ otoi (mask)))) {
  22705. X    sprintf (report_msg, "mkdir1(%s): mkdir %s failed, errno %d\n",
  22706. X         full_path, dir, errno);
  22707. X    return FALSE;
  22708. X      }
  22709. X    } 
  22710. X    else if ((st.st_mode & S_IFMT) != S_IFDIR) {
  22711. X      sprintf (report_msg, "mkdir1: %s is not a directory", dir);
  22712. X      return FALSE;
  22713. X    }
  22714. X  }
  22715. X  return TRUE;
  22716. X}
  22717. X
  22718. X/*
  22719. X  Convert an octal number stored in a string to integer.
  22720. X*/
  22721. X
  22722. Xint otoi (char *s)
  22723. X{
  22724. X  int i, n;
  22725. X
  22726. X  n = 0;
  22727. X  for (i = 0; s[i] >= '0' && s[i] <= '7'; ++i)
  22728. X    n = 8 * n + (s[i] - '0');
  22729. X  return n;
  22730. X}
  22731. X
  22732. X/*
  22733. X  Find a field in *src ending with "sep". Leave src pointing at char after sep,
  22734. X  store field in dst. If src points at end of string, return FALSE. If src
  22735. X  points at a separator, make dst a null string.
  22736. X
  22737. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  22738. X*/
  22739. X
  22740. XBOOLEAN get_field (char **src, char sep, char *dst)
  22741. X{
  22742. X  char *s = *src;
  22743. X  int len;
  22744. X
  22745. X  if (**src == EOS)
  22746. X    return FALSE;
  22747. X
  22748. X  while (**src != EOS && **src != sep)
  22749. X    ++*src;
  22750. X
  22751. X  if (*src == s) {
  22752. X    *dst = EOS;
  22753. X    if (**src != EOS)
  22754. X      ++*src;
  22755. X    return TRUE;
  22756. X  }
  22757. X
  22758. X  len = *src - s;
  22759. X  (void) strncpy (dst, s, len);
  22760. X  dst[len] = EOS;
  22761. X
  22762. X  if (**src != EOS)                  /* advance past separator */
  22763. X    ++*src;
  22764. X
  22765. X  return TRUE;
  22766. X}
  22767. X
  22768. X/*
  22769. X  Make the directory for dirf (a DIR file) and create/update all
  22770. X  necessary INDEX files.
  22771. X
  22772. X  USER CONTRIBUTED FUNCTION: Warren Burstein
  22773. X*/
  22774. X
  22775. XBOOLEAN make_indexes (char *dirf, char *farch_dir, char *password, char *error,
  22776. X              char *mask)
  22777. X{
  22778. X  char dirname [MAX_LINE], *p, *q;
  22779. X  struct dirmatch {
  22780. X    char *s;
  22781. X    BOOLEAN match;
  22782. X  } *dirs;
  22783. X  int n_dirs, i, j;
  22784. X  extern FILE *report;
  22785. X
  22786. X  /* Get the directory that INDEX/DIR is in and make it if needed. */
  22787. X  strcpy (dirname, dirf);
  22788. X  if (p = strrchr (dirname, '/'))
  22789. X   *p = EOS;
  22790. X  if (!mkdir1 (dirname, error, mask))
  22791. X    return FALSE;
  22792. X
  22793. X  /* The number of dirs is one higher than the number of slashes. Add one
  22794. X     more for the top level directory, ARCHIVE_DIR */
  22795. X  for (p = farch_dir, n_dirs = 2; *p != EOS; p++)
  22796. X    if (*p == '/')
  22797. X      ++n_dirs;
  22798. X
  22799. X  if (! (dirs = (struct dirmatch *) calloc (n_dirs, sizeof (dirs[0]))))
  22800. X    report_progress (report, "\nmake_indexes(): calloc() failed", TRUE),
  22801. X    exit (11);
  22802. X
  22803. X  if (! (dirs[0].s =
  22804. X     (char *) malloc ((strlen (ARCHIVE_DIR) +
  22805. X               strlen (DEFAULT_ARCHIVE) + 2) * sizeof (char))))
  22806. X    report_progress (report, "\nmake_indexes(): malloc() failed", TRUE),
  22807. X    exit (11);
  22808. X  sprintf (dirs[0].s, "%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE);
  22809. X
  22810. X  for (i = 1, p = farch_dir; i < n_dirs; i++) {
  22811. X    int len;
  22812. X
  22813. X    /* Find end of the directory - slash or end of string */
  22814. X    for (q = p; *q != EOS && *q != '/'; q++);
  22815. X    len = q - p;
  22816. X
  22817. X    if (i == 1) {
  22818. X      if (! (dirs[i].s =
  22819. X         (char *) malloc ((strlen (ARCHIVE_DIR) + len + 2) *
  22820. X                  sizeof (char))))
  22821. X    report_progress (report, "\nmake_indexes(): malloc() failed", TRUE),
  22822. X    exit (11);
  22823. X      sprintf (dirs[i].s, "%s/%.*s", ARCHIVE_DIR, len, p);
  22824. X    }
  22825. X    else {
  22826. X      if (! (dirs[i].s = (char *) malloc ((strlen (dirs[i - 1].s) + len + 2) *
  22827. X                      sizeof (char))))
  22828. X    report_progress (report, "\nmake_indexes(): malloc() failed", TRUE),
  22829. X    exit (11);
  22830. X      sprintf (dirs[i].s, "%s/%.*s", dirs[i - 1].s, len, p);
  22831. X    }
  22832. X
  22833. X    /* In case there are extra slashes, skip them */
  22834. X    for (; *q != EOS && *q == '/'; q++);
  22835. X    p = q;
  22836. X
  22837. X    if (*p == EOS)
  22838. X      break;            /* premature end of string - too many /'s */
  22839. X  }
  22840. X
  22841. X  for (i = 0; i < n_dirs; i++) {
  22842. X    char indexf [MAX_LINE], dirf [MAX_LINE];
  22843. X    char line [MAX_LINE], arch [MAX_LINE], fullpath [MAX_LINE];
  22844. X    BOOLEAN missing;
  22845. X    FILE *fp;
  22846. X
  22847. X    if (!dirs[i].s)
  22848. X      continue;
  22849. X
  22850. X    /* Make INDEX and DIR files if not already there */
  22851. X    sprintf (indexf, "%s/%s", dirs[i].s, INDEX);
  22852. X    sprintf (dirf, "%s/%s", dirs[i].s, DIRF);
  22853. X    if (access (indexf, 0))
  22854. X      close (creat (indexf, 0644 & (0644 ^ otoi (mask))));
  22855. X    if (access (dirf, 0))
  22856. X      close (creat (dirf, 0644 & (0644 ^ otoi (mask))));
  22857. X
  22858. X    /* Read the index file for i, set match fields to TRUE for j >= i if dir
  22859. X       for j is not in there. */
  22860. X    OPEN_FILE (fp, indexf, "r", "make_indexes");
  22861. X
  22862. X    for (j = i; j < n_dirs; j++)
  22863. X      dirs[j].match = FALSE;
  22864. X
  22865. X    while (!feof (fp)) {
  22866. X      arch[0] = fullpath[0] = RESET (line);
  22867. X      fgets (line, MAX_LINE - 2, fp);
  22868. X      sscanf (line, "%s %s", arch, fullpath);
  22869. X      for (j = i; j < n_dirs; j++)
  22870. X        if (dirs[j].s && !strcmp (fullpath, dirs[j].s))
  22871. X          dirs[j].match = TRUE;
  22872. X    }
  22873. X    fclose (fp);
  22874. X
  22875. X    /* Set 'missing' if any j doesn't have match set. Add lines if missing. */
  22876. X    missing = FALSE;
  22877. X    for (j = i; j < n_dirs; j++)
  22878. X      if (!dirs[j].match)
  22879. X        missing = TRUE;
  22880. X
  22881. X    if (missing) {
  22882. X      OPEN_FILE (fp, indexf, "a", "make_indexes");
  22883. X      for (j = i; j < n_dirs; j++)
  22884. X        if (dirs[j].s && !dirs[j].match)
  22885. X          fprintf (fp, "%s %s %s\n", strrchr (dirs[j].s, '/') + 1, dirs[j].s,
  22886. X           (password ? password : ""));
  22887. X      fclose (fp);
  22888. X    }
  22889. X    free ((char *) dirs[i].s);
  22890. X  }
  22891. X  free ((struct dirmatch *) dirs);
  22892. X  return TRUE;
  22893. X}
  22894. X
  22895. X/*
  22896. X  Insert 'nwords' to 's' starting at 'index' in 'words'. Return the total
  22897. X  length of the words inserted; blanks are inserted between words.
  22898. X  While making space for the new words, 'replace' so many number of characters.
  22899. X*/
  22900. X
  22901. Xint insert_word (char *s, char **words, int nwords, int index, int replace)
  22902. X{
  22903. X  int i, j, nbytes = 0;
  22904. X  char *c = NULL;
  22905. X
  22906. X  for (i = 0; i < nwords; i++)
  22907. X    nbytes += strlen (words [index + i]) + 1;
  22908. X  if (nbytes < replace)
  22909. X    for (i = 0; i < replace; i++)
  22910. X      s[i] = ' ';
  22911. X  else
  22912. X    for (i = 0; i < nbytes - replace; i++)
  22913. X      for (c = s + strlen (s); c >= s + replace; c--)
  22914. X    *(c + 1) = *c;
  22915. X  for (i = 0, j = 0; i < nwords; i++)
  22916. X    memcpy (s + j, words [index + i], strlen (words [index + i])),
  22917. X    j += strlen (words [index + i]) + 1,
  22918. X    *(s + j - 1) = ' ';
  22919. X  return nbytes >= replace ? nbytes : replace;
  22920. X}
  22921. X
  22922. X/*
  22923. X  Skip over words in a string and return the address of the beginning of the
  22924. X  requested word, or NULL if the word is beyond the end of string.
  22925. X*/
  22926. X
  22927. Xchar *skip_to_word (char *s, int word)
  22928. X{
  22929. X  BOOLEAN quote;
  22930. X
  22931. X  while (*s != EOS && isspace (*s))    /* Skip to first word */
  22932. X    ++s;
  22933. X  while ((--word)) {
  22934. X    quote = FALSE;
  22935. X    while ((*s != EOS && !isspace (*s)) || (isspace (*s) && quote)) {
  22936. X      if (*s == '\"' || *s == '\'')
  22937. X    quote = !quote;
  22938. X      ++s;
  22939. X    }
  22940. X    while (*s != EOS && isspace (*s))
  22941. X      ++s;
  22942. X  }
  22943. X  if (*s == EOS)
  22944. X    return NULL;
  22945. X  return s;
  22946. X}
  22947. X
  22948. X/*
  22949. X  Some UNIXes do not provide strdup().
  22950. X*/
  22951. X
  22952. Xchar *mystrdup (char *s)
  22953. X{
  22954. X  char *r;
  22955. X
  22956. X  r = (char *) malloc ((strlen (s) + 1) * sizeof (char));
  22957. X  if (r)
  22958. X    strcpy (r, s);
  22959. X  return r;
  22960. X}
  22961. X
  22962. X#ifdef NEED_VSPRINTF
  22963. Xint vsprintf (dest, pat, args)
  22964. Xchar *dest, *pat, *args;
  22965. X{
  22966. X    FILE fakebuf;
  22967. X
  22968. X    fakebuf._ptr = dest;
  22969. X    fakebuf._cnt = 32767;
  22970. X#ifndef _IOSTRG
  22971. X#define _IOSTRG 0
  22972. X#endif
  22973. X    fakebuf._flag = _IOWRT|_IOSTRG;
  22974. X    _doprnt(pat, args, &fakebuf);
  22975. X    putc('\0', &fakebuf);
  22976. X    return 0;
  22977. X}
  22978. X#endif
  22979. *-*-END-of-src/misc.c-*-*
  22980. echo x - src/pqueue.c
  22981. sed 's/^X//' >src/pqueue.c <<'*-*-END-of-src/pqueue.c-*-*'
  22982. X/*
  22983. X  ----------------------------------------------------------------------------
  22984. X  |                    MAIL QUEUE PROCESSING ROUTINES                        |
  22985. X  |                                                                          |
  22986. X  |                             Version 1.1                                  |
  22987. X  |                                                                          |
  22988. X  |                (or, when Computer Science gets to you)                   |
  22989. X  |                                                                          |
  22990. X  |                    Written by Anastasios Kotsikonas                      |
  22991. X  |                           (tasos@cs.bu.edu)                              |
  22992. X  |                                                                          |
  22993. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  22994. X  | whole and not in parts, as long as you do not remove or alter the author |
  22995. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  22996. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  22997. X  | provided for your personal use, you you may not alter the functions      |
  22998. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  22999. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  23000. X  | any changes you may have made. No part of the source code bearing a         |
  23001. X  | copyright notice can be included in commercial software systems without  |
  23002. X  | written permission by the author.                         |
  23003. X  | By using this software you are bound by this agreement.                  |
  23004. X  | This software comes with no warranties and cannot be sold for profit.    |
  23005. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  23006. X  | files when distributing this software.                                   |
  23007. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  23008. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  23009. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  23010. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  23011. X  | (ii).                                                                    |
  23012. X  ----------------------------------------------------------------------------
  23013. X
  23014. X  The 'system' mailmethod is used to attempt another delivery of the
  23015. X  specified files. If it cannot be done, the files are queued again.
  23016. X*/
  23017. X
  23018. X#include <stdio.h>
  23019. X#ifdef SYSLOG
  23020. X# ifdef ultrix
  23021. X#  include <sys/syslog.h>
  23022. X# else
  23023. X#  include <syslog.h>
  23024. X# endif
  23025. X#endif
  23026. X#ifndef unknown_port
  23027. X# ifndef __NeXT__
  23028. X#  include <unistd.h>
  23029. X# else
  23030. X#  include <libc.h>
  23031. X# endif
  23032. X#endif
  23033. X#include <sys/types.h>
  23034. X#include <sys/stat.h>
  23035. X#if !defined (sequent) && !defined (__NeXT__) && !defined (__convex__) && \
  23036. X !defined (apollo) && !defined (i386) && !defined (unknown_port)
  23037. X# include <sys/termio.h>
  23038. X#endif
  23039. X#ifndef sun
  23040. X# include <sys/ioctl.h>
  23041. X#endif
  23042. X#include <fcntl.h>
  23043. X#include <signal.h>
  23044. X#include "defs.h"
  23045. X#include "struct.h"
  23046. X#include "global.h"
  23047. X#include "pqueue.h"
  23048. X#if defined (__NeXT__) || defined (unknown_port)
  23049. X# include "next.h"
  23050. X#endif
  23051. X
  23052. X#ifdef __STDC__
  23053. Xextern char *tsprintf (char *, ...);
  23054. X#else
  23055. Xextern char *tsprintf ();
  23056. X#endif
  23057. Xextern int  _getopt (int, char **, char *);
  23058. Xextern void init_signals (void);
  23059. Xextern void catch_signals (void); 
  23060. Xextern void report_progress (FILE *, char *, int);
  23061. Xextern BOOLEAN sysmail (char *);
  23062. Xextern int  lock_file (char *, int, int, BOOLEAN);
  23063. Xextern void unlock_file (int);
  23064. Xextern int  otoi (char *);
  23065. X
  23066. Xvoid   main (int, char **, char **);
  23067. Xvoid   usage (void);
  23068. Xint    gexit (int);
  23069. X
  23070. Xvoid main (int argc, char **argv, char **envp)
  23071. X{
  23072. X  char *options = "eD", *mask;
  23073. X  int c;
  23074. X  FILE *f;
  23075. X  struct stat stat_buf;
  23076. X  extern int optind;
  23077. X  extern char *getenv();
  23078. X
  23079. X  prog = argv[0];
  23080. X  while ((c = _getopt (argc, argv, options)) != EOF)
  23081. X    switch ((char) c) {
  23082. X    case 'e': tty_echo = TRUE; break;
  23083. X    case 'D': debug = TRUE; break;
  23084. X    case '?':
  23085. X    default:
  23086. X      usage ();
  23087. X  }
  23088. X  if (optind == argc)
  23089. X    fprintf (stderr, "pqueue: filename(s) missing.\n"),
  23090. X    exit (3);
  23091. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  23092. X    umask (otoi (mask));
  23093. X  else
  23094. X    mask = "066",
  23095. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  23096. X#ifndef NO_LOCKS
  23097. X  if ((lfd = lock_file (PQUEUE_LOCK_FILE, O_RDWR, 0, FALSE)) < 0)
  23098. X    fprintf (stderr, "pqueue: Unable to lock %s. Aborting.\n",
  23099. X         PQUEUE_LOCK_FILE),
  23100. X    exit (1);
  23101. X#endif
  23102. X  init_signals();
  23103. X  catch_signals();
  23104. X#if defined (TIOCNOTTY) && defined (SIGTTOU) && defined (SIGTTIN)
  23105. X  if (!tty_echo)
  23106. X    if ((c = open ("/dev/tty", 2)) >=0)
  23107. X      ioctl (c, TIOCNOTTY, 0),
  23108. X      close (c);
  23109. X#endif
  23110. X#ifdef SYSLOG
  23111. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  23112. X# ifndef i386
  23113. X       |LOG_NOWAIT
  23114. X# endif
  23115. X       , SYSLOG);
  23116. X# ifndef ultrix
  23117. X  setlogmask (LOG_UPTO (LOG_INFO));
  23118. X# endif
  23119. X#else
  23120. X  if ((report = fopen (REPORT_PQUEUE, "a")) == NULL)
  23121. X    fprintf (stderr, "pqueue: Could not open %s\n", REPORT_PQUEUE),
  23122. X    exit (1);
  23123. X  chmod (REPORT_PQUEUE, 384);
  23124. X#endif
  23125. X  if ((f = fopen (PID_PQUEUE, "w")) != NULL)
  23126. X    fprintf (f, "%d", getpid()),
  23127. X    fclose (f);
  23128. X  signal (SIGINT, (void (*)()) gexit);
  23129. X  while (--argc >= optind) { /* main loop */
  23130. X    if (stat (argv [argc], &stat_buf))
  23131. X      report_progress (report, tsprintf ("\nmain(): Could not stat %s",
  23132. X                     argv [argc]), TRUE),
  23133. X      gexit (1);
  23134. X    if (sysmail (argv [argc]))
  23135. X      if (unlink (argv [argc]))
  23136. X     report_progress (report, tsprintf ("\nmain(): Could not unlink file %s",
  23137. X                       argv [argc]), TRUE),
  23138. X    gexit (1);
  23139. X  }
  23140. X#ifdef SYSLOG
  23141. X  closelog ();
  23142. X#else
  23143. X  fclose (report);
  23144. X#endif
  23145. X  gexit (0);
  23146. X}
  23147. X
  23148. Xvoid usage ()
  23149. X{
  23150. X  fprintf (stderr, "Usage: pqueue [-e] [-D] <files>\n\
  23151. X-e: Echo reports to the screen.\n\
  23152. X-D: Turn debug on.\n");
  23153. X  exit (3);
  23154. X}
  23155. X
  23156. X/*
  23157. X  Graceful exit. Remove pid file.
  23158. X*/
  23159. X
  23160. Xint gexit (int exitcode)
  23161. X{
  23162. X  unlink (PID_PQUEUE);
  23163. X#ifndef NO_LOCKS
  23164. X  unlock_file (lfd);
  23165. X#endif
  23166. X  exit (exitcode);
  23167. X}
  23168. *-*-END-of-src/pqueue.c-*-*
  23169. echo x - src/regerror.c
  23170. sed 's/^X//' >src/regerror.c <<'*-*-END-of-src/regerror.c-*-*'
  23171. X/*
  23172. X  Tasos Kotsikonas (8/20/92): Changed function so that it stores the error
  23173. X  message to a global variable.
  23174. X*/
  23175. X
  23176. X#include <stdio.h>
  23177. Xchar *regerr;
  23178. X
  23179. Xvoid
  23180. Xregerror(s)
  23181. Xchar *s;
  23182. X{
  23183. X  regerr = (char *) malloc ((strlen (s) + 1) * sizeof (char));
  23184. X  strcpy (regerr, s);
  23185. X}
  23186. *-*-END-of-src/regerror.c-*-*
  23187. echo x - src/regex.c
  23188. sed 's/^X//' >src/regex.c <<'*-*-END-of-src/regex.c-*-*'
  23189. X/*
  23190. X  ----------------------------------------------------------------------------
  23191. X  |                         REGULAR EXPRESSIONS                              |
  23192. X  |                                                                          |
  23193. X  |                             Version 1.0                                  |
  23194. X  |                                                                          |
  23195. X  |                (or, when Computer Science gets to you)                   |
  23196. X  |                                                                          |
  23197. X  |                    Written by Anastasios Kotsikonas                      |
  23198. X  |                           (tasos@cs.bu.edu)                              |
  23199. X  |                                                                          |
  23200. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  23201. X  | whole and not in parts, as long as you do not remove or alter the author |
  23202. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  23203. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  23204. X  | provided for your personal use, you you may not alter the functions      |
  23205. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  23206. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  23207. X  | any changes you may have made. No part of the source code bearing a         |
  23208. X  | copyright notice can be included in commercial software systems without  |
  23209. X  | written permission by the author.                         |
  23210. X  | By using this software you are bound by this agreement.                  |
  23211. X  | This software comes with no warranties and cannot be sold for profit.    |
  23212. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  23213. X  | files when distributing this software.                                   |
  23214. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  23215. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  23216. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  23217. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  23218. X  | (ii).                                                                    |
  23219. X  ----------------------------------------------------------------------------
  23220. X
  23221. X  Author: Tasos Kotsikonas (tasos@cs.bu.edu)
  23222. X  Disclaimer: All proper disclaimers apply; these include death, damage of any
  23223. X          kind to anything and anyone, and this kind of legal garbage.
  23224. X  Copying: You may copy, alter and redistribute this software as you see fit,
  23225. X         but you may not sell it for profit.
  23226. X
  23227. X  Do pattern matching of two flavors: strict egrep(1), or extended egrep(1).
  23228. X  If the symbol egrep is #define'd below, strict egrep(1) syntax is used.
  23229. X
  23230. X  The main routine is re_strcmp() which takes a regular expression, a
  23231. X  string to match against, and a string specifying which of the matched
  23232. X  subparts are to be used to form a new string -- if this string is NULL no
  23233. X  such action is taken.
  23234. X
  23235. X  The new string is stored in the same space, so this string should be
  23236. X  long enough not to cause memory overwrites. To be able to do this match
  23237. X  substitution, the desired subparts of the regular expression should
  23238. X  be enclosed in ( and ). Each subpart is referenced to as \n where n is
  23239. X  a digit from 1 to 9.
  23240. X
  23241. X  For example, the following call:
  23242. X
  23243. X  strcpy (match, "\\2@\\1.UUCP");
  23244. X  re_strcmp ("[^!@]*!([^!@.]*)!([^!@]*)@.*", "GATE!HOP!USER@UUCP.SOME.COM",
  23245. X           match);
  23246. X
  23247. X  will return TRUE and store in 'match' "USER@HOP.UUCP". See the man page
  23248. X  for Henry Spencer's routines included for more information.
  23249. X
  23250. X  In extended mode, regular expressions may use the logical operators ~ (not),
  23251. X  & (and) and group expressions further with < and >. Because of the latter,
  23252. X  < and > may not be used in the ed(1) sense (\< is the default in the
  23253. X  context these routines were developed, and \> is useless in the same context).
  23254. X  To use any of these characters literally, precede them with a backslash (\).
  23255. X
  23256. X  For example:
  23257. X
  23258. X  re_strcmp ("~<.*\.COM|.*\.EDU>&~TASOS*", "TASOS@FOO.US", NULL)
  23259. X
  23260. X  will return FALSE.
  23261. X
  23262. X  re_strcmp() returns TRUE on success, FALSE if no match was found, or
  23263. X  -1 on error. In the latter case, the (char *) variable regerr contains the
  23264. X  actual error message.
  23265. X
  23266. X  The system uses modified pattern matching routines written by Henry Spencer
  23267. X  (Copyright (c) 1986 by University of Toronto) -- actually only regerror.c
  23268. X  was modified. Many thanks and kudos to Henry for this wonderful piece of code.
  23269. X
  23270. X  It is possible to use the ls(1) style wild characters * and ? by altering
  23271. X  the symbols START and QMARK below.
  23272. X
  23273. X  It is also possible to turn off ed(1) style pattern matching (i.e. turn
  23274. X  off the meaning of [ ] { } etc.) by using the function escape_re() where
  23275. X  marked with ###.
  23276. X
  23277. X  To test these routines compile with -Dtest and run independently as follows:
  23278. X
  23279. X        % cc -Dtest -I. regexp.c regsub.c regex.c regerror.c
  23280. X        % a.out 'regular-expression' file [match]
  23281. X
  23282. X  NOTICE: Spencer's $ matches the enf-of-line without mathing a newline
  23283. X  character. When compiling with -Dtest, $ is replaced with .$
  23284. X*/
  23285. X
  23286. X#include <stdio.h>
  23287. X#include <sys/types.h>
  23288. X#include <string.h>
  23289. X#include <ctype.h>
  23290. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  23291. X && !defined (sequent) && !defined (unknown_port)
  23292. X# include <malloc.h>
  23293. X#endif
  23294. X#include "regexp.h"
  23295. X
  23296. X/*
  23297. X#define egrep    Define it if you want to use strict egrep(1) regular expressions
  23298. X*/
  23299. X
  23300. X#define MAXLENGTH    1024    /* Maximum length of each regular expression */
  23301. X#define EOS        '\0'
  23302. X
  23303. Xint  re_strcmp (char *, char *, char *);
  23304. Xint  prevch (char *, char *);
  23305. Xint  nextch (char *);
  23306. X
  23307. X#ifdef test
  23308. Xint  main (int, char **);
  23309. Xvoid workaround (char *);
  23310. X#else
  23311. Xextern void report_progress (FILE *, char *, int);
  23312. Xextern FILE *report;
  23313. X#endif
  23314. X#ifndef egrep
  23315. Xvoid escape_re (char *);
  23316. Xchar *convert_re (char *);
  23317. Xint  icp (int);
  23318. Xint  push (int);
  23319. Xint  pop (void);
  23320. Xint  do_op (int, int, int);
  23321. Xvoid pop_op (void);
  23322. Xint  new_op (int);
  23323. Xint  eval (void);
  23324. Xint  isop (char *, char *);
  23325. X
  23326. X# define STAR        "*"    /* If ".*" then the meaning is that of ls(1) */
  23327. X# define QMARK        "?"    /* If "." then the meaning is that of ls(1) */
  23328. X# define LGROUPCH    '<'    /* Avoid ( and ) */
  23329. X# define RGROUPCH    '>'
  23330. X# define OR        1    /* Operators should be > 0 */
  23331. X# define AND        2
  23332. X# define NOT        3
  23333. X# define LPAREN        4
  23334. X# define RPAREN        5
  23335. X
  23336. Xtypedef struct _operator_stack {
  23337. X  int op;
  23338. X  int isp;    /* In-stack priority */
  23339. X  struct _operator_stack *next, *prev;
  23340. X} OPERATOR_STACK;
  23341. X
  23342. Xtypedef struct _operand_stack {
  23343. X  int val;
  23344. X  struct _operand_stack *next, *prev;
  23345. X} OPERAND_STACK;
  23346. X
  23347. XOPERATOR_STACK *op_top;
  23348. XOPERAND_STACK *val_top;
  23349. X#endif
  23350. X
  23351. Xint pliteral, literal, nliteral;
  23352. X
  23353. Xextern char *regerr;
  23354. X
  23355. X#ifdef test
  23356. Xint main (int argc, char **argv)
  23357. X{
  23358. X  FILE *f;
  23359. X  char s [1024], matches [1024];
  23360. X  int match;
  23361. X
  23362. X  if (argc < 3)
  23363. X    printf ("Usage: %s 'regular-expression' file [match]\n", argv[0]), exit (1);
  23364. X  if ((f = fopen (argv[2], "r")) == NULL)
  23365. X    printf ("%s: ", argv[2]), fflush (stdout), perror (""), exit (1);
  23366. X  while (!feof (f)) {
  23367. X    memset (s, EOS, sizeof (s));
  23368. X    fgets (s, sizeof (s) - 1, f);
  23369. X    if (argc > 3)
  23370. X      strcpy (matches, argv[3]);
  23371. X    if ((match = re_strcmp (argv[1], s, matches)) > 0)
  23372. X      printf ("MATCHES:%s\n", matches),
  23373. X      printf ("%s", s);
  23374. X    else if (match < 0)
  23375. X      printf ("Error in regular expression\n"),
  23376. X      exit (1);
  23377. X  }
  23378. X  fclose (f);
  23379. X  exit (0);
  23380. X}
  23381. X#endif
  23382. X
  23383. X/*
  23384. X  Check 'subject' againt the 'regexpr'. Return 1 on match, 0 if no match,
  23385. X  or -1 on error. To negegate a regular expression precede it with '~';
  23386. X  multiple regular expressions are separated by '|' or '&' (logical OR and
  23387. X  AND) and may be grouped with LGROUPCH and RGROUPCH. To escape the key
  23388. X  characters LGROUPCH * ? | & RGROUPCH use \.
  23389. X*/
  23390. X
  23391. Xint re_strcmp (char *regexpr, char *subject, char *result)
  23392. X{
  23393. X  char *re, *readdr, *s, _re[MAXLENGTH], matches [1024], *error;
  23394. X  int op, i;
  23395. X  regexp *cmp;
  23396. X
  23397. X  s = (char *) malloc ((strlen (regexpr) + 1) * sizeof (char));
  23398. X  strcpy (s, regexpr);
  23399. X#ifdef test
  23400. X  workaround (s);    /* Work around bugs with Spencer's code */
  23401. X#endif
  23402. X#ifndef egrep
  23403. X/*###        Do not escape ed(1) special characters.
  23404. X  escape_re (s);
  23405. X*/
  23406. X  readdr = re = convert_re (s);
  23407. X#else
  23408. X  re = s;
  23409. X#endif
  23410. X  do {
  23411. X#ifndef egrep
  23412. X    if ((op = isop (re, readdr))) {
  23413. X      if (new_op (op)) {
  23414. X    eval ();    /* Empty stacks */
  23415. X    return -1;
  23416. X      }
  23417. X      ++re;
  23418. X    }
  23419. X    else 
  23420. X#endif
  23421. X    {
  23422. X      i = 0;
  23423. X      while (*re != EOS && i < MAXLENGTH
  23424. X#ifndef egrep
  23425. X         && !isop (re, readdr)
  23426. X#endif
  23427. X        )
  23428. X    _re [i++] = *re,
  23429. X    ++re;
  23430. X      if (i == MAXLENGTH)    /* Overflow */
  23431. X    return -1;
  23432. X      _re [i] = EOS;
  23433. X      if (! (cmp = (regexp *) regcomp (_re))) {
  23434. X#ifndef test
  23435. X    error = (char *) malloc ((strlen (regerr) + strlen (_re) + 7) * 
  23436. X                 sizeof (char));
  23437. X    sprintf (error, "RE %s: %s\n", _re, regerr);
  23438. X    report_progress (report, error, 1);
  23439. X#else
  23440. X        printf ("RE %s: %s\n", _re, regerr);
  23441. X#endif
  23442. X    free ((char *) regerr);
  23443. X    free ((char *) error);
  23444. X#ifndef egrep
  23445. X    eval ();    /* Empty stacks */
  23446. X    free ((char *) readdr);
  23447. X#endif
  23448. X        return -1;
  23449. X      }
  23450. X      if (regexec (cmp, subject)) {
  23451. X    if (result)
  23452. X      regsub (cmp, result, matches),
  23453. X      strcpy (result, matches);
  23454. X    free ((regexp *) cmp);
  23455. X#ifndef egrep
  23456. X    push (1);
  23457. X#else
  23458. X    free ((char *) s);
  23459. X    return 1;
  23460. X#endif
  23461. X      }
  23462. X      else {
  23463. X    free ((regexp *) cmp);
  23464. X#ifndef egrep
  23465. X    push (0);
  23466. X#else
  23467. X    free ((char *) s);
  23468. X    return 0;
  23469. X#endif
  23470. X      }
  23471. X    }
  23472. X  } while (*re != EOS);
  23473. X#ifndef egrep
  23474. X  free ((char *) readdr);
  23475. X  free ((char *) s);
  23476. X  return eval ();
  23477. X#endif
  23478. X}
  23479. X
  23480. X/*
  23481. X  Scan 's' and escape the following characters: [ ] < > { } , ; . ^ $ + -
  23482. X  for regular expression matching.
  23483. X
  23484. X  To be used if one does not want ed(1) style pattern matching. Currently, this
  23485. X  function is unused.
  23486. X*/
  23487. X
  23488. X#ifndef egrep
  23489. Xvoid escape_re (char *s)
  23490. X{
  23491. X  char *r;
  23492. X
  23493. X  while (*s != EOS) {
  23494. X    switch (*s) {
  23495. X    case '[': case ']': case '<': case '>': case '+': case '-':
  23496. X    case ';': case ',': case '.': case '^': case '$': case '{': case '}':
  23497. X      r = s + strlen (s);       /* Start from the end */
  23498. X      while (r != s)
  23499. X        *(r + 1) = *r,
  23500. X        --r;
  23501. X      *(r + 1) = *r;
  23502. X      *r = '\\';
  23503. X      ++s;
  23504. X      break;
  23505. X    }
  23506. X    ++s;
  23507. X  }
  23508. X}
  23509. X
  23510. X/*
  23511. X  Possibly convert the wild characters * and ? to ed(1) regular expressions.
  23512. X  Handle escaped characters.
  23513. X*/
  23514. X
  23515. Xchar *convert_re (char *re)
  23516. X{
  23517. X  char *r, *b = re;
  23518. X  int i = 0;
  23519. X
  23520. X  if (! (r = (char *) malloc (sizeof (char))))
  23521. X# ifndef test
  23522. X    report_progress (report, "\nconvert_re(): malloc() failed", 1),
  23523. X    exit (11);
  23524. X# else
  23525. X    fprintf (stderr, "convert_re(): malloc() failed\n"),
  23526. X    exit (11);
  23527. X# endif
  23528. X  while (*re != EOS) {
  23529. X    prevch (re, b);    /* See if *re is literal */
  23530. X    switch (*re) {
  23531. X    case '\\':
  23532. X      if (re != b && literal) {
  23533. X    if (! (r = (char *) realloc (r, (i + 2) * sizeof (char))))
  23534. X# ifndef test
  23535. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23536. X      exit (11);
  23537. X# else
  23538. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23539. X      exit (11);
  23540. X# endif
  23541. X    strncpy (r + i, "\\\\", 2);
  23542. X    i += 2;
  23543. X      }
  23544. X      break;
  23545. X    case '?':        /* Match one character */
  23546. X      if (re != b && literal) {    /* Literal */
  23547. X    if (! (r = (char *) realloc (r, (i + 1) * sizeof (char))))
  23548. X# ifndef test
  23549. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23550. X      exit (11);
  23551. X# else
  23552. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23553. X      exit (11);
  23554. X# endif
  23555. X    *(r + i) = *re;
  23556. X    ++i;
  23557. X      }
  23558. X      else {
  23559. X    if (! (r = (char *) realloc (r, (i + strlen (QMARK)) * sizeof (char))))
  23560. X# ifndef test
  23561. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23562. X      exit (11);
  23563. X# else
  23564. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23565. X      exit (11);
  23566. X# endif
  23567. X    strncpy (r + i, QMARK, strlen (QMARK));
  23568. X    i += strlen (QMARK);
  23569. X      }
  23570. X      break;
  23571. X    case '*':        /* Match multiple characters */
  23572. X      if (re != b && literal) {    /* Literal */
  23573. X    if (! (r = (char *) realloc (r, (i + 2) * sizeof (char))))
  23574. X# ifndef test
  23575. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23576. X      exit (11);
  23577. X# else
  23578. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23579. X      exit (11);
  23580. X# endif
  23581. X    strncpy (r + i, "\\*", 2);
  23582. X    i += 2;
  23583. X      }
  23584. X      else {
  23585. X    if (! (r = (char *) realloc (r, (i + strlen (STAR)) * sizeof (char))))
  23586. X# ifndef test
  23587. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23588. X      exit (11);
  23589. X# else
  23590. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23591. X      exit (11);
  23592. X# endif
  23593. X    strncpy (r + i, STAR, strlen (STAR));
  23594. X    i += strlen (STAR);
  23595. X      }
  23596. X      break;
  23597. X    default:
  23598. X      if (re != b && literal) {    /* carry over */
  23599. X    if (! (r = (char *) realloc (r, (i + 2) * sizeof (char))))
  23600. X# ifndef test
  23601. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23602. X      exit (11);
  23603. X# else
  23604. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23605. X      exit (11);
  23606. X# endif
  23607. X    *(r + i) = *(re - 1);
  23608. X    *(r + i + 1) = *re;
  23609. X    i += 2;
  23610. X      }
  23611. X      else {
  23612. X    if (! (r = (char *) realloc (r, (i + 1) * sizeof (char))))
  23613. X# ifndef test
  23614. X      report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23615. X      exit (11);
  23616. X# else
  23617. X      fprintf (stderr, "convert_re(): realloc() failed\n"),
  23618. X      exit (11);
  23619. X# endif
  23620. X    *(r + i) = *re;
  23621. X    ++i;
  23622. X      }
  23623. X    }
  23624. X    ++re;
  23625. X  }
  23626. X  if (! (r = (char *) realloc (r, (i + 1) * sizeof (char))))
  23627. X# ifndef test
  23628. X    report_progress (report, "\nconvert_re(): realloc() failed", 1),
  23629. X    exit (11);
  23630. X# else
  23631. X    fprintf (stderr, "convert_re(): realloc() failed\n"),
  23632. X    exit (11);
  23633. X# endif
  23634. X  *(r + i) = EOS;
  23635. X  return r;
  23636. X}
  23637. X
  23638. X/*
  23639. X  Return the in-coming priority of an operator.
  23640. X*/
  23641. X
  23642. Xint icp (int op)
  23643. X{
  23644. X  if (op == OR || op == AND) return 1;
  23645. X  if (op == LPAREN || op == NOT) return 4;
  23646. X  return 0;
  23647. X}
  23648. X
  23649. X/*
  23650. X  Push a new operand onto OPERAND_STACK.
  23651. X*/
  23652. X
  23653. Xint push (int val)
  23654. X{
  23655. X  OPERAND_STACK *s;
  23656. X
  23657. X  if (! (s = (OPERAND_STACK *) malloc (sizeof (OPERAND_STACK))))
  23658. X# ifndef test
  23659. X    report_progress (report, "\npush(): malloc() failed", 1),
  23660. X    exit (11);
  23661. X# else
  23662. X    fprintf (stderr, "push(): malloc() failed\n"),
  23663. X    exit (11);
  23664. X# endif
  23665. X  s->val = val;
  23666. X  s->prev = val_top;
  23667. X  s->next = NULL;
  23668. X  if (val_top)
  23669. X    val_top->next = s;
  23670. X  val_top = s;
  23671. X  return val;
  23672. X}
  23673. X
  23674. X/*
  23675. X  Pop an operand from OPERAND_STACK. Return 0 or 1, or -1 on error.
  23676. X*/
  23677. X
  23678. Xint pop ()
  23679. X{
  23680. X  int val;
  23681. X
  23682. X  if (!val_top)    /* Empty stack */
  23683. X    return -1;
  23684. X  val = val_top->val;
  23685. X  if (val_top->prev)
  23686. X    val_top = val_top->prev,
  23687. X    free ((OPERAND_STACK *) val_top->next),
  23688. X    val_top->next = NULL;
  23689. X  else
  23690. X    free ((OPERAND_STACK *) val_top),
  23691. X    val_top = NULL;
  23692. X  return val;
  23693. X}
  23694. X
  23695. X/*
  23696. X  Perform a boolean operation and return the result, or -1 on error.
  23697. X*/
  23698. X
  23699. Xint do_op (int op, int val1, int val2)
  23700. X{
  23701. X  if (val1 < 0 || val2 < 0)
  23702. X    return -1;
  23703. X  if (op == OR)
  23704. X    return val1 | val2;
  23705. X  if (op == AND)
  23706. X    return val1 & val2;
  23707. X  return !val1;
  23708. X}
  23709. X
  23710. X/*
  23711. X  Pop an operator. An operator will always be present.
  23712. X*/
  23713. X
  23714. Xvoid pop_op ()
  23715. X{
  23716. X  OPERATOR_STACK *s;
  23717. X
  23718. X  s = op_top;
  23719. X  op_top = op_top->prev;
  23720. X  if (op_top)
  23721. X    op_top->next = NULL;
  23722. X  free ((OPERATOR_STACK *) s);
  23723. X}
  23724. X
  23725. X/*
  23726. X  Process a new operator: push it anyway, or push it after popping other
  23727. X  operators with higher priority. Return -1 on error condition.
  23728. X*/
  23729. X
  23730. Xint new_op (int op)
  23731. X{
  23732. X  OPERATOR_STACK *s;
  23733. X  int res;
  23734. X
  23735. X  if (op < OR)
  23736. X    return -1;
  23737. X  if (op == RPAREN) {
  23738. X    do {    /* Pop and process operators till LPAREN */
  23739. X      if (!op_top)
  23740. X    return -1;
  23741. X      if (op_top->op != LPAREN) {
  23742. X    if (op_top->op == OR || op_top->op == AND)
  23743. X      res = push (do_op (op_top->op, pop (), pop ()));
  23744. X    else    /* NOT */
  23745. X      res = push (do_op (op_top->op, pop (), 0));
  23746. X    if (res < 0)    /* Error with operands */
  23747. X      return res;
  23748. X    pop_op ();    /* Pop processed operator */
  23749. X    if (!op_top)
  23750. X      return -1;
  23751. X      }
  23752. X    } while (op_top->op != LPAREN);
  23753. X    pop_op ();    /* LPAREN */
  23754. X  }
  23755. X  else {    /* Push new operator */
  23756. X    while (op_top && op_top->isp >= icp (op)) {    /* Process op w/ > priority */
  23757. X      if (op_top->op == OR || op_top->op == AND)
  23758. X    res = push (do_op (op_top->op, pop (), pop ()));
  23759. X      else    /* NOT */
  23760. X    res = push (do_op (op_top->op, pop (), 0));
  23761. X      if (res < 0)
  23762. X    return res;
  23763. X      pop_op ();
  23764. X    }
  23765. X    if (! (s = (OPERATOR_STACK *) malloc (sizeof (OPERATOR_STACK))))
  23766. X# ifndef test
  23767. X      report_progress (report, "\nnew_op(): malloc() failed", 1),
  23768. X      exit (11);
  23769. X# else
  23770. X      fprintf (stderr, "new_op(): malloc() failed\n"),
  23771. X      exit (11);
  23772. X# endif
  23773. X    s->op = op;
  23774. X    if (op == OR) s->isp = 1;
  23775. X    else if (op == AND) s->isp = 1;
  23776. X    else if (op == NOT) s->isp = 2;
  23777. X    else s->isp = 0;
  23778. X    s->prev = op_top;
  23779. X    s->next = NULL;
  23780. X    if (op_top)
  23781. X      op_top->next = s;
  23782. X    op_top = s;
  23783. X  }
  23784. X  return 0;
  23785. X}
  23786. X
  23787. X/*
  23788. X  Process the remaining operators and values. Return -1 on error.
  23789. X*/
  23790. X
  23791. Xint eval ()
  23792. X{
  23793. X  OPERATOR_STACK *op;
  23794. X  int res;
  23795. X
  23796. X  if (!op_top && !val_top)
  23797. X    return 0;
  23798. X  while (op_top) {
  23799. X    if (op_top->op != AND && op_top->op != OR && op_top->op != NOT) {
  23800. X      if (op_top->op < OR || op_top->op > RPAREN)
  23801. X# ifndef test
  23802. X    report_progress (report, "Internal error: unexpected op", 1);
  23803. X# else
  23804. X    printf ("Internal error: unexpected op %d\n", op_top->op);
  23805. X# endif
  23806. X      return -1;
  23807. X    }
  23808. X    if (op_top->op == OR || op_top->op == AND)
  23809. X      res = push (do_op (op_top->op, pop (), pop ()));
  23810. X    else    /* NOT */
  23811. X      res = push (do_op (op_top->op, pop (), 0));
  23812. X    if (res < 0)
  23813. X      return res;
  23814. X    op = op_top;
  23815. X    op_top = op_top->prev;
  23816. X    free ((OPERATOR_STACK *) op);
  23817. X  }
  23818. X  if (!val_top) {
  23819. X# ifndef test
  23820. X    report_progress (report, "Internal error: empty operand stack", 1);
  23821. X# else
  23822. X    printf ("Internal error: empty operand stack\n");
  23823. X# endif
  23824. X    return -1;
  23825. X  }
  23826. X  return pop ();
  23827. X}
  23828. X
  23829. X/*
  23830. X  Return the operator id if indeed 's' points to an operator. Return -1
  23831. X  on error.
  23832. X*/
  23833. X
  23834. Xint isop (char *s, char *b)
  23835. X{
  23836. X  char pch, nch;
  23837. X
  23838. X  pch = prevch (s, b);
  23839. X  if (literal) return 0;
  23840. X  nch = nextch (s);
  23841. X  if (*s == LGROUPCH)
  23842. X    if ((pch == '|' || pch == '&' || pch == '~' || pch == LGROUPCH) &&
  23843. X    !pliteral && ((nch != '|' && nch != '&' && nch != EOS) || nliteral))
  23844. X      return LPAREN;
  23845. X    else
  23846. X      return -1;
  23847. X  if (*s == RGROUPCH)
  23848. X    if (((pch != '|' && pch != '&' && pch != '~') || pliteral) && !nliteral &&
  23849. X    (nch == RGROUPCH || nch == '&' || nch == '|' || nch == EOS))
  23850. X      return RPAREN;
  23851. X    else
  23852. X      return -1;
  23853. X  if (*s == '~')
  23854. X    if ((pch == LGROUPCH || pch == '|' || pch == '&' || pch == '~') &&
  23855. X    !pliteral &&
  23856. X    ((nch != '|' && nch != '&' && nch != RGROUPCH && nch != EOS) ||
  23857. X     nliteral))
  23858. X      return NOT;
  23859. X    else
  23860. X      return -1;
  23861. X  if (*s == '|' || *s == '&')
  23862. X    if (((pch != '~' && pch != '|' && pch != '&') || pliteral) &&
  23863. X    ((nch != '|' && nch != '&' && nch != RGROUPCH &&
  23864. X      nch != EOS) || nliteral))
  23865. X      return (*s == '|' ? OR : AND);
  23866. X    else
  23867. X      return -1;
  23868. X  return 0;
  23869. X}
  23870. X#endif
  23871. X
  23872. X/*
  23873. X  Return the previous character from the current position in the
  23874. X  string. Set 'pliteral' to 1 if that previous character is escaped with \ and
  23875. X  'literal' to 1 if the current character is escaped with \.
  23876. X  In the comments, ^ means "beginning of the string", ? matches any character
  23877. X  except \, * matches absolutely any character and x is the current position.
  23878. X*/
  23879. X
  23880. Xint prevch (char *s, char *b)
  23881. X{
  23882. X  return
  23883. X    ((s) <= (b) ? 
  23884. X     (pliteral = literal = 0, *(s)) : /* ^x */
  23885. X     (((s) - 1) == (b) ? 
  23886. X      (*((s) - 1) == '\\' ? (pliteral = !(literal = 1), *((s) - 1)) /* ^\x */
  23887. X       : (pliteral = literal = 0, *((s) - 1))) /* ^?x */
  23888. X      : (*(s) == '\\' ? 
  23889. X     (*((s) - 2) == '\\' ? (pliteral = !(literal = 0), *((s) - 1)) /* \*\ */
  23890. X      : (*((s) - 1) == '\\' ? (pliteral = !(literal = 1), *((s) - 2)) /* ?\\ */
  23891. X         : (pliteral = literal = 0, *((s) - 1)))) /* ??\ */
  23892. X     : (*((s) - 1) == '\\' ? 
  23893. X        (*((s) - 2) == '\\' ? 
  23894. X         (((s) - 2) == (b) ? (pliteral = !(literal = 0), *((s) - 1)) /* ^\\x */
  23895. X          : (*((s) - 3) == '\\' ? (pliteral = literal = 1,*((s) - 2)) /* \\\x */
  23896. X         : (pliteral = !(literal = 0), *((s) - 1)))) /* ?\\x */
  23897. X         : (((s) - 2) == (b) ? (pliteral = !(literal = 1),*((s) - 2)) /* ^?\x */
  23898. X        : (*((s) - 3) == '\\' ? (pliteral = literal = 1, *((s) - 2)) /* \?\x */
  23899. X           : (pliteral = !(literal = 1),  *((s) - 2))))) /* ??\x */
  23900. X        : (*((s) - 2) == '\\' ? (pliteral = !(literal = 0),*((s) - 1)) /* \?x */
  23901. X           : (pliteral = literal = 0, *((s) - 1))))))); /* ??x */
  23902. X}
  23903. X
  23904. X/*
  23905. X  Return the next character from the current position. The current character
  23906. X  is guarranteed not to be a literal. In the comments below * matches
  23907. X  absolutely any character, ? matches anything but EOS, $ is the EOS and
  23908. X  x marks the current position. Also set 'nliteral' to 1 if the next character
  23909. X  is escaped with \.
  23910. X*/
  23911. X
  23912. Xint nextch (char *s)
  23913. X{
  23914. X  return
  23915. X    (*((s) + 1) == EOS ? (nliteral = 0, EOS) /* x$ */
  23916. X     : (*((s) + 1) == '\\' ? 
  23917. X    (*((s) + 2) == EOS ? (nliteral = 0, *((s) + 1)) /* x\$ */
  23918. X     : (nliteral = 1, *((s) + 2))) /* x\? */
  23919. X    : (nliteral = 0, *((s) + 1)))); /* x* */
  23920. X}
  23921. X#ifdef test
  23922. X
  23923. X/*
  23924. X  Henry Spencer's code requires that $ be converted to .$
  23925. X*/
  23926. X
  23927. Xvoid workaround (char *s)
  23928. X{
  23929. X  char *r, *b = s;
  23930. X
  23931. X  while (*s != EOS) {
  23932. X    switch (*s) {
  23933. X    case '$':
  23934. X      prevch (s, b);    /* See if thi char is a literal */
  23935. X      if (literal) {
  23936. X    ++s;
  23937. X    continue;
  23938. X      }
  23939. X      r = s + strlen (s);       /* Start from the end */
  23940. X      while (r != s)
  23941. X        *(r + 1) = *r,
  23942. X        --r;
  23943. X      *(r + 1) = *r;
  23944. X      *r = '.';
  23945. X      ++s;
  23946. X      break;
  23947. X    }
  23948. X    ++s;
  23949. X  }
  23950. X}
  23951. X#endif
  23952. *-*-END-of-src/regex.c-*-*
  23953. echo x - src/regexp.c
  23954. sed 's/^X//' >src/regexp.c <<'*-*-END-of-src/regexp.c-*-*'
  23955. X/*
  23956. X * regcomp and regexec -- regsub and regerror are elsewhere
  23957. X *
  23958. X *    Copyright (c) 1986 by University of Toronto.
  23959. X *    Written by Henry Spencer.  Not derived from licensed software.
  23960. X *
  23961. X *    Permission is granted to anyone to use this software for any
  23962. X *    purpose on any computer system, and to redistribute it freely,
  23963. X *    subject to the following restrictions:
  23964. X *
  23965. X *    1. The author is not responsible for the consequences of use of
  23966. X *        this software, no matter how awful, even if they arise
  23967. X *        from defects in it.
  23968. X *
  23969. X *    2. The origin of this software must not be misrepresented, either
  23970. X *        by explicit claim or by omission.
  23971. X *
  23972. X *    3. Altered versions must be plainly marked as such, and must not
  23973. X *        be misrepresented as being the original software.
  23974. X *
  23975. X * Beware that some of this code is subtly aware of the way operator
  23976. X * precedence is structured in regular expressions.  Serious changes in
  23977. X * regular-expression syntax might require a total rethink.
  23978. X */
  23979. X#include <stdio.h>
  23980. X#include "regexp.h"
  23981. X#include "regmagic.h"
  23982. X
  23983. X/*
  23984. X * The "internal use only" fields in regexp.h are present to pass info from
  23985. X * compile to execute that permits the execute phase to run lots faster on
  23986. X * simple cases.  They are:
  23987. X *
  23988. X * regstart    char that must begin a match; '\0' if none obvious
  23989. X * reganch    is the match anchored (at beginning-of-line only)?
  23990. X * regmust    string (pointer into program) that match must include, or NULL
  23991. X * regmlen    length of regmust string
  23992. X *
  23993. X * Regstart and reganch permit very fast decisions on suitable starting points
  23994. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  23995. X * of lines that cannot possibly match.  The regmust tests are costly enough
  23996. X * that regcomp() supplies a regmust only if the r.e. contains something
  23997. X * potentially expensive (at present, the only such thing detected is * or +
  23998. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  23999. X * supplied because the test in regexec() needs it and regcomp() is computing
  24000. X * it anyway.
  24001. X */
  24002. X
  24003. X/*
  24004. X * Structure for regexp "program".  This is essentially a linear encoding
  24005. X * of a nondeterministic finite-state machine (aka syntax charts or
  24006. X * "railroad normal form" in parsing technology).  Each node is an opcode
  24007. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  24008. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  24009. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  24010. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  24011. X * opposed to a collection of them) is never concatenated with anything
  24012. X * because of operator precedence.)  The operand of some types of node is
  24013. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  24014. X * particular, the operand of a BRANCH node is the first node of the branch.
  24015. X * (NB this is *not* a tree structure:  the tail of the branch connects
  24016. X * to the thing following the set of BRANCHes.)  The opcodes are:
  24017. X */
  24018. X
  24019. X/* definition    number    opnd?    meaning */
  24020. X#define    END    0    /* no    End of program. */
  24021. X#define    BOL    1    /* no    Match "" at beginning of line. */
  24022. X#define    EOL    2    /* no    Match "" at end of line. */
  24023. X#define    ANY    3    /* no    Match any one character. */
  24024. X#define    ANYOF    4    /* str    Match any character in this string. */
  24025. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  24026. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  24027. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  24028. X#define    EXACTLY    8    /* str    Match this string. */
  24029. X#define    NOTHING    9    /* no    Match empty string. */
  24030. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  24031. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  24032. X#define    OPEN    20    /* no    Mark this point in input as start of #n. */
  24033. X            /*    OPEN+1 is number 1, etc. */
  24034. X#define    CLOSE    30    /* no    Analogous to OPEN. */
  24035. X
  24036. X/*
  24037. X * Opcode notes:
  24038. X *
  24039. X * BRANCH    The set of branches constituting a single choice are hooked
  24040. X *        together with their "next" pointers, since precedence prevents
  24041. X *        anything being concatenated to any individual branch.  The
  24042. X *        "next" pointer of the last BRANCH in a choice points to the
  24043. X *        thing following the whole choice.  This is also where the
  24044. X *        final "next" pointer of each individual branch points; each
  24045. X *        branch starts with the operand node of a BRANCH node.
  24046. X *
  24047. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  24048. X *        exists to make loop structures possible.
  24049. X *
  24050. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  24051. X *        BRANCH structures using BACK.  Simple cases (one character
  24052. X *        per match) are implemented with STAR and PLUS for speed
  24053. X *        and to minimize recursive plunges.
  24054. X *
  24055. X * OPEN,CLOSE    ...are numbered at compile time.
  24056. X */
  24057. X
  24058. X/*
  24059. X * A node is one char of opcode followed by two chars of "next" pointer.
  24060. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  24061. X * value is a positive offset from the opcode of the node containing it.
  24062. X * An operand, if any, simply follows the node.  (Note that much of the
  24063. X * code generation knows about this implicit relationship.)
  24064. X *
  24065. X * Using two bytes for the "next" pointer is vast overkill for most things,
  24066. X * but allows patterns to get big without disasters.
  24067. X */
  24068. X#define    OP(p)    (*(p))
  24069. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + *((p)+2)&0377)
  24070. X#define    OPERAND(p)    ((p) + 3)
  24071. X
  24072. X/*
  24073. X * See regmagic.h for one further detail of program structure.
  24074. X */
  24075. X
  24076. X
  24077. X/*
  24078. X * Utility definitions.
  24079. X */
  24080. X#ifndef CHARBITS
  24081. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  24082. X#else
  24083. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  24084. X#endif
  24085. X
  24086. X#define    FAIL(m)    { regerror(m); return(NULL); }
  24087. X#define    ISMULT(c)    ((c) == '*' || (c) == '+' || (c) == '?')
  24088. X#define    META    "^$.[()|?+*\\"
  24089. X
  24090. X/*
  24091. X * Flags to be passed up and down.
  24092. X */
  24093. X#define    HASWIDTH    01    /* Known never to match null string. */
  24094. X#define    SIMPLE        02    /* Simple enough to be STAR/PLUS operand. */
  24095. X#define    SPSTART        04    /* Starts with * or +. */
  24096. X#define    WORST        0    /* Worst case. */
  24097. X
  24098. X/*
  24099. X * Global work variables for regcomp().
  24100. X */
  24101. Xstatic char *regparse;        /* Input-scan pointer. */
  24102. Xstatic int regnpar;        /* () count. */
  24103. Xstatic char regdummy;
  24104. Xstatic char *regcode;        /* Code-emit pointer; ®dummy = don't. */
  24105. Xstatic long regsize;        /* Code size. */
  24106. X
  24107. X/*
  24108. X * Forward declarations for regcomp()'s friends.
  24109. X */
  24110. X#ifndef STATIC
  24111. X#define    STATIC    static
  24112. X#endif
  24113. XSTATIC char *reg();
  24114. XSTATIC char *regbranch();
  24115. XSTATIC char *regpiece();
  24116. XSTATIC char *regatom();
  24117. XSTATIC char *regnode();
  24118. XSTATIC char *regnext();
  24119. XSTATIC void regc();
  24120. XSTATIC void reginsert();
  24121. XSTATIC void regtail();
  24122. XSTATIC void regoptail();
  24123. X#ifdef STRCSPN
  24124. XSTATIC int strcspn();
  24125. X#endif
  24126. X
  24127. X/*
  24128. X - regcomp - compile a regular expression into internal code
  24129. X *
  24130. X * We can't allocate space until we know how big the compiled form will be,
  24131. X * but we can't compile it (and thus know how big it is) until we've got a
  24132. X * place to put the code.  So we cheat:  we compile it twice, once with code
  24133. X * generation turned off and size counting turned on, and once "for real".
  24134. X * This also means that we don't allocate space until we are sure that the
  24135. X * thing really will compile successfully, and we never have to move the
  24136. X * code and thus invalidate pointers into it.  (Note that it has to be in
  24137. X * one piece because free() must be able to free it all.)
  24138. X *
  24139. X * Beware that the optimization-preparation code in here knows about some
  24140. X * of the structure of the compiled regexp.
  24141. X */
  24142. Xregexp *
  24143. Xregcomp(exp)
  24144. Xchar *exp;
  24145. X{
  24146. X    register regexp *r;
  24147. X    register char *scan;
  24148. X    register char *longest;
  24149. X    register int len;
  24150. X    int flags;
  24151. X    extern char *malloc();
  24152. X
  24153. X    if (exp == NULL)
  24154. X        FAIL("NULL argument");
  24155. X
  24156. X    /* First pass: determine size, legality. */
  24157. X    regparse = exp;
  24158. X    regnpar = 1;
  24159. X    regsize = 0L;
  24160. X    regcode = ®dummy;
  24161. X    regc(MAGIC);
  24162. X    if (reg(0, &flags) == NULL)
  24163. X        return(NULL);
  24164. X
  24165. X    /* Small enough for pointer-storage convention? */
  24166. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  24167. X        FAIL("regexp too big");
  24168. X
  24169. X    /* Allocate space. */
  24170. X    r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
  24171. X    if (r == NULL)
  24172. X        FAIL("out of space");
  24173. X
  24174. X    /* Second pass: emit code. */
  24175. X    regparse = exp;
  24176. X    regnpar = 1;
  24177. X    regcode = r->program;
  24178. X    regc(MAGIC);
  24179. X    if (reg(0, &flags) == NULL)
  24180. X        return(NULL);
  24181. X
  24182. X    /* Dig out information for optimizations. */
  24183. X    r->regstart = '\0';    /* Worst-case defaults. */
  24184. X    r->reganch = 0;
  24185. X    r->regmust = NULL;
  24186. X    r->regmlen = 0;
  24187. X    scan = r->program+1;            /* First BRANCH. */
  24188. X    if (OP(regnext(scan)) == END) {        /* Only one top-level choice. */
  24189. X        scan = OPERAND(scan);
  24190. X
  24191. X        /* Starting-point info. */
  24192. X        if (OP(scan) == EXACTLY)
  24193. X            r->regstart = *OPERAND(scan);
  24194. X        else if (OP(scan) == BOL)
  24195. X            r->reganch++;
  24196. X
  24197. X        /*
  24198. X         * If there's something expensive in the r.e., find the
  24199. X         * longest literal string that must appear and make it the
  24200. X         * regmust.  Resolve ties in favor of later strings, since
  24201. X         * the regstart check works with the beginning of the r.e.
  24202. X         * and avoiding duplication strengthens checking.  Not a
  24203. X         * strong reason, but sufficient in the absence of others.
  24204. X         */
  24205. X        if (flags&SPSTART) {
  24206. X            longest = NULL;
  24207. X            len = 0;
  24208. X            for (; scan != NULL; scan = regnext(scan))
  24209. X                if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
  24210. X                    longest = OPERAND(scan);
  24211. X                    len = strlen(OPERAND(scan));
  24212. X                }
  24213. X            r->regmust = longest;
  24214. X            r->regmlen = len;
  24215. X        }
  24216. X    }
  24217. X
  24218. X    return(r);
  24219. X}
  24220. X
  24221. X/*
  24222. X - reg - regular expression, i.e. main body or parenthesized thing
  24223. X *
  24224. X * Caller must absorb opening parenthesis.
  24225. X *
  24226. X * Combining parenthesis handling with the base level of regular expression
  24227. X * is a trifle forced, but the need to tie the tails of the branches to what
  24228. X * follows makes it hard to avoid.
  24229. X */
  24230. Xstatic char *
  24231. Xreg(paren, flagp)
  24232. Xint paren;            /* Parenthesized? */
  24233. Xint *flagp;
  24234. X{
  24235. X    register char *ret;
  24236. X    register char *br;
  24237. X    register char *ender;
  24238. X    register int parno;
  24239. X    int flags;
  24240. X
  24241. X    *flagp = HASWIDTH;    /* Tentatively. */
  24242. X
  24243. X    /* Make an OPEN node, if parenthesized. */
  24244. X    if (paren) {
  24245. X        if (regnpar >= NSUBEXP)
  24246. X            FAIL("too many ()");
  24247. X        parno = regnpar;
  24248. X        regnpar++;
  24249. X        ret = regnode(OPEN+parno);
  24250. X    } else
  24251. X        ret = NULL;
  24252. X
  24253. X    /* Pick up the branches, linking them together. */
  24254. X    br = regbranch(&flags);
  24255. X    if (br == NULL)
  24256. X        return(NULL);
  24257. X    if (ret != NULL)
  24258. X        regtail(ret, br);    /* OPEN -> first. */
  24259. X    else
  24260. X        ret = br;
  24261. X    if (!(flags&HASWIDTH))
  24262. X        *flagp &= ~HASWIDTH;
  24263. X    *flagp |= flags&SPSTART;
  24264. X    while (*regparse == '|') {
  24265. X        regparse++;
  24266. X        br = regbranch(&flags);
  24267. X        if (br == NULL)
  24268. X            return(NULL);
  24269. X        regtail(ret, br);    /* BRANCH -> BRANCH. */
  24270. X        if (!(flags&HASWIDTH))
  24271. X            *flagp &= ~HASWIDTH;
  24272. X        *flagp |= flags&SPSTART;
  24273. X    }
  24274. X
  24275. X    /* Make a closing node, and hook it on the end. */
  24276. X    ender = regnode((paren) ? CLOSE+parno : END);    
  24277. X    regtail(ret, ender);
  24278. X
  24279. X    /* Hook the tails of the branches to the closing node. */
  24280. X    for (br = ret; br != NULL; br = regnext(br))
  24281. X        regoptail(br, ender);
  24282. X
  24283. X    /* Check for proper termination. */
  24284. X    if (paren && *regparse++ != ')') {
  24285. X        FAIL("unmatched ()");
  24286. X    } else if (!paren && *regparse != '\0') {
  24287. X        if (*regparse == ')') {
  24288. X            FAIL("unmatched ()");
  24289. X        } else
  24290. X            FAIL("junk on end");    /* "Can't happen". */
  24291. X        /* NOTREACHED */
  24292. X    }
  24293. X
  24294. X    return(ret);
  24295. X}
  24296. X
  24297. X/*
  24298. X - regbranch - one alternative of an | operator
  24299. X *
  24300. X * Implements the concatenation operator.
  24301. X */
  24302. Xstatic char *
  24303. Xregbranch(flagp)
  24304. Xint *flagp;
  24305. X{
  24306. X    register char *ret;
  24307. X    register char *chain;
  24308. X    register char *latest;
  24309. X    int flags;
  24310. X
  24311. X    *flagp = WORST;        /* Tentatively. */
  24312. X
  24313. X    ret = regnode(BRANCH);
  24314. X    chain = NULL;
  24315. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  24316. X        latest = regpiece(&flags);
  24317. X        if (latest == NULL)
  24318. X            return(NULL);
  24319. X        *flagp |= flags&HASWIDTH;
  24320. X        if (chain == NULL)    /* First piece. */
  24321. X            *flagp |= flags&SPSTART;
  24322. X        else
  24323. X            regtail(chain, latest);
  24324. X        chain = latest;
  24325. X    }
  24326. X    if (chain == NULL)    /* Loop ran zero times. */
  24327. X        (void) regnode(NOTHING);
  24328. X
  24329. X    return(ret);
  24330. X}
  24331. X
  24332. X/*
  24333. X - regpiece - something followed by possible [*+?]
  24334. X *
  24335. X * Note that the branching code sequences used for ? and the general cases
  24336. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  24337. X * both the endmarker for their branch list and the body of the last branch.
  24338. X * It might seem that this node could be dispensed with entirely, but the
  24339. X * endmarker role is not redundant.
  24340. X */
  24341. Xstatic char *
  24342. Xregpiece(flagp)
  24343. Xint *flagp;
  24344. X{
  24345. X    register char *ret;
  24346. X    register char op;
  24347. X    register char *next;
  24348. X    int flags;
  24349. X
  24350. X    ret = regatom(&flags);
  24351. X    if (ret == NULL)
  24352. X        return(NULL);
  24353. X
  24354. X    op = *regparse;
  24355. X    if (!ISMULT(op)) {
  24356. X        *flagp = flags;
  24357. X        return(ret);
  24358. X    }
  24359. X
  24360. X    if (!(flags&HASWIDTH) && op != '?')
  24361. X        FAIL("*+ operand could be empty");
  24362. X    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
  24363. X
  24364. X    if (op == '*' && (flags&SIMPLE))
  24365. X        reginsert(STAR, ret);
  24366. X    else if (op == '*') {
  24367. X        /* Emit x* as (x&|), where & means "self". */
  24368. X        reginsert(BRANCH, ret);            /* Either x */
  24369. X        regoptail(ret, regnode(BACK));        /* and loop */
  24370. X        regoptail(ret, ret);            /* back */
  24371. X        regtail(ret, regnode(BRANCH));        /* or */
  24372. X        regtail(ret, regnode(NOTHING));        /* null. */
  24373. X    } else if (op == '+' && (flags&SIMPLE))
  24374. X        reginsert(PLUS, ret);
  24375. X    else if (op == '+') {
  24376. X        /* Emit x+ as x(&|), where & means "self". */
  24377. X        next = regnode(BRANCH);            /* Either */
  24378. X        regtail(ret, next);
  24379. X        regtail(regnode(BACK), ret);        /* loop back */
  24380. X        regtail(next, regnode(BRANCH));        /* or */
  24381. X        regtail(ret, regnode(NOTHING));        /* null. */
  24382. X    } else if (op == '?') {
  24383. X        /* Emit x? as (x|) */
  24384. X        reginsert(BRANCH, ret);            /* Either x */
  24385. X        regtail(ret, regnode(BRANCH));        /* or */
  24386. X        next = regnode(NOTHING);        /* null. */
  24387. X        regtail(ret, next);
  24388. X        regoptail(ret, next);
  24389. X    }
  24390. X    regparse++;
  24391. X    if (ISMULT(*regparse))
  24392. X        FAIL("nested *?+");
  24393. X
  24394. X    return(ret);
  24395. X}
  24396. X
  24397. X/*
  24398. X - regatom - the lowest level
  24399. X *
  24400. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  24401. X * it can turn them into a single node, which is smaller to store and
  24402. X * faster to run.  Backslashed characters are exceptions, each becoming a
  24403. X * separate node; the code is simpler that way and it's not worth fixing.
  24404. X */
  24405. Xstatic char *
  24406. Xregatom(flagp)
  24407. Xint *flagp;
  24408. X{
  24409. X    register char *ret;
  24410. X    int flags;
  24411. X
  24412. X    *flagp = WORST;        /* Tentatively. */
  24413. X
  24414. X    switch (*regparse++) {
  24415. X    case '^':
  24416. X        ret = regnode(BOL);
  24417. X        break;
  24418. X    case '$':
  24419. X        ret = regnode(EOL);
  24420. X        break;
  24421. X    case '.':
  24422. X        ret = regnode(ANY);
  24423. X        *flagp |= HASWIDTH|SIMPLE;
  24424. X        break;
  24425. X    case '[': {
  24426. X            register int class;
  24427. X            register int classend;
  24428. X
  24429. X            if (*regparse == '^') {    /* Complement of range. */
  24430. X                ret = regnode(ANYBUT);
  24431. X                regparse++;
  24432. X            } else
  24433. X                ret = regnode(ANYOF);
  24434. X            if (*regparse == ']' || *regparse == '-')
  24435. X                regc(*regparse++);
  24436. X            while (*regparse != '\0' && *regparse != ']') {
  24437. X                if (*regparse == '-') {
  24438. X                    regparse++;
  24439. X                    if (*regparse == ']' || *regparse == '\0')
  24440. X                        regc('-');
  24441. X                    else {
  24442. X                        class = UCHARAT(regparse-2)+1;
  24443. X                        classend = UCHARAT(regparse);
  24444. X                        if (class > classend+1)
  24445. X                            FAIL("invalid [] range");
  24446. X                        for (; class <= classend; class++)
  24447. X                            regc(class);
  24448. X                        regparse++;
  24449. X                    }
  24450. X                } else
  24451. X                    regc(*regparse++);
  24452. X            }
  24453. X            regc('\0');
  24454. X            if (*regparse != ']')
  24455. X                FAIL("unmatched []");
  24456. X            regparse++;
  24457. X            *flagp |= HASWIDTH|SIMPLE;
  24458. X        }
  24459. X        break;
  24460. X    case '(':
  24461. X        ret = reg(1, &flags);
  24462. X        if (ret == NULL)
  24463. X            return(NULL);
  24464. X        *flagp |= flags&(HASWIDTH|SPSTART);
  24465. X        break;
  24466. X    case '\0':
  24467. X    case '|':
  24468. X    case ')':
  24469. X        FAIL("internal urp");    /* Supposed to be caught earlier. */
  24470. X        break;
  24471. X    case '?':
  24472. X    case '+':
  24473. X    case '*':
  24474. X        FAIL("?+* follows nothing");
  24475. X        break;
  24476. X    case '\\':
  24477. X        if (*regparse == '\0')
  24478. X            FAIL("trailing \\");
  24479. X        ret = regnode(EXACTLY);
  24480. X        regc(*regparse++);
  24481. X        regc('\0');
  24482. X        *flagp |= HASWIDTH|SIMPLE;
  24483. X        break;
  24484. X    default: {
  24485. X            register int len;
  24486. X            register char ender;
  24487. X
  24488. X            regparse--;
  24489. X            len = strcspn(regparse, META);
  24490. X            if (len <= 0)
  24491. X                FAIL("internal disaster");
  24492. X            ender = *(regparse+len);
  24493. X            if (len > 1 && ISMULT(ender))
  24494. X                len--;        /* Back off clear of ?+* operand. */
  24495. X            *flagp |= HASWIDTH;
  24496. X            if (len == 1)
  24497. X                *flagp |= SIMPLE;
  24498. X            ret = regnode(EXACTLY);
  24499. X            while (len > 0) {
  24500. X                regc(*regparse++);
  24501. X                len--;
  24502. X            }
  24503. X            regc('\0');
  24504. X        }
  24505. X        break;
  24506. X    }
  24507. X
  24508. X    return(ret);
  24509. X}
  24510. X
  24511. X/*
  24512. X - regnode - emit a node
  24513. X */
  24514. Xstatic char *            /* Location. */
  24515. Xregnode(op)
  24516. Xchar op;
  24517. X{
  24518. X    register char *ret;
  24519. X    register char *ptr;
  24520. X
  24521. X    ret = regcode;
  24522. X    if (ret == ®dummy) {
  24523. X        regsize += 3;
  24524. X        return(ret);
  24525. X    }
  24526. X
  24527. X    ptr = ret;
  24528. X    *ptr++ = op;
  24529. X    *ptr++ = '\0';        /* Null "next" pointer. */
  24530. X    *ptr++ = '\0';
  24531. X    regcode = ptr;
  24532. X
  24533. X    return(ret);
  24534. X}
  24535. X
  24536. X/*
  24537. X - regc - emit (if appropriate) a byte of code
  24538. X */
  24539. Xstatic void
  24540. Xregc(b)
  24541. Xchar b;
  24542. X{
  24543. X    if (regcode != ®dummy)
  24544. X        *regcode++ = b;
  24545. X    else
  24546. X        regsize++;
  24547. X}
  24548. X
  24549. X/*
  24550. X - reginsert - insert an operator in front of already-emitted operand
  24551. X *
  24552. X * Means relocating the operand.
  24553. X */
  24554. Xstatic void
  24555. Xreginsert(op, opnd)
  24556. Xchar op;
  24557. Xchar *opnd;
  24558. X{
  24559. X    register char *src;
  24560. X    register char *dst;
  24561. X    register char *place;
  24562. X
  24563. X    if (regcode == ®dummy) {
  24564. X        regsize += 3;
  24565. X        return;
  24566. X    }
  24567. X
  24568. X    src = regcode;
  24569. X    regcode += 3;
  24570. X    dst = regcode;
  24571. X    while (src > opnd)
  24572. X        *--dst = *--src;
  24573. X
  24574. X    place = opnd;        /* Op node, where operand used to be. */
  24575. X    *place++ = op;
  24576. X    *place++ = '\0';
  24577. X    *place++ = '\0';
  24578. X}
  24579. X
  24580. X/*
  24581. X - regtail - set the next-pointer at the end of a node chain
  24582. X */
  24583. Xstatic void
  24584. Xregtail(p, val)
  24585. Xchar *p;
  24586. Xchar *val;
  24587. X{
  24588. X    register char *scan;
  24589. X    register char *temp;
  24590. X    register int offset;
  24591. X
  24592. X    if (p == ®dummy)
  24593. X        return;
  24594. X
  24595. X    /* Find last node. */
  24596. X    scan = p;
  24597. X    for (;;) {
  24598. X        temp = regnext(scan);
  24599. X        if (temp == NULL)
  24600. X            break;
  24601. X        scan = temp;
  24602. X    }
  24603. X
  24604. X    if (OP(scan) == BACK)
  24605. X        offset = scan - val;
  24606. X    else
  24607. X        offset = val - scan;
  24608. X    *(scan+1) = (offset>>8)&0377;
  24609. X    *(scan+2) = offset&0377;
  24610. X}
  24611. X
  24612. X/*
  24613. X - regoptail - regtail on operand of first argument; nop if operandless
  24614. X */
  24615. Xstatic void
  24616. Xregoptail(p, val)
  24617. Xchar *p;
  24618. Xchar *val;
  24619. X{
  24620. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  24621. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  24622. X        return;
  24623. X    regtail(OPERAND(p), val);
  24624. X}
  24625. X
  24626. X/*
  24627. X * regexec and friends
  24628. X */
  24629. X
  24630. X/*
  24631. X * Global work variables for regexec().
  24632. X */
  24633. Xstatic char *reginput;        /* String-input pointer. */
  24634. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  24635. Xstatic char **regstartp;    /* Pointer to startp array. */
  24636. Xstatic char **regendp;        /* Ditto for endp. */
  24637. X
  24638. X/*
  24639. X * Forwards.
  24640. X */
  24641. XSTATIC int regtry();
  24642. XSTATIC int regmatch();
  24643. XSTATIC int regrepeat();
  24644. X
  24645. X#ifdef DEBUG
  24646. Xint regnarrate = 0;
  24647. Xvoid regdump();
  24648. XSTATIC char *regprop();
  24649. X#endif
  24650. X
  24651. X/*
  24652. X - regexec - match a regexp against a string
  24653. X */
  24654. Xint
  24655. Xregexec(prog, string)
  24656. Xregister regexp *prog;
  24657. Xregister char *string;
  24658. X{
  24659. X    register char *s;
  24660. X    extern char *strchr();
  24661. X
  24662. X    /* Be paranoid... */
  24663. X    if (prog == NULL || string == NULL) {
  24664. X        regerror("NULL parameter");
  24665. X        return(0);
  24666. X    }
  24667. X
  24668. X    /* Check validity of program. */
  24669. X    if (UCHARAT(prog->program) != MAGIC) {
  24670. X        regerror("corrupted program");
  24671. X        return(0);
  24672. X    }
  24673. X
  24674. X    /* If there is a "must appear" string, look for it. */
  24675. X    if (prog->regmust != NULL) {
  24676. X        s = string;
  24677. X        while ((s = strchr(s, prog->regmust[0])) != NULL) {
  24678. X            if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  24679. X                break;    /* Found it. */
  24680. X            s++;
  24681. X        }
  24682. X        if (s == NULL)    /* Not present. */
  24683. X            return(0);
  24684. X    }
  24685. X
  24686. X    /* Mark beginning of line for ^ . */
  24687. X    regbol = string;
  24688. X
  24689. X    /* Simplest case:  anchored match need be tried only once. */
  24690. X    if (prog->reganch)
  24691. X        return(regtry(prog, string));
  24692. X
  24693. X    /* Messy cases:  unanchored match. */
  24694. X    s = string;
  24695. X    if (prog->regstart != '\0')
  24696. X        /* We know what char it must start with. */
  24697. X        while ((s = strchr(s, prog->regstart)) != NULL) {
  24698. X            if (regtry(prog, s))
  24699. X                return(1);
  24700. X            s++;
  24701. X        }
  24702. X    else
  24703. X        /* We don't -- general case. */
  24704. X        do {
  24705. X            if (regtry(prog, s))
  24706. X                return(1);
  24707. X        } while (*s++ != '\0');
  24708. X
  24709. X    /* Failure. */
  24710. X    return(0);
  24711. X}
  24712. X
  24713. X/*
  24714. X - regtry - try match at specific point
  24715. X */
  24716. Xstatic int            /* 0 failure, 1 success */
  24717. Xregtry(prog, string)
  24718. Xregexp *prog;
  24719. Xchar *string;
  24720. X{
  24721. X    register int i;
  24722. X    register char **sp;
  24723. X    register char **ep;
  24724. X
  24725. X    reginput = string;
  24726. X    regstartp = prog->startp;
  24727. X    regendp = prog->endp;
  24728. X
  24729. X    sp = prog->startp;
  24730. X    ep = prog->endp;
  24731. X    for (i = NSUBEXP; i > 0; i--) {
  24732. X        *sp++ = NULL;
  24733. X        *ep++ = NULL;
  24734. X    }
  24735. X    if (regmatch(prog->program + 1)) {
  24736. X        prog->startp[0] = string;
  24737. X        prog->endp[0] = reginput;
  24738. X        return(1);
  24739. X    } else
  24740. X        return(0);
  24741. X}
  24742. X
  24743. X/*
  24744. X - regmatch - main matching routine
  24745. X *
  24746. X * Conceptually the strategy is simple:  check to see whether the current
  24747. X * node matches, call self recursively to see whether the rest matches,
  24748. X * and then act accordingly.  In practice we make some effort to avoid
  24749. X * recursion, in particular by going through "ordinary" nodes (that don't
  24750. X * need to know whether the rest of the match failed) by a loop instead of
  24751. X * by recursion.
  24752. X */
  24753. Xstatic int            /* 0 failure, 1 success */
  24754. Xregmatch(prog)
  24755. Xchar *prog;
  24756. X{
  24757. X    register char *scan;    /* Current node. */
  24758. X    char *next;        /* Next node. */
  24759. X    extern char *strchr();
  24760. X
  24761. X    scan = prog;
  24762. X#ifdef DEBUG
  24763. X    if (scan != NULL && regnarrate)
  24764. X        fprintf(stderr, "%s(\n", regprop(scan));
  24765. X#endif
  24766. X    while (scan != NULL) {
  24767. X#ifdef DEBUG
  24768. X        if (regnarrate)
  24769. X            fprintf(stderr, "%s...\n", regprop(scan));
  24770. X#endif
  24771. X        next = regnext(scan);
  24772. X
  24773. X        switch (OP(scan)) {
  24774. X        case BOL:
  24775. X            if (reginput != regbol)
  24776. X                return(0);
  24777. X            break;
  24778. X        case EOL:
  24779. X            if (*reginput != '\0')
  24780. X                return(0);
  24781. X            break;
  24782. X        case ANY:
  24783. X            if (*reginput == '\0')
  24784. X                return(0);
  24785. X            reginput++;
  24786. X            break;
  24787. X        case EXACTLY: {
  24788. X                register int len;
  24789. X                register char *opnd;
  24790. X
  24791. X                opnd = OPERAND(scan);
  24792. X                /* Inline the first character, for speed. */
  24793. X                if (*opnd != *reginput)
  24794. X                    return(0);
  24795. X                len = strlen(opnd);
  24796. X                if (len > 1 && strncmp(opnd, reginput, len) != 0)
  24797. X                    return(0);
  24798. X                reginput += len;
  24799. X            }
  24800. X            break;
  24801. X        case ANYOF:
  24802. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
  24803. X                return(0);
  24804. X            reginput++;
  24805. X            break;
  24806. X        case ANYBUT:
  24807. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
  24808. X                return(0);
  24809. X            reginput++;
  24810. X            break;
  24811. X        case NOTHING:
  24812. X            break;
  24813. X        case BACK:
  24814. X            break;
  24815. X        case OPEN+1:
  24816. X        case OPEN+2:
  24817. X        case OPEN+3:
  24818. X        case OPEN+4:
  24819. X        case OPEN+5:
  24820. X        case OPEN+6:
  24821. X        case OPEN+7:
  24822. X        case OPEN+8:
  24823. X        case OPEN+9: {
  24824. X                register int no;
  24825. X                register char *save;
  24826. X
  24827. X                no = OP(scan) - OPEN;
  24828. X                save = reginput;
  24829. X
  24830. X                if (regmatch(next)) {
  24831. X                    /*
  24832. X                     * Don't set startp if some later
  24833. X                     * invocation of the same parentheses
  24834. X                     * already has.
  24835. X                     */
  24836. X                    if (regstartp[no] == NULL)
  24837. X                        regstartp[no] = save;
  24838. X                    return(1);
  24839. X                } else
  24840. X                    return(0);
  24841. X            }
  24842. X            break;
  24843. X        case CLOSE+1:
  24844. X        case CLOSE+2:
  24845. X        case CLOSE+3:
  24846. X        case CLOSE+4:
  24847. X        case CLOSE+5:
  24848. X        case CLOSE+6:
  24849. X        case CLOSE+7:
  24850. X        case CLOSE+8:
  24851. X        case CLOSE+9: {
  24852. X                register int no;
  24853. X                register char *save;
  24854. X
  24855. X                no = OP(scan) - CLOSE;
  24856. X                save = reginput;
  24857. X
  24858. X                if (regmatch(next)) {
  24859. X                    /*
  24860. X                     * Don't set endp if some later
  24861. X                     * invocation of the same parentheses
  24862. X                     * already has.
  24863. X                     */
  24864. X                    if (regendp[no] == NULL)
  24865. X                        regendp[no] = save;
  24866. X                    return(1);
  24867. X                } else
  24868. X                    return(0);
  24869. X            }
  24870. X            break;
  24871. X        case BRANCH: {
  24872. X                register char *save;
  24873. X
  24874. X                if (OP(next) != BRANCH)        /* No choice. */
  24875. X                    next = OPERAND(scan);    /* Avoid recursion. */
  24876. X                else {
  24877. X                    do {
  24878. X                        save = reginput;
  24879. X                        if (regmatch(OPERAND(scan)))
  24880. X                            return(1);
  24881. X                        reginput = save;
  24882. X                        scan = regnext(scan);
  24883. X                    } while (scan != NULL && OP(scan) == BRANCH);
  24884. X                    return(0);
  24885. X                    /* NOTREACHED */
  24886. X                }
  24887. X            }
  24888. X            break;
  24889. X        case STAR:
  24890. X        case PLUS: {
  24891. X                register char nextch;
  24892. X                register int no;
  24893. X                register char *save;
  24894. X                register int min;
  24895. X
  24896. X                /*
  24897. X                 * Lookahead to avoid useless match attempts
  24898. X                 * when we know what character comes next.
  24899. X                 */
  24900. X                nextch = '\0';
  24901. X                if (OP(next) == EXACTLY)
  24902. X                    nextch = *OPERAND(next);
  24903. X                min = (OP(scan) == STAR) ? 0 : 1;
  24904. X                save = reginput;
  24905. X                no = regrepeat(OPERAND(scan));
  24906. X                while (no >= min) {
  24907. X                    /* If it could work, try it. */
  24908. X                    if (nextch == '\0' || *reginput == nextch)
  24909. X                        if (regmatch(next))
  24910. X                            return(1);
  24911. X                    /* Couldn't or didn't -- back up. */
  24912. X                    no--;
  24913. X                    reginput = save + no;
  24914. X                }
  24915. X                return(0);
  24916. X            }
  24917. X            break;
  24918. X        case END:
  24919. X            return(1);    /* Success! */
  24920. X            break;
  24921. X        default:
  24922. X            regerror("memory corruption");
  24923. X            return(0);
  24924. X            break;
  24925. X        }
  24926. X
  24927. X        scan = next;
  24928. X    }
  24929. X
  24930. X    /*
  24931. X     * We get here only if there's trouble -- normally "case END" is
  24932. X     * the terminating point.
  24933. X     */
  24934. X    regerror("corrupted pointers");
  24935. X    return(0);
  24936. X}
  24937. X
  24938. X/*
  24939. X - regrepeat - repeatedly match something simple, report how many
  24940. X */
  24941. Xstatic int
  24942. Xregrepeat(p)
  24943. Xchar *p;
  24944. X{
  24945. X    register int count = 0;
  24946. X    register char *scan;
  24947. X    register char *opnd;
  24948. X
  24949. X    scan = reginput;
  24950. X    opnd = OPERAND(p);
  24951. X    switch (OP(p)) {
  24952. X    case ANY:
  24953. X        count = strlen(scan);
  24954. X        scan += count;
  24955. X        break;
  24956. X    case EXACTLY:
  24957. X        while (*opnd == *scan) {
  24958. X            count++;
  24959. X            scan++;
  24960. X        }
  24961. X        break;
  24962. X    case ANYOF:
  24963. X        while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
  24964. X            count++;
  24965. X            scan++;
  24966. X        }
  24967. X        break;
  24968. X    case ANYBUT:
  24969. X        while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  24970. X            count++;
  24971. X            scan++;
  24972. X        }
  24973. X        break;
  24974. X    default:        /* Oh dear.  Called inappropriately. */
  24975. X        regerror("internal foulup");
  24976. X        count = 0;    /* Best compromise. */
  24977. X        break;
  24978. X    }
  24979. X    reginput = scan;
  24980. X
  24981. X    return(count);
  24982. X}
  24983. X
  24984. X/*
  24985. X - regnext - dig the "next" pointer out of a node
  24986. X */
  24987. Xstatic char *
  24988. Xregnext(p)
  24989. Xregister char *p;
  24990. X{
  24991. X    register int offset;
  24992. X
  24993. X    if (p == ®dummy)
  24994. X        return(NULL);
  24995. X
  24996. X    offset = NEXT(p);
  24997. X    if (offset == 0)
  24998. X        return(NULL);
  24999. X
  25000. X    if (OP(p) == BACK)
  25001. X        return(p-offset);
  25002. X    else
  25003. X        return(p+offset);
  25004. X}
  25005. X
  25006. X#ifdef DEBUG
  25007. X
  25008. XSTATIC char *regprop();
  25009. X
  25010. X/*
  25011. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  25012. X */
  25013. Xvoid
  25014. Xregdump(r)
  25015. Xregexp *r;
  25016. X{
  25017. X    register char *s;
  25018. X    register char op = EXACTLY;    /* Arbitrary non-END op. */
  25019. X    register char *next;
  25020. X    extern char *strchr();
  25021. X
  25022. X
  25023. X    s = r->program + 1;
  25024. X    while (op != END) {    /* While that wasn't END last time... */
  25025. X        op = OP(s);
  25026. X        printf("%2d%s", s-r->program, regprop(s));    /* Where, what. */
  25027. X        next = regnext(s);
  25028. X        if (next == NULL)        /* Next ptr. */
  25029. X            printf("(0)");
  25030. X        else 
  25031. X            printf("(%d)", (s-r->program)+(next-s));
  25032. X        s += 3;
  25033. X        if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  25034. X            /* Literal string, where present. */
  25035. X            while (*s != '\0') {
  25036. X                putchar(*s);
  25037. X                s++;
  25038. X            }
  25039. X            s++;
  25040. X        }
  25041. X        putchar('\n');
  25042. X    }
  25043. X
  25044. X    /* Header fields of interest. */
  25045. X    if (r->regstart != '\0')
  25046. X        printf("start `%c' ", r->regstart);
  25047. X    if (r->reganch)
  25048. X        printf("anchored ");
  25049. X    if (r->regmust != NULL)
  25050. X        printf("must have \"%s\"", r->regmust);
  25051. X    printf("\n");
  25052. X}
  25053. X
  25054. X/*
  25055. X - regprop - printable representation of opcode
  25056. X */
  25057. Xstatic char *
  25058. Xregprop(op)
  25059. Xchar *op;
  25060. X{
  25061. X    register char *p;
  25062. X    static char buf[50];
  25063. X
  25064. X    (void) strcpy(buf, ":");
  25065. X
  25066. X    switch (OP(op)) {
  25067. X    case BOL:
  25068. X        p = "BOL";
  25069. X        break;
  25070. X    case EOL:
  25071. X        p = "EOL";
  25072. X        break;
  25073. X    case ANY:
  25074. X        p = "ANY";
  25075. X        break;
  25076. X    case ANYOF:
  25077. X        p = "ANYOF";
  25078. X        break;
  25079. X    case ANYBUT:
  25080. X        p = "ANYBUT";
  25081. X        break;
  25082. X    case BRANCH:
  25083. X        p = "BRANCH";
  25084. X        break;
  25085. X    case EXACTLY:
  25086. X        p = "EXACTLY";
  25087. X        break;
  25088. X    case NOTHING:
  25089. X        p = "NOTHING";
  25090. X        break;
  25091. X    case BACK:
  25092. X        p = "BACK";
  25093. X        break;
  25094. X    case END:
  25095. X        p = "END";
  25096. X        break;
  25097. X    case OPEN+1:
  25098. X    case OPEN+2:
  25099. X    case OPEN+3:
  25100. X    case OPEN+4:
  25101. X    case OPEN+5:
  25102. X    case OPEN+6:
  25103. X    case OPEN+7:
  25104. X    case OPEN+8:
  25105. X    case OPEN+9:
  25106. X        sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
  25107. X        p = NULL;
  25108. X        break;
  25109. X    case CLOSE+1:
  25110. X    case CLOSE+2:
  25111. X    case CLOSE+3:
  25112. X    case CLOSE+4:
  25113. X    case CLOSE+5:
  25114. X    case CLOSE+6:
  25115. X    case CLOSE+7:
  25116. X    case CLOSE+8:
  25117. X    case CLOSE+9:
  25118. X        sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
  25119. X        p = NULL;
  25120. X        break;
  25121. X    case STAR:
  25122. X        p = "STAR";
  25123. X        break;
  25124. X    case PLUS:
  25125. X        p = "PLUS";
  25126. X        break;
  25127. X    default:
  25128. X        regerror("corrupted opcode");
  25129. X        break;
  25130. X    }
  25131. X    if (p != NULL)
  25132. X        (void) strcat(buf, p);
  25133. X    return(buf);
  25134. X}
  25135. X#endif
  25136. X
  25137. X/*
  25138. X * The following is provided for those people who do not have strcspn() in
  25139. X * their C libraries.  They should get off their butts and do something
  25140. X * about it; at least one public-domain implementation of those (highly
  25141. X * useful) string routines has been published on Usenet.
  25142. X */
  25143. X#ifdef STRCSPN
  25144. X/*
  25145. X * strcspn - find length of initial segment of s1 consisting entirely
  25146. X * of characters not from s2
  25147. X */
  25148. X
  25149. Xstatic int
  25150. Xstrcspn(s1, s2)
  25151. Xchar *s1;
  25152. Xchar *s2;
  25153. X{
  25154. X    register char *scan1;
  25155. X    register char *scan2;
  25156. X    register int count;
  25157. X
  25158. X    count = 0;
  25159. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  25160. X        for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  25161. X            if (*scan1 == *scan2++)
  25162. X                return(count);
  25163. X        count++;
  25164. X    }
  25165. X    return(count);
  25166. X}
  25167. X#endif
  25168. *-*-END-of-src/regexp.c-*-*
  25169. echo x - src/regsub.c
  25170. sed 's/^X//' >src/regsub.c <<'*-*-END-of-src/regsub.c-*-*'
  25171. X/*
  25172. X * regsub
  25173. X *
  25174. X *    Copyright (c) 1986 by University of Toronto.
  25175. X *    Written by Henry Spencer.  Not derived from licensed software.
  25176. X *
  25177. X *    Permission is granted to anyone to use this software for any
  25178. X *    purpose on any computer system, and to redistribute it freely,
  25179. X *    subject to the following restrictions:
  25180. X *
  25181. X *    1. The author is not responsible for the consequences of use of
  25182. X *        this software, no matter how awful, even if they arise
  25183. X *        from defects in it.
  25184. X *
  25185. X *    2. The origin of this software must not be misrepresented, either
  25186. X *        by explicit claim or by omission.
  25187. X *
  25188. X *    3. Altered versions must be plainly marked as such, and must not
  25189. X *        be misrepresented as being the original software.
  25190. X */
  25191. X#include <stdio.h>
  25192. X#include "regexp.h"
  25193. X#include "regmagic.h"
  25194. X
  25195. X#ifndef CHARBITS
  25196. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  25197. X#else
  25198. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  25199. X#endif
  25200. X
  25201. X/*
  25202. X - regsub - perform substitutions after a regexp match
  25203. X */
  25204. Xvoid
  25205. Xregsub(prog, source, dest)
  25206. Xregexp *prog;
  25207. Xchar *source;
  25208. Xchar *dest;
  25209. X{
  25210. X    register char *src;
  25211. X    register char *dst;
  25212. X    register char c;
  25213. X    register int no;
  25214. X    register int len;
  25215. X    extern char *strncpy();
  25216. X
  25217. X    if (prog == NULL || source == NULL || dest == NULL) {
  25218. X        regerror("NULL parm to regsub");
  25219. X        return;
  25220. X    }
  25221. X    if (UCHARAT(prog->program) != MAGIC) {
  25222. X        regerror("damaged regexp fed to regsub");
  25223. X        return;
  25224. X    }
  25225. X
  25226. X    src = source;
  25227. X    dst = dest;
  25228. X    while ((c = *src++) != '\0') {
  25229. X        if (c == '&')
  25230. X            no = 0;
  25231. X        else if (c == '\\' && '0' <= *src && *src <= '9')
  25232. X            no = *src++ - '0';
  25233. X        else
  25234. X            no = -1;
  25235. X
  25236. X        if (no < 0) {    /* Ordinary character. */
  25237. X            if (c == '\\' && (*src == '\\' || *src == '&'))
  25238. X                c = *src++;
  25239. X            *dst++ = c;
  25240. X        }
  25241. X        else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
  25242. X            len = prog->endp[no] - prog->startp[no];
  25243. X            (void) strncpy(dst, prog->startp[no], len);
  25244. X            dst += len;
  25245. X            if (len != 0 && *(dst-1) == '\0') {        /* strncpy hit NUL. */
  25246. X                regerror("damaged match string");
  25247. X                return;
  25248. X            }
  25249. X        }
  25250. X    }
  25251. X    *dst++ = '\0';
  25252. X}
  25253. *-*-END-of-src/regsub.c-*-*
  25254. echo x - src/rev.c
  25255. sed 's/^X//' >src/rev.c <<'*-*-END-of-src/rev.c-*-*'
  25256. X/*
  25257. X  ----------------------------------------------------------------------------
  25258. X  |               REVERSE ORDER OF INPUT                 |
  25259. X  |                                         |
  25260. X  |                Version 1.0                     |
  25261. X  |                                         |
  25262. X  |                (or, when Computer Science gets to you)                   |
  25263. X  |                                         |
  25264. X  |               Written by Anastasios Kotsikonas                      |
  25265. X  |                      (tasos@cs.bu.edu)                          |
  25266. X  |                                                                         |
  25267. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  25268. X  | whole and not in parts, as long as you do not remove or alter the author |
  25269. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  25270. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  25271. X  | provided for your personal use, you you may not alter the functions      |
  25272. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  25273. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  25274. X  | any changes you may have made. No part of the source code bearing a         |
  25275. X  | copyright notice can be included in commercial software systems without  |
  25276. X  | written permission by the author.                         |
  25277. X  | By using this software you are bound by this agreement.                  |
  25278. X  | This software comes with no warranties and cannot be sold for profit.    |
  25279. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  25280. X  | files when distributing this software.                                   |
  25281. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  25282. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  25283. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  25284. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  25285. X  | (ii).                                                                    |
  25286. X  ----------------------------------------------------------------------------
  25287. X*/
  25288. X
  25289. X#include <stdio.h>
  25290. X
  25291. Xmain ()
  25292. X{
  25293. X  char linein[65536];
  25294. X  char lineout[65536];
  25295. X  long int i, j;
  25296. X
  25297. X  while (!feof (stdin)) {
  25298. X    linein[0] = lineout[0] = '\0';
  25299. X    fgets (linein, 65535, stdin);
  25300. X    if (linein [(j = strlen (linein)) - 1] == '\n')
  25301. X      lineout [j - 1]= '\n',
  25302. X      --j;
  25303. X    for (i = j - 1, j = 0; i >= 0; i--)
  25304. X      lineout[j++] = linein[i];
  25305. X    if (lineout[j] == '\n') j++;
  25306. X    lineout[j] = '\0';
  25307. X    fputs (lineout, stdout);
  25308. X  }
  25309. X  exit (0);
  25310. X}
  25311. *-*-END-of-src/rev.c-*-*
  25312. echo x - src/sem.c
  25313. sed 's/^X//' >src/sem.c <<'*-*-END-of-src/sem.c-*-*'
  25314. X/*
  25315. X  ----------------------------------------------------------------------------
  25316. X  |                SEMAPHORE OPERATIONS                 |
  25317. X  |                                         |
  25318. X  |                     version 1.0                 |
  25319. X  |                                         |
  25320. X  | User contributed code.                             |
  25321. X  | Author: Thimios Panagos <thimios@cs.bu.edu>                     |
  25322. X  ----------------------------------------------------------------------------
  25323. X*/
  25324. X
  25325. X#include <signal.h>
  25326. X#include "defs.h"
  25327. X#ifdef GO_INTERACTIVE
  25328. X# include <stdio.h>
  25329. X# include <sys/types.h>
  25330. X# include <sys/ipc.h>
  25331. X# include <sys/sem.h>
  25332. X
  25333. Xint semtran (int);
  25334. Xint semcall (int, int);
  25335. Xint P (int);
  25336. Xint V (int);
  25337. Xvoid semremove (int);
  25338. X
  25339. X/*
  25340. X  Create a semaphore. Return the semaphore id, or -1 on error.
  25341. X*/
  25342. X
  25343. Xint semtran (int key) 
  25344. X{
  25345. X  int sid;
  25346. X
  25347. X  if ((sid = semget ((key_t) key, 1, 0700 | IPC_CREAT | SEM_UNDO)) < 0)
  25348. X    return -1;
  25349. X  if (V (sid))          /* Initialize semaphore value to 1 */
  25350. X    return -1;
  25351. X  return sid;
  25352. X}
  25353. X
  25354. X/*
  25355. X  Operate on a semaphore (increment or decrement).
  25356. X*/
  25357. X
  25358. Xint semcall (int sid, int op)
  25359. X{
  25360. X  struct sembuf sb;
  25361. X
  25362. X  sb.sem_num = sb.sem_flg = 0;
  25363. X  sb.sem_op = op;
  25364. X
  25365. X  if (semop (sid, &sb, 1) == -1)
  25366. X    return -1;
  25367. X  return 0;
  25368. X}
  25369. X
  25370. X/*
  25371. X  P semaphore; call when attempting to get into critical section.
  25372. X*/
  25373. X
  25374. Xint P (int sid)     
  25375. X{
  25376. X  if (semcall (sid, -1))
  25377. X    return -1;
  25378. X  return 0;
  25379. X}
  25380. X
  25381. X/*
  25382. X  V semaphore; call when out of critical section.
  25383. X*/
  25384. X
  25385. Xint V (int sid)  
  25386. X{
  25387. X  if (semcall (sid, 1))
  25388. X    return -1;
  25389. X  return 0;
  25390. X}
  25391. X
  25392. X/*
  25393. X  Destroy a semaphore.
  25394. X*/
  25395. X
  25396. Xvoid semremove (int sid)
  25397. X{
  25398. X  (void) semctl (sid, 0, IPC_RMID, 0); 
  25399. X}
  25400. X#endif
  25401. *-*-END-of-src/sem.c-*-*
  25402. echo x - src/sender.c
  25403. sed 's/^X//' >src/sender.c <<'*-*-END-of-src/sender.c-*-*'
  25404. X/*
  25405. X  ----------------------------------------------------------------------------
  25406. X  |                      SENDER ORIENTED FUNCTIONS                 |
  25407. X  |                                                                          |
  25408. X  |                              Version 2.3                                 |
  25409. X  |                                                                          |
  25410. X  |                (or, when Computer Science gets to you)                   |
  25411. X  |                                                                          |
  25412. X  |                    Written by Anastasios Kotsikonas                      |
  25413. X  |                           (tasos@cs.bu.edu)                              |
  25414. X  |                                                                          |
  25415. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  25416. X  | whole and not in parts, as long as you do not remove or alter the author |
  25417. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  25418. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  25419. X  | provided for your personal use, you you may not alter the functions      |
  25420. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  25421. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  25422. X  | any changes you may have made. No part of the source code bearing a         |
  25423. X  | copyright notice can be included in commercial software systems without  |
  25424. X  | written permission by the author.                         |
  25425. X  | By using this software you are bound by this agreement.                  |
  25426. X  | This software comes with no warranties and cannot be sold for profit.    |
  25427. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  25428. X  | files when distributing this software.                                   |
  25429. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  25430. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  25431. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  25432. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  25433. X  | (ii).                                                                    |
  25434. X  ----------------------------------------------------------------------------
  25435. X*/
  25436. X
  25437. X#include <stdio.h>
  25438. X#ifndef unknown_port
  25439. X# ifndef __NeXT__
  25440. X#  include <unistd.h>
  25441. X# else
  25442. X#  include <libc.h>
  25443. X# endif
  25444. X#endif
  25445. X#include <string.h>
  25446. X#include <ctype.h>
  25447. X#include <errno.h>
  25448. X#ifdef unknown_port
  25449. Xextern int errno;
  25450. X#endif
  25451. X#include "defs.h"
  25452. X
  25453. X#define    _SUBSCRIBERS    1
  25454. X#define    _ALIASES    2
  25455. X#define    OTHER        3
  25456. X
  25457. X#ifdef __STDC__
  25458. Xextern  char *tsprintf (char *, ...);
  25459. X#else
  25460. Xextern  char *tsprintf ();
  25461. X#endif
  25462. Xextern  char **alternate_addresses;
  25463. X
  25464. Xextern  void report_progress (FILE *, char *, int);
  25465. Xextern  char *upcase (char *);
  25466. Xextern  int  gexit (int);
  25467. Xextern  int  re_strcmp (char *, char *, char *);
  25468. X
  25469. XBOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
  25470. XBOOLEAN check_file (FILE *, char *, char *, BOOLEAN);
  25471. XBOOLEAN ignore_sender (FILE *, char *, FILE *, BOOLEAN);
  25472. XBOOLEAN owner_listed (char *, char *, char *, FILE *);
  25473. XBOOLEAN host_listed (char *, char *, FILE *);
  25474. Xvoid    check_aliases (char *, char *);
  25475. XBOOLEAN extract_sender (char *);
  25476. XBOOLEAN extract_subscriber (FILE *, char *, BOOLEAN);
  25477. Xvoid    extract_origin (char *);
  25478. Xvoid    extract_address (char *);
  25479. Xvoid    escape_address (char *);
  25480. X
  25481. X/*
  25482. X  Check if 'sender' is subscribed. Return SUBSCRIBED, NEWS, PEER or
  25483. X  NOTSUBSCRIBED. Comparisons are done in upper case.
  25484. X*/
  25485. X
  25486. XBOOLEAN subscribed (FILE *report, char *sender, char *Subscribersf,
  25487. X            char *Newsf, char *Peersf, char *Aliasesf)
  25488. X{
  25489. X  if (!Subscribersf) /* call made by distribute () in listserv.c */
  25490. X    return NOTSUBSCRIBED;
  25491. X  alternate_addresses = NULL;
  25492. X  if (check_file (report, sender, Subscribersf, _SUBSCRIBERS) ||
  25493. X      (check_file (report, sender, Aliasesf, _ALIASES) &&
  25494. X       check_file (report, sender, Subscribersf, _SUBSCRIBERS)))
  25495. X    return SUBSCRIBED;
  25496. X  else if (Newsf &&
  25497. X       (check_file (report, sender, Newsf, OTHER) ||
  25498. X        (check_file (report, sender, Aliasesf, _ALIASES) &&
  25499. X         check_file (report, sender, Newsf, OTHER))))
  25500. X    return NEWS;
  25501. X  else if (Peersf &&
  25502. X       (check_file (report, sender, Peersf, OTHER) ||
  25503. X        (check_file (report, sender, Aliasesf, _ALIASES) &&
  25504. X         check_file (report, sender, Peersf, OTHER))))
  25505. X    return PEER;
  25506. X  return NOTSUBSCRIBED;
  25507. X}
  25508. X
  25509. X/*
  25510. X  Check the given file for subscription. If the file is an aliases file
  25511. X  and the sender is listed in there, store his actual mailing address
  25512. X  in 'sender'.
  25513. X*/
  25514. X
  25515. XBOOLEAN check_file (FILE *report, char *sender, char *file,
  25516. X            BOOLEAN which_file)
  25517. X{
  25518. X  char subscriber [MAX_LINE];
  25519. X  char sender_copy [MAX_LINE];
  25520. X  char mode [MAX_LINE];
  25521. X  char othermode [MAX_LINE];
  25522. X  char name [MAX_LINE];
  25523. X  char *at, *dot;
  25524. X  FILE *f;
  25525. X  int i, nmatches = 0;
  25526. X  extern char password_in_sub_file [];
  25527. X
  25528. X  if (file == NULL || *sender == EOS) /* serverd does not check the aliases files */
  25529. X    return NOTSUBSCRIBED;
  25530. X  OPEN_FILE (f, file, "r", "check_file");
  25531. X  upcase (sender);          /* Convert to upper case */
  25532. X  while (!feof (f)) {  /* Check list of subscribers/peers/news/aliases */
  25533. X    subscriber[0] = mode[0] = othermode[0] = RESET (name);
  25534. X    extract_subscriber (f, subscriber, (which_file == _ALIASES ? TRUE : FALSE));
  25535. X    if (subscriber[0] != EOS) {
  25536. X      fscanf (f, "%s ", mode);
  25537. X      if (which_file == _SUBSCRIBERS) /* Only this file may have more options */
  25538. X        for (i = 1; i < MAX_SET_OPTIONS - 1; i++) {
  25539. X          fscanf (f, "%s ", othermode);
  25540. X      if (i == 1) /* Save user's password */
  25541. X        strcpy (password_in_sub_file, othermode);
  25542. X        }
  25543. X      if (which_file != _ALIASES)
  25544. X        fgets (name, MAX_LINE - 2, f);
  25545. X      upcase (subscriber);
  25546. X      if ((which_file == _ALIASES && re_strcmp (subscriber, sender, mode) > 0)
  25547. X      || (which_file != _ALIASES && !strcmp (subscriber, sender))) {
  25548. X        fclose (f);
  25549. X        if (which_file == _ALIASES)
  25550. X      upcase (mode),
  25551. X      strcpy (sender, mode); /* Note: mode now is address-as-subscribed */
  25552. X        return SUBSCRIBED;
  25553. X      }
  25554. X      strcpy (sender_copy, sender);
  25555. X      if ((at = strchr (sender_copy, '@')) && (dot = strchr (at, '.'))) {
  25556. X    sprintf (at + 1, ".*%s", dot + 1);
  25557. X    if (re_strcmp (sender_copy, subscriber, NULL) > 0) {
  25558. X      if (!alternate_addresses) {
  25559. X        if ((alternate_addresses = (char **) malloc (2 * sizeof (char *)))
  25560. X        == NULL)
  25561. X          report_progress (report, "\ncheck_file(): malloc() failed", TRUE),
  25562. X          gexit (11);
  25563. X      }
  25564. X      else
  25565. X        if ((alternate_addresses = (char **)
  25566. X         realloc ((char **) alternate_addresses,
  25567. X              sizeof (char *) * (nmatches + 2))) == NULL)
  25568. X          report_progress (report, "\ncheck_file(): realloc() failed", TRUE),
  25569. X          gexit (11);
  25570. X      alternate_addresses [nmatches + 1] = NULL;
  25571. X      alternate_addresses [nmatches] = (char *)
  25572. X        malloc ((strlen (subscriber) + 1) * sizeof (char));
  25573. X      strcpy (alternate_addresses [nmatches++], subscriber);
  25574. X    }
  25575. X      }
  25576. X    }
  25577. X  }
  25578. X  fclose (f);
  25579. X  return NOTSUBSCRIBED;
  25580. X}
  25581. X
  25582. X/*
  25583. X  Check if 'sender' appears in the IGNORED file or MESSAGE_IDS.
  25584. X*/
  25585. X
  25586. XBOOLEAN ignore_sender (FILE *ignored, char *sender, FILE *report,
  25587. X               BOOLEAN literal_match)
  25588. X{
  25589. X  char ignored_user [MAX_LINE];
  25590. X  char line[MAX_LINE];
  25591. X
  25592. X  rewind (ignored);
  25593. X  while (!feof (ignored)) { /* Check the IGNORED file first */
  25594. X    line[0] = RESET (ignored_user);
  25595. X    fgets (line, MAX_LINE - 2, ignored);
  25596. X    sscanf (line, "%s", ignored_user);
  25597. X    upcase (ignored_user);
  25598. X    if (ignored_user[0] != EOS) {
  25599. X      if (!literal_match) {
  25600. X    if (re_strcmp (ignored_user, sender, NULL) > 0) {
  25601. X      report_progress (report, tsprintf ("User %s and message ignored.\n",
  25602. X                         sender), FALSE);
  25603. X      return TRUE;
  25604. X    }
  25605. X      }
  25606. X      else if (!strcmp (ignored_user, sender)) {
  25607. X    report_progress (report, tsprintf ("User %s and message ignored.\n",
  25608. X                       sender), FALSE);
  25609. X    return TRUE;
  25610. X      }
  25611. X    }
  25612. X  }
  25613. X  return FALSE;
  25614. X}
  25615. X
  25616. X/*
  25617. X  Check whether the list 'owner' is listed.
  25618. X*/
  25619. X
  25620. XBOOLEAN owner_listed (char *owners, char *owner, char *list, FILE *report)
  25621. X{
  25622. X  char registered_owner [MAX_LINE];
  25623. X  char assigned_list [MAX_LINE];
  25624. X  char line [MAX_LINE];
  25625. X  FILE *f;
  25626. X
  25627. X  OPEN_FILE (f, owners, "r", "owner_listed");
  25628. X  while (!feof (f)) {
  25629. X    line[0] = assigned_list[0] = RESET (registered_owner);
  25630. X    fgets (line, MAX_LINE - 2, f);
  25631. X    sscanf (line, "%s %s", registered_owner, assigned_list);
  25632. X    upcase (registered_owner);
  25633. X    upcase (assigned_list);
  25634. X    if (registered_owner[0] != EOS)
  25635. X      if (!strcmp (registered_owner, owner) && !strcmp (assigned_list, list)) {
  25636. X    fclose (f);
  25637. X    return OWNER;
  25638. X      }
  25639. X  }
  25640. X  fclose (f);
  25641. X  return FALSE;
  25642. X}
  25643. X
  25644. X/*
  25645. X  Check whether the given host appears in a hosts file.
  25646. X*/
  25647. X
  25648. XBOOLEAN host_listed (char *hosts, char *host, FILE *report)
  25649. X{
  25650. X  char _host [MAX_LINE];
  25651. X  FILE* f;
  25652. X
  25653. X  OPEN_FILE (f, hosts, "r", "host_listed");
  25654. X  while (!feof (f)) {
  25655. X    RESET (_host);
  25656. X    fscanf (f, "%s", _host);
  25657. X    upcase (_host);
  25658. X    if (_host[0] == '#') {
  25659. X      fgets (_host, MAX_LINE - 2, f);
  25660. X      continue;
  25661. X    }
  25662. X    if (_host[0] != EOS && re_strcmp (_host, host, NULL) > 0) {
  25663. X      fclose (f);
  25664. X      return TRUE;
  25665. X    }
  25666. X  }
  25667. X  fclose (f);
  25668. X  return FALSE;
  25669. X}
  25670. X
  25671. X/*
  25672. X  Look up 'sender' in the 'aliases' file. If a match is found, use
  25673. X  the alternate address.
  25674. X*/
  25675. X
  25676. Xvoid check_aliases (char *aliases, char *sender)
  25677. X{
  25678. X  char line [MAX_LINE];
  25679. X  char newalias [MAX_LINE];
  25680. X  char alias [MAX_LINE];
  25681. X  FILE *f;
  25682. X
  25683. X  if ((f = fopen (aliases, "r")) == NULL)
  25684. X    return;
  25685. X  upcase (sender);
  25686. X  while (!feof (f)) {
  25687. X    line[0] = alias[0] = RESET (newalias);
  25688. X    fgets (line, MAX_LINE - 2, f);
  25689. X    sscanf (line, "%s %s", alias, newalias);
  25690. X    upcase (alias);
  25691. X    if (alias[0] != EOS)
  25692. X      if (re_strcmp (alias, sender, newalias) > 0)
  25693. X    upcase (newalias),
  25694. X    strcpy (sender, newalias);
  25695. X  }
  25696. X  fclose (f);
  25697. X  return;
  25698. X}
  25699. X
  25700. X/*
  25701. X  Extract the sender's email address. To do that, skip over the leading
  25702. X  "From ". That's where the address starts. Then put an EOS character at
  25703. X  the end of this address (a blank terminates this address string).
  25704. X  Addresses that contain single quotes are treated as invalid (contrary to
  25705. X  RFC 822 specs) since they create problems with the shell.
  25706. X*/
  25707. X
  25708. XBOOLEAN extract_sender (char *s)
  25709. X{
  25710. X  int nsquote = 0, ndquote = 0, nparen = 0, nangle = 0, nsquare = 0;
  25711. X  BOOLEAN done = FALSE, invalid_char = FALSE;
  25712. X  char *r = s;
  25713. X#ifdef DEBUG
  25714. X  char *p = s + strlen (s);
  25715. X#endif
  25716. X
  25717. X  if (strncmp (s, START_OF_MESSAGE, strlen (START_OF_MESSAGE))) {
  25718. X    s [strlen (START_OF_MESSAGE)] = EOS;
  25719. X    return FALSE;
  25720. X  }
  25721. X  sprintf (s, "%s", s + strlen (START_OF_MESSAGE));
  25722. X  while (*s != EOS && !done) { /* Look for end of address substring */
  25723. X    (*s == '`' || *s == '*' || *s == '?' || *s == '|' ? invalid_char = TRUE : 0);
  25724. X/*
  25725. X    (*s == '/' && (s == r || *(s - 1) == ';') ? invalid_char = TRUE : 0);
  25726. X*/
  25727. X    (*s == '\'' ? (nsquote = 1) : 0);
  25728. X    (*s == '\"' ? (s != r ? (*(s - 1) != '\\' ? (ndquote = !ndquote) : 0) :
  25729. X           (ndquote = !ndquote)) : 0);
  25730. X    (*s == '(' ? (!ndquote ? ++nparen : 0) : 0);
  25731. X    (*s == ')' ? (!ndquote ? --nparen : 0) : 0);
  25732. X    (*s == '<' ? (!ndquote ? ++nangle : 0) : 0);
  25733. X    (*s == '>' ? (!ndquote ? --nangle : 0) : 0);
  25734. X    (*s == '[' ? (!ndquote ? ++nsquare : 0): 0);
  25735. X    (*s == ']' ? (!ndquote ? --nsquare : 0) : 0);
  25736. X    (isspace (*s) ?
  25737. X     ((ndquote || nparen || nangle || nsquare) ? 0 : (done = TRUE)) : 0);
  25738. X    ++s;
  25739. X#ifdef DEBUG
  25740. X    if (s > p) { /* Beyond EOS */
  25741. X      extern FILE *report;
  25742. X      report_progress (report, "extract_sender(): memory being overwritten",
  25743. X                       TRUE);
  25744. X    }
  25745. X#endif
  25746. X  }
  25747. X  *(s - 1) = EOS;  /* 's' is now pointing to the sender's address */
  25748. X  if (nsquote || ndquote || nparen || nangle || nsquare || invalid_char)
  25749. X    return FALSE;    /* Error in address */
  25750. X  return TRUE;
  25751. X}
  25752. X
  25753. X/*
  25754. X  Extract the subscriber's address from the file. Addresses that contain
  25755. X  single quotes are treated as invalid (contrary to RFC 822 specs) since they
  25756. X  create problems with the shell.
  25757. X*/
  25758. X
  25759. XBOOLEAN extract_subscriber (FILE *f, char *subscriber, BOOLEAN aliases_file)
  25760. X{
  25761. X  int ndquote = 0, nparen = 0, nangle = 0, nsquare = 0, i = 0;
  25762. X  int nsquote = 0;
  25763. X  BOOLEAN done = FALSE, invalid_char = FALSE;
  25764. X  char c = EOS, pc;
  25765. X
  25766. X  while (!feof (f) && !done && i < MAX_LINE) {
  25767. X    pc = c;
  25768. X    c = fgetc (f);
  25769. X    (c == '`' || c == '*' || c == '?' || c == '|' ? invalid_char = TRUE : 0);
  25770. X/*
  25771. X    (c == '/' && (pc == EOS || pc == ';') ? invalid_char = TRUE : 0);
  25772. X*/
  25773. X    (c == '\'' ? (nsquote = 1) : 0);
  25774. X    (c == '\"' ? (pc != '\\' ? (ndquote = !ndquote) : 0) : 0);
  25775. X    (c == '(' ? (!ndquote ? ++nparen : 0) : 0);
  25776. X    (c == ')' ? (!ndquote ? --nparen : 0) : 0);
  25777. X    (c == '<' ? (!ndquote ? ++nangle : 0) : 0);
  25778. X    (c == '>' ? (!ndquote ? --nangle : 0) : 0);
  25779. X    (c == '[' ? (!ndquote ? ++nsquare : 0): 0);
  25780. X    (c == ']' ? (!ndquote ? --nsquare : 0) : 0);
  25781. X    (isspace (c) ?
  25782. X     ((!aliases_file && (ndquote || nparen || nangle || nsquare)) ? 0 
  25783. X      : (done = TRUE)) : 0);
  25784. X    subscriber [i++] = c;
  25785. X  }
  25786. X  if (i > 0)
  25787. X    subscriber [i - 1] = EOS;
  25788. X  if (!aliases_file &&
  25789. X      (nsquote || ndquote || nparen || nangle || nsquare || invalid_char))
  25790. X    return FALSE;    /* Error in address */
  25791. X  return TRUE;
  25792. X}
  25793. X
  25794. X/*
  25795. X  Extract the originator of the message, i.e. the list that the original
  25796. X  message first originated from.
  25797. X*/
  25798. X
  25799. Xvoid extract_origin (char *s)
  25800. X{
  25801. X  char *p;
  25802. X
  25803. X  if (p = strchr (s, '<'))
  25804. X    sprintf (s, "%s", p + 1); /* Remove '<' */
  25805. X  if (p = strchr (s, '>'))
  25806. X    *p = EOS;  /* Remove '>' */
  25807. X  else {  /* Get to the end of the address */
  25808. X    while (*s != EOS && !isspace (*s))
  25809. X      ++s;
  25810. X    *s = EOS;
  25811. X  }
  25812. X}
  25813. X
  25814. X/*
  25815. X  Given an RFC 822 From: line address, strip comments etc. and extract
  25816. X  the actual address.
  25817. X*/
  25818. X
  25819. Xvoid extract_address (char *s)
  25820. X{
  25821. X  char *p;
  25822. X
  25823. X  if (p = strchr (s, '<'))
  25824. X    sprintf (s, "%s", p + 1); /* Remove '<' */
  25825. X  if (*s == '|' || *s == ':')
  25826. X    *s = EOS;  /* Protect against trojans */
  25827. X  if (p = strchr (s, '>'))
  25828. X    *p = EOS;  /* Remove '>' */
  25829. X  if (p = strchr (s, '('))
  25830. X    *p = EOS; /* Remove comments */
  25831. X  else {  /* Get to the end of the address */
  25832. X    while (*s != EOS && !isspace (*s))
  25833. X      ++s;
  25834. X    *s = EOS;
  25835. X  }
  25836. X}
  25837. X
  25838. X/*
  25839. X  Scan 's' and escape the following characters:
  25840. X  ( ) [ ] < > { } \ : ; ' ` . ^ $ *
  25841. X*/
  25842. X
  25843. Xvoid escape_address (char *s)
  25844. X{
  25845. X  char *r;
  25846. X
  25847. X  while (*s != EOS) {
  25848. X    switch (*s) {
  25849. X    case '(': case ')': case '[': case ']': case '<': case '>': case '\\':
  25850. X    case ':': case ';': case '\'': case '`': case '.': case '^':
  25851. X    case '$': case '*': case '{': case '}':
  25852. X      r = s + strlen (s);    /* Start from the end */
  25853. X      while (r != s)
  25854. X        *(r + 1) = *r,
  25855. X    --r;
  25856. X      *(r + 1) = *r;
  25857. X      *r = '\\';
  25858. X      ++s;
  25859. X      break;
  25860. X    }
  25861. X    ++s;
  25862. X  }
  25863. X}
  25864. *-*-END-of-src/sender.c-*-*
  25865. echo x - src/serverd.c
  25866. sed 's/^X//' >src/serverd.c <<'*-*-END-of-src/serverd.c-*-*'
  25867. X/*
  25868. X  ----------------------------------------------------------------------------
  25869. X  |                      UNIX LISTSERVER SYSTEM DAEMON                 |
  25870. X  |                                                                          |
  25871. X  |                               Version 5.0                                |
  25872. X  |                                                                          |
  25873. X  |                (or, when Computer Science gets to you)                   |
  25874. X  |                                                                          |
  25875. X  |                    Written by Anastasios Kotsikonas                      |
  25876. X  |                           (tasos@cs.bu.edu)                              |
  25877. X  |                                                                          |
  25878. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  25879. X  | whole and not in parts, as long as you do not remove or alter the author |
  25880. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  25881. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  25882. X  | provided for your personal use, you you may not alter the functions      |
  25883. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  25884. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  25885. X  | any changes you may have made. No part of the source code bearing a         |
  25886. X  | copyright notice can be included in commercial software systems without  |
  25887. X  | written permission by the author.                         |
  25888. X  | By using this software you are bound by this agreement.             |
  25889. X  | This software comes with no warranties and cannot be sold for profit.    |
  25890. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  25891. X  | files when distributing this software.                                   |
  25892. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  25893. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  25894. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  25895. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  25896. X  | (ii).                                                                    |
  25897. X  |                                                                          |
  25898. X  | Enhanced by: Warren Burstein.                                            |
  25899. X  ----------------------------------------------------------------------------
  25900. X
  25901. X  Spawn list or listserv upon arrival of new messages. Send mail to
  25902. X  MANAGER if something went wrong (only if using UCB mail).
  25903. X  serverd will not spawn if the current load average is above max_load
  25904. X  and the -l flag is on, until it has delayed MAX_TRIES * 30 seconds.
  25905. X  serverd communicates with listerv via exit statuses 6 and 7; these are
  25906. X  the requests to shutdown/restart the system; on status 7, serverd spawns
  25907. X  start and dies; if it cannot restart, it sends mail and commits suicide.
  25908. X  serverd reports to REPORT_SERVERD.
  25909. X
  25910. X  The server may also run in interactive mode and listen for TCP connections
  25911. X  at a specified port. Users are able of entering requests and getting replies
  25912. X  live. For this, a separate listener process is spawned which accepts or
  25913. X  rejects the connections, then it in turn forks off children to handle
  25914. X  accepted connections.
  25915. X
  25916. X        Master process    (looks for email requests/messages)
  25917. X               |
  25918. X            Listener    (accepts or rejects connection requests)
  25919. X               |
  25920. X              /|\
  25921. X            children    (process live requests)
  25922. X
  25923. X  If the Master process dies in any way but a SIGKILL signal, then all
  25924. X  processes abort. If the Listener process dies (including a SIGKILL signal),
  25925. X  all processes abort as well. If the Master is killed with SIGKILL, behavior
  25926. X  will be undefined and a semaphore will be left unused in the system (use
  25927. X  ipcrm to remove it). If any of the children die abnormally (including a
  25928. X  SIGKILL signal) the Listener process will report to that effect; however,
  25929. X  the connection will remain "open" on the other end until it times out
  25930. X  locally.
  25931. X
  25932. X  A "restart" or "shutdown" request (live or not) will kill all processes and
  25933. X  in the case of "restart", a new Master and Listener will be created.
  25934. X
  25935. X  Synchronization between all processes is done via a semaphore. Removing or
  25936. X  altering the semaphore while the system is running will bring the system
  25937. X  down.
  25938. X
  25939. X  COMMAND LINE OPTIONS:
  25940. X    -1: Execute only once -- to be used with cron.
  25941. X    -l: Enforce restrictions based on the current load average.
  25942. X    -e: Echo reports to the screen.
  25943. X    -i: Interactive server; it listens for tcp connections. The argument
  25944. X    that follows is the maximum duration (in seconds) of each connection.
  25945. X
  25946. X  EXIT CODES:
  25947. X    0: OK
  25948. X    1: Could not open or lock file
  25949. X    2: SIGINT signal
  25950. X    3: Command line option error
  25951. X    4: Syntax error in file
  25952. X    5: Could not spawn
  25953. X    6: Shutdown request
  25954. X    7: Restart request
  25955. X    8: Received system signal
  25956. X    9: Too many multiple recipients
  25957. X   10: Could not deliver mail
  25958. X   11: Malloc failed
  25959. X   12: Cannot fork
  25960. X   13: Socket connection problem
  25961. X   14: Semaphore error
  25962. X   15: Cannot setuid, setgid
  25963. X   16: Internal error
  25964. X
  25965. X*/
  25966. X
  25967. X#include <stdio.h>
  25968. X#ifdef SYSLOG
  25969. X# ifdef ultrix
  25970. X#  include <sys/syslog.h>
  25971. X# else
  25972. X#  include <syslog.h>
  25973. X# endif
  25974. X#endif
  25975. X#ifndef unknown_port
  25976. X# ifndef __NeXT__
  25977. X#  include <unistd.h>
  25978. X# else
  25979. X#  include <libc.h>
  25980. X# endif
  25981. X#endif
  25982. X#include <sys/types.h>
  25983. X#if defined (stardent) || defined (stellar) || defined (titan)
  25984. X# include <rpc/types.h>
  25985. X#endif
  25986. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  25987. X && !defined (sequent) && !defined (unknown_port)
  25988. X# include <malloc.h>
  25989. X#endif
  25990. X#include <sys/stat.h>
  25991. X#include <signal.h>
  25992. X#include <fcntl.h>
  25993. X#include <time.h>
  25994. X#include <ctype.h>
  25995. X#include <string.h>
  25996. X#include <errno.h>
  25997. X#ifdef unknown_port
  25998. Xextern int errno;
  25999. X#endif
  26000. X#include <math.h>
  26001. X#include <sys/wait.h>
  26002. X#if !defined (sequent) && !defined (__NeXT__) && !defined (__convex__) && \
  26003. X !defined (apollo) && !defined (i386) && !defined (unknown_port)
  26004. X# include <sys/termio.h>
  26005. X#endif
  26006. X#ifndef sun
  26007. X# include <sys/ioctl.h>
  26008. X#endif
  26009. X#include "defs.h"
  26010. X#include "serverd.h"
  26011. X#include "struct.h"
  26012. X#include "global.h"
  26013. X#if defined (__NeXT__) || defined (unknown_port)
  26014. X# include "next.h"
  26015. X#endif
  26016. X
  26017. X#ifdef GO_INTERACTIVE
  26018. X# include <sys/socket.h>
  26019. X# ifndef stellar
  26020. X#  include <sys/time.h>
  26021. X# endif
  26022. X# include <netinet/in.h>
  26023. X# include <netdb.h>
  26024. X# include <sys/ipc.h>
  26025. X# include <sys/sem.h>
  26026. X# include <pwd.h>
  26027. X#endif
  26028. X
  26029. X#ifdef __STDC__
  26030. X# include <stdarg.h>
  26031. Xextern int  syscom (char *, ...);
  26032. Xextern char *tsprintf (char *, ...);
  26033. X#else
  26034. X# include <varargs.h>
  26035. Xextern int  syscom ();
  26036. Xextern char *tsprintf ();
  26037. X#endif
  26038. X
  26039. X#if !defined (__NeXT__) && !defined (__osf__) && !defined (_AIX)
  26040. Xextern double atof ();
  26041. Xextern long int atoi (char *);
  26042. X#else
  26043. Xextern int atoi (const char *);
  26044. X#endif
  26045. Xextern int  sys_config (FILE *, SYS *);
  26046. Xextern int  _getopt (int, char **, char *);
  26047. Xextern void setup_string (char *, char *, char *);
  26048. Xextern void init_signals (void);
  26049. Xextern void catch_signals (void);
  26050. Xextern void report_progress (FILE *, char *, int);
  26051. Xextern int  lock_file (char *, int, int, BOOLEAN);
  26052. Xextern void unlock_file (int);
  26053. Xextern void clean_request (char *);
  26054. Xextern char *upcase (char *);
  26055. Xextern BOOLEAN owner_listed (char *, char *, char *, FILE *);
  26056. Xextern BOOLEAN host_listed (char *, char *, FILE *);
  26057. Xextern BOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
  26058. Xextern int long write_to_fd (int, char *, long int);
  26059. Xextern int otoi (char *);
  26060. Xextern char *_strstr (char *, char *);
  26061. Xextern void my_abort (int);
  26062. Xextern int echo (char *, char *);
  26063. Xextern int cat_append (char *, char *);
  26064. Xextern int re_strcmp (char *, char *, char *);
  26065. Xextern int insert_word (char *, char **, int, int, int);
  26066. Xextern char *mystrdup (char *);
  26067. Xextern int semtran (int);
  26068. Xextern int P (int);
  26069. Xextern int V (int);
  26070. Xextern void semremove (int);
  26071. X
  26072. X
  26073. Xvoid   main (int, char **, char **);
  26074. Xvoid   serverd_config (void);
  26075. Xvoid   usage (void);
  26076. Xint    gexit (int);
  26077. Xvoid   load_wait (float);
  26078. Xvoid   run_program (char *, BOOLEAN, int);
  26079. X#ifdef GO_INTERACTIVE
  26080. Xvoid   sighandle (int);
  26081. Xvoid   listener_exited (void);
  26082. Xvoid   close_connection (int);
  26083. Xint    check_timeout (CLIENT []);
  26084. Xint    create_connection (void);
  26085. Xvoid   process_live_request (int, struct sockaddr_in);
  26086. XBOOLEAN check_for_redirection (char *, char *, int *, int, BOOLEAN, BOOLEAN);
  26087. XBOOLEAN writeable_file (char *, int, BOOLEAN);
  26088. XBOOLEAN child_alive (int, CLIENT []);
  26089. X#endif
  26090. X
  26091. X
  26092. Xvoid main (int argc, char **argv, char **envp)
  26093. X{
  26094. X  struct stat stat_buf;
  26095. X  int rlfd = 2;
  26096. X  FILE *f, *fp;
  26097. X  float max_load;
  26098. X  BOOLEAN loadr = FALSE, execute_once = FALSE;
  26099. X  char list [MAX_LINE];
  26100. X  char server [MAX_LINE];
  26101. X  char msg [4096];
  26102. X  char *mask;
  26103. X  int c;
  26104. X#ifdef GO_INTERACTIVE
  26105. X  char *options = "1l:i:e", *s, reply [MAX_LINE], version [MAX_LINE], *ch;
  26106. X  char welcome [65536];
  26107. X  int connid = 0, port, l, pid, _nforks;
  26108. X  struct sockaddr_in client;
  26109. X  struct hostent *hp;
  26110. X  union semun {
  26111. X    int val;
  26112. X    struct semid_ds *buf;
  26113. X    ushort *array;
  26114. X  } sembuf;
  26115. X  int smask;
  26116. X#else
  26117. X  char *options = "1l:e";
  26118. X#endif
  26119. X  long int time_is = 0, current_date = -1, new_date, time_then = 0;
  26120. X  struct tm *t;
  26121. X  extern char *optarg, *getenv();
  26122. X  extern int optopt;
  26123. X  int i;
  26124. X
  26125. X  prog = argv[0];
  26126. X  while ((c = _getopt (argc, argv, options)) != EOF)
  26127. X    switch ((char) c) {
  26128. X      case '1': execute_once = TRUE; break;
  26129. X      case 'e': tty_echo = TRUE; break;
  26130. X      case 'l': loadr = TRUE; 
  26131. X        max_load = (float) atof (optarg); 
  26132. X        break;
  26133. X#ifdef GO_INTERACTIVE
  26134. X      case 'i':
  26135. X    interactive = TRUE;
  26136. X    if ((conn_duration = atoi (optarg)) <= 0)
  26137. X      fprintf (stderr, "-i %d ???\n", conn_duration),
  26138. X      exit (3);
  26139. X    break;
  26140. X#endif
  26141. X      case ':': 
  26142. X        fprintf (stderr, "serverd:  Option '%c' requires an argument.\n",
  26143. X         optopt);
  26144. X    exit (3);
  26145. X      case '?':
  26146. X      default:
  26147. X    usage ();
  26148. X    }
  26149. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  26150. X    umask (otoi (mask));
  26151. X  else
  26152. X    mask = "066",
  26153. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  26154. X#ifndef NO_LOCKS
  26155. X  if ((lfd = lock_file (SERVERD_LOCK_FILE, O_RDWR, 0, FALSE)) < 0)
  26156. X    fprintf (stderr, "serverd: Unable to lock %s. Aborting.\n", 
  26157. X             SERVERD_LOCK_FILE),
  26158. X    exit (2);
  26159. X#endif
  26160. X#ifdef SYSLOG
  26161. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  26162. X# ifndef i386
  26163. X       |LOG_NOWAIT
  26164. X# endif
  26165. X       , SYSLOG);
  26166. X# ifndef ultrix
  26167. X  setlogmask (LOG_UPTO (LOG_INFO));
  26168. X# endif
  26169. X#else
  26170. X  if ((report = fopen (REPORT_SERVERD, "a")) == NULL)
  26171. X    fprintf (stderr, "serverd: Could not open %s\n", REPORT_SERVERD),
  26172. X    exit (1);
  26173. X  chmod (REPORT_SERVERD, 384);
  26174. X  fprintf (report, "%s", COPYRIGHT);
  26175. X  fflush (report);
  26176. X#endif
  26177. X
  26178. X#ifdef GO_INTERACTIVE
  26179. X  if ((pwentry = getpwuid (getuid ())) == NULL)
  26180. X    report_progress (report, "main(): Invalid user account", TRUE),
  26181. X    exit (3);
  26182. X# ifndef SYSLOG
  26183. X  if (chown (REPORT_SERVERD, pwentry->pw_uid, pwentry->pw_gid))
  26184. X    report_progress (report, "\nmain(): Cannot chown()", TRUE),
  26185. X    exit (15);
  26186. X# endif
  26187. X#endif
  26188. X  if ((f = fopen (PID_SERVERD, "w")) != NULL)
  26189. X    fprintf (f, "%d", getpid()),
  26190. X    fclose (f)
  26191. X#ifdef GO_INTERACTIVE
  26192. X    ,chown (PID_SERVERD, pwentry->pw_uid, pwentry->pw_gid);
  26193. X#else
  26194. X    ;
  26195. X#endif
  26196. X
  26197. X  signal (SIGINT, (void (*)()) gexit);
  26198. X#ifdef GO_INTERACTIVE
  26199. X# if defined (bsd)
  26200. X  sigsetmask (0);
  26201. X# elif defined (svr3) || defined (svr4)
  26202. X#  ifdef SIGCLD
  26203. X  sigrelse (SIGCLD);
  26204. X#  else
  26205. X  sigrelse (SIGCHLD);
  26206. X#  endif
  26207. X# endif
  26208. X# ifdef SIGCLD
  26209. X  signal (SIGCLD, (void (*)()) sighandle);
  26210. X# else
  26211. X  signal (SIGCHLD, (void (*)()) sighandle);
  26212. X# endif
  26213. X  signal (ABORT_SIG, (void (*)()) listener_exited);
  26214. X#endif
  26215. X  init_signals();
  26216. X  catch_signals ();
  26217. X
  26218. X  time (&time_is);
  26219. X
  26220. X  nlists = sys_config (report, &sys);
  26221. X  if (sys.fax.prog[0] == EOS)
  26222. X    strcat (sys.server.cmdoptions, " -d fax");
  26223. X#if defined (TIOCNOTTY) && defined (SIGTTOU) && defined (SIGTTIN)
  26224. X  if (!tty_echo)
  26225. X    if ((i = open ("/dev/tty", 2)) >=0)
  26226. X      ioctl (i, TIOCNOTTY, 0),
  26227. X      close (i);
  26228. X#endif
  26229. X
  26230. X  ppid = getpid ();
  26231. X#ifdef GO_INTERACTIVE
  26232. X  if (interactive) { /* Spawn Listener process */
  26233. X    if ((sid = semtran (0)) < 0)    /* Get semaphore id */
  26234. X      report_progress (report, "\nmain(): Cannot get semaphore", TRUE),
  26235. X      exit (14);
  26236. X    if ((sembuf.buf = (struct semid_ds *) malloc (sizeof (struct semid_ds))) ==
  26237. X    NULL)
  26238. X      report_progress (report, "\nmain(): malloc() failed", TRUE),
  26239. X      exit (11);
  26240. X    sembuf.buf->sem_perm.uid = pwentry->pw_uid;
  26241. X    sembuf.buf->sem_perm.gid = pwentry->pw_gid;
  26242. X    sembuf.buf->sem_perm.mode = 0700;
  26243. X    if (semctl (sid, 1, IPC_SET, sembuf)) /* Change owner to server */
  26244. X      report_progress (report, "\nmain(): Cannot semctl (sid)", TRUE),
  26245. X      exit (14);
  26246. X    free ((struct semid_ds *) sembuf.buf);
  26247. X
  26248. X    if (getuid () & geteuid ())
  26249. X      report_progress (report, "WARNING: serverd not started with root \
  26250. Xprivileges", TRUE);
  26251. X    if ((chpid = fork()) < 0)
  26252. X      report_progress (report, "\nmain(): Master process cannot fork Listener \
  26253. Xprocess", TRUE),
  26254. X      exit (12);
  26255. X    else if (chpid == 0) { /* Child process */
  26256. X      chpid = getpid ();   /* Set for signal handling purposes */
  26257. X      signal (SIGINT, (void (*)()) sighandle);
  26258. X# ifdef SIGCLD
  26259. X      signal (SIGCLD, (void (*)()) sighandle);
  26260. X# else
  26261. X      signal (SIGCHLD, (void (*)()) sighandle);
  26262. X# endif
  26263. X      signal (SIGTERM, (void (*)()) sighandle);
  26264. X      signal (SIGSEGV, (void (*)()) sighandle);
  26265. X      signal (SIGILL, (void (*)()) sighandle);
  26266. X      signal (SIGQUIT, (void (*)()) sighandle);
  26267. X      signal (SIGBUS, (void (*)()) sighandle);
  26268. X      strcpy (version, VERSION);
  26269. X      ch = strchr (version, ' ');
  26270. X      *ch = EOS;
  26271. X
  26272. X      if ((sock_fd = create_connection ()) < 0)
  26273. X    report_progress (report, "\nmain(): Listener process cannot create \
  26274. Xconnection", TRUE),
  26275. X    kill (ppid, ABORT_SIG),
  26276. X    exit (13);
  26277. X      if (setuid (pwentry->pw_uid) || setgid (pwentry->pw_gid))
  26278. X    report_progress (report, "\nmain(): Listener process cannot \
  26279. Xsetuid()/setgid()", TRUE),
  26280. X    kill (ppid, ABORT_SIG),
  26281. X    exit (15);
  26282. X      while (007) { /* Listen for ever */
  26283. X
  26284. X    l = sizeof (client);
  26285. X    if ((msg_sock = accept (sock_fd, (struct sockaddr *) &client,
  26286. X                (int *) &l)) < 0) {
  26287. X      if (errno != EINTR
  26288. X#ifdef ERESTART
  26289. X          && errno != ERESTART
  26290. X#endif
  26291. X          )
  26292. X        report_progress (report, "\nmain(): Listener process cannot accept()",
  26293. X                 TRUE),
  26294. X        kill (ppid, ABORT_SIG),
  26295. X        exit (13);
  26296. X      continue;
  26297. X    }
  26298. X    else { /* New client; see if we can handle it */
  26299. X      hp = gethostbyaddr ((char *) &client.sin_addr,
  26300. X                  sizeof (struct in_addr), client.sin_family);
  26301. X      report_progress (report,
  26302. X               tsprintf ("Connection request from %s: ",
  26303. X                     upcase ((s = (hp ? hp->h_name :
  26304. X                           (char *) inet_ntoa (client.sin_addr))))),
  26305. X               FALSE);
  26306. X      if (!stat (PRIVILEGED_HOSTSF, &stat_buf))
  26307. X        if (!host_listed (PRIVILEGED_HOSTSF, s, report)) {
  26308. X          CANNOT_CONNECT ("not a privileged host", CONN_ABORTED,
  26309. X                  "Not a privileged host.\n");
  26310. X          continue;
  26311. X        }
  26312. X      if (host_listed (UNWANTED_HOSTSF, s, report)) {
  26313. X        CANNOT_CONNECT ("unwanted host", CONN_ABORTED,
  26314. X                "Not a privileged host.\n");
  26315. X        continue;
  26316. X      }
  26317. X
  26318. X      if (nforks < 0 || nforks > MAX_CONNECTIONS)
  26319. X        report_progress (report, tsprintf ("\nmain(): Listener process: \
  26320. Xinternal error: nforks=%d", nforks), TRUE),
  26321. X        kill (ppid, ABORT_SIG),
  26322. X        exit (16);
  26323. X      if (nforks + 1 > MAX_CONNECTIONS) { /* Too many connections */
  26324. X        if ((pid = check_timeout (clients)) > 0) {
  26325. X          IN_CRITICAL_SECTION ("main", 0);
  26326. X          kill (pid, TIMEOUT_SIG);    /* Tell it to commit suicide */
  26327. X          while (child_alive (pid, clients)); /* Wait */
  26328. X          OUT_OF_CRITICAL_SECTION ("main");
  26329. X        }
  26330. X        else { /* No children have timed out, so tough */
  26331. X          CANNOT_CONNECT ("refused", SERVER_BUSY, SERVER_BUSY_);
  26332. X          continue;
  26333. X        }
  26334. X      }
  26335. X      report_progress (report, tsprintf ("connected (client #%d)", connid),
  26336. X               TRUE);
  26337. X      /* Parent increments the number of times it has forked */
  26338. X      _nforks = nforks;
  26339. X      clients [nforks].time = time (0); /* Save time child spawned */
  26340. X      clients [nforks].connid = connid++;
  26341. X      strcpy (clients [nforks++].name,
  26342. X          (hp ? hp->h_name : (char *) inet_ntoa (client.sin_addr)));
  26343. X# if defined (bsd)
  26344. X#  ifdef SIGCLD
  26345. X      smask = sigblock (sigmask (SIGCLD));
  26346. X#  else
  26347. X      smask = sigblock (sigmask (SIGCHLD));
  26348. X#  endif
  26349. X# elif defined (svr4) || defined (svr3)
  26350. X#  ifdef SIGCLD
  26351. X      sighold (SIGCLD);
  26352. X#  else
  26353. X      sighold (SIGCHLD);
  26354. X#  endif
  26355. X# endif
  26356. X      if ((pid = fork ()) < 0) {    /* fork */
  26357. X        CANNOT_CONNECT ("cannot fork", SYS_ERROR, "Remote system error.\n");
  26358. X# if defined (bsd)
  26359. X        sigsetmask (smask);
  26360. X# elif defined (svr3) || defined (svr4)
  26361. X#  ifdef SIGCLD
  26362. X        sigrelse (SIGCLD);
  26363. X#  else
  26364. X        sigrelse (SIGCHLD);
  26365. X#  endif
  26366. X# endif
  26367. X        continue;
  26368. X      }
  26369. X      else if (pid == 0) {        /* Child process */
  26370. X        close (sock_fd);    /* Close unused parent socket */
  26371. X# ifdef SIGCLD
  26372. X        signal (SIGCLD, SIG_DFL);
  26373. X# else
  26374. X        signal (SIGCHLD, SIG_DFL);
  26375. X# endif
  26376. X        signal (TIMEOUT_SIG, (void (*)()) close_connection);
  26377. X        signal (ABORT_SIG, (void (*)()) close_connection);
  26378. X        signal (SIGALRM, (void (*)()) close_connection);
  26379. X        signal (SIGPIPE, (void (*)()) close_connection);
  26380. X        signal (SIGINT, (void (*)()) SIG_IGN);
  26381. X        signal (SIGTERM, (void (*)()) close_connection);
  26382. X        signal (SIGSEGV, (void (*)()) close_connection);
  26383. X        signal (SIGILL, (void (*)()) close_connection);
  26384. X        signal (SIGQUIT, (void (*)()) close_connection);
  26385. X        signal (SIGBUS, (void (*)()) close_connection);
  26386. X        alarm (conn_duration);
  26387. X        time_is = time (0);
  26388. X        sprintf (welcome, "%s interactive UNIX ListServer.\nVersion %s %s\
  26389. XMaximum connection duration is %d seconds.\n",
  26390. X             sys.organization, version, ctime (&time_is),
  26391. X             conn_duration);
  26392. X        if ((f = fopen (WELCOMEF, "r"))) {
  26393. X          while (!feof (f))
  26394. X        fgets (welcome + strlen (welcome), MAX_LINE, f);
  26395. X          fclose (f);
  26396. X        }
  26397. X        sprintf (msg, "%d %d %s %d %d\n%d %d \n\n%s", CONNECT,
  26398. X                       conn_duration, version, strlen (PROMPT),
  26399. X                       strlen (CONT_PROMPT), OK,
  26400. X                       strlen (welcome) +
  26401. X                       strlen (LOGIN) + 1, welcome);
  26402. X        if (write_to_fd (msg_sock, msg, strlen (msg)) < 0)
  26403. X          CLIENT_LOST (13);
  26404. X        process_live_request (msg_sock, client);
  26405. X      }
  26406. X      else
  26407. X        clients [_nforks].pid = pid,
  26408. X# if defined (bsd)
  26409. X        sigsetmask (smask),
  26410. X# elif defined (svr3) || defined (svr4)
  26411. X#  ifdef SIGCLD
  26412. X        sigrelse (SIGCLD),
  26413. X#  else
  26414. X        sigrelse (SIGCHLD),
  26415. X#  endif
  26416. X# endif
  26417. X        close (msg_sock);
  26418. X    }
  26419. X      }
  26420. X    }
  26421. X  }
  26422. X#endif
  26423. X
  26424. X#ifdef GO_INTERACTIVE
  26425. X  if (setuid (pwentry->pw_uid) || setgid (pwentry->pw_gid))
  26426. X    report_progress (report, "\nmain(): Master process cannot \
  26427. Xsetuid()/setgid()", TRUE),
  26428. X    gexit (15);
  26429. X#endif
  26430. X
  26431. X  serverd_config ();
  26432. X  while (007) {
  26433. X    for (i = 0; i < nlists; ++i) {
  26434. X
  26435. X      if (!stat (lists[i].list_mail_f, &stat_buf) && stat_buf.st_size > 0 &&
  26436. X      (rlfd = lock_file (lists[i].list_mail_f, O_RDWR, 0, FALSE)) >= 0) {
  26437. X    unlock_file (rlfd);
  26438. X
  26439. X    if (sys.lists[i].max_messages) {
  26440. X      time (&time_is);
  26441. X      t = localtime (&time_is);
  26442. X      new_date = t->tm_mon + 1 + t->tm_mday + t->tm_year;
  26443. X      if (new_date != lists[i].current_date)
  26444. X        lists[i].nmessages = 0,
  26445. X        lists[i].done_for_the_day = FALSE,
  26446. X        lists[i].current_date = new_date,
  26447. X        echo (tsprintf ("0 %d %d %d", t->tm_mon + 1, t->tm_mday,
  26448. X                t->tm_year),
  26449. X          lists[i].list_limitsf);
  26450. X      if (!lists[i].done_for_the_day) {
  26451. X        if ((f = fopen (lists[i].list_limitsf, "r"))) {
  26452. X          fscanf (f, "%d", &lists[i].nmessages);
  26453. X          fclose (f);
  26454. X        }
  26455. X        if (lists[i].nmessages >= sys.lists[i].max_messages) {
  26456. X          lists[i].done_for_the_day = TRUE;
  26457. X          lists[i].nmessages = 0;
  26458. X          goto xxx;
  26459. X        }
  26460. X      }
  26461. X      else
  26462. X        goto xxx;
  26463. X    }
  26464. X
  26465. X    report_progress (report, tsprintf ("\n--- NEW MAIL FOR %s ---\n",
  26466. X                       sys.lists[i].alias), FALSE);
  26467. X
  26468. X    if (loadr) /* enforce restrictions */
  26469. X      load_wait (max_load);
  26470. X
  26471. X    RESET (list);
  26472. X    sprintf (list, "%s %s %s", LIST, sys.lists[i].alias,
  26473. X         sys.lists[i].cmdoptions);
  26474. X#ifdef GO_INTERACTIVE
  26475. X    IN_CRITICAL_SECTION ("main", 0);
  26476. X#endif
  26477. X    run_program (list, FALSE, -1);
  26478. X#ifdef GO_INTERACTIVE
  26479. X    OUT_OF_CRITICAL_SECTION ("main");
  26480. X#endif
  26481. X      xxx: ;
  26482. X      }
  26483. X/*
  26484. X      if (sys.frequency > 0)
  26485. X        sleep (sys.frequency);     do a quickie to The Spy Who Loved Him
  26486. X*/
  26487. X      if (!stat (lists[i].digest_msgf, &stat_buf) && stat_buf.st_size > 0) {
  26488. X        /*
  26489. X       Something in the digest message file, see how long it's been
  26490. X       since last message was sent by reading digest_timef.
  26491. X        */
  26492. X        if (fp = fopen (lists[i].digest_timef, "r"))
  26493. X      fscanf (fp, "%ld\n", &time_then),
  26494. X      fclose (fp);
  26495. X        if ((time(0) - time_then) / 3600 >= sys.lists[i].digest_hours) {
  26496. X      report_progress (report,
  26497. X               tsprintf ("\n--- DIGEST TIME REACHED FOR %s ---\n",
  26498. X                     sys.lists[i].alias), FALSE);
  26499. X
  26500. X          if (loadr)
  26501. X        load_wait (max_load);
  26502. X
  26503. X          RESET (list);
  26504. X          sprintf (list, "%s %s %s -d", LIST, sys.lists[i].alias,
  26505. X               sys.lists[i].cmdoptions);
  26506. X#ifdef GO_INTERACTIVE
  26507. X      IN_CRITICAL_SECTION ("main", 0);
  26508. X#endif
  26509. X          run_program (list, FALSE, -1);
  26510. X#ifdef GO_INTERACTIVE
  26511. X      OUT_OF_CRITICAL_SECTION ("main");
  26512. X#endif
  26513. X        }
  26514. X      }
  26515. X    }
  26516. X
  26517. X    if (!stat (BATCH_FILE, &stat_buf) && stat_buf.st_size > 0) {
  26518. X      time (&time_is);
  26519. X      t = localtime (&time_is);
  26520. X      new_date = t->tm_mon + 1 + t->tm_mday + t->tm_year;
  26521. X      if (new_date != current_date) { /* Process batch on new day only */
  26522. X    current_date = new_date; /* New day or first time through loop */
  26523. X    report_progress (report, "\n--- PROCESSING THE BATCH QUEUE ---\n",
  26524. X             FALSE);
  26525. X    RESET (server);
  26526. X    sprintf (server, "%s %s -B", SERVER, sys.server.cmdoptions);
  26527. X#ifdef GO_INTERACTIVE
  26528. X    IN_CRITICAL_SECTION ("main", 0);
  26529. X#endif
  26530. X    run_program (server, TRUE, -1);
  26531. X#ifdef GO_INTERACTIVE
  26532. X    OUT_OF_CRITICAL_SECTION ("main");
  26533. X#endif
  26534. X      }
  26535. X    }
  26536. X
  26537. X    if (!stat (SERVER_MAIL_FILE, &stat_buf) && stat_buf.st_size > 0 &&
  26538. X    (rlfd = lock_file (SERVER_MAIL_FILE, O_RDWR, 0, FALSE)) >= 0) {
  26539. X      unlock_file (rlfd);
  26540. X
  26541. X      time (&time_is);
  26542. X      t = localtime (&time_is);
  26543. X      new_date = t->tm_mon + 1 + t->tm_mday + t->tm_year;
  26544. X      current_date = new_date; /* New day or first time through loop */
  26545. X      report_progress (report, "\n--- NEW MAIL FOR SERVER ---\n", FALSE);
  26546. X
  26547. X      if (loadr) /* Enforce restrictions */
  26548. X    load_wait (max_load);
  26549. X
  26550. X      RESET (server);
  26551. X      sprintf (server, "%s %s", SERVER, sys.server.cmdoptions);
  26552. X#ifdef GO_INTERACTIVE
  26553. X      IN_CRITICAL_SECTION ("main", 0);
  26554. X#endif
  26555. X      run_program (server, TRUE, -1);
  26556. X#ifdef GO_INTERACTIVE
  26557. X      OUT_OF_CRITICAL_SECTION ("main");
  26558. X#endif
  26559. X    }
  26560. X
  26561. X    if (execute_once)
  26562. X      gexit (0);
  26563. X    if (sys.frequency > 0)
  26564. X      sleep (sys.frequency);     /* do a quickie to Money Penny */
  26565. X  }
  26566. X}
  26567. X
  26568. Xvoid serverd_config ()
  26569. X{
  26570. X  int i, mon, day, year;
  26571. X  FILE *f;
  26572. X
  26573. X  for (i = 0; i < nlists; ++i) {
  26574. X    setup_string (lists[i].list_mail_f, sys.lists[i].alias, LIST_MAIL_FILE);
  26575. X    setup_string (lists[i].digest_msgf, sys.lists[i].alias, DIGEST_MSG);
  26576. X    setup_string (lists[i].digest_timef, sys.lists[i].alias, DIGEST_TIME);
  26577. X    setup_string (lists[i].list_limitsf, sys.lists[i].alias, LIST_LIMITS);
  26578. X    lists[i].nmessages = mon = day = year = 0;
  26579. X    lists[i].done_for_the_day = FALSE;
  26580. X    if ((f = fopen (lists[i].list_limitsf, "r")))
  26581. X      fscanf (f, "%d %d %d %d", &lists[i].nmessages, &mon, &day, &year),
  26582. X      fclose (f);
  26583. X    lists[i].current_date = mon + day + year;
  26584. X  }
  26585. X}
  26586. X
  26587. Xvoid usage ()
  26588. X{
  26589. X#ifdef GO_INTERACTIVE
  26590. X  fprintf (stderr, "Usage: serverd [-1] [-e] [-l load] [-i duration]\n\
  26591. X-1: Execute only once.\n\
  26592. X-e: Echo reports to the screen.\n\
  26593. X-l: Enforce load restrictions.\n\
  26594. X-i: Go into interactive mode also; listen for TCP connections;\n\
  26595. X    each connection is limited to 'duration' seconds.\n");
  26596. X#else
  26597. Xfprintf (stderr, "Usage: serverd [-1] [-e] [-l load]\n\
  26598. X-1: Execute only once.\n\
  26599. X-e: Echo reports to the screen.\n\
  26600. X-l: Enforce load restrictions.\n");
  26601. X#endif
  26602. X  exit (3);
  26603. X}
  26604. X
  26605. X/*
  26606. X  Graceful exit. Remove pid file.
  26607. X*/
  26608. X
  26609. Xint gexit (int exitcode)
  26610. X{
  26611. X  unlink (PID_SERVERD);
  26612. X#ifndef NO_LOCKS
  26613. X  unlock_file (lfd);
  26614. X#endif
  26615. X#ifdef GO_INTERACTIVE
  26616. X  if (interactive) {
  26617. X    semremove (sid);
  26618. X    kill (chpid, SIGINT);
  26619. X    while (!chdied);
  26620. X  }
  26621. X#endif
  26622. X  exit (exitcode);
  26623. X}
  26624. X
  26625. X/*
  26626. X  Wait MAX_TRIES * 30 seconds for load to drop to max_load.
  26627. X
  26628. X  USER CONTRIBUTED MODIFIED CODE (for version 5.5): Warren Burstein.
  26629. X*/
  26630. X
  26631. Xvoid load_wait (float max_load)
  26632. X{
  26633. X  int try;
  26634. X  float load;
  26635. X  FILE *loadf;
  26636. X
  26637. X  for (try = 0 ;; try++) {
  26638. X#if defined (__NeXT__) || defined (unknown_port)
  26639. X    syscom ("%s | %s -F, '{ n=split($4,f,\" \");print f[3] }' > %s",
  26640. X        UPTIME, AWK, LOAD_FILE);
  26641. X#elif defined (_AIX)
  26642. X    syscom ("%s | %s -F, '{ n=split($3,f,\" \");print f[2] }' > %s",
  26643. X        UPTIME, AWK, LOAD_FILE);
  26644. X#else
  26645. X    syscom ("%s | %s -F, '{ print $4 }' | %s -d' ' -f5 > %s",
  26646. X            UPTIME, AWK, CUT, LOAD_FILE);
  26647. X#endif
  26648. X    OPEN_FILE (loadf, LOAD_FILE, "r", "main");
  26649. X    fscanf (loadf, "%f", &load);
  26650. X    fclose (loadf);
  26651. X    unlink (LOAD_FILE);
  26652. X
  26653. X    if (load <= max_load)
  26654. X      break;
  26655. X
  26656. X    sleep (30);
  26657. X  }
  26658. X}
  26659. X
  26660. X/*
  26661. X  Execute 'command' using the system call.
  26662. X
  26663. X  USER CONTRIBUTED MODIFIED CODE (for version 5.5): Warren Burstein.
  26664. X*/
  26665. X
  26666. Xvoid run_program (char *command, BOOLEAN is_listserv, int msg_sock)
  26667. X{
  26668. X  int status, mask;
  26669. X  char msg [MAX_LINE];
  26670. X  char reply [MAX_LINE];
  26671. X
  26672. X  report_progress (report, command, TRUE);
  26673. X
  26674. X#ifdef GO_INTERACTIVE
  26675. X  if (ppid == getpid())
  26676. X# if defined (bsd)
  26677. X#  ifdef SIGCLD
  26678. X    mask = sigblock (sigmask (SIGCLD)),
  26679. X#  else
  26680. X    mask = sigblock (sigmask (SIGCHLD)),
  26681. X#  endif
  26682. X    status = system (command),
  26683. X    sigsetmask (mask);
  26684. X# elif (defined (svr4) || defined (svr3)) && !defined (stellar)
  26685. X#  ifdef SIGCLD
  26686. X    sighold (SIGCLD),
  26687. X#  else
  26688. X    sighold (SIGCHLD),
  26689. X#  endif
  26690. X    status = system (command),
  26691. X#  ifdef SIGCLD
  26692. X    sigrelse (SIGCLD);
  26693. X#  else
  26694. X    sigrelse (SIGCHLD);
  26695. X#  endif
  26696. X# else
  26697. X#  ifdef SIGCLD
  26698. X    signal (SIGCLD, SIG_DFL),
  26699. X#  else
  26700. X    signal (SIGCHLD, SIG_DFL),
  26701. X#  endif
  26702. X    status = system (command),
  26703. X#  ifdef SIGCLD
  26704. X    signal (SIGCLD, (void (*)()) sighandle);
  26705. X#  else
  26706. X    signal (SIGCHLD, (void (*)()) sighandle);
  26707. X#  endif
  26708. X# endif
  26709. X  else
  26710. X#endif
  26711. X    status = system (command);
  26712. X  if (status > 127) {
  26713. X    sprintf (msg, "%s %s: %s: %s",
  26714. X         (ppid == getpid() ? "serverd" : "IUL client"),
  26715. X         (WEXITSTATUS (status) == 7) ? "restarts" : "died",
  26716. X             is_listserv ? "LISTSERV" : "LIST",
  26717. X             (WEXITSTATUS (status) >= 0 && WEXITSTATUS (status) <= 16 ?
  26718. X          exit_string[WEXITSTATUS (status)] : exit_string[17]));
  26719. X    if (sys.options & BSD_MAIL)
  26720. X      syscom ("echo '' | %s -s '%s' %s", UCB_MAIL, msg, sys.manager);
  26721. X    report_progress (report, msg, TRUE);
  26722. X
  26723. X    if (is_listserv) {
  26724. X      if (WEXITSTATUS (status) == 6) { /* Shutdown request */
  26725. X#ifdef SYSLOG
  26726. X    closelog ();
  26727. X#else
  26728. X    fclose (report);
  26729. X#endif
  26730. X#ifdef GO_INTERACTIVE
  26731. X    if (interactive) {
  26732. X      CLOSE_CLIENT (msg_sock);
  26733. X      if (ppid == getpid()) /* Master process notifies */
  26734. X        gexit (6);    /* It will kill chpid */
  26735. X      exit (6);
  26736. X    }
  26737. X#endif
  26738. X    gexit (6);
  26739. X      }
  26740. X
  26741. X      if (WEXITSTATUS (status) == 7) { /* Restart request */
  26742. X    unlink (PID_SERVERD);
  26743. X#ifndef NO_LOCKS
  26744. X        unlock_file (lfd);
  26745. X#endif
  26746. X#ifdef GO_INTERACTIVE
  26747. X    if (interactive) {
  26748. X      CLOSE_CLIENT (msg_sock);
  26749. X      if (ppid == getpid()) { /* Master process notifies and continues */
  26750. X        semremove (sid);
  26751. X# ifdef SIGCLD
  26752. X        signal (SIGCLD, SIG_DFL);
  26753. X# else
  26754. X        signal (SIGCHLD, SIG_DFL);
  26755. X# endif
  26756. X        kill (chpid, SIGINT);
  26757. X        while (!chdied);
  26758. X      }
  26759. X      else
  26760. X        exit (7);
  26761. X    }
  26762. X#endif
  26763. X    signal (SIGALRM, SIG_IGN); /* Just in case */
  26764. X        execl (START, START, START_OPTIONS, NULL);
  26765. X        sprintf (msg, "serverd commits suicide: Could not restart \
  26766. Xsystem");
  26767. X        report_progress (report, msg, TRUE);
  26768. X#ifdef SYSLOG
  26769. X        closelog ();
  26770. X#else
  26771. X    fclose (report);
  26772. X#endif
  26773. X        if (sys.options & BSD_MAIL)
  26774. X          syscom ("echo '' | %s -s '%s' %s", UCB_MAIL, msg, sys.manager);
  26775. X#ifdef GO_INTERACTIVE
  26776. X    if (interactive)
  26777. X      exit (5);
  26778. X#endif
  26779. X    gexit (5);
  26780. X      }
  26781. X    }
  26782. X#ifdef SYSLOG
  26783. X    closelog ();
  26784. X#else
  26785. X    fclose (report);
  26786. X#endif
  26787. X#ifdef GO_INTERACTIVE
  26788. X    if (interactive) {
  26789. X      CLOSE_CLIENT (msg_sock);
  26790. X      if (ppid == getpid()) /* Master process notifies */
  26791. X    gexit (WEXITSTATUS (status));    /* Will kill chpid */
  26792. X      exit (WEXITSTATUS (status));
  26793. X    }
  26794. X#endif
  26795. X    gexit (WEXITSTATUS (status));
  26796. X  }
  26797. X
  26798. X  if (status == 127) {
  26799. X    sprintf (msg, "serverd died: could not execute shell for %s",
  26800. X             is_listserv ? "listserv" : "list");
  26801. X    if (sys.options & BSD_MAIL)
  26802. X      syscom ("echo '' | %s -s '%s' %s", UCB_MAIL, msg, sys.manager);
  26803. X    report_progress (report, msg, TRUE);
  26804. X#ifdef SYSLOG
  26805. X    closelog ();
  26806. X#else
  26807. X    fclose (report);
  26808. X#endif
  26809. X#ifdef GO_INTERACTIVE
  26810. X    if (interactive)
  26811. X      exit (5);
  26812. X#endif
  26813. X    gexit (5);
  26814. X  }
  26815. X  else if (status > 0 && status < 127) {
  26816. X    sprintf (msg, "serverd commits suicide: status %d while trying to \
  26817. Xspawn %s: no tty; see the documentation", status, command);
  26818. X    report_progress (report, msg, TRUE);
  26819. X#ifdef SYSLOG
  26820. X    closelog ();
  26821. X#else
  26822. X    fclose (report);
  26823. X#endif
  26824. X#ifdef GO_INTERACTIVE
  26825. X    if (interactive)
  26826. X      exit (5);
  26827. X#endif
  26828. X    gexit (5);
  26829. X  }
  26830. X  else if (status < 0)
  26831. X    report_progress (report, "Cannot get child exit status", TRUE);
  26832. X}
  26833. X
  26834. X#ifdef GO_INTERACTIVE
  26835. X/*
  26836. X  Handle signals, especially SIGCLD.
  26837. X*/
  26838. X
  26839. Xvoid sighandle (int sig)
  26840. X{
  26841. X#ifdef WAIT3_NEEDS_UNION
  26842. X  union wait status;
  26843. X#else
  26844. X  int status = 1;
  26845. X#endif
  26846. X  int pid, i, j, _nforks, mask, pids[MAX_CONNECTIONS], exstatus;
  26847. X  char reply [MAX_LINE];
  26848. X  BOOLEAN restart = FALSE;
  26849. X
  26850. X# ifdef SIGCLD
  26851. X  if (sig != SIGCLD)
  26852. X    signal (sig, SIG_IGN);
  26853. X  if (sig == SIGCLD) {
  26854. X# else
  26855. X  if (sig != SIGCHLD)
  26856. X    signal (sig, SIG_IGN);
  26857. X  if (sig == SIGCHLD) {
  26858. X# endif
  26859. X# if defined (bsd)
  26860. X#  ifdef SIGCLD
  26861. X    mask = sigblock (sigmask (SIGCLD));
  26862. X#  else
  26863. X    mask = sigblock (sigmask (SIGCHLD));
  26864. X#  endif
  26865. X# elif defined (svr4) || defined (svr3)
  26866. X#  ifdef SIGCLD
  26867. X    sighold (SIGCLD);
  26868. X#  else
  26869. X    sighold (SIGCHLD);
  26870. X#  endif
  26871. X# endif
  26872. X    if (ppid == getpid()) {    /* Listener process died, or system() bug */
  26873. X# if defined (sequent) || defined (stardent) || defined (stellar) || \
  26874. X  defined (titan) || defined (unknown_port)
  26875. X      do {
  26876. X    pid = wait3 (&status, WNOHANG, NULL);
  26877. X      } while (pid && pid != chpid);
  26878. X# else
  26879. X      pid = waitpid (chpid, &status, WNOHANG);
  26880. X# endif
  26881. X      if (!pid) {    /* system() bug */
  26882. X# if defined (bsd)
  26883. X    sigsetmask (mask);
  26884. X# elif defined (svr3) || defined (svr4)
  26885. X#  ifdef SIGCLD
  26886. X    sigrelse (SIGCLD);
  26887. X#  else
  26888. X    sigrelse (SIGCHLD);
  26889. X#  endif
  26890. X# endif
  26891. X    signal (sig, (void (*)()) sighandle);
  26892. X    return;
  26893. X      }
  26894. X    }
  26895. X    else    /* Listener process: "live" child died */
  26896. X      pid = wait (&status);   /* Get child's pid */
  26897. X    for (i = 0; i < nforks; i++) {
  26898. X      if (clients [i].pid == pid) { /* Remove dead child's pid */
  26899. X    report_progress (report,
  26900. X             tsprintf ("Connection closed with %s (client #%d)",
  26901. X                   clients [i].name, clients [i].connid), TRUE);
  26902. X    for (j = i; j < nforks - 1; j++)
  26903. X    memcpy ((char *) &clients [j], (char *) &clients [j + 1], 
  26904. X        sizeof (CLIENT));
  26905. X    break;
  26906. X      }
  26907. X    }
  26908. X    if (i == nforks && chpid == getpid())
  26909. X      report_progress (report, "Connection closed with last client", TRUE);
  26910. X    --nforks;
  26911. X    if (!semctl (sid, 0, GETVAL) && semctl (sid, 0, GETPID) == pid)
  26912. X      if (V (sid) < 0) /* Out of critical section */
  26913. X      report_progress (report, tsprintf ("\nsighandle(): %s process: \
  26914. XError V(). Unexpected behavior is imminent",
  26915. X                         (chpid == getpid () ? "Listener" :
  26916. X                          "Master")), TRUE);
  26917. X    if (WIFSIGNALED (status))  {
  26918. X      if (WTERMSIG (status) > SIGINT &&
  26919. X      WTERMSIG (status) != ABORT_SIG && WTERMSIG (status) != TIMEOUT_SIG)
  26920. X    report_progress (report, tsprintf ("\nsighandle(): Child died \
  26921. Xabnormally: signal %d",
  26922. X                       WTERMSIG (status)), TRUE);
  26923. X    }
  26924. X    else if (WIFEXITED (status)) { /* Abnormal child exit status ? */
  26925. X      if ((exstatus = WEXITSTATUS (status)) == 0 && pid != chpid) {
  26926. X# if defined (bsd)
  26927. X    sigsetmask (mask);
  26928. X# elif defined (svr3) || defined (svr4)
  26929. X#  ifdef SIGCLD
  26930. X    sigrelse (SIGCLD);
  26931. X#  else
  26932. X    sigrelse (SIGCHLD);
  26933. X#  endif
  26934. X# endif
  26935. X    signal (sig, (void (*)()) sighandle);
  26936. X    return;
  26937. X      }
  26938. X      if (exstatus == 6 || exstatus == 7 || exstatus == 8 || exstatus == 11 ||
  26939. X      exstatus == 13 || exstatus == 14 || exstatus == 15 || exstatus == 16) {
  26940. X       /* Shutdown or restart request, semaphore/socket error */
  26941. X    if (exstatus == 7 && ppid == getpid())
  26942. X      restart = TRUE; /* Only master process may restart */
  26943. X    else if (exstatus == 8)
  26944. X      report_progress (report, "\nsighandle(): Child received SIGTERM",
  26945. X               TRUE);
  26946. X    else if (exstatus == 11 || exstatus == 13 || exstatus == 15 ||
  26947. X         exstatus == 16) {
  26948. X      report_progress (report,
  26949. X               tsprintf ("\nsighandle(): Child experienced %s \
  26950. Xerror", (exstatus == 11 ? "malloc()" : (exstatus == 13 ? "socket" :
  26951. X(exstatus == 15 ? "setuid()/setgid()" : "internal")))), TRUE);
  26952. X# if defined (bsd)
  26953. X      sigsetmask (mask);
  26954. X# elif defined (svr3) || defined (svr4)
  26955. X#  ifdef SIGCLD
  26956. X      sigrelse (SIGCLD);
  26957. X#  else
  26958. X      sigrelse (SIGCHLD);
  26959. X#  endif
  26960. X# endif
  26961. X      signal (sig, (void (*)()) sighandle);
  26962. X      return;
  26963. X    }
  26964. X    else if (exstatus == 14)
  26965. X      report_progress (report, "\nsighandle(): Child experienced semaphore\
  26966. X error", TRUE);
  26967. X    if (ppid != getpid()) { /* Master process will exit gracefully */
  26968. X      _nforks = nforks; /* As children die nforks decreases */
  26969. X# if defined (bsd)
  26970. X      sigsetmask (mask);
  26971. X# elif defined (svr3) || defined (svr4)
  26972. X#  ifdef SIGCLD
  26973. X      sigrelse (SIGCLD);
  26974. X#  else
  26975. X      sigrelse (SIGCHLD);
  26976. X#  endif
  26977. X# endif
  26978. X      signal (sig, (void (*)()) sighandle);
  26979. X      for (i = 0; i < _nforks; i++)
  26980. X        pids[i] = clients [i].pid;
  26981. X      for (i = 0; i < _nforks; i++) /* Kill any "live" children */
  26982. X        kill (pids[i], ABORT_SIG);
  26983. X      kill (ppid, ABORT_SIG);
  26984. X      exit (exstatus);
  26985. X    }
  26986. X      }
  26987. X    }
  26988. X# if defined (bsd)
  26989. X    sigsetmask (mask);
  26990. X# elif defined (svr3) || defined (svr4)
  26991. X#  ifdef SIGCLD
  26992. X    sigrelse (SIGCLD);
  26993. X#  else
  26994. X    sigrelse (SIGCHLD);
  26995. X#  endif
  26996. X# endif
  26997. X    signal (sig, (void (*)()) sighandle);
  26998. X    if (ppid != getpid()) /* Master process will die */
  26999. X      return;
  27000. X    else if (pid != chpid) /* Master cares only about the Listener process */
  27001. X      return;
  27002. X    unlink (PID_SERVERD);
  27003. X  }
  27004. X# ifdef SIGCLD
  27005. X  signal (SIGCLD, SIG_DFL);
  27006. X# else
  27007. X  signal (SIGCHLD, SIG_DFL);
  27008. X# endif
  27009. X  if (chpid == getpid()) { /* Listener process */
  27010. X    for (i = 0; i < nforks; i++) { /* Kill any "live" children */
  27011. X      report_progress (report, tsprintf ("Connection closed with %s (client #%d)",
  27012. X                     clients [i].name, clients [i].connid),
  27013. X               TRUE);
  27014. X      kill (clients [i].pid, ABORT_SIG);
  27015. X    }
  27016. X    kill (ppid, ABORT_SIG);  /* Notify master process we are dying */
  27017. X  }
  27018. X  /* Next two lines are currently useless; kept for future use */
  27019. X  if (getpid() != chpid && getpid() != ppid) /* Live process */
  27020. X    CLOSE_CLIENT (msg_sock);
  27021. X  if (ppid == getpid ())
  27022. X    semremove (sid);    /* Only master process may remove it */
  27023. X  if (restart) {
  27024. X# ifndef NO_LOCKS
  27025. X    unlock_file (lfd);
  27026. X# endif
  27027. X    execl (START, START, START_OPTIONS, NULL);
  27028. X    report_progress (report, "serverd commits suicide: Could not restart system",
  27029. X             TRUE);
  27030. X# ifdef SYSLOG
  27031. X    closelog ();
  27032. X# else
  27033. X    fclose (report);
  27034. X# endif
  27035. X    if (sys.options & BSD_MAIL)
  27036. X      syscom ("echo '' | %s -s '%s' %s", UCB_MAIL, reply, sys.manager);
  27037. X    exit (5);
  27038. X  }
  27039. X# ifndef NO_LOCKS
  27040. X  unlock_file (lfd);
  27041. X# endif
  27042. X# ifdef SYSLOG
  27043. X  closelog ();
  27044. X# else
  27045. X  fclose (report);
  27046. X# endif
  27047. X  exit (0);
  27048. X}
  27049. X
  27050. X/*
  27051. X  Called when Listener process has exited.
  27052. X*/
  27053. X
  27054. Xvoid listener_exited ()
  27055. X{
  27056. X  chdied = TRUE;
  27057. X}
  27058. X
  27059. X/*
  27060. X  Child has been notified that it should commit suicide, so it does after
  27061. X  notifying the client.
  27062. X*/
  27063. X
  27064. Xvoid close_connection (int sig)
  27065. X{
  27066. X  char s [256];
  27067. X
  27068. X  signal (sig, SIG_IGN);
  27069. X  if (sig == SIGALRM && !semctl (sid, 0, GETVAL) &&
  27070. X      semctl (sid, 0, GETPID) == getpid()) {
  27071. X    signal (SIGALRM, (void (*)()) close_connection);
  27072. X    alarm (5);
  27073. X    return;
  27074. X  }
  27075. X  if (sig == TIMEOUT_SIG || sig == SIGALRM)
  27076. X    sprintf (s, "%d %d \n%s", CONN_TIMEOUT, strlen (CONN_TIMED_OUT),
  27077. X         CONN_TIMED_OUT);
  27078. X  else if (sig == SIGTERM)
  27079. X    sprintf (s, "%d %d \n%s", CONN_CLOSED, strlen (GOOD_BYE), GOOD_BYE);
  27080. X  else if (sig == ABORT_SIG)
  27081. X    sprintf (s, "%d %d \n%s", CONN_ABORTED, strlen (SERVER_SHUTS_DOWN),
  27082. X         SERVER_SHUTS_DOWN);
  27083. X  else
  27084. X    sprintf (s, "%d %d \n%s", CONN_ABORTED, strlen (REMOTE_SYS_ERROR),
  27085. X         REMOTE_SYS_ERROR);
  27086. X  write_to_fd (msg_sock, s, strlen (s));
  27087. X  close (msg_sock);
  27088. X#ifndef SYSLOG
  27089. X  fclose (report);
  27090. X#endif
  27091. X  unlink (requests_file);
  27092. X  _exit (0);
  27093. X}
  27094. X
  27095. X/*
  27096. X  Check whether a child process has been running longer than 'conn_duration'
  27097. X  seconds and return its pid, or 0 otherwise.
  27098. X*/
  27099. X
  27100. Xint check_timeout (CLIENT clients [])
  27101. X{
  27102. X  int i;
  27103. X
  27104. X  for (i = 0; i < nforks; i++)
  27105. X    if ((time (0) - clients [i].time) > conn_duration)
  27106. X      return clients [i].pid;
  27107. X  return 0;
  27108. X}
  27109. X
  27110. X/*
  27111. X  Create a socket and bind it to the local address and to an available port.
  27112. X  Return the socket file descriptor, or -1 on error.
  27113. X*/
  27114. X
  27115. Xint create_connection ()
  27116. X{
  27117. X  struct sockaddr_in server;
  27118. X  struct servent *service;
  27119. X  struct hostent *hostentry;
  27120. X  int sock, timeout = 0, sendbuf = BUFFSIZ, recvbuf = BUFFSIZ, val = 1;
  27121. X
  27122. X#ifndef IUL_PORT
  27123. X  if (! (service = getservbyname (SERVICE, NULL))) {
  27124. X    report_progress (report, "\ncreate_connection(): Service unavailable",
  27125. X             TRUE);
  27126. X    return -1;
  27127. X  }
  27128. X#endif
  27129. X  if (! (hostentry = gethostbyname ("localhost"))) {
  27130. X    report_progress (report, "\ncreate_connection(): No such host", TRUE);
  27131. X    return -1;
  27132. X  }
  27133. X  if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  27134. X    report_progress (report, "\ncreate_connection(): Could not create socket",
  27135. X             TRUE);
  27136. X    return -1;
  27137. X  }
  27138. X  if (setsockopt (sock, SOL_SOCKET, SO_SNDBUF, (char *) &sendbuf,
  27139. X          sizeof (sendbuf)) < 0)
  27140. X    report_progress (report, "\ncreate_connection(): WARNING: Could not \
  27141. Xset send-buffer size: setsockopt() error", TRUE);
  27142. X  if (setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *) &recvbuf,
  27143. X          sizeof (recvbuf)) < 0)
  27144. X    report_progress (report, "\ncreate_connection(): WARNING: Could not \
  27145. Xset receive-buffer size: setsockopt() error", TRUE);
  27146. X  if (setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
  27147. X      sizeof (val)) < 0)
  27148. X    report_progress (report, "\ncreate_connection():WARNING: Cannot toggle \
  27149. Xkeep-alive connections: setsockopt() error", TRUE);
  27150. X  val = 1;
  27151. X  if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
  27152. X      sizeof (val)) < 0)
  27153. X    report_progress (report, "\ncreate_connection():WARNING: Cannot toggle \
  27154. Xreuse of local address: setsockopt() error", TRUE);
  27155. X
  27156. X  server.sin_family = AF_INET;            /* Internet protocol */
  27157. X  server.sin_addr.s_addr = INADDR_ANY;
  27158. X#ifndef IUL_PORT
  27159. X  server.sin_port = service->s_port;
  27160. X#else
  27161. X  server.sin_port = htons (IUL_PORT);
  27162. X#endif
  27163. X
  27164. X  while (bind (sock, (struct sockaddr *) &server, sizeof (server)) < 0 &&
  27165. X     errno == EADDRINUSE && timeout < 180) { /* For perm port keep trying */
  27166. X    ++timeout;
  27167. X    errno = 0;
  27168. X    sleep (1);
  27169. X  }
  27170. X  if (timeout >= 180) {
  27171. X    report_progress (report, "\ncreate_connection(): Could not bind", TRUE);
  27172. X    return -1;
  27173. X  }
  27174. X  listen (sock, 5);
  27175. X  return sock;
  27176. X}
  27177. X
  27178. X/*
  27179. X  Process all live requests coming in from the tcp connection.
  27180. X
  27181. X  PLEASE DO NOT MODIFY THIS ROUTINE AS YOU MAY BREAK THE PROTOCOL AND CREATE
  27182. X  HAVOC WITH PEER INTERACTIVE UNIX LISTSERVERS. A LOT OF UNDOCUMENTED
  27183. X  ASSUMPTIONS ARE MADE. YOU SHOULD CONTACT ME ABOUT ANY CHANGES YOU WISH TO
  27184. X  MAKE.
  27185. X
  27186. X  [What a messy routine]
  27187. X*/
  27188. X
  27189. Xvoid process_live_request (int msg_sock, struct sockaddr_in client)
  27190. X{
  27191. X  char ch, *buf, *dash, server [MAX_LINE], msg [MAX_LINE];
  27192. X  char denied_req [6][MAX_LINE], login [MAX_LINE], *passwd;
  27193. X  char *perms [6], *s, *r, *rr;
  27194. X  char outfile [MAX_LINE], reply [MAX_LINE], arg [MAX_LINE];
  27195. X  char localhost [MAX_LINE], _localhost [MAX_LINE], localaddr [MAX_LINE];
  27196. X  char rhost [MAX_LINE], raddr [MAX_LINE];
  27197. X  FILE *f;
  27198. X  long int t, time_started, sig_mask, naddr, naddr2, nlines, buffsiz = BUFFSIZ;
  27199. X  long int i, j;
  27200. X  int response, fmode, l, auth = NOTSUBSCRIBED, bytes_read = 0, rcode, err;
  27201. X  int listid;
  27202. X  BOOLEAN more_input = FALSE, reply_code, bin = TRUE, put_request,
  27203. X    already_continued = FALSE;
  27204. X  struct hostent *hp, *rhp;
  27205. X  struct stat stat_buf;
  27206. X  struct in_addr _addr;
  27207. X
  27208. X  sprintf (denied_req [MANAGER], "-d execute -d fax");
  27209. X  sprintf (denied_req [OWNER], "%s -d shutdown -d restart",
  27210. X       denied_req [MANAGER]);
  27211. X  sprintf (denied_req [SUBSCRIBED], "%s -d subscribe -d system -d reports \
  27212. X-d edit -d put -d approve -d discard", denied_req [OWNER]);
  27213. X  sprintf (denied_req [NOTSUBSCRIBED], "%s -d unsubscribe -d set -d which \
  27214. X-d run",
  27215. X       denied_req [SUBSCRIBED]);
  27216. X  perms [MANAGER] = MANAGER_LOGIN;
  27217. X  perms [OWNER] = OWNER_LOGIN;
  27218. X  perms [SUBSCRIBED] = SUBSCRIBER_LOGIN;
  27219. X  perms [NOTSUBSCRIBED] = GENERAL_LOGIN;
  27220. X
  27221. X  time_started = time (0);
  27222. X  gethostname (localhost, sizeof (localhost));
  27223. X  strcpy (_localhost, localhost);
  27224. X  upcase (_localhost);
  27225. X  if (write_to_fd (msg_sock, LOGIN, strlen (LOGIN)) < 0)
  27226. X    CLIENT_LOST (13);
  27227. X  outfile[0] = RESET (login);
  27228. X  GET_LOGIN (login);
  27229. X  if (!strcmp (login, "__abort__")) /* Client aborted -- Reserved */
  27230. X    goto abort;
  27231. X  if (login [0] != EOS) { /* Proceed with authentication */
  27232. X    strcpy (msg, login);  /* Used to form a "From " line */
  27233. X    rr = s = mystrdup (login);
  27234. X    upcase (s);
  27235. X    while ((s = _strstr (s, "IUL:"))) {
  27236. X      s += 4;    /* Point to remote host */
  27237. X      sscanf (s, "%s", rhost);
  27238. X      if ((r = strchr (rhost, ';')))
  27239. X    *r = EOS;
  27240. X      if (!strcmp (rhost, _localhost)) { /* Loop */
  27241. X    sprintf (msg, "Loop detected.\n");
  27242. X    REPLY (msg_sock, PEER_UNAVAIL, strlen (msg));
  27243. X    write_to_fd (msg_sock, msg, strlen (msg));
  27244. X    goto ciao;
  27245. X      }
  27246. X      rhp = hp = gethostbyname (rhost);
  27247. X      if (hp) {
  27248. X    if ((rhp = (struct hostent *) malloc (sizeof (struct hostent))) == NULL)
  27249. X      report_progress (report, "\nprocess_live_request(): malloc() failed",
  27250. X               TRUE),
  27251. X      exit (11);
  27252. X    memcpy ((char *) rhp, (char *) hp, sizeof (*hp));
  27253. X#ifdef h_addr
  27254. X    if ((rhp->h_addr_list = (char **) malloc (sizeof (char *))) == NULL)
  27255. X      report_progress (report, "\nprocess_live_request(): malloc() failed",
  27256. X               TRUE),
  27257. X      exit (11);
  27258. X    naddr = 0;
  27259. X    while (hp->h_addr_list[naddr]) {
  27260. X      if ((rhp->h_addr_list = (char **)
  27261. X           realloc (rhp->h_addr_list, (naddr + 2) * sizeof (char *))) ==
  27262. X          NULL)
  27263. X        report_progress (report,
  27264. X                 "\nprocess_live_request(): realloc() failed", TRUE),
  27265. X        exit (11);
  27266. X      if ((rhp->h_addr_list[naddr] = (char *)
  27267. X           malloc (rhp->h_length * sizeof (char))) == NULL)
  27268. X        report_progress (report,
  27269. X                 "\nprocess_live_request(): malloc() failed", TRUE),
  27270. X        exit (11);
  27271. X      memcpy ((char *) rhp->h_addr_list[naddr],
  27272. X          (char *) hp->h_addr_list[naddr], hp->h_length);
  27273. X      rhp->h_addr_list[++naddr] = NULL;
  27274. X    }
  27275. X    naddr = 0;
  27276. X    while (rhp->h_addr_list[naddr]) {
  27277. X      memcpy ((char *) &_addr, (char *) rhp->h_addr_list[naddr++],
  27278. X          rhp->h_length);
  27279. X      strcpy (raddr, (char *) inet_ntoa (_addr));
  27280. X      hp = gethostbyname (localhost);
  27281. X      naddr2 = 0;
  27282. X      while (hp && hp->h_addr_list[naddr2]) {
  27283. X        memcpy ((char *) &_addr, (char *) hp->h_addr_list[naddr2++],
  27284. X            hp->h_length);
  27285. X        strcpy (localaddr, (char *) inet_ntoa (_addr));
  27286. X        if (!strcmp (raddr, localaddr)) { /* Loop */
  27287. X          sprintf (msg, "Loop detected.\n");
  27288. X          REPLY (msg_sock, PEER_UNAVAIL, strlen (msg));
  27289. X          write_to_fd (msg_sock, msg, strlen (msg));
  27290. X          goto ciao;
  27291. X        }
  27292. X      }
  27293. X    }
  27294. X    naddr = 0;
  27295. X    while (rhp->h_addr_list[naddr])
  27296. X      free ((char *) rhp->h_addr_list[naddr++]);
  27297. X    free ((char **) rhp->h_addr_list);
  27298. X#else
  27299. X    if ((rhp->h_addr = (char *) malloc ((strlen (hp->h_addr) + 1) *
  27300. X                        sizeof (char))) == NULL) {
  27301. X      report_progress (report, "\nsiul(): malloc() failed", TRUE);
  27302. X      close (ofd);
  27303. X      return -1;
  27304. X    }
  27305. X    memcpy ((char *) rhp->h_addr, (char *) hp->h_addr, hp->h_length);
  27306. X    memcpy ((char *) &_addr, (char *) rhp->h_addr, rhp->h_length);
  27307. X    strcpy (raddr, (char *) inet_ntoa (_addr));
  27308. X    hp = gethostbyname (rhost);
  27309. X    memcpy ((char *) &_addr, (char *) hp->h_addr, hp->h_length);
  27310. X    strcpy (localaddr, (char *) inet_ntoa (_addr));
  27311. X    if (!strcmp (raddr, localaddr)) { /* Loop */
  27312. X      write_to_fd (ofd, "Loop detected.\n", 15);
  27313. X      cmd = PEER_UNAVAIL;
  27314. X      goto abort;
  27315. X    }
  27316. X    free ((char *) rhp->h_addr);
  27317. X#endif
  27318. X    free ((struct hostent *) rhp);
  27319. X      }
  27320. X      hp = gethostbyname (localhost);
  27321. X      naddr = 0;
  27322. X#ifdef h_addr
  27323. X      while (hp && hp->h_addr_list[naddr]) {
  27324. X    memcpy ((char *) &_addr, (char *) hp->h_addr_list[naddr++],
  27325. X        hp->h_length);
  27326. X    strcpy (localaddr, (char *) inet_ntoa (_addr));
  27327. X    if (!strcmp (rhost, localaddr)) { /* Loop */
  27328. X      sprintf (msg, "Loop detected.\n");
  27329. X      REPLY (msg_sock, PEER_UNAVAIL, strlen (msg));
  27330. X      write_to_fd (msg_sock, msg, strlen (msg));
  27331. X      goto ciao;
  27332. X    }
  27333. X      }
  27334. X#else
  27335. X      memcpy ((char *) &_addr, (char *) hp->h_addr, hp->h_length);
  27336. X      strcpy (localaddr, (char *) inet_ntoa (_addr));
  27337. X      if (!strcmp (rhost, localaddr)) { /* Loop */
  27338. X    sprintf (msg, "Loop detected.\n");
  27339. X    REPLY (msg_sock, PEER_UNAVAIL, strlen (msg));
  27340. X    write_to_fd (msg_sock, msg, strlen (msg));
  27341. X    goto ciao;
  27342. X      }
  27343. X#endif
  27344. X    }
  27345. X    free ((char *) rr);
  27346. X    REPLY (msg_sock, PASSWORD_REQUIRED, strlen (PASSWORD));
  27347. X    if (write_to_fd (msg_sock, PASSWORD, strlen (PASSWORD)) < 0)
  27348. X      CLIENT_LOST (13);
  27349. X    if ((passwd = (char *) malloc (MAX_LINE * sizeof (char))) == NULL)
  27350. X      report_progress (report,
  27351. X               "\nprocess_live_request(): malloc() failed", TRUE),
  27352. X      exit (11);
  27353. X    RESET (passwd);
  27354. X    GET_LOGIN (passwd);
  27355. X    if (!strcmp (passwd, "__abort__")) /* Client aborted -- Reserved */
  27356. X      goto abort;
  27357. X    upcase (passwd);
  27358. X    if (!strcmp (login, sys.manager)) /* Check to see if he's the manager */
  27359. X      if (!strcmp (passwd, sys.server.password)) {
  27360. X    auth = MANAGER;
  27361. X    REPLY (msg_sock, OK, strlen (perms [auth]) + strlen (PROMPT));
  27362. X    if (write_to_fd (msg_sock, perms [auth], strlen (perms [auth])) < 0)
  27363. X      CLIENT_LOST (13);
  27364. X    goto skip;
  27365. X      }
  27366. X    upcase (login);
  27367. X    for (listid = 0; listid < nlists; listid++) /* Check to see if he is an owner */
  27368. X      if (owner_listed (OWNERSF, login, sys.lists[listid].alias, report) ==
  27369. X      OWNER)
  27370. X    if (!strcmp (passwd, sys.lists[listid].password)) {
  27371. X      auth = OWNER;
  27372. X      REPLY (msg_sock, OK, strlen (perms [auth]) + strlen (PROMPT));
  27373. X      if (write_to_fd (msg_sock, perms [auth], strlen (perms [auth])) < 0)
  27374. X        CLIENT_LOST (13);
  27375. X      goto skip;
  27376. X    }
  27377. X
  27378. X    for (listid = 0; listid < nlists; listid++) { /* Check for regular subscription */
  27379. X      setup_string (subscribersf, sys.lists[listid].alias, SUBSCRIBERS);
  27380. X      sprintf (password_in_sub_file, "%d", time (0));
  27381. X      if (subscribed (report, login, subscribersf, NULL, NULL, NULL) ==
  27382. X      SUBSCRIBED)
  27383. X    if (!strcmp (passwd, password_in_sub_file)) {
  27384. X      auth = SUBSCRIBED;
  27385. X      REPLY (msg_sock, OK, strlen (perms [auth]) + strlen (PROMPT));
  27386. X      if (write_to_fd (msg_sock, perms [auth], strlen (perms [auth])) < 0)
  27387. X        CLIENT_LOST (13);
  27388. X      goto skip;
  27389. X        }
  27390. X    }
  27391. X  }
  27392. X  else
  27393. X    REPLY (msg_sock, OK, 0);
  27394. X  REPLY (msg_sock, OK, strlen (perms [auth]) + strlen (PROMPT));
  27395. X  if (write_to_fd (msg_sock, perms [auth], strlen (perms [auth])) < 0)
  27396. X    CLIENT_LOST (13);
  27397. X  hp = gethostbyaddr ((char *) &client.sin_addr,
  27398. X              sizeof (struct in_addr), client.sin_family);
  27399. X  sprintf (msg, "IUL:%s;%s",
  27400. X       (hp ? hp->h_name : (char *) inet_ntoa (client.sin_addr)),
  27401. X       login);
  27402. X
  27403. X skip:
  27404. X  hp = gethostbyaddr ((char *) &client.sin_addr,
  27405. X              sizeof (struct in_addr), client.sin_family);
  27406. X  if (write_to_fd (msg_sock, PROMPT, strlen (PROMPT)) < 0)
  27407. X    CLIENT_LOST (13);
  27408. X
  27409. X  if ((buf = (char *) malloc (buffsiz * sizeof (char))) == NULL)
  27410. X    report_progress (report,
  27411. X             "\nprocess_live_request(): malloc() failed", TRUE),
  27412. X    exit (11);
  27413. X
  27414. X  ch = RESET (buf);
  27415. X
  27416. X  while (ch != EOF && bytes_read < MAX_LINE) { /* Get request & process it */
  27417. X    errno = 0;
  27418. X    if (read (msg_sock, &ch, 1) <= 0) {
  27419. X      l = sizeof (err);
  27420. X      if (!getsockopt (sock_fd, SOL_SOCKET, SO_ERROR, (char *) &err, (char *) &l)) {
  27421. X    if (err)
  27422. X      CLIENT_LOST (13);
  27423. X      }
  27424. X      else {
  27425. X    REPLY (msg_sock, SYS_ERROR, strlen (REMOTE_SYS_ERROR));
  27426. X    write_to_fd (msg_sock, REMOTE_SYS_ERROR, strlen (REMOTE_SYS_ERROR));
  27427. X    CLIENT_LOST (13);
  27428. X      }
  27429. X      if (errno == EINTR
  27430. X#ifdef ERESTART
  27431. X      || errno == ERESTART
  27432. X#endif
  27433. X      )
  27434. X    continue;
  27435. X      break;
  27436. X    }
  27437. X    if (time (0) - time_started > conn_duration) /* In case SIGALRM f_cks up */
  27438. X      close_connection (TIMEOUT_SIG);
  27439. X    ++bytes_read;
  27440. X    if (ch >= ' ' || (isspace (ch) && ch != '\r')) {
  27441. X      if (ch != '\n') /* Buffer request */
  27442. X    buf [(l = strlen (buf))] = ch,
  27443. X    buf [l + 1] = EOS;
  27444. X      else {    /* End of request? process it */
  27445. X    if (strlen (buf) && buf [strlen (buf) - 1] == '&' &&
  27446. X        ! already_continued) { /* Request continues */
  27447. X      buf [strlen (buf) - 1] = EOS; /* Replace & */
  27448. X      REPLY (msg_sock, CONTINUED, strlen (CONT_PROMPT));
  27449. X      if (write_to_fd (msg_sock, CONT_PROMPT, strlen (CONT_PROMPT)) < 0)
  27450. X        CLIENT_LOST (13);
  27451. X      already_continued = TRUE;
  27452. X      continue;
  27453. X    }
  27454. X    if (!more_input) {
  27455. X      already_continued = FALSE;
  27456. X      clean_request (buf);
  27457. X      if (!strncmp (buf, "quit", 4) || !strncmp (buf, "exit", 4))
  27458. X        break;
  27459. X      if (!strncmp (buf, "__abort__", 4)) /* Reserved */
  27460. X        goto abort;
  27461. X# ifdef bsd
  27462. X      sig_mask = sigblock (sigmask (SIGALRM));
  27463. X# elif defined (svr4) || defined (svr3)
  27464. X      sighold (SIGALRM);
  27465. X# endif
  27466. X      if (!strncmp (buf, "binary", 3)) {
  27467. X        bin = TRUE;
  27468. X        REPLY (msg_sock, OK, strlen (BINARY_XFER) + strlen (PROMPT));
  27469. X        if (write_to_fd (msg_sock, BINARY_XFER, strlen (BINARY_XFER)) < 0)
  27470. X          CLIENT_LOST (13);
  27471. X        goto Skip;
  27472. X      }
  27473. X      if (!strncmp (buf, "ascii", 3)) {
  27474. X        bin = FALSE;
  27475. X        REPLY (msg_sock, OK, strlen (ASCII_XFER) + strlen (PROMPT));
  27476. X        if (write_to_fd (msg_sock, ASCII_XFER, strlen (ASCII_XFER)) < 0)
  27477. X          CLIENT_LOST (13);
  27478. X        goto Skip;
  27479. X      }
  27480. X      if (buf [0] == '?' || !strncmp (buf, "privileges", 4)) {
  27481. X        REPLY (msg_sock, OK, strlen (perms [auth]) + strlen (PROMPT));
  27482. X        if (write_to_fd (msg_sock, perms [auth], strlen (perms [auth])) < 0)
  27483. X          CLIENT_LOST (13);
  27484. X        goto Skip;
  27485. X      }
  27486. X      if (!strncmp (buf, "timeleft", 4)) {
  27487. X        sprintf (buf, "Time left: %d seconds\n", conn_duration - time (0) +
  27488. X             time_started);
  27489. X        REPLY (msg_sock, OK, strlen (buf) + strlen (PROMPT));
  27490. X        if (write_to_fd (msg_sock, buf, strlen (buf)) < 0)
  27491. X          CLIENT_LOST (13);
  27492. X        goto Skip;
  27493. X      }
  27494. X
  27495. X      sprintf (requests_file, "/tmp/.live.%d", getpid());
  27496. X      OPEN_FILE (f, requests_file, "w", "process_live_request");
  27497. X      chown (requests_file, pwentry->pw_uid, pwentry->pw_gid);
  27498. X      t = time (0);
  27499. X      fprintf (f, "From %s %sComment: IUL connection from %s\nAccess: ",
  27500. X           msg, ctime (&t),
  27501. X           (hp ? hp->h_name : (char *) inet_ntoa (client.sin_addr)));
  27502. X      if (auth == SUBSCRIBED)
  27503. X        fprintf (f, "Subscriber to list %s", sys.lists[listid].alias);
  27504. X      else if (auth == OWNER)
  27505. X        fprintf (f, "Owner of list %s", sys.lists[listid].alias);
  27506. X      else if (auth == MANAGER)
  27507. X        fprintf (f, "Manager");
  27508. X      else
  27509. X        fprintf (f, "Casual");
  27510. X      fprintf (f, "\n\n");
  27511. X
  27512. X      put_request = FALSE;
  27513. X      RESET (arg);
  27514. X      sscanf (buf, "%s", arg);
  27515. X      if (re_strcmp ("^PUT$|^PUT[ \t]", upcase (arg), NULL) > 0) {
  27516. X        if (!check_for_redirection (buf, outfile, &fmode, msg_sock, bin,
  27517. X        FALSE)) {
  27518. X          fclose (f);
  27519. X          goto Skip;
  27520. X        }
  27521. X        if (outfile [0] != EOS &&
  27522. X        !writeable_file (outfile, msg_sock, FALSE)) {
  27523. X          fclose (f);
  27524. X          goto Skip;
  27525. X        }
  27526. X        REPLY (msg_sock, MORE_INPUT_REQUIRED, strlen (MORE_INPUT));
  27527. X        if (write_to_fd (msg_sock, MORE_INPUT, strlen (MORE_INPUT)) < 0)
  27528. X          CLIENT_LOST (13);
  27529. X        more_input = TRUE;
  27530. X        reply_code = FALSE;
  27531. X        put_request = TRUE;
  27532. X        if (auth >= SUBSCRIBED && (dash = _strstr (buf, " - ")))
  27533. X          insert_word (dash + 1, &passwd, 1, 0, 1);
  27534. X      }
  27535. X    }
  27536. X
  27537. X    if (!strcmp (buf, ".") && more_input)
  27538. X      more_input = FALSE;
  27539. X    if (!strncmp (buf, "..", 2) && more_input)  /* Remove one dot */
  27540. X      for (l = 0; l < strlen (buf); l++)
  27541. X        buf [l] = buf [l + 1];
  27542. X
  27543. X    if (more_input && ch == '\n' && buf[0] == EOS)
  27544. X      strcat (buf, " ");    /* Kludge */
  27545. X
  27546. X    if (buf[0] != EOS) { /* Not \n only */
  27547. X
  27548. X      if (!more_input) {
  27549. X        IN_CRITICAL_SECTION ("process_live_request", msg_sock);
  27550. X
  27551. X        if (!put_request) { /* Redirection has been checked and verified */
  27552. X          if (!check_for_redirection (buf, outfile, &fmode, msg_sock, bin,
  27553. X          TRUE)) {
  27554. X            fclose (f);
  27555. X        OUT_OF_CRITICAL_SECTION ("process_live_request");
  27556. X            goto Skip;
  27557. X          }
  27558. X          RESET (arg);
  27559. X          sscanf (buf, "%s", arg);
  27560. X              if (outfile [0] != EOS || !strcmp (upcase (arg), "GET")) {
  27561. X            if (outfile [0] == EOS && !strcmp (arg, "GET"))
  27562. X          sscanf (buf, "%s %s %s", arg, arg, outfile),
  27563. X          fmode = (bin ? WRITE_TO_FILE_BIN : WRITE_TO_FILE_ASC);
  27564. X            if (!writeable_file (outfile, msg_sock, TRUE)) {
  27565. X          fclose (f);
  27566. X          OUT_OF_CRITICAL_SECTION ("process_live_request");
  27567. X              goto Skip;
  27568. X        }
  27569. X          }
  27570. X        }
  27571. X        if (strcmp (buf, ".")) {
  27572. X          if (auth >= SUBSCRIBED && (dash = _strstr (buf, " - ")))
  27573. X        insert_word (dash + 1, &passwd, 1, 0, 1);
  27574. X          fprintf (f, "%s\n", buf);
  27575. X        }
  27576. X        fclose (f);
  27577. X        cat_append (requests_file, LIVE_REQUESTS_F);
  27578. X        chown (LIVE_REQUESTS_F, pwentry->pw_uid, pwentry->pw_gid);
  27579. X        unlink (requests_file);
  27580. X
  27581. X        sprintf (server, "%s -i %s %s", SERVER, sys.server.cmdoptions,
  27582. X             denied_req [auth]);
  27583. X        run_program (server, TRUE, msg_sock);
  27584. X        if ((f = fopen (ULISTSERVER_REPLY, "r")) != NULL)
  27585. X          fscanf (f, "%d", &rcode),
  27586. X          fclose (f);
  27587. X        else
  27588. X          rcode = SYS_ERROR;
  27589. X        if ((response = open (MAILFORWARD, O_RDONLY)) >= 0) {
  27590. X          stat (MAILFORWARD, &stat_buf);
  27591. X          nlines = 0;
  27592. X          if (outfile [0] != EOS &&
  27593. X          (rcode == WRITE_TO_FILE_ASC || rcode == WRITE_TO_FILE_BIN ||
  27594. X           rcode == OK || rcode == RESTRICTED_REQ ||
  27595. X           rcode == PERMISSION_DENIED)) {
  27596. X        if (!bin) { /* Count # of \n chars */
  27597. X          bytes_read = 1;
  27598. X          while (bytes_read > 0) {
  27599. X            errno = 0;
  27600. X            while ((bytes_read = read (response, buf, BUFFSIZ - 1)) < 0
  27601. X               && (errno == EINTR
  27602. X#ifdef ERESTART
  27603. X               || errno == ERESTART)
  27604. X#else
  27605. X                   )
  27606. X#endif
  27607. X               )
  27608. X              errno = 0;
  27609. X            if (errno && errno != EINTR
  27610. X#ifdef ERESTART
  27611. X            && errno != ERESTART
  27612. X#endif
  27613. X              ) {
  27614. X              OUT_OF_CRITICAL_SECTION ("process_live_request");
  27615. X              CLOSE_CLIENT (msg_sock);
  27616. X# ifndef SYSLOG
  27617. X              fclose (report);
  27618. X# endif
  27619. X
  27620. X              _exit (13);
  27621. X            }
  27622. X            for (i = 0; i < bytes_read; ++i)
  27623. X              if (buf[i] == '\n') ++nlines;
  27624. X          }
  27625. X          lseek (response, 0L, SEEK_SET);
  27626. X        }
  27627. X        REPLY_FILE (msg_sock, fmode,
  27628. X                stat_buf.st_size + strlen (PROMPT) + nlines, 
  27629. X                outfile)
  27630. X          }
  27631. X          else
  27632. X            REPLY (msg_sock, rcode, stat_buf.st_size + strlen (PROMPT));
  27633. X          bytes_read = 1;
  27634. X          while (bytes_read > 0) {
  27635. X        errno = 0;
  27636. X        while ((bytes_read = read (response, buf, BUFFSIZ)) < 0
  27637. X               && (errno == EINTR
  27638. X#ifdef ERESTART
  27639. X               || errno == ERESTART)
  27640. X#else
  27641. X               )
  27642. X#endif
  27643. X              )
  27644. X          errno = 0;
  27645. X        if (errno && errno != EINTR
  27646. X#ifdef ERESTART
  27647. X            && errno != ERESTART
  27648. X#endif
  27649. X            ) {
  27650. X          OUT_OF_CRITICAL_SECTION ("process_live_request");
  27651. X          CLOSE_CLIENT (msg_sock);
  27652. X# ifndef SYSLOG
  27653. X          fclose (report);
  27654. X# endif
  27655. X          _exit (13);
  27656. X        }
  27657. X        if (bytes_read > 0) {
  27658. X          if (!bin && outfile[0] != EOS &&
  27659. X              (rcode == WRITE_TO_FILE_ASC ||
  27660. X               rcode == WRITE_TO_FILE_BIN ||
  27661. X               rcode == OK || rcode == RESTRICTED_REQ ||
  27662. X               rcode == PERMISSION_DENIED))
  27663. X            for (i = 0; i < bytes_read; i++)
  27664. X              if (buf [i] == '\n') {
  27665. X            if (bytes_read == buffsiz)
  27666. X              if ((buf = (char *)
  27667. X                   realloc (buf, (++buffsiz) * sizeof (char))) ==
  27668. X                  NULL) {
  27669. X                OUT_OF_CRITICAL_SECTION ("process_live_request");
  27670. X                report_progress (report, "\nprocess_live_request():\
  27671. X realloc() failed", TRUE),
  27672. X                exit (11);
  27673. X              }
  27674. X            for (j = bytes_read; j > i; j--)
  27675. X              buf [j] = buf [j - 1];
  27676. X            buf [i] = '\r';
  27677. X            ++bytes_read;
  27678. X            ++i;
  27679. X              }
  27680. X          if (write_to_fd (msg_sock, buf, bytes_read) < 0) {
  27681. X            OUT_OF_CRITICAL_SECTION ("process_live_request");
  27682. X            CLIENT_LOST (13);
  27683. X          }
  27684. X        }
  27685. X          }
  27686. X          close (response);
  27687. X          unlink (MAILFORWARD);
  27688. X          unlink (ULISTSERVER_REPLY);
  27689. X        }
  27690. X        else
  27691. X          REPLY (msg_sock, SYS_ERROR, strlen (PROMPT));
  27692. X        RESET (outfile);
  27693. X        OUT_OF_CRITICAL_SECTION ("process_live_request");
  27694. X      }
  27695. X      else {    /* More input */
  27696. X        fprintf (f, "%s\n", buf);
  27697. X        if (reply_code)    /* Kludge */
  27698. X          REPLY (msg_sock, OK, 0);
  27699. X        reply_code = TRUE;
  27700. X      }
  27701. X    }
  27702. X    else { /* Empty request */
  27703. X      fclose (f);
  27704. X      REPLY (msg_sock, OK, strlen (PROMPT));
  27705. X    }
  27706. X      Skip:
  27707. X    if (!more_input)
  27708. X      if (write_to_fd (msg_sock, PROMPT, strlen (PROMPT)) < 0)
  27709. X        CLIENT_LOST (13);
  27710. X    bytes_read = 0;
  27711. X    ch = RESET (buf);
  27712. X# ifdef bsd
  27713. X    sigsetmask (sig_mask);
  27714. X# elif defined (svr4) || defined (svr3)
  27715. X    sigrelse (SIGALRM);
  27716. X# endif
  27717. X      }
  27718. X    }
  27719. X  }
  27720. X  abort:
  27721. X  REPLY (msg_sock, CONN_CLOSED, strlen (GOOD_BYE));
  27722. X  write_to_fd (msg_sock, GOOD_BYE, strlen (GOOD_BYE));
  27723. X  ciao:
  27724. X  free ((char *) buf);
  27725. X  free ((char *) passwd);
  27726. X  unlink (requests_file);
  27727. X  close (msg_sock);
  27728. X# ifndef SYSLOG
  27729. X  fclose (report);
  27730. X# endif
  27731. X  _exit (0);
  27732. X}
  27733. X
  27734. X/*
  27735. X  Check for redirection to a file; return TRUE if no errors, FALSE otherwise.
  27736. X  The file to written to (if any) will be stored in 'outfile' and 'fmode'
  27737. X  will be set.
  27738. X*/
  27739. X
  27740. XBOOLEAN check_for_redirection (char *buf, char *outfile, int *fmode,
  27741. Xint msg_sock, BOOLEAN bin, BOOLEAN in_critical_section)
  27742. X{
  27743. X  char *s = strrchr (buf, EOS), reply [MAX_LINE];
  27744. X  int i, nquote = 0;
  27745. X
  27746. X  RESET (outfile);
  27747. X  *fmode = 0;
  27748. X  while (s >= buf) {
  27749. X    if (!nquote) {
  27750. X      if (*s == '\'' && (s == buf || *(s - 1) != '\\')) /* Count single quotes */
  27751. X    nquote = 1;
  27752. X      else if (*s == '"' && (s == buf || *(s - 1) != '\\')) /* Count double quotes */
  27753. X    nquote = 2;
  27754. X      else if (*s == '>')
  27755. X    if (s != buf && *(s - 1) == '\\')
  27756. X      sprintf (s - 1, "%s", s), /* Remove \ */
  27757. X      --s;
  27758. X    else if (outfile[0] == EOS) {
  27759. X      sscanf (s + 1, "%s", outfile);
  27760. X      if (outfile [0] == EOS) {
  27761. X        REPLY (msg_sock, SYNTAX_ERROR, strlen (NULL_REDIRECT) +
  27762. X           strlen (PROMPT));
  27763. X        i = write_to_fd (msg_sock, NULL_REDIRECT, strlen (NULL_REDIRECT));
  27764. X        if (in_critical_section && V (sid) < 0) { /* Out of critical section */
  27765. X          report_progress (report, "\ncheck_for_redirection(): \
  27766. XError V()", TRUE);
  27767. X# ifndef SYSLOG
  27768. X          fclose (report);
  27769. X# endif
  27770. X          CLOSE_CLIENT (msg_sock);
  27771. X          _exit (14);
  27772. X        }
  27773. X        if (i < 0)
  27774. X          CLIENT_LOST (13);
  27775. X        return FALSE;
  27776. X      }
  27777. X      else {
  27778. X        *fmode = (bin ? WRITE_TO_FILE_BIN : WRITE_TO_FILE_ASC);
  27779. X        if (*(s - 1) == '>') {
  27780. X          if (s - 1 != buf && *(s - 2) == '\\')
  27781. X        sprintf (s - 2, "%s", s - 1);
  27782. X          else
  27783. X        *fmode = (bin ? APPEND_TO_FILE_BIN : APPEND_TO_FILE_ASC);
  27784. X          --s;
  27785. X        }
  27786. X      }
  27787. X      *s = EOS;
  27788. X    }
  27789. X    }
  27790. X    else if ((nquote == 1 && *s == '\'' &&
  27791. X          (s != buf ? *(s - 1) != '\\' : 1)) ||
  27792. X         (nquote == 2 && *s == '"' && 
  27793. X          (s != buf ? *(s - 1) != '\\' : 1)))
  27794. X      nquote = 0;
  27795. X    --s;
  27796. X  }
  27797. X  return TRUE;
  27798. X}
  27799. X
  27800. X/*
  27801. X  Return TRUE if the file is writeable on the client side, FALSE otherwise.
  27802. X*/
  27803. X
  27804. XBOOLEAN writeable_file (char *outfile, int msg_sock,
  27805. X            BOOLEAN in_critical_section)
  27806. X{
  27807. X  char reply [MAX_LINE];
  27808. X  int i = 0, err;
  27809. X
  27810. X  REPLY_FILE (msg_sock, TEST_FILE_PERMISSIONS, 0, outfile);
  27811. X  errno = 0;
  27812. X  while (read (msg_sock, reply, 3) < 0 && (errno == EINTR
  27813. X#ifdef ERESTART
  27814. X     || errno == ERESTART)
  27815. X#else
  27816. X                       )
  27817. X#endif
  27818. X     ) {
  27819. X    i = sizeof (err);
  27820. X    if (!getsockopt (sock_fd, SOL_SOCKET, SO_ERROR, (char *) &err, (char *) &i)) {
  27821. X      i = 0;
  27822. X      if (err) {
  27823. X    if (in_critical_section && V (sid) < 0) /* Out of critical section */
  27824. X      report_progress (report, "\nwriteable_file(): Error V()", TRUE),
  27825. X      i = 1;
  27826. X    CLIENT_LOST (13 + i);
  27827. X      }
  27828. X    }
  27829. X    else {
  27830. X      REPLY (msg_sock, SYS_ERROR, strlen (REMOTE_SYS_ERROR));
  27831. X      write_to_fd (msg_sock, REMOTE_SYS_ERROR, strlen (REMOTE_SYS_ERROR));
  27832. X      CLIENT_LOST (13);
  27833. X    }
  27834. X    errno = 0;
  27835. X  }
  27836. X  if (errno && errno != EINTR
  27837. X#ifdef ERESTART
  27838. X      && errno != ERESTART
  27839. X#endif
  27840. X      ) {
  27841. X    if (in_critical_section && V (sid) < 0) /* Out of critical section */
  27842. X      report_progress (report, "\nwriteable_file(): Error V()", TRUE),
  27843. X      i = 1;
  27844. X    CLIENT_LOST (13 + i);
  27845. X  }
  27846. X  reply [3] = EOS;
  27847. X  if (atoi (reply) == PERMISSION_DENIED) {
  27848. X    REPLY (msg_sock, OK, strlen (PROMPT));
  27849. X    RESET (outfile);
  27850. X    if (in_critical_section && V (sid) < 0) { /* Out of critical section */
  27851. X      report_progress (report, "\nwriteable_file(): Error V()", TRUE);
  27852. X# ifndef SYSLOG
  27853. X      fclose (report);
  27854. X# endif
  27855. X      CLOSE_CLIENT (msg_sock);
  27856. X      _exit (14);
  27857. X    }
  27858. X    return FALSE;
  27859. X  }
  27860. X  return TRUE;
  27861. X}
  27862. X
  27863. X/*
  27864. X  Return TRUE id 'pid' in in 'clients', FALSE otherwise.
  27865. X*/
  27866. X
  27867. XBOOLEAN child_alive (int pid, CLIENT clients [])
  27868. X{
  27869. X  int i;
  27870. X
  27871. X  for (i = 0; i < nforks; i++)
  27872. X    if (clients[i].pid == pid)
  27873. X      return TRUE;
  27874. X  return FALSE;
  27875. X}
  27876. X#endif
  27877. *-*-END-of-src/serverd.c-*-*
  27878. echo x - src/signals.c
  27879. sed 's/^X//' >src/signals.c <<'*-*-END-of-src/signals.c-*-*'
  27880. X/*
  27881. X  ----------------------------------------------------------------------------
  27882. X  |                            SIGNAL FUNCTIONS                              |
  27883. X  |                                                                          |
  27884. X  |                              Version 2.2                                 |
  27885. X  |                                                                          |
  27886. X  |                (or, when Computer Science gets to you)                   |
  27887. X  |                                                                          |
  27888. X  |                    Written by Anastasios Kotsikonas                      |
  27889. X  |                           (tasos@cs.bu.edu)                              |
  27890. X  |                                                                          |
  27891. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  27892. X  | whole and not in parts, as long as you do not remove or alter the author |
  27893. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  27894. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  27895. X  | provided for your personal use, you you may not alter the functions      |
  27896. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  27897. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  27898. X  | any changes you may have made. No part of the source code bearing a         |
  27899. X  | copyright notice can be included in commercial software systems without  |
  27900. X  | written permission by the author.                         |
  27901. X  | By using this software you are bound by this agreement.                  |
  27902. X  | This software comes with no warranties and cannot be sold for profit.    |
  27903. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  27904. X  | files when distributing this software.                                   |
  27905. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  27906. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  27907. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  27908. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  27909. X  | (ii).                                                                    |
  27910. X  ----------------------------------------------------------------------------
  27911. X*/
  27912. X
  27913. X#include <stdio.h>
  27914. X#include <signal.h>
  27915. X#ifndef unknown_port
  27916. X# ifndef __NeXT__
  27917. X#  include <unistd.h>
  27918. X# else
  27919. X#  include <libc.h>
  27920. X# endif
  27921. X#endif
  27922. X#include "defs.h"
  27923. X#include "struct.h"
  27924. X
  27925. X#ifdef __STDC__
  27926. X# include <stdarg.h>
  27927. Xextern int  syscom (char *, ...);
  27928. Xextern char *tsprintf (char *, ...);
  27929. X#else
  27930. X# include <varargs.h>
  27931. Xextern int  syscom ();
  27932. Xextern char *tsprintf ();
  27933. X#endif
  27934. Xextern void report_progress (FILE *, char *, int);
  27935. Xextern char *extract_filename (char *);
  27936. Xextern int  gexit (int);
  27937. X
  27938. Xvoid   init_signals (void);
  27939. Xvoid   catch_signals (void);
  27940. Xvoid   my_abort (int);
  27941. X
  27942. Xstatic char *signals[MAX_SIGNAL + 1];   /* Signal names */
  27943. X
  27944. X/*
  27945. X  Initialize the signals[].
  27946. X*/
  27947. X
  27948. Xvoid init_signals ()
  27949. X{
  27950. X  signals[SIGILL] = "SIGILL";
  27951. X  signals[SIGQUIT] = "SIGQUIT";
  27952. X  signals[SIGTERM] = "SIGTERM";
  27953. X  signals[SIGBUS] = "SIGBUS";
  27954. X  signals[SIGSEGV] = "SIGSEGV";
  27955. X  signals[SIGKILL] = "SIGKILL";
  27956. X}
  27957. X
  27958. X/*
  27959. X  Catch signals to print messages before aborting.
  27960. X*/
  27961. X
  27962. Xvoid catch_signals ()
  27963. X{
  27964. X#ifdef _AIX
  27965. X  struct sigaction s;
  27966. X#endif
  27967. X  
  27968. X#ifdef SIGTSTP
  27969. X  signal (SIGTSTP, SIG_IGN);
  27970. X#endif
  27971. X#ifdef SIGTTIN
  27972. X  signal (SIGTTIN, SIG_IGN);
  27973. X#endif
  27974. X#ifdef SIGTTOU
  27975. X  signal (SIGTTOU, SIG_IGN);
  27976. X#endif
  27977. X  signal (SIGHUP, SIG_IGN);
  27978. X  signal (SIGILL, my_abort);
  27979. X  signal (SIGQUIT, my_abort);
  27980. X  signal (SIGTERM, my_abort);
  27981. X  signal (SIGSEGV, my_abort);
  27982. X  signal (SIGBUS, my_abort);
  27983. X  signal (SIGKILL, my_abort); /* Can't be caught, but why not try? */
  27984. X#ifdef _AIX
  27985. X  s.sa_handler = my_abort;
  27986. X  s.sa_mask.losigs = s.sa_mask.hisigs = 0;
  27987. X  s.sa_flags = SA_FULLDUMP;
  27988. X  sigaction (SIGSEGV, &s, (struct sigaction *) NULL);
  27989. X  sigaction (SIGILL, &s, (struct sigaction *) NULL);
  27990. X  sigaction (SIGQUIT, &s, (struct sigaction *) NULL);
  27991. X  sigaction (SIGBUS, &s, (struct sigaction *) NULL); 
  27992. X#endif
  27993. X}
  27994. X
  27995. X/*
  27996. X  Kill program after sending message to MANAGER that this is
  27997. X  about to happen (message is sent only when using UCB mail).
  27998. X*/
  27999. X
  28000. Xvoid my_abort (int sig)
  28001. X{
  28002. X  extern SYS sys;
  28003. X  extern char *prog;
  28004. X  extern FILE *report;
  28005. X  char *s;
  28006. X
  28007. X  signal (sig, SIG_IGN);
  28008. X  report_progress (report, tsprintf ("\n*** %s: Received %s signal ***\n", prog,
  28009. X           signals[sig]), -TRUE);
  28010. X  if (sys.options & BSD_MAIL)
  28011. X    syscom ("echo '' | %s -s '%s received %s' %s &", UCB_MAIL,
  28012. X        (prog ? prog : "???"), signals[sig], sys.manager);
  28013. X  if (sig == SIGQUIT || sig == SIGILL || sig == SIGSEGV || sig == SIGBUS) {
  28014. X    if (prog)
  28015. X      s = extract_filename (prog),
  28016. X#ifdef __STDC__
  28017. X      syscom ("rm -f %s/core; touch %s/core.%s; ln -s %s/core.%s %s/core",
  28018. X          PATH, PATH, s, PATH, s, PATH),
  28019. X#else
  28020. X      syscom ("rm -f %s/core; touch %s/core.%s; ln -s %s/core.%s %s/core",
  28021. X          PATH", PATH", s, PATH", s, PATH"),
  28022. X#endif
  28023. X      abort ();
  28024. X  }
  28025. X  gexit (8);
  28026. X}
  28027. *-*-END-of-src/signals.c-*-*
  28028. echo x - src/siul.c
  28029. sed 's/^X//' >src/siul.c <<'*-*-END-of-src/siul.c-*-*'
  28030. X/*
  28031. X  ----------------------------------------------------------------------------
  28032. X  |                 SYSTEM INTERACTIVE UNIX-LISTSERVER CLIENT             |
  28033. X  |                                         |
  28034. X  |                  Version 1.0                     |
  28035. X  |                                                                          |
  28036. X  |                (or, when Computer Science gets to you)                   |
  28037. X  |                                                                          |
  28038. X  |                    Written by Anastasios Kotsikonas                      |
  28039. X  |                           (tasos@cs.bu.edu)                              |
  28040. X  |                                                                          |
  28041. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  28042. X  | whole and not in parts, as long as you do not remove or alter the author |
  28043. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  28044. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  28045. X  | provided for your personal use, you you may not alter the functions      |
  28046. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  28047. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  28048. X  | any changes you may have made. No part of the source code bearing a         |
  28049. X  | copyright notice can be included in commercial software systems without  |
  28050. X  | written permission by the author.                         |
  28051. X  | By using this software you are bound by this agreement.             |
  28052. X  | This software comes with no warranties and cannot be sold for profit.    |
  28053. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  28054. X  | files when distributing this software.                                   |
  28055. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  28056. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  28057. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  28058. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  28059. X  | (ii).                                                                    |
  28060. X  ----------------------------------------------------------------------------
  28061. X
  28062. X  This is a copy of the iul client (iul.c) ported for internal use by listserv
  28063. X  for connections to remote servers while processing requests for remote lists.
  28064. X
  28065. X  Refer to the man page (iul.1) or iul.c for more information.
  28066. X
  28067. X  PLEASE DO NOT MODIFY THESE ROUTINES AS YOU MAY BREAK THE PROTOCOL AND CREATE
  28068. X  HAVOC WITH PEER INTERACTIVE UNIX LISTSERVERS. A LOT OF UNDOCUMENTED
  28069. X  ASSUMPTIONS ARE MADE. YOU SHOULD CONTACT ME ABOUT ANY CHANGES YOU WISH TO
  28070. X  MAKE.
  28071. X*/
  28072. X
  28073. X#include <signal.h>
  28074. X#include "defs.h"
  28075. X#undef     NSIG
  28076. X#ifdef GO_INTERACTIVE
  28077. X# include <stdio.h>
  28078. X# include <sys/types.h>
  28079. X# include <string.h>
  28080. X# if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  28081. X && !defined (sequent) && !defined (unknown_port)
  28082. X# include <malloc.h>
  28083. X# endif
  28084. X# ifndef unknown_port
  28085. X#  ifndef __NeXT__
  28086. X#   include <unistd.h>
  28087. X#  else
  28088. X#   include <libc.h>
  28089. X#  endif
  28090. X# endif
  28091. X# if defined (stardent) || defined (stellar) || defined (titan)
  28092. X#  include <rpc/types.h>
  28093. X# endif
  28094. X# include <sys/stat.h>
  28095. X# include <fcntl.h>
  28096. X# include <errno.h>
  28097. X#ifdef unknown_port
  28098. Xextern int errno;
  28099. X#endif
  28100. X# include <sys/socket.h>
  28101. X# include <netinet/in.h>
  28102. X# include <netdb.h>
  28103. X# include <sys/file.h>
  28104. X# include <sys/ioctl.h>
  28105. X# if defined (sco) || defined (M_XENIX) || defined (M_UNIX)
  28106. X#  include <sys/stropts.h>
  28107. X# endif
  28108. X# if (defined (sco) || defined (M_XENIX) || defined (M_UNIX)) && \
  28109. X  defined (HAVE_SELECT_H)
  28110. X#  include <sys/times.h>
  28111. X# else
  28112. X#  include <sys/time.h>
  28113. X# endif
  28114. X# ifdef HAVE_SETJMP_H
  28115. X#  include <setjmp.h>
  28116. X# endif
  28117. X# ifdef HAVE_SELECT_H
  28118. X#  include <sys/select.h>
  28119. X# endif
  28120. X# ifdef HAVE_ULIMIT_H
  28121. X#  include <ulimit.h>
  28122. X# endif
  28123. X# include "iul.h"
  28124. X
  28125. X# ifndef UL_GDESLIM
  28126. X#  define UL_GDESLIM    4
  28127. X# endif
  28128. X
  28129. X# ifndef FD_SET          /* for 4.2BSD */
  28130. X#  define FD_SETSIZE      (sizeof(fd_set) * 8)
  28131. X#  define FD_SET(n, p)    (((fd_set *) (p))->fds_bits[0] |= (1 << ((n) % 32)))
  28132. X#  define FD_CLR(n, p)    (((fd_set *) (p))->fds_bits[0] &= ~(1 << ((n) % 32)))
  28133. X#  define FD_ISSET(n, p)  (((fd_set *) (p))->fds_bits[0] & (1 << ((n) % 32)))
  28134. X#  define FD_ZERO(p)      memset ((char *)(p), '\0', sizeof(*(p)))
  28135. X# endif
  28136. X
  28137. X# ifndef __NeXT__
  28138. Xextern    long int atoi (char *);
  28139. X# else
  28140. Xextern    int atoi (const char *);
  28141. X# endif
  28142. Xextern  long int write_to_fd (int, char *, long int);
  28143. Xextern  void report_progress (FILE *, char *, BOOLEAN);
  28144. Xextern  char *upcase (char *);
  28145. Xextern    char *_strstr (char *, char *);
  28146. X
  28147. Xextern  FILE *report;
  28148. X
  28149. Xint     iul_server_response (int, int);
  28150. Xint      connect_to_iul_server (char *, int);
  28151. Xint     sighandle (int);
  28152. Xint     urg_data (int);
  28153. Xlong int read_from_fd (int, long int, int);
  28154. Xint     open_file (char *, int, int);
  28155. Xint      check_server_response (int, char *, int);
  28156. Xint     check_for_redirection (char *, char *);
  28157. X
  28158. Xlong int nbytes, sock_fd;
  28159. Xint  to_file, prompt_len, ofd, check_sio, append_output = 0;
  28160. Xchar args [256];
  28161. Xvoid (*f1)(), (*f2)(), (*f3)();
  28162. X# ifdef HAVE_SETJMP_H
  28163. Xjmp_buf env;
  28164. X# endif
  28165. X
  28166. X#else
  28167. X# include "iulp.h"
  28168. X#endif
  28169. X
  28170. X#ifdef __STDC__
  28171. X# include <stdarg.h>
  28172. Xint     siul (char *, int, char *, char *, int, char *, char *, ...);
  28173. Xextern  char *tsprintf (char *, ...);
  28174. X#else
  28175. X# include <varargs.h>
  28176. Xint     siul ();
  28177. Xextern  char *tsprintf ();
  28178. X#endif
  28179. X
  28180. X/*
  28181. X  Main function. Connect to server, issue requests and receive replies.
  28182. X
  28183. X  Returns: an IULP code or -1 on error.
  28184. X*/
  28185. X
  28186. X#ifdef __STDC__
  28187. Xint siul (char *Host, int port, char *Login, char *Passwd,
  28188. X      int response_timeout, char *outfile, char *control, ...)
  28189. X#else
  28190. Xint siul (Host, port, Login, Passwd, response_timeout, outfile, control,
  28191. X      va_alist)
  28192. Xchar *Host, *outfile, *Login, *Passwd, *control;
  28193. Xint port, response_timeout;
  28194. Xva_dcl
  28195. X#endif
  28196. X{
  28197. X#ifndef GO_INTERACTIVE
  28198. X  return SYS_ERROR;
  28199. X#else
  28200. X  char *buf, *tmp, infile [256], wbuf [256], *sep = "IUL:", *s, *r, rhost [256];
  28201. X  char login [256], passwd [256], host [256], raddr [256], taddr [256];
  28202. X  char version [80];
  28203. X  int cmd, i, sprompt_len, timeout, rfd, bytes_alloced = 0, naddr, naddr2,
  28204. X    _prompt_len;
  28205. X  struct stat stat_buf;
  28206. X  struct hostent *hp, *thp;
  28207. X  struct in_addr _addr;
  28208. X  va_list ap;
  28209. X
  28210. X
  28211. X  check_sio = 0;
  28212. X  strncpy (login, Login, 255);
  28213. X  strncpy (passwd, Passwd, 255);
  28214. X  strncpy (host, Host, 255);
  28215. X  login [255] = passwd [255] = host [255] = EOS;
  28216. X  if ((ofd = open (outfile, O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0) {
  28217. X    report_progress (report, tsprintf ("\nsiul(): Cannot open %s", outfile),
  28218. X             TRUE);
  28219. X    return -1;
  28220. X  }
  28221. X  bytes_alloced = 256;
  28222. X  if ((buf = (char *) malloc (bytes_alloced * sizeof (char))) == NULL) {
  28223. X    report_progress (report, "\nsiul(): malloc() failed", TRUE);
  28224. X    close (ofd);
  28225. X    return -1;
  28226. X  }
  28227. X
  28228. X# ifdef HAVE_SETJMP_H
  28229. X#  ifdef SIGIO
  28230. X  f1 = (void (*)()) signal (SIGIO, (void (*)()) urg_data);
  28231. X#  endif
  28232. X#  ifdef SIGURG
  28233. X  f2 = (void (*)()) signal (SIGURG, (void (*)()) urg_data);
  28234. X#  endif
  28235. X  f3 = (void (*)()) signal (SIGPIPE, (void (*)()) sighandle);
  28236. X# endif
  28237. X# ifdef __STDC__
  28238. X  va_start (ap, control);
  28239. X# else
  28240. X  va_start (ap);
  28241. X# endif
  28242. X
  28243. X  upcase (login);
  28244. X  s = login;
  28245. X  i = 0;
  28246. X  while (i < MAX_HOPS && (s = _strstr (s, sep)))
  28247. X    ++i,
  28248. X    ++s;
  28249. X  if (i >= MAX_HOPS) {
  28250. X    write_to_fd (ofd, "Too many hops.\n", 15);
  28251. X    cmd = PEER_UNAVAIL;
  28252. X    goto abort;
  28253. X  }
  28254. X  s = login;
  28255. X  upcase (host);
  28256. X  while ((s = _strstr (s, sep))) {    /* Check for loop */
  28257. X    s += 4;   /* Point to remote host */
  28258. X    sscanf (s, "%s", rhost);
  28259. X    if ((r = strchr (rhost, ';')))
  28260. X      *r = EOS;
  28261. X    thp = hp = gethostbyname (host);
  28262. X    if (hp) { /* Just got IP address(es) of host */
  28263. X      if ((thp = (struct hostent *) malloc (sizeof (struct hostent))) == NULL) {
  28264. X    report_progress (report, "\nsiul(): malloc() failed", TRUE);
  28265. X    close (ofd);
  28266. X    return -1;
  28267. X      }
  28268. X      memcpy ((char *) thp, (char *) hp, sizeof (*hp));
  28269. X#ifdef h_addr
  28270. X      naddr = 0;
  28271. X      if ((thp->h_addr_list = (char **) malloc (sizeof (char *))) == NULL) {
  28272. X    report_progress (report, "\nsiul(): malloc() failed", TRUE);
  28273. X    close (ofd);
  28274. X    return -1;
  28275. X      }
  28276. X      while (hp->h_addr_list[naddr]) { /* Copy all IP addresses */
  28277. X    if ((thp->h_addr_list = (char **)
  28278. X         realloc (thp->h_addr_list, (naddr + 2) * sizeof (char *))) == NULL) {
  28279. X      report_progress (report, "\nsiul(): realloc() failed", TRUE);
  28280. X      close (ofd);
  28281. X      return -1;
  28282. X    }
  28283. X    if ((thp->h_addr_list[naddr] =
  28284. X         (char *) malloc (thp->h_length * sizeof (char))) == NULL) {
  28285. X      report_progress (report, "\nsiul(): malloc() failed", TRUE);
  28286. X      close (ofd);
  28287. X      return -1;
  28288. X    }
  28289. X    memcpy ((char *) thp->h_addr_list[naddr],
  28290. X        (char *) hp->h_addr_list[naddr], hp->h_length);
  28291. X    thp->h_addr_list[++naddr] = NULL;
  28292. X      }
  28293. X      naddr = 0;
  28294. X      while (thp->h_addr_list[naddr]) { /* For all target addresses */
  28295. X    memcpy ((char *) &_addr, (char *) thp->h_addr_list[naddr++],
  28296. X        thp->h_length);
  28297. X    strcpy (taddr, (char *) inet_ntoa (_addr));
  28298. X    hp = gethostbyname (rhost);
  28299. X    naddr2 = 0;
  28300. X    while (hp && hp->h_addr_list[naddr2]) { /* Check all hosts visited */
  28301. X      memcpy ((char *) &_addr, (char *) hp->h_addr_list[naddr2++],
  28302. X          hp->h_length);
  28303. X      strcpy (raddr, (char *) inet_ntoa (_addr));
  28304. X      if (!strcmp (taddr, raddr)) { /* Loop */
  28305. X        write_to_fd (ofd, "Loop detected.\n", 15);
  28306. X        cmd = PEER_UNAVAIL;
  28307. X        goto abort;
  28308. X      }
  28309. X    }
  28310. X    /* Assume gethostbyname() failed */
  28311. X    if (!strcmp (host, rhost) || !strcmp (taddr, rhost)) { /* Loop !!! */
  28312. X      write_to_fd (ofd, "Loop detected.\n", 15);
  28313. X      cmd = PEER_UNAVAIL;
  28314. X      goto abort;
  28315. X    }
  28316. X      }
  28317. X      naddr = 0;
  28318. X      while (thp->h_addr_list[naddr])
  28319. X    free ((char *) thp->h_addr_list[naddr++]);
  28320. X      free ((char **) thp->h_addr_list);
  28321. X#else
  28322. X      if ((thp->h_addr = (char *) malloc ((strlen (hp->h_addr) + 1) *
  28323. X                      sizeof (char))) == NULL) {
  28324. X    report_progress (report, "\nsiul(): malloc() failed", TRUE);
  28325. X    close (ofd);
  28326. X    return -1;
  28327. X      }
  28328. X      memcpy ((char *) thp->h_addr, (char *) hp->h_addr, hp->h_length);
  28329. X      memcpy ((char *) &_addr, (char *) thp->h_addr, thp->h_length);
  28330. X      strcpy (taddr, (char *) inet_ntoa (_addr));
  28331. X      hp = gethostbyname (rhost);
  28332. X      memcpy ((char *) &_addr, (char *) hp->h_addr, hp->h_length);
  28333. X      strcpy (raddr, (char *) inet_ntoa (_addr));
  28334. X      if (!strcmp (taddr, raddr)) { /* Loop */
  28335. X    write_to_fd (ofd, "Loop detected.\n", 15);
  28336. X    cmd = PEER_UNAVAIL;
  28337. X    goto abort;
  28338. X      }
  28339. X      free ((char *) thp->h_addr);
  28340. X#endif
  28341. X      free ((struct hostent *) thp);
  28342. X    }
  28343. X    else { /* Host is an IP address */
  28344. X      naddr = 0;
  28345. X      hp = gethostbyname (rhost);
  28346. X#ifdef h_addr
  28347. X      while (hp && hp->h_addr_list[naddr]) { /* Check all hosts visited */
  28348. X    memcpy ((char *) &_addr, (char *) hp->h_addr_list[naddr++],
  28349. X        hp->h_length);
  28350. X    strcpy (raddr, (char *) inet_ntoa (_addr));
  28351. X    if (!strcmp (raddr, host)) { /* Loop */
  28352. X      write_to_fd (ofd, "Loop detected.\n", 15);
  28353. X      cmd = PEER_UNAVAIL;
  28354. X      goto abort;
  28355. X    }
  28356. X      }
  28357. X#else
  28358. X      memcpy ((char *) &_addr, (char *) hp->h_addr, hp->h_length);
  28359. X      strcpy (raddr, (char *) inet_ntoa (_addr));
  28360. X      if (!strcmp (raddr, host)) { /* Loop */
  28361. X    write_to_fd (ofd, "Loop detected.\n", 15);
  28362. X    cmd = PEER_UNAVAIL;
  28363. X    goto abort;
  28364. X      }
  28365. X#endif
  28366. X    }
  28367. X  }
  28368. X
  28369. X  if ((sock_fd = connect_to_iul_server (host, port)) < 0)
  28370. X    if ((sock_fd = connect_to_iul_server (host, (((port & 0xff00) >> 8) |
  28371. X     ((port & 0xff) << 8)))) < 0) {
  28372. X      write_to_fd (ofd, "Could not connect to host.\n", 27);
  28373. X      cmd = PEER_UNAVAIL;
  28374. X      goto abort;
  28375. X    }
  28376. X
  28377. X  if ((cmd = iul_server_response (sock_fd, response_timeout)) != CONNECT) {
  28378. X    write_to_fd (ofd, "Handshake failed, not an interactive UNIX ListServer \
  28379. Xserver.\n", 59);
  28380. X    goto abort;
  28381. X  }
  28382. X
  28383. X# ifdef HAVE_SETJMP_H
  28384. X  if (!setjmp (env)) {    /* No signal; proceed */
  28385. X# endif
  28386. X
  28387. X  if (check_server_response (cmd, args, response_timeout))
  28388. X# ifdef HAVE_SETJMP_H
  28389. X    longjmp (env, 1);
  28390. X# else
  28391. X    goto abort;
  28392. X# endif
  28393. X  if ((timeout = nbytes) < response_timeout)
  28394. X    response_timeout = timeout;
  28395. X  sscanf (args, "%s %d %d\n", version, &_prompt_len, &sprompt_len);
  28396. X
  28397. X  if ((cmd = iul_server_response (sock_fd, response_timeout)) < 0)
  28398. X# ifdef HAVE_SETJMP_H
  28399. X    longjmp (env, 1);
  28400. X# else
  28401. X    goto abort;
  28402. X# endif
  28403. X  check_server_response (cmd, args, response_timeout);
  28404. X  if (cmd == CONN_CLOSED || cmd == SERVER_BUSY || cmd == PEER_UNAVAIL ||
  28405. X      cmd == CONN_ABORTED || cmd == SYS_ERROR || cmd == CONN_TIMEOUT)
  28406. X    append_output = 1;
  28407. X  if (read_from_fd (sock_fd, nbytes, response_timeout) < 0)
  28408. X# ifdef HAVE_SETJMP_H
  28409. X    longjmp (env, 1);
  28410. X# else
  28411. X    goto abort;
  28412. X# endif
  28413. X  if (cmd == CONN_CLOSED || cmd == SERVER_BUSY || cmd == PEER_UNAVAIL ||
  28414. X      cmd == CONN_ABORTED || cmd == SYS_ERROR || cmd == CONN_TIMEOUT)
  28415. X# ifdef HAVE_SETJMP_H
  28416. X    longjmp (env, 1);
  28417. X# else
  28418. X    goto abort;
  28419. X# endif
  28420. X  prompt_len = _prompt_len;
  28421. X  strcat (login, "\n");
  28422. X  if (write_to_fd (sock_fd, login, strlen (login)) < 0)
  28423. X# ifdef HAVE_SETJMP_H
  28424. X    longjmp (env, 1);
  28425. X# else
  28426. X    goto abort;
  28427. X# endif
  28428. X  if ((cmd = iul_server_response (sock_fd, response_timeout)) < 0)
  28429. X# ifdef HAVE_SETJMP_H
  28430. X    longjmp (env, 1);
  28431. X# else
  28432. X    goto abort;
  28433. X# endif
  28434. X  if (check_server_response (cmd, args, response_timeout))
  28435. X# ifdef HAVE_SETJMP_H
  28436. X    longjmp (env, 1);
  28437. X# else
  28438. X    goto abort;
  28439. X# endif
  28440. X  if (cmd == PASSWORD_REQUIRED) {
  28441. X    strcat (passwd, "\n");
  28442. X    if (write_to_fd (sock_fd, passwd, strlen (passwd)) < 0)
  28443. X# ifdef HAVE_SETJMP_H
  28444. X      longjmp (env, 1);
  28445. X# else
  28446. X      goto abort;
  28447. X# endif
  28448. X  }
  28449. X  else if (cmd == PEER_UNAVAIL)
  28450. X# ifdef HAVE_SETJMP_H
  28451. X    longjmp (env, 1);
  28452. X# else
  28453. X    goto abort;
  28454. X# endif
  28455. X
  28456. X  RESET (buf);
  28457. X  vsprintf (buf, control, ap);
  28458. X  va_end (ap);
  28459. X  strcat (buf, "\nquit\n");    /* Just in case */
  28460. X  while (cmd != CONN_CLOSED && cmd != CONN_ABORTED && cmd != CONN_TIMEOUT) {
  28461. X    check_sio = 0;
  28462. X    if ((cmd = iul_server_response (sock_fd, response_timeout)) < 0) break;
  28463. X    if (check_server_response (cmd, args, response_timeout)) break;
  28464. X    if (cmd == TEST_FILE_PERMISSIONS) continue;
  28465. X    if (cmd != CONN_ABORTED && cmd != CONN_TIMEOUT)
  28466. X      if (read_from_fd (sock_fd, nbytes, response_timeout) < 0) break;
  28467. X    check_sio = ! (append_output = 0);
  28468. X    if (cmd != CONN_CLOSED && cmd != CONN_ABORTED && cmd != CONN_TIMEOUT) {
  28469. X      if (buf [0] == EOS) {
  28470. X        RESET (infile);
  28471. X        if ((rfd = check_for_redirection (buf, infile)) < 0)
  28472. X      strcpy (buf, "\n");
  28473. X        if (rfd >= 0 && infile [0] != EOS) { /* Input redirection */
  28474. X      fstat (rfd, &stat_buf);
  28475. X      if (!(stat_buf.st_mode & S_IFREG)) {
  28476. X        printf ("%s: Not a regular file\n", infile);
  28477. X        strcpy (buf, "\n");
  28478. X        goto skip;
  28479. X      }
  28480. X      if ((stat_buf.st_size + strlen (buf) + 2) > bytes_alloced) {
  28481. X        bytes_alloced = stat_buf.st_size + strlen (buf) + 2;
  28482. X        if ((buf = (char *) realloc (buf, bytes_alloced * sizeof (char))) ==
  28483. X            NULL) {
  28484. X          write_to_fd (ofd, "FATAL: internal memory error.\n", 30);
  28485. X          report_progress (report, "\nsiul(): realloc() failed", TRUE);
  28486. X          cmd = -1;
  28487. X          break;
  28488. X        }
  28489. X      }
  28490. X      i = strlen (buf);
  28491. X      if (read (rfd, &buf [strlen (buf)], stat_buf.st_size) <
  28492. X          stat_buf.st_size) {
  28493. X        write_to_fd (ofd, "FATAL: Failed to read all of the input \
  28494. Xfile.\n", 45);
  28495. X        cmd = -1;
  28496. X        break;
  28497. X      }
  28498. X      buf [i + stat_buf.st_size] = EOS;
  28499. X      if (buf [i + stat_buf.st_size - 1] != '\n')
  28500. X        strcat (&buf [i + stat_buf.st_size], "\n");
  28501. X      close (rfd);
  28502. X        }
  28503. X      }
  28504. X      skip:
  28505. X      strncpy (wbuf, buf, 174);
  28506. X      while (!(tmp = strchr (wbuf, '\n')))
  28507. X    wbuf [174] = '\n';
  28508. X      if (tmp != wbuf) /* Not an empty line */
  28509. X        sprintf (tmp, " >> %s\n", outfile);
  28510. X      if (write_to_fd (sock_fd, wbuf, strlen (wbuf)) < 0) break;
  28511. X      sprintf (buf, "%s", strchr (buf, '\n') + 1);
  28512. X      if (strncmp (wbuf, "quit", 4) && strncmp (wbuf, "exit", 4) &&
  28513. X      strncmp (wbuf, "__abort__", 9))
  28514. X    append_output = 1;
  28515. X    }
  28516. X  }
  28517. X
  28518. X# ifdef HAVE_SETJMP_H
  28519. X  } /* if (!setjmp (env)) ... */
  28520. X  else { /* Return from longjmp () */
  28521. X  }
  28522. X# endif
  28523. X
  28524. X abort:
  28525. X# ifdef HAVE_SETJMP_H
  28526. X#  ifdef SIGIO
  28527. X  signal (SIGIO, (void (*)()) f1);
  28528. X#  endif
  28529. X#  ifdef SIGURG
  28530. X  signal (SIGURG, (void (*)()) f2);
  28531. X#  endif
  28532. X  signal (SIGPIPE, (void (*)()) f3);
  28533. X# endif
  28534. X  if (sock_fd >= 0)
  28535. X    close (sock_fd);
  28536. X  close (ofd);
  28537. X  if (buf)
  28538. X    free ((char *) buf);
  28539. X  return cmd;
  28540. X#endif
  28541. X}
  28542. X
  28543. X#ifdef GO_INTERACTIVE
  28544. X/*
  28545. X  Get server response. Store in 'nbytes' the number of bytes in the actual
  28546. X  message that follows, and in 'args' the (optional) file name.
  28547. X
  28548. X  Returns: the server reply code, CONN_TIMEOUT, CONN_ABORTED, or -1 on 
  28549. X  protocol errors.
  28550. X*/
  28551. X
  28552. Xint iul_server_response (int sock_fd, int response_timeout)
  28553. X{
  28554. X  char buf [256];
  28555. X  int cmd = -1, i, bytes_to_read = 4, bytes_read = 0, err, l = sizeof (int);
  28556. X  long int time_started;
  28557. X
  28558. X  time_started = time (0);
  28559. X  memset (buf, EOS, 256);
  28560. X  while (bytes_to_read) {
  28561. X    errno = 0;
  28562. X    /* Get server command */
  28563. X    bytes_read = read (sock_fd, &buf [4 - bytes_to_read], bytes_to_read);
  28564. X    if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  28565. X    errno == ECONNREFUSED) {
  28566. X      nbytes = 0;
  28567. X      return CONN_ABORTED;
  28568. X    }
  28569. X    if (!getsockopt (sock_fd, SOL_SOCKET, SO_ERROR, (char *) &err, (char *) &l)) {
  28570. X      if (err || buf [4 - bytes_to_read] == EOF) {
  28571. X    nbytes = 0;
  28572. X    return CONN_ABORTED;
  28573. X      }
  28574. X    }
  28575. X    else {
  28576. X      nbytes = 0;
  28577. X      return SYS_ERROR;
  28578. X    }
  28579. X    if (errno || bytes_read < 1)
  28580. X      if ((time (0) - time_started) > response_timeout) {
  28581. X    nbytes = 0;
  28582. X    return CONN_TIMEOUT;
  28583. X      }
  28584. X    if (bytes_read > 0)
  28585. X      bytes_to_read -= bytes_read;
  28586. X  }
  28587. X  buf[3] = EOS;
  28588. X  cmd = atoi (buf);
  28589. X  i = 0;
  28590. X  do {        /* Get # of bytes in actual message */
  28591. X    again1:
  28592. X    if (read (sock_fd, &buf[i], 1) < 1) {
  28593. X      if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  28594. X      errno == ECONNREFUSED) {
  28595. X    nbytes = 0;
  28596. X    return CONN_ABORTED;
  28597. X      }
  28598. X      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
  28599. X    if ((time (0) - time_started) > response_timeout) {
  28600. X      nbytes = 0;
  28601. X      return CONN_TIMEOUT;
  28602. X    }
  28603. X    goto again1;
  28604. X      }
  28605. X      write_to_fd (ofd, "Protocol error in control string.\n", 34);
  28606. X      return -1;
  28607. X    }
  28608. X    i++;
  28609. X  } while (buf[i - 1] != ' ');
  28610. X
  28611. X  buf[i - 1] = EOS;
  28612. X  nbytes = atoi (buf);
  28613. X  RESET (args);
  28614. X  i = 0;
  28615. X  do {        /* Get filename (optional) */
  28616. X    again2:
  28617. X    if (read (sock_fd, &args[i], 1) < 1) {
  28618. X      if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  28619. X          errno == ECONNREFUSED) {
  28620. X    nbytes = 0;
  28621. X        return CONN_ABORTED;
  28622. X      }
  28623. X      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
  28624. X        if ((time (0) - time_started) > response_timeout) {
  28625. X          nbytes = 0;
  28626. X          return CONN_TIMEOUT;
  28627. X        }
  28628. X        goto again2;
  28629. X      }
  28630. X      write_to_fd (ofd, "Protocol error in control string.\n", 34);
  28631. X      return -1;
  28632. X    }
  28633. X    ++i;
  28634. X  } while (args[i - 1] != '\n');
  28635. X  args[i - 1]= EOS;
  28636. X  return cmd;
  28637. X}
  28638. X
  28639. X/*
  28640. X  Establish connection with unix-listserver. The socket is marked as
  28641. X  non-blocking.
  28642. X
  28643. X  Returns: the socket file descriptor, or -1 on error.
  28644. X*/
  28645. X
  28646. Xint connect_to_iul_server (char *host, int port)
  28647. X{
  28648. X  int sock_fd, sendbuf = BUFFSIZ, recvbuf = BUFFSIZ, value = 1, nfds, naddr = 0;
  28649. X  struct sockaddr_in sin;
  28650. X  struct hostent *hostentry;
  28651. X  struct timeval timeout;
  28652. X  fd_set readfds, writefds;
  28653. X  timeout.tv_sec = timeout.tv_usec = 0;
  28654. X  if (!(hostentry = gethostbyname (host))) { /* Host name failed; try IP */
  28655. X    sin.sin_addr.s_addr = inet_addr (host);
  28656. X    if (! (hostentry = gethostbyaddr ((char *) &sin.sin_addr,
  28657. X                      sizeof (struct in_addr),
  28658. X                      AF_INET))) {
  28659. X      write_to_fd (ofd, "Invalid host.\n", 14);
  28660. X      return -1;
  28661. X    }
  28662. X  }
  28663. X
  28664. X  do {
  28665. X    if ((sock_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  28666. X      report_progress (report, "\nconnect_to_iul_server(): Could not create \
  28667. Xsocket", TRUE);
  28668. X      return -1;
  28669. X    }
  28670. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_SNDBUF, (char *) &sendbuf,
  28671. X            sizeof (sendbuf)) < 0)
  28672. X      report_progress (report, "\nconnect_to_iul_server(): WARNING: Could not \
  28673. Xset send-buffer size: setsockopt() error", TRUE);
  28674. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_RCVBUF, (char *) &recvbuf,
  28675. X            sizeof (recvbuf)) < 0)
  28676. X      report_progress (report, "\nconnect_to_iul_server(): WARNING: Could not \
  28677. Xset receive-buffer size: setsockopt() error", TRUE);
  28678. X    if (setsockopt (sock_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &value,
  28679. X            sizeof (value)) < 0)
  28680. X      report_progress (report, "\nconnect_to_iul_server(): WARNING: Cannot \
  28681. Xtoggle keep-alive connections: setsockopt() error", TRUE);
  28682. X
  28683. X#ifdef h_addr
  28684. X    memcpy ((char *) &sin.sin_addr.s_addr,
  28685. X        (char *) hostentry->h_addr_list[naddr++],
  28686. X        hostentry->h_length);
  28687. X#else
  28688. X    memcpy ((char *) &sin.sin_addr.s_addr,
  28689. X        (char *) hostentry->h_addr,
  28690. X        hostentry->h_length);
  28691. X#endif
  28692. X    sin.sin_family = AF_INET;
  28693. X    sin.sin_port = htons (port);
  28694. X    memset (sin.sin_zero, EOS, sizeof (sin.sin_zero));
  28695. X    if (connect (sock_fd, (struct sockaddr *) &sin,
  28696. X         sizeof (struct sockaddr_in)) < 0) {
  28697. X      if (errno != EINPROGRESS) {
  28698. X#ifdef h_addr
  28699. X    if (!hostentry->h_addr_list[naddr]) {
  28700. X#endif
  28701. X      close (sock_fd);
  28702. X      return -1;
  28703. X#ifdef h_addr
  28704. X    }
  28705. X    else {
  28706. X      close (sock_fd);
  28707. X      continue;
  28708. X    }
  28709. X#endif
  28710. X      }
  28711. X      FD_ZERO (&readfds);
  28712. X      FD_ZERO (&writefds);
  28713. X      do {
  28714. X    FD_SET (sock_fd, &readfds);
  28715. X    FD_SET (sock_fd, &writefds);
  28716. X    errno = 0;
  28717. X# if defined (sequent) || defined (__NeXT__) || defined (__convex__) || \
  28718. X  defined (apollo) || defined (unknown_port)
  28719. X    nfds = getdtablesize ();
  28720. X# else
  28721. X    nfds = ulimit (UL_GDESLIM);
  28722. X# endif
  28723. X    value = select ((nfds > 0 ? nfds : 20), &readfds, &writefds, NULL,
  28724. X            &timeout);
  28725. X      } while (value == -1 && errno == EINTR);
  28726. X
  28727. X      if (value < 0) {
  28728. X    close (sock_fd);
  28729. X    return -1;
  28730. X      }
  28731. X      break;    /* Successful connection */
  28732. X    }
  28733. X    else
  28734. X      break;
  28735. X  } while (007);
  28736. X# ifdef NONBLOCKING_IO
  28737. X  if (fcntl (sock_fd, F_SETFL, (fcntl (sock_fd, F_GETFL, 0) | O_NDELAY)) < 0) {
  28738. X    report_progress (report, "\nconnect_to_iul_server(): Could not set \
  28739. Xnon-blocking I/O", TRUE);
  28740. X    close (sock_fd);
  28741. X    return -1;
  28742. X  }
  28743. X# endif
  28744. X# ifdef HAVE_SETJMP_H
  28745. X#  if defined (sco) || defined (M_XENIX) || defined (M_UNIX)
  28746. X  if (ioctl (sock_fd, I_SETSIG, S_INPUT) < 0) {
  28747. X    report_progress (report, "\nconnect_to_iul_server(): Cannot set SIGIO",
  28748. X             TRUE);
  28749. X    close (sock_fd);
  28750. X    return -1;
  28751. X  }
  28752. X#  else
  28753. X#   ifdef F_SETOWN
  28754. X  if (fcntl (sock_fd, F_SETOWN, getpid()) < 0) {
  28755. X    report_progress (report, "\nconnect_to_iul_server(): Cannot assign \
  28756. Xsocket to process group", TRUE);
  28757. X    close (sock_fd);
  28758. X    return -1;
  28759. X  }
  28760. X#   elif defined (SIOCSPGRP)
  28761. X  value = -getpid();
  28762. X  if (ioctl (sock_fd, SIOCSPGRP, (char *) &value) < 0) {
  28763. X    report_progress (report, "\nconnect_to_iul_server(): Cannot assign \
  28764. Xsocket to process group", TRUE);
  28765. X    close (sock_fd);
  28766. X    return -1;
  28767. X  }
  28768. X#   else
  28769. X  report_progress (report, "\nconnect_to_iul_server(): Cannot assign \
  28770. Xsocket to process group", TRUE);
  28771. X  close (sock_fd);
  28772. X  return -1;
  28773. X#   endif
  28774. X#   ifdef FASYNC
  28775. X  if (fcntl (sock_fd, F_SETFL, (fcntl (sock_fd, F_GETFL, 0) | FASYNC)) < 0) {
  28776. X    report_progress (report, "\nconnect_to_iul_server(): Cannot set \
  28777. Xasynchronous I/O for socket", TRUE);
  28778. X    close (sock_fd);
  28779. X    return -1;
  28780. X  }
  28781. X#   elif defined (FIOASYNC)
  28782. X  value = 1;
  28783. X  if (ioctl (sock_fd, FIOASYNC, (char *) &value) < 0) {
  28784. X    report_progress (report, "\nconnect_to_iul_server(): Cannot set \
  28785. Xasynchronous I/O for socket", TRUE);
  28786. X    close (sock_fd);
  28787. X    return -1;
  28788. X  }
  28789. X#   else
  28790. X  report_progress (report, "\nconnect_to_iul_server(): Cannot set \
  28791. Xasynchronous I/O for socket", TRUE);
  28792. X  close (sock_fd);
  28793. X  return -1;
  28794. X#   endif
  28795. X#  endif
  28796. X# endif
  28797. X  return sock_fd;
  28798. X}
  28799. X
  28800. X# ifdef HAVE_SETJMP_H
  28801. X/*
  28802. X  Handle signals; the client sends an '__abort__' command and returns (long
  28803. X  jump); '__abort__' causes the other end to shut down.
  28804. X*/
  28805. X
  28806. Xint sighandle (int sig)
  28807. X{
  28808. X  check_sio = 0;
  28809. X  write (sock_fd, "__abort__\n", 10);
  28810. X  longjmp (env, 1);
  28811. X}
  28812. X
  28813. X/*
  28814. X  Urgent data from server; read it and return. Urgent data is received
  28815. X  when a connection is timed out or when the server shuts down.
  28816. X*/
  28817. X
  28818. Xint urg_data (int sig)
  28819. X{
  28820. X  int cmd;
  28821. X
  28822. X  if (!check_sio) {
  28823. X    signal (sig, (void (*)()) urg_data);
  28824. X    return;
  28825. X  }
  28826. X  signal (sig, SIG_IGN);
  28827. X  if ((cmd = iul_server_response (sock_fd, 30)) >= 0)
  28828. X    if (cmd == CONN_ABORTED || cmd == CONN_TIMEOUT || cmd == CONN_CLOSED)
  28829. X      check_server_response (cmd, args, 30),
  28830. X      append_output = 1,
  28831. X      read_from_fd (sock_fd, nbytes, 30);
  28832. X  longjmp (env, 1);
  28833. X}
  28834. X# endif
  28835. X
  28836. X/*
  28837. X  Read from a socket and write to ofd.
  28838. X
  28839. X  Returns: the actual number of bytes read on succes, or the negative of
  28840. X  that number (or -1) on error.
  28841. X*/
  28842. X
  28843. Xlong int read_from_fd (int rfd, long int bytes_to_read, int response_timeout)
  28844. X{
  28845. X  long int bytes_read, total_bytes = 0, time_started;
  28846. X  char buf [BUFFSIZ];
  28847. X
  28848. X  time_started = time (0);
  28849. X  if (bytes_to_read <= 0)
  28850. X    return 0;
  28851. X  errno = 0;
  28852. X  while ((bytes_read = read (rfd, buf, MIN (bytes_to_read, BUFFSIZ))) <
  28853. X     bytes_to_read) {
  28854. X    if (bytes_read < 0 && errno && errno != EWOULDBLOCK && errno != EAGAIN &&
  28855. X    errno != EINTR
  28856. X#ifdef ERESTART
  28857. X    && errno != ERESTART
  28858. X#endif
  28859. X    ) {
  28860. X      char error [256];
  28861. X      sprintf (error, "\nread_from_fd(): ");
  28862. X      switch (errno) {
  28863. X    case EBADF: strcat (error, "Bad file number"); break;
  28864. X    case EFAULT: strcat (error, "Bad address"); break;
  28865. X    case EFBIG: strcat (error, "File limit reached"); break;
  28866. X    case EINVAL: strcat (error, "Negative seek pointer"); break;
  28867. X    case EIO: strcat (error, "I/O error"); break;
  28868. X    case ENOSPC: strcat (error, "No space left on device"); break;
  28869. X    case ENXIO: strcat (error, "No such device or address"); break;
  28870. X    case ERANGE: sprintf (error + strlen (error), "Bytes to read (%d) \
  28871. Xout of range", bytes_to_read); break;
  28872. X    default: sprintf (error + strlen (error), "Error number %d", errno);
  28873. X      }
  28874. X      report_progress (report, error, TRUE);
  28875. X      return (total_bytes > 0 ? -total_bytes : -1);
  28876. X    }
  28877. X    else if ((time (0) - time_started) > response_timeout)
  28878. X      return (total_bytes > 0 ? -total_bytes : -1);
  28879. X    if (bytes_read > 0) {
  28880. X      total_bytes += bytes_read;
  28881. X      bytes_to_read -= bytes_read;
  28882. X      if (to_file) {
  28883. X    if (bytes_to_read < prompt_len)
  28884. X      to_file = 0;
  28885. X    if (write_to_fd (ofd, buf,
  28886. X             (bytes_to_read < prompt_len ? 
  28887. X              bytes_read - prompt_len + bytes_to_read :
  28888. X              bytes_read)) < 0)
  28889. X      return (total_bytes > 0 ? -total_bytes : -1);
  28890. X      }
  28891. X      else if (append_output)
  28892. X    if (write_to_fd (ofd, buf,
  28893. X             (bytes_to_read < prompt_len ? 
  28894. X              bytes_read - prompt_len + bytes_to_read :
  28895. X              bytes_read)) < 0)
  28896. X      return (total_bytes > 0 ? -total_bytes : -1);
  28897. X    }
  28898. X    errno = 0;
  28899. X  }
  28900. X  if (bytes_read > 0) {
  28901. X    total_bytes += bytes_read;
  28902. X    if ((append_output || to_file) && bytes_read > prompt_len)
  28903. X      if (write_to_fd (ofd, buf, bytes_read - prompt_len) < 0)
  28904. X    return -1;
  28905. X  }
  28906. X  to_file = 0;
  28907. X  return total_bytes;
  28908. X}
  28909. X
  28910. X/*
  28911. X  Open a file for writing or appending. If 'test' is set, make sure
  28912. X  the file is writeable, notify the server and close the file; else prepare
  28913. X  for the transfer. When the server is inquiring about a file's write
  28914. X  permissions it sends zero bytes as the length of the message.
  28915. X
  28916. X  Returns: 0 on succes, -1 otherwise.
  28917. X*/
  28918. X
  28919. Xint open_file (char *file, int mode, int test)
  28920. X{
  28921. X  char msg [MAX_LINE];
  28922. X  int fd;
  28923. X
  28924. X  if ((fd = open (file, O_CREAT | mode, 0600)) < 0)
  28925. X    to_file = 0,
  28926. X    sprintf (msg, "%s: Permission denied.\n", file),
  28927. X    write_to_fd (ofd, msg, strlen (msg)),
  28928. X    nbytes = prompt_len,
  28929. X    sprintf (msg, "%d", PERMISSION_DENIED);
  28930. X  else {
  28931. X    if (nbytes > 0)
  28932. X      to_file = 1;
  28933. X    else
  28934. X      sprintf (msg, "%d", OK);
  28935. X    close (fd);
  28936. X  }
  28937. X  if (test)
  28938. X    if (write_to_fd (sock_fd, msg, strlen (msg)) < 0)
  28939. X      return -1;
  28940. X  return 0;
  28941. X}
  28942. X
  28943. X/*
  28944. X  Identify the server's response and take appropriate action.
  28945. X
  28946. X  Returns: 0 on success, -1 otherwise.
  28947. X*/
  28948. X
  28949. Xint check_server_response (int cmd, char *file, int response_timeout)
  28950. X{
  28951. X    switch (cmd) {
  28952. X    case OK:
  28953. X    case CONNECT:
  28954. X    case SYNTAX_ERROR:
  28955. X    case INVALID_REQ:
  28956. X    case BAD_ARCHIVE:
  28957. X    case RESTRICTED_REQ:
  28958. X    case NOT_OWNER:
  28959. X    case SYS_ERROR:
  28960. X    case SERVER_BUSY:
  28961. X    case PERMISSION_DENIED:
  28962. X    case CONN_CLOSED:
  28963. X    case PEER_UNAVAIL:
  28964. X    case MORE_INPUT_REQUIRED:
  28965. X    case CONTINUED: break;
  28966. X    case PASSWORD_REQUIRED:
  28967. X     if (read_from_fd (sock_fd, nbytes, response_timeout) < 0) return -1;
  28968. X     break;
  28969. X    case CONN_ABORTED:
  28970. X    case CONN_TIMEOUT: return -1; break;
  28971. X    case TEST_FILE_PERMISSIONS:
  28972. X     if (open_file (file, O_WRONLY | O_APPEND, 1)) return -1;
  28973. X     break;
  28974. X    case WRITE_TO_FILE_ASC:
  28975. X     if (open_file (file, O_WRONLY | O_TRUNC, 0)) return -1;
  28976. X     break;
  28977. X    case WRITE_TO_FILE_BIN:
  28978. X     if (open_file (file, O_WRONLY | O_TRUNC, 0)) return -1;
  28979. X     break;
  28980. X    case APPEND_TO_FILE_ASC:
  28981. X     if (open_file (file, O_WRONLY | O_APPEND, 0)) return -1;
  28982. X     break;
  28983. X    case APPEND_TO_FILE_BIN:
  28984. X     if (open_file (file, O_WRONLY | O_APPEND, 0)) return -1;
  28985. X     break;
  28986. X    default: write_to_fd (ofd, "Protocol error.\n", 16); return -1;
  28987. X  }
  28988. X  return 0;
  28989. X}
  28990. X
  28991. X/*
  28992. X  Check for input redirection, and if so check for for permissions too.
  28993. X
  28994. X  Returns: the opened file descriptor on succes, -1 on error.
  28995. X*/
  28996. X
  28997. Xint check_for_redirection (char *buf, char *infile)
  28998. X{
  28999. X  char *redirect, *s;
  29000. X  int fd = 0;
  29001. X
  29002. X  if ((redirect = strrchr (buf, '<')) != NULL)
  29003. X    if (redirect != buf && *(redirect - 1) == '\\')
  29004. X      sprintf (redirect - 1, "%s", redirect); /* Remove \ */
  29005. X    else {
  29006. X      RESET (infile);
  29007. X      sscanf (redirect + 1, "%s", infile);
  29008. X      if (infile [0] == EOS) {
  29009. X    write_to_fd (ofd, "Invalid null input redirect.\n", 29);
  29010. X    return -1;
  29011. X      }
  29012. X      if ((fd = open (infile, O_RDONLY)) < 0) {
  29013. X    write_to_fd (ofd, "File not found or inadequate permissions.\n", 42);
  29014. X    return -1;
  29015. X      }
  29016. X      s = redirect + 1; /* Remove < and file name */
  29017. X      while (*s == ' ' || *s == '\t') ++s;
  29018. X      while (*s != ' ' && *s != '\t' && *s != '\n') ++s;
  29019. X      sprintf (redirect, "%s", s);
  29020. X    }
  29021. X  return fd;
  29022. X}
  29023. X#endif
  29024. *-*-END-of-src/siul.c-*-*
  29025. echo x - src/start.c
  29026. sed 's/^X//' >src/start.c <<'*-*-END-of-src/start.c-*-*'
  29027. X/*
  29028. X  ----------------------------------------------------------------------------
  29029. X  |                  UNIX LISTSERVER SYSTEM HOUSEKEEPER                      |
  29030. X  |                                                                          |
  29031. X  |                              Version 2.8                                 |
  29032. X  |                                                                          |
  29033. X  |                (or, when Computer Science gets to you)                   |
  29034. X  |                                                                          |
  29035. X  |                    Written by Anastasios Kotsikonas                      |
  29036. X  |                           (tasos@cs.bu.edu)                              |
  29037. X  |                                                                          |
  29038. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  29039. X  | whole and not in parts, as long as you do not remove or alter the author |
  29040. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  29041. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  29042. X  | provided for your personal use, you you may not alter the functions      |
  29043. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  29044. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  29045. X  | any changes you may have made. No part of the source code bearing a         |
  29046. X  | copyright notice can be included in commercial software systems without  |
  29047. X  | written permission by the author.                         |
  29048. X  | By using this software you are bound by this agreement.                  |
  29049. X  | This software comes with no warranties and cannot be sold for profit.    |
  29050. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  29051. X  | files when distributing this software.                                   |
  29052. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas             |
  29053. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  29054. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  29055. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  29056. X  | (ii).                                                                    |
  29057. X  ----------------------------------------------------------------------------
  29058. X
  29059. X  This is the proper way of starting the system. The program verifies
  29060. X  that no other serverd, queued, list or listserv programs are running on the 
  29061. X  system (and kills them before proceeding -- after confirming), 
  29062. X  makes sure the required files exist (and creates new ones if missing -- 
  29063. X  after confirming), backs up all reports into files with extension .acc,
  29064. X  creates new directories for new mailing lists as necessary,
  29065. X  and finally spawns serverd. start reports to REPORT_START.
  29066. X
  29067. X  COMMAND LINE OPTIONS:
  29068. X    -k: just kill all pertinent programs that may already be running; no
  29069. X    mailing list is started in this case.
  29070. X    -c: Do not confirm before killing a process.
  29071. X    -r: Do not report; useful when starting up when system is rebooted.
  29072. X    -s: After a process is killed, start sleeps for some time. This turns
  29073. X    sleeping off -- to be used only when restarting the system via
  29074. X    a 'restart' request.
  29075. X  
  29076. X  WARNING: The program won't work correctly in the absence of an extended
  29077. X  egrep facility that does matching at the end of a line with a $ and 
  29078. X  accepts multiple regular expressions separated by a |. In this case,
  29079. X  the user may have to manually look for and terminate any such programs.
  29080. X  Also when the output of the 'ps' command exceeds 80 characters (due perhaps
  29081. X  to long path names) the user may again have to terminate programs by hand.
  29082. X  Note that a file locking mechanism  for serverd, list and listserv is used 
  29083. X  to ensure against multiple executions of the same program.
  29084. X
  29085. X  WARNING: When using the SYSV ps command and it chops output to 80 characters,
  29086. X  start may not be able to locate processes already running; this may occur if
  29087. X  the path to HOMEDIR is too long.
  29088. X*/
  29089. X
  29090. X#include <stdio.h>
  29091. X#include <sys/types.h>
  29092. X#include <string.h>
  29093. X#ifdef SYSLOG
  29094. X# ifdef ultrix
  29095. X#  include <sys/syslog.h>
  29096. X# else
  29097. X#  include <syslog.h>
  29098. X# endif
  29099. X#endif
  29100. X#include <signal.h>
  29101. X#if !defined (__convex__) && !defined (__NeXT__) && !defined (apollo) \
  29102. X && !defined (sequent) && !defined (unknown_port)
  29103. X# include <malloc.h>
  29104. X#endif
  29105. X#ifndef unknown_port
  29106. X# ifndef __NeXT__
  29107. X#  include <unistd.h>
  29108. X# else
  29109. X#  include <libc.h>
  29110. X# endif
  29111. X#endif
  29112. X#include <sys/stat.h>
  29113. X#include "defs.h"
  29114. X#include "start.h"
  29115. X#include "struct.h"
  29116. X#include "global.h"
  29117. X#if defined (__NeXT__) || defined (unknown_port)
  29118. X# include "next.h"
  29119. X#endif
  29120. X
  29121. X/*
  29122. X  Function prototypes:
  29123. X*/
  29124. X
  29125. X#ifdef __STDC__
  29126. X# include "ansi/misc.h"
  29127. X# include <stdarg.h>
  29128. Xextern int  syscom (char *, ...);
  29129. Xextern char *tsprintf (char *, ...);
  29130. X#else
  29131. X# include "nonansi/misc.h"
  29132. X# include <varargs.h>
  29133. Xextern int  syscom ();
  29134. Xextern char *tsprintf ();
  29135. X#endif
  29136. Xextern int  sys_config (FILE *, SYS *);
  29137. Xextern char *extract_filename (char *);
  29138. Xextern void report_progress (FILE *, char *, int);
  29139. Xextern int  _getopt (int, char **, char *);
  29140. Xextern void setup_string (char *, char *, char *);
  29141. Xextern void shrink (char *);
  29142. Xextern char *mystrdup (char *);
  29143. Xextern int echo (char *, char *);
  29144. Xextern int echo_append (char *, char *);
  29145. Xextern int mv (char *, char *);
  29146. Xextern int cp (char *, char *);
  29147. Xextern int cat (char *, char *);
  29148. Xextern int cat_append (char *, char *);
  29149. Xextern int touch (char *);
  29150. Xextern void init_signals (void);
  29151. Xextern void catch_signals (void);
  29152. Xextern int otoi (char *);
  29153. X
  29154. Xvoid   main (int, char **);
  29155. XBOOLEAN check_for (char *, FILE *, BOOLEAN, BOOLEAN);
  29156. Xvoid   check_unprocessed (char *, FILE *, BOOLEAN);
  29157. Xvoid   usage (void);
  29158. Xvoid   backup (char *, char *);
  29159. Xvoid   start_config (char *);
  29160. Xint    gexit (int);
  29161. Xchar   get_response (void);
  29162. X
  29163. Xvoid main (int argc, char **argv)
  29164. X{
  29165. X  char command [256];
  29166. X  char line [MAX_LINE];
  29167. X  char dir [MAX_LINE];
  29168. X  char *addr1, *addr2, *addr3, *addr4, *options = "ckrs";
  29169. X  int c;
  29170. X  FILE *f, *p;
  29171. X  int i, nlists, pid, procs_killed = 0, procs;
  29172. X  BOOLEAN just_kill = FALSE, confirm = TRUE, do_report = TRUE, sleepok = TRUE;
  29173. X  char *tmpps, *tmpfound, *tmpnprocs;
  29174. X  struct stat stat_buf;
  29175. X  extern char *getenv();
  29176. X  
  29177. X  while ((c = _getopt (argc, argv, options)) != EOF)
  29178. X    switch ((char) c) {
  29179. X      case 'c': confirm = FALSE; break;
  29180. X      case 'k': just_kill = TRUE; break;
  29181. X      case 'r': do_report = FALSE; break;
  29182. X      case 's': sleepok = FALSE; tty_echo = FALSE; break;
  29183. X      case '?':
  29184. X      default:
  29185. X    usage();
  29186. X    }
  29187. X
  29188. X  /* First make sure no other SERVERD programs are running. If so, kill
  29189. X     them all (after confirming) before proceeding. */
  29190. X  init_signals ();
  29191. X  catch_signals ();
  29192. X  signal (SIGINT, (void (*)()) gexit);
  29193. X  signal (SIGALRM, SIG_IGN);
  29194. X  if ((mask = getenv ("ULISTSERVER_UMASK")))
  29195. X    umask (otoi (mask));
  29196. X  else
  29197. X    mask = "066",
  29198. X    umask (S_IRWXG|S_IRWXO); /* 600 */
  29199. X#ifdef SYSLOG
  29200. X  openlog ("UNIX ListServer: catmail", LOG_NDELAY
  29201. X# ifndef i386
  29202. X       |LOG_NOWAIT
  29203. X# endif
  29204. X       , SYSLOG);
  29205. X# ifndef ultrix
  29206. X  setlogmask (LOG_UPTO (LOG_INFO));
  29207. X# endif
  29208. X#else
  29209. X  backup (REPORT_START, REPORT_START_ACC);
  29210. X  if ((report = fopen (REPORT_START, "a")) == NULL)
  29211. X    fprintf (stderr, "start: Could not open %s\n", REPORT_START),
  29212. X    START_ABORT;
  29213. X  chmod (REPORT_START, 384); /* 600 */
  29214. X#endif
  29215. X  nlists = sys_config (report, &sys);
  29216. X  if (just_kill)
  29217. X    report_progress (report, "\n--- SHUTTING UNIX LISTSERVER SYSTEM DOWN ---\n",
  29218. X             FALSE);
  29219. X  else
  29220. X    report_progress (report, "\n--- STARTING UNIX LISTSERVER SYSTEM ---\n",
  29221. X             FALSE);
  29222. X#ifndef _MINIX
  29223. X  if (sys.options & BSD_PS)
  29224. X    syscom ("ps -gx > %s", (tmpps = mystrdup (tmpnam (NULL))));
  29225. X  else
  29226. X    syscom ("ps -ef | grep %s > %s",
  29227. X        ((addr1 = (char *) getenv ("LOGNAME")) == NULL ?
  29228. X          ((addr1 = (char *) getenv ("USER")) == NULL ? "server" : addr1) :
  29229. X          addr1), (tmpps = mystrdup (tmpnam (NULL))));
  29230. X  tty_echo = FALSE;
  29231. X  addr1 = extract_filename (SERVERD);
  29232. X  addr2 = extract_filename (LIST);
  29233. X  addr3 = extract_filename (SERVER);
  29234. X  addr4 = extract_filename (PQUEUE);
  29235. X  syscom ("egrep '%s$|%s|%s$|%s |%s$|%s |%s|%s |queued' %s > %s",
  29236. X      addr1, addr1, addr2, addr2, addr3, addr3, addr4, addr4, tmpps,
  29237. X      (tmpfound = mystrdup (tmpnam (NULL))));
  29238. X  free ((char *) addr1);
  29239. X  free ((char *) addr2);
  29240. X  free ((char *) addr3);
  29241. X  free ((char *) addr4);
  29242. X  unlink (tmpps);
  29243. X  free ((char *) tmpps);
  29244. X  if (sleepok)
  29245. X    tty_echo = TRUE;
  29246. X  if ((f = fopen (tmpfound, "r")) == NULL)
  29247. X    report_progress (report,
  29248. X             tsprintf ("Error opening %s. Aborting. %s", tmpfound,
  29249. X                   ((just_kill == FALSE) ?
  29250. X                "System not started." : "")), TRUE),
  29251. X    START_ABORT;
  29252. X  
  29253. X  syscom ("wc -l %s > %s", tmpfound, (tmpnprocs = mystrdup (tmpnam (NULL))));
  29254. X  if ((p = fopen (tmpnprocs, "r")) != NULL) {
  29255. X    fscanf (p, "%d", &procs);
  29256. X    if (do_report)
  29257. X      report_progress (report,
  29258. X               tsprintf ("OLD UNIX LISTSERVER PROCESSES RUNNING: %d\n",
  29259. X                 procs), FALSE);
  29260. X    fclose (p);
  29261. X    unlink (tmpnprocs);
  29262. X    free ((char *) tmpnprocs);
  29263. X  }
  29264. X  else
  29265. X    report_progress (report,
  29266. X             tsprintf ("Error opening %s. Aborting. %s", tmpnprocs,
  29267. X                   ((just_kill == FALSE) ?
  29268. X                "System not started." : "")), TRUE),
  29269. X    START_ABORT;
  29270. X  
  29271. X  while (!feof (f)) {  /* get pid's and kill processes after confirming */
  29272. X    RESET (line);
  29273. X    fgets (line, MAX_LINE - 2, f);
  29274. X    if (line[0] != EOS) {
  29275. X      if (sys.options & BSD_PS)
  29276. X        sscanf (line, "%d ", &pid);
  29277. X      else
  29278. X        sscanf (line, "%s %d ", command, &pid);
  29279. X      if (confirm) {
  29280. X# ifdef SIGSTOP
  29281. X    kill (pid, SIGSTOP);
  29282. X# elif defined (SIGSTP)
  29283. X    kill (pid, SIGSTP);
  29284. X# endif
  29285. X    c = EOS;
  29286. X        while (c != EOF && c != 'Y' && c != 'N') {
  29287. X# ifdef SYSLOG
  29288. X      printf ("\n%s\n%c[7m%s%c[mKill it to proceed ? (capital Y/N) ",
  29289. X          ((just_kill == FALSE) ? 
  29290. X           "ERROR: another UNIX ListServer system program running:" : 
  29291. X           "UNIX ListServer system program found:"),
  29292. X          27, line, 27);
  29293. X# else
  29294. X      report_progress (report,
  29295. X               tsprintf ("\n%s\n%c[7m%s%c[mKill it to \
  29296. Xproceed ? (capital Y/N) ",
  29297. X                     ((just_kill == FALSE) ? 
  29298. X                      "ERROR: another UNIX ListServer system program running:" : 
  29299. X                      "UNIX ListServer system program found:"),
  29300. X                     27, line, 27), FALSE);
  29301. X# endif
  29302. X      c = get_response ();
  29303. X        }
  29304. X# ifdef SIGCONT
  29305. X    kill (pid, SIGCONT);
  29306. X# elif defined (SIGCNT)
  29307. X    kill (pid, SIGCNT);
  29308. X# endif
  29309. X        if (c == 'N' || c == EOF)
  29310. X      report_progress (report, tsprintf ("start aborted. %s\n",
  29311. X                         ((just_kill == FALSE) ?
  29312. X                          "System not started.":"")), TRUE),
  29313. X      unlink (tmpfound),
  29314. X      exit (1);
  29315. X      }
  29316. X      kill (pid, SIGINT);
  29317. X      ++procs_killed;
  29318. X    }
  29319. X  }
  29320. X  fclose (f);
  29321. X  unlink (tmpfound);
  29322. X  free ((char *) tmpfound);
  29323. X  if (sleepok)
  29324. X    sleep (2);
  29325. X  for (i = 0; pids[i]; i++)
  29326. X    if ((f = fopen (pids[i], "r")) != NULL)
  29327. X      fscanf (f, "%d", &pid),
  29328. X      kill (pid, SIGINT),
  29329. X      ++procs_killed,
  29330. X      fclose (f),
  29331. X      unlink (pids[i]);
  29332. X  if (do_report)
  29333. X    report_progress (report, tsprintf ("OLD UNIX LISTSERVER PROCESSES KILLED: \
  29334. X%d\n", procs_killed), FALSE);
  29335. X  
  29336. X  if (just_kill)  /* Done */
  29337. X    report_progress (report, "", -TRUE),
  29338. X# ifdef SYSLOG
  29339. X    closelog (),
  29340. X# else
  29341. X    fclose (report),
  29342. X# endif
  29343. X    exit (0);
  29344. X  if (sleepok)
  29345. X    sleep (2);
  29346. X#endif
  29347. X  
  29348. X  echo ("Serverd lock file", SERVERD_LOCK_FILE);
  29349. X  echo ("List lock file", LIST_LOCK_FILE);
  29350. X  echo ("Server lock file", SERVER_LOCK_FILE);
  29351. X  echo ("Pqueue lock file", PQUEUE_LOCK_FILE);
  29352. X
  29353. X  backup (REPORT_SERVER, REPORT_SERVER_ACC);
  29354. X  backup (REPORT_SERVERD, REPORT_SERVERD_ACC);
  29355. X  backup (REPORT_PQUEUE, REPORT_PQUEUE_ACC);
  29356. X  SETUP_IGNOREDF;
  29357. X  check_for (server_ignoredf, report, do_report, confirm);
  29358. X  check_for (OWNERSF, report, do_report, confirm);
  29359. X  check_for (ALIASESF, report, do_report, confirm);
  29360. X  shrink (REPORT_CATMAIL);
  29361. X  syscom ("chmod u+s %s", CATMAIL);
  29362. X  for (i = 0; i < nlists; ++i) {
  29363. X    start_config (sys.lists[i].alias);
  29364. X    SETUP_DIR;
  29365. X    if (stat (dir, &stat_buf)) {
  29366. X      if (mkdir (dir, /*448*/ 0777 & (0777 ^ otoi (mask))))
  29367. X    report_progress (report, tsprintf ("Could not create directory %s", dir),
  29368. X             TRUE),
  29369. X    START_ABORT;
  29370. X      if (do_report)
  29371. X        report_progress (report, tsprintf ("*** New list %s ***\n",
  29372. X                       sys.lists[i].alias), FALSE);
  29373. X      cp (server_ignoredf, dir);
  29374. X      syscom ("echo '^%s$' >> %s/%s", sys.lists[i].alias, dir, IGNORED);
  29375. X      echo_append (sys.lists[i].address, tsprintf ("%s/%s", dir, IGNORED));
  29376. X      syscom ("echo %s | sed 's/listserver/server/' | sed 's/listserv/server/' \
  29377. X>> %s/%s", sys.server.address, dir, IGNORED);
  29378. X      touch (infof);
  29379. X      touch (welcomef);
  29380. X      touch (list_mail_f);
  29381. X      chmod (list_mail_f, /*416*/ 0666 & (0666 ^ otoi (mask)));
  29382. X      touch (tsprintf ("%s/%s", dir, MODERATED_MAIL_FILE));
  29383. X      chmod (tsprintf ("%s/%s", dir, MODERATED_MAIL_FILE),
  29384. X         0666 & (0666 ^ otoi (mask)));
  29385. X    }
  29386. X    check_for (subscribersf, report, do_report, confirm);
  29387. X    if (!check_for (aliasesf, report, do_report, confirm))
  29388. X      echo_append (DEFAULT_ALIASES, aliasesf);
  29389. X    check_for (newsf, report, do_report, confirm);
  29390. X    check_for (peersf, report, do_report, confirm);
  29391. X    check_for (restrictedf, report, do_report, confirm);
  29392. X    check_unprocessed (sys.lists[i].alias, report, do_report);
  29393. X    backup (report_listf, report_list_accf);
  29394. X  }
  29395. X  syscom ("%s %s &", SERVERD, sys.serverd_cmdoptions);
  29396. X  report_progress (report, "", -TRUE);
  29397. X#ifdef SYSLOG
  29398. X  closelog ();
  29399. X#else
  29400. X  fclose (report);
  29401. X#endif
  29402. X  exit (0);
  29403. X}
  29404. X
  29405. X/*
  29406. X  Make sure that file 's' exists. Create a new one if necessary. Return
  29407. X  TRUE if file exists, FALSE otherwise.
  29408. X*/
  29409. X
  29410. XBOOLEAN check_for (char *s, FILE *report, BOOLEAN do_report, BOOLEAN confirm)
  29411. X{
  29412. X  int c = EOS;
  29413. X  struct stat stat_buf;
  29414. X
  29415. X  if (stat (s, &stat_buf)) { /* make sure we have file 's' */
  29416. X    if (confirm) {
  29417. X      while (c != EOF && c != 'Y' && c != 'N') {
  29418. X     if (do_report)
  29419. X#ifdef SYSLOG
  29420. X          printf ("No %s file found. Create a new one? (capital Y/N) ",s),
  29421. X#else
  29422. X      report_progress (report, tsprintf ("No %s file found. Create a new \
  29423. Xone? (capital Y/N) ",s), FALSE);
  29424. X#endif
  29425. X        c = get_response ();
  29426. X      }
  29427. X      if (c == 'N' || c == EOF)
  29428. X        START_ABORT;
  29429. X    }
  29430. X    touch (s);
  29431. X    return FALSE;
  29432. X  }
  29433. X  return TRUE;
  29434. X}
  29435. X
  29436. X/*
  29437. X  Check for incomplete delivery for a list during the last run. The files
  29438. X  .unprocessed.* in the list's directory signify undelivered mail for
  29439. X  a subset of the subscribers/newsgroups/peers. Prepend the last undelivered
  29440. X  messages to the mail file, so that they are distributed again to the remaining
  29441. X  subscribers/newsgroups/peers.
  29442. X*/
  29443. X
  29444. Xvoid check_unprocessed (char *list, FILE *report, BOOLEAN do_report)
  29445. X{
  29446. X  struct stat stat_buf;
  29447. X  char *tmpmail;
  29448. X
  29449. X  if (!stat (unprocessed_subscribersf, &stat_buf) ||
  29450. X      !stat (unprocessed_peersf, &stat_buf) ||
  29451. X      !stat (unprocessed_newsf, &stat_buf) ||
  29452. X      !stat (unprocessed_digestf, &stat_buf) ||
  29453. X      !stat (unprocessed_messages, &stat_buf)) { /* Last delivery incomplete */
  29454. X    if (do_report)
  29455. X      report_progress (report, tsprintf ("\nList %s did not complete last \
  29456. Xdelivery\n", list), FALSE);
  29457. X    if (stat (unprocessed_messages, &stat_buf) &&
  29458. X    stat (unprocessed_digestf, &stat_buf)) {
  29459. X    if (do_report)
  29460. X      report_progress (report, tsprintf ("Last set of mail messages for \
  29461. Xlist %s lost; cannot resume delivery\n", list), FALSE);
  29462. X        unlink (unprocessed_subscribersf);
  29463. X        unlink (unprocessed_peersf);
  29464. X        unlink (unprocessed_newsf);
  29465. X        return;
  29466. X      }
  29467. X      else if (do_report)
  29468. X        report_progress (report, "Mail will be delivered to the remaining \
  29469. Xsubscribers/newsgroups/peers shortly\n", FALSE);
  29470. X    /* Create empty .unprocessed files for subscribers/newsgroups/peers
  29471. X       that do not exist. */
  29472. X    touch (unprocessed_subscribersf);
  29473. X    touch (unprocessed_peersf);
  29474. X    touch (unprocessed_newsf);
  29475. X    /* Now prepend undelivered message(s) to the mail file */
  29476. X    mv (list_mail_f, (tmpmail = mystrdup (tmpnam (NULL))));
  29477. X    cat (unprocessed_messages, list_mail_f);
  29478. X    cat_append (tmpmail, list_mail_f);
  29479. X    unlink (tmpmail);
  29480. X    free ((char *) tmpmail);
  29481. X    unlink (unprocessed_messages);
  29482. X    chmod (list_mail_f, /*416*/ 0666 & (0666 ^ otoi (mask)));
  29483. X  }
  29484. X}
  29485. X
  29486. X/*
  29487. X  Append 'src' to 'dest' and create a brand new 'src'.
  29488. X*/
  29489. X
  29490. Xvoid backup (char *src, char *dest)
  29491. X{
  29492. X  struct stat stat_buf;
  29493. X
  29494. X  if (!stat (src, &stat_buf)) /* prepare for backup */
  29495. X    cat_append (src, dest),
  29496. X    chmod (dest, 384), /* 600 */
  29497. X    unlink (src),
  29498. X    touch (src),
  29499. X    chmod (src, 384);
  29500. X}
  29501. X
  29502. X/*
  29503. X  Print usage.
  29504. X*/
  29505. X
  29506. Xvoid usage ()
  29507. X{
  29508. X  fprintf (stderr, "Usage: start [-k] [-c] [-r]\n\
  29509. X-k: Just kill any UNIX ListServer system programs running.\n\
  29510. X-c: Do not confirm before killing processes.\n\
  29511. X-r: Restrict reporting to screen.\n");
  29512. X  exit (1);
  29513. X}
  29514. X
  29515. Xvoid start_config (char *alias)
  29516. X{
  29517. X  setup_string (subscribersf, alias, SUBSCRIBERS);
  29518. X  setup_string (aliasesf, alias, ALIASES);
  29519. X  setup_string (newsf, alias, NEWSF);
  29520. X  setup_string (peersf, alias, PEERS);
  29521. X  setup_string (restrictedf, alias, RESTRICTED);
  29522. X  setup_string (ignoredf, alias, IGNORED);
  29523. X  setup_string (report_listf, alias, REPORT_LIST);
  29524. X  setup_string (infof, alias, INFO_FILE);
  29525. X  setup_string (welcomef, alias, WELCOME_FILE);
  29526. X  setup_string (unprocessed_subscribersf, alias, UNPROC_SUBSCRIBERS);
  29527. X  setup_string (unprocessed_peersf, alias, UNPROC_PEERS);
  29528. X  setup_string (unprocessed_newsf, alias, UNPROC_NEWS);
  29529. X  setup_string (unprocessed_messages, alias, UNPROC_MESSAGES);
  29530. X  setup_string (unprocessed_digestf, alias, UNPROC_DIGEST);
  29531. X  setup_string (list_mail_f, alias, LIST_MAIL_FILE);
  29532. X  setup_string (report_list_accf, alias, REPORT_LIST_ACC);
  29533. X}
  29534. X
  29535. X/*
  29536. X  Required to avoid undefined symbols.
  29537. X*/
  29538. X
  29539. Xint gexit (int exitcode)
  29540. X{
  29541. X  exit (exitcode);
  29542. X}
  29543. X
  29544. X/*
  29545. X  Get a one-character response from stdin.
  29546. X*/
  29547. X
  29548. Xchar get_response ()
  29549. X{
  29550. X  char c;
  29551. X
  29552. X  fflush (stdout);
  29553. X  fflush (stdin);
  29554. X  c = fgetc (stdin);
  29555. X
  29556. X  if (c != '\n' && c != EOF)
  29557. X    while (fgetc (stdin) != '\n');
  29558. X  fflush (stdin);
  29559. X  return c;
  29560. X}
  29561. *-*-END-of-src/start.c-*-*
  29562. echo x - src/strftime.c
  29563. sed 's/^X//' >src/strftime.c <<'*-*-END-of-src/strftime.c-*-*'
  29564. X#ifndef lint
  29565. X#ifndef NOID
  29566. Xstatic char    elsieid[] = "@(#)strftime.c    7.1";
  29567. X/*
  29568. X** Based on the UCB version whose ID appears below.
  29569. X** This is ANSIish only when time is treated identically in all locales and
  29570. X** when "multibyte character == plain character".
  29571. X*/
  29572. X#endif /* !defined NOID */
  29573. X#endif /* !defined lint */
  29574. X/*
  29575. X * Copyright (c) 1989 The Regents of the University of California.
  29576. X * All rights reserved.
  29577. X *
  29578. X * Redistribution and use in source and binary forms are permitted
  29579. X * provided that the above copyright notice and this paragraph are
  29580. X * duplicated in all such forms and that any documentation,
  29581. X * advertising materials, and other materials related to such
  29582. X * distribution and use acknowledge that the software was developed
  29583. X * by the University of California, Berkeley.  The name of the
  29584. X * University may not be used to endorse or promote products derived
  29585. X * from this software without specific prior written permission.
  29586. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  29587. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  29588. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  29589. X */
  29590. X
  29591. X#if defined(LIBC_SCCS) && !defined(lint)
  29592. Xstatic char sccsid[] = "@(#)strftime.c    5.4 (Berkeley) 3/14/89";
  29593. X#endif /* LIBC_SCCS and not lint */
  29594. X
  29595. X#include <sys/types.h>
  29596. X#include <time.h>
  29597. X#ifdef HAVE_TZFILE_H
  29598. X# include <tzfile.h>
  29599. X#else
  29600. X# define TM_YEAR_BASE    1900
  29601. X#endif
  29602. X
  29603. Xstatic char *afmt[] = {
  29604. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  29605. X};
  29606. Xstatic char *Afmt[] = {
  29607. X    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
  29608. X    "Saturday",
  29609. X};
  29610. Xstatic char *bfmt[] = {
  29611. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  29612. X    "Oct", "Nov", "Dec",
  29613. X};
  29614. Xstatic char *Bfmt[] = {
  29615. X    "January", "February", "March", "April", "May", "June", "July",
  29616. X    "August", "September", "October", "November", "December",
  29617. X};
  29618. X
  29619. Xstatic size_t gsize;
  29620. Xstatic char *pt;
  29621. X
  29622. Xstatic void _add();
  29623. Xstatic void _conv();
  29624. Xstatic void _fmt();
  29625. X
  29626. Xsize_t
  29627. Xucb_strftime(s, maxsize, format, t)
  29628. X    char *s;
  29629. X    char *format;
  29630. X    size_t maxsize;
  29631. X    struct tm *t;
  29632. X{
  29633. X    pt = s;
  29634. X    gsize = maxsize;
  29635. X    _fmt(format, t);
  29636. X    if (gsize <= 0)
  29637. X        return(0);
  29638. X    *pt = '\0';
  29639. X    return(maxsize - gsize);
  29640. X}
  29641. X
  29642. Xstatic void
  29643. X_fmt(format, t)
  29644. X    register char *format;
  29645. X    struct tm *t;
  29646. X{
  29647. X    for (; *format; ++format) {
  29648. X        if (*format == '%')
  29649. X            switch(*++format) {
  29650. X            case '\0':
  29651. X                --format;
  29652. X                break;
  29653. X            case 'A':
  29654. X                if (t->tm_wday < 0 || t->tm_wday > 6)
  29655. X                    _add("?");
  29656. X                else    _add(Afmt[t->tm_wday]);
  29657. X                continue;
  29658. X            case 'a':
  29659. X                if (t->tm_wday < 0 || t->tm_wday > 6)
  29660. X                    _add("?");
  29661. X                else    _add(afmt[t->tm_wday]);
  29662. X                continue;
  29663. X            case 'B':
  29664. X                if (t->tm_mon < 0 || t->tm_mon > 11)
  29665. X                    _add("?");
  29666. X                else    _add(Bfmt[t->tm_mon]);
  29667. X                continue;
  29668. X            case 'b':
  29669. X            case 'h':
  29670. X                if (t->tm_mon < 0 || t->tm_mon > 11)
  29671. X                    _add("?");
  29672. X                else    _add(bfmt[t->tm_mon]);
  29673. X                continue;
  29674. X            case 'c':
  29675. X                _fmt("%D %X", t);
  29676. X                continue;
  29677. X            case 'C':
  29678. X                _fmt("%a %b %e %X %Y", t);
  29679. X                continue;
  29680. X            case 'D':
  29681. X            case 'x':
  29682. X                _fmt("%m/%d/%y", t);
  29683. X                continue;
  29684. X            case 'd':
  29685. X                _conv(t->tm_mday, 2, '0');
  29686. X                continue;
  29687. X            case 'e':
  29688. X                _conv(t->tm_mday, 2, ' ');
  29689. X                continue;
  29690. X            case 'H':
  29691. X                _conv(t->tm_hour, 2, '0');
  29692. X                continue;
  29693. X            case 'I':
  29694. X                _conv(t->tm_hour % 12 ?
  29695. X                    t->tm_hour % 12 : 12, 2, '0');
  29696. X                continue;
  29697. X            case 'j':
  29698. X                _conv(t->tm_yday + 1, 3, '0');
  29699. X                continue;
  29700. X            case 'k':
  29701. X                _conv(t->tm_hour % 12 ?
  29702. X                    t->tm_hour % 12 : 12, 2, ' ');
  29703. X                continue;
  29704. X#ifdef KITCHEN_SINK
  29705. X            case 'K':
  29706. X                _add("kitchen sink");
  29707. X                continue;
  29708. X#endif /* defined KITCHEN_SINK */
  29709. X            case 'l':
  29710. X                _conv(t->tm_hour, 2, ' ');
  29711. X                continue;
  29712. X            case 'M':
  29713. X                _conv(t->tm_min, 2, '0');
  29714. X                continue;
  29715. X            case 'm':
  29716. X                _conv(t->tm_mon + 1, 2, '0');
  29717. X                continue;
  29718. X            case 'n':
  29719. X                _add("\n");
  29720. X                continue;
  29721. X            case 'p':
  29722. X                _add(t->tm_hour >= 12 ? "PM" : "AM");
  29723. X                continue;
  29724. X            case 'R':
  29725. X                _fmt("%H:%M", t);
  29726. X                continue;
  29727. X            case 'r':
  29728. X                _fmt("%I:%M:%S %p", t);
  29729. X                continue;
  29730. X            case 'S':
  29731. X                _conv(t->tm_sec, 2, '0');
  29732. X                continue;
  29733. X            case 'T':
  29734. X            case 'X':
  29735. X                _fmt("%H:%M:%S", t);
  29736. X                continue;
  29737. X            case 't':
  29738. X                _add("\t");
  29739. X                continue;
  29740. X            case 'U':
  29741. X                _conv((t->tm_yday + 7 - t->tm_wday) / 7,
  29742. X                    2, '0');
  29743. X                continue;
  29744. X            case 'W':
  29745. X                _conv((t->tm_yday + 7 -
  29746. X                    (t->tm_wday ? (t->tm_wday - 1) : 6))
  29747. X                    / 7, 2, '0');
  29748. X                continue;
  29749. X            case 'w':
  29750. X                _conv(t->tm_wday, 1, '0');
  29751. X                continue;
  29752. X            case 'y':
  29753. X                _conv((t->tm_year + TM_YEAR_BASE) % 100,
  29754. X                    2, '0');
  29755. X                continue;
  29756. X            case 'Y':
  29757. X                _conv(t->tm_year + TM_YEAR_BASE, 4, '0');
  29758. X                continue;
  29759. X            case 'Z':
  29760. X#ifdef TM_ZONE
  29761. X                if (t->TM_ZONE)
  29762. X                    _add(t->TM_ZONE);
  29763. X                else
  29764. X#endif /* defined TM_ZONE */
  29765. X                if (t->tm_isdst == 0 || t->tm_isdst == 1) {
  29766. X                    extern char *    tzname[2];
  29767. X
  29768. X                    _add(tzname[t->tm_isdst]);
  29769. X                } else    _add("?");
  29770. X                continue;
  29771. X            case '%':
  29772. X            /*
  29773. X             * X311J/88-090 (4.12.3.5): if conversion char is
  29774. X             * undefined, behavior is undefined.  Print out the
  29775. X             * character itself as printf(3) also does.
  29776. X             */
  29777. X            default:
  29778. X                break;
  29779. X        }
  29780. X        if (gsize <= 0)
  29781. X            return;
  29782. X        *pt++ = *format;
  29783. X        --gsize;
  29784. X    }
  29785. X}
  29786. X
  29787. Xstatic void
  29788. X_conv(n, digits, fill)
  29789. X    int n, digits, fill;
  29790. X{
  29791. X    static char buf[10];
  29792. X    register char *p;
  29793. X
  29794. X    for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
  29795. X        *p-- = n % 10 + '0';
  29796. X    while (p > buf && digits-- > 0)
  29797. X        *p-- = fill;
  29798. X    _add(++p);
  29799. X}
  29800. X
  29801. Xstatic void
  29802. X_add(str)
  29803. X    register char *str;
  29804. X{
  29805. X    for (;; ++pt, --gsize) {
  29806. X        if (gsize <= 0)
  29807. X            return;
  29808. X        if (!(*pt = *str++))
  29809. X            return;
  29810. X    }
  29811. X}
  29812. X
  29813. *-*-END-of-src/strftime.c-*-*
  29814. echo x - src/sysmail.c
  29815. sed 's/^X//' >src/sysmail.c <<'*-*-END-of-src/sysmail.c-*-*'
  29816. X/*
  29817. X  ----------------------------------------------------------------------------
  29818. X  |                       SYSTEM MAILING ROUTINES                            |
  29819. X  |                                         |
  29820. X  |                             Version 2.6                                  |
  29821. X  |                                                                          |
  29822. X  |                (or, when Computer Science gets to you)                   |
  29823. X  |                                                                          |
  29824. X  |                    Written by Anastasios Kotsikonas                      |
  29825. X  |                           (tasos@cs.bu.edu)                              |
  29826. X  |                                                                          |
  29827. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  29828. X  | whole and not in parts, as long as you do not remove or alter the author |
  29829. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  29830. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  29831. X  | provided for your personal use, you you may not alter the functions      |
  29832. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  29833. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  29834. X  | any changes you may have made. No part of the source code bearing a         |
  29835. X  | copyright notice can be included in commercial software systems without  |
  29836. X  | written permission by the author.                         |
  29837. X  | By using this software you are bound by this agreement.                  |
  29838. X  | This software comes with no warranties and cannot be sold for profit.    |
  29839. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  29840. X  | files when distributing this software.                                   |
  29841. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  29842. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  29843. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  29844. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  29845. X  | (ii).                                                                    |
  29846. X  ----------------------------------------------------------------------------
  29847. X
  29848. X  These routines implement the 'system' mailmethod. The system opens a socket
  29849. X  and connects directly with sendmail for mail delivery. During the process
  29850. X  of porting the code to various platforms, lots of grosse things were
  29851. X  encountered with sockets and protocols, so the code may seem kludgy.
  29852. X
  29853. X  When mail cannot be sent due to network problems, it is queued up and will 
  29854. X  be delivered later by the queue daemon.
  29855. X*/
  29856. X
  29857. X#include <stdio.h>
  29858. X#include <string.h>
  29859. X#ifndef unknown_port
  29860. X# ifndef __NeXT__
  29861. X#  include <unistd.h>
  29862. X# else
  29863. X#  include <libc.h>
  29864. X# endif
  29865. X#endif
  29866. X#include <sys/types.h>
  29867. X#include <sys/stat.h>
  29868. X#include "defs.h"
  29869. X#include "struct.h"
  29870. X#include "sysmail.h"
  29871. X#ifdef TCP_IP
  29872. X# include <fcntl.h>
  29873. X# include <errno.h>
  29874. X#ifdef unknown_port
  29875. Xextern int errno;
  29876. X#endif
  29877. X# include <sys/types.h>
  29878. X# include <sys/socket.h>
  29879. X# include <netinet/in.h>
  29880. X# include <netdb.h>
  29881. X#endif
  29882. X
  29883. X#ifdef __STDC__
  29884. X# include <stdarg.h>
  29885. Xextern int  syscom (char *, ...);
  29886. Xextern char *tsprintf (char *, ...);
  29887. X#else
  29888. X# include <varargs.h>
  29889. Xextern int  syscom ();
  29890. Xextern char *tsprintf ();
  29891. X#endif
  29892. Xextern FILE *report;
  29893. Xextern SYS sys;
  29894. Xextern BOOLEAN debug;
  29895. Xextern int listid;
  29896. X
  29897. X#ifndef __NeXT__
  29898. Xextern long int atoi (char *);
  29899. X#else
  29900. Xextern int atoi (const char *);
  29901. X#endif
  29902. Xextern void report_progress (FILE *, char *, int);
  29903. Xextern int gexit (int);
  29904. Xextern int echo (char *, char *);
  29905. Xextern int mv (char *, char *);
  29906. X
  29907. XBOOLEAN sysmail (char *);
  29908. X#ifdef TCP_IP
  29909. XBOOLEAN _sysmail (char *, int);
  29910. Xint     server_response (int);
  29911. Xint     build_tcp_connection (FILE *);
  29912. Xvoid    queue_up (char *file);
  29913. X#endif
  29914. X
  29915. X/*
  29916. X  The return value depends on the return value of _sysmail ().
  29917. X*/
  29918. X
  29919. XBOOLEAN sysmail (char *file)
  29920. X{
  29921. X#ifdef TCP_IP
  29922. X  queue = FALSE;
  29923. X  if (debug) {
  29924. X    OPEN_FILE (sent, SENT, "w", "sysmail");
  29925. X    OPEN_FILE (received, RECEIVED_, "w", "sysmail");
  29926. X  }
  29927. X  return _sysmail (file, 1);
  29928. X#endif
  29929. X}
  29930. X#ifdef TCP_IP
  29931. X
  29932. X/*
  29933. X  'system' mailmethod. It returns TRUE if the mail was successfully
  29934. X  delivered, FALSE if it was queued.
  29935. X*/
  29936. X
  29937. XBOOLEAN _sysmail (char *file, int call)
  29938. X{
  29939. X  char buf [MAX_LINE] ;
  29940. X  FILE *msg;
  29941. X  int sock_fd, cmd, bytes_to_write, bytes_written, i;
  29942. X   
  29943. X  OPEN_FILE (msg, file, "r", "_sysmail");
  29944. X  if ((sock_fd = build_tcp_connection (report)) < 0) {
  29945. X    queue = TRUE;
  29946. X    goto abort;
  29947. X  }
  29948. X  if ((cmd = server_response (sock_fd)) != ACKNOWLEDGE) {
  29949. X    report_progress (report, "\n_sysmail(): Could not connect to sendmail",
  29950. X             TRUE);
  29951. X    queue = TRUE;
  29952. X    goto abort;
  29953. X  }
  29954. X
  29955. X  PROTOCOL (DATA);
  29956. X  while (!feof (msg) && strcmp (buf, END_OF_TEXT)) { /* Copy header and text */
  29957. X    RESET (buf);
  29958. X    fgets (buf, MAX_LINE - 2, msg);
  29959. X    WRITE_TO_SOCKET (sock_fd, buf);
  29960. X  }
  29961. X  cmd = server_response (sock_fd);
  29962. X  CHECK_SERVER_RESPONSE (cmd, OK, NULL);
  29963. X  PROTOCOL (CLOSE_CONNECTION);
  29964. X
  29965. X  abort:
  29966. X  if (queue)
  29967. X    queue_up (file);
  29968. X  CLOSEF;
  29969. X  if (debug)
  29970. X    fclose (sent),
  29971. X    fclose (received);
  29972. X  return !queue;
  29973. X}
  29974. X
  29975. X/*
  29976. X  Get server response. Return the command number that sendmail sent,
  29977. X  CONN_TIMEOUT or HOST_ABORTED.
  29978. X*/
  29979. X
  29980. Xint server_response (int sock_fd)
  29981. X{
  29982. X  char buf [MAX_LINE];
  29983. X  long int cmd, i, column = 3, bytes_to_read = 3, bytes_read = 0, time_started;
  29984. X  BOOLEAN done = FALSE, continued = FALSE;
  29985. X
  29986. X  time_started = time (0);
  29987. X  RESET (buf);
  29988. X  while (bytes_to_read) {
  29989. X    errno = 0;
  29990. X    /* Get server command */
  29991. X    bytes_read = read (sock_fd, &buf [3 - bytes_to_read], bytes_to_read);
  29992. X    if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  29993. X    errno == ECONNREFUSED)
  29994. X      return HOST_ABORTED;
  29995. X    if (errno || bytes_read < 1)
  29996. X      if ((time (0) - time_started) > TIMEOUT)
  29997. X    return CONN_TIMEOUT;
  29998. X    if (bytes_read > 0)
  29999. X      bytes_to_read -= bytes_read;
  30000. X  }
  30001. X  RESET (message);
  30002. X  buf[3] = EOS;
  30003. X  cmd = atoi (buf);
  30004. X  sprintf (message, "%s", buf);
  30005. X  i = strlen (message);
  30006. X  if (debug)
  30007. X    fprintf (received, "%s", buf),
  30008. X    fflush (received);
  30009. X  while (!done) { /* Read till the end of socket */
  30010. X    errno = 0;
  30011. X    while ((bytes_read = read (sock_fd, buf, 1)) < 1) {
  30012. X      if (errno == EBADF || errno == ECONNRESET || errno == ECONNABORTED ||
  30013. X      errno == ECONNREFUSED)
  30014. X    return HOST_ABORTED;
  30015. X      if (errno)
  30016. X    if ((time (0) - time_started) > TIMEOUT)
  30017. X      return CONN_TIMEOUT;
  30018. X    }
  30019. X    ++column;
  30020. X    if (buf[0] == '\n') {
  30021. X      column = 0;
  30022. X      if (!continued)
  30023. X    done = TRUE;
  30024. X    }
  30025. X    if (column == 4)
  30026. X      if (buf[0] != '-')
  30027. X    continued = FALSE;
  30028. X      else
  30029. X    continued = TRUE;
  30030. X    message [i++] = (buf[0] != '\n' ? buf[0] : EOS);
  30031. X    if (debug)
  30032. X      fprintf (received, "%c", buf[0]),
  30033. X      fflush (received);
  30034. X  }
  30035. X  return cmd;
  30036. X}
  30037. X
  30038. X/*
  30039. X  Establish connection with sendmail/smtp.
  30040. X*/
  30041. X
  30042. Xint build_tcp_connection (FILE *report)
  30043. X{
  30044. X  int sock_fd;
  30045. X  struct sockaddr_in sin;
  30046. X  struct hostent *hostentry;
  30047. X   
  30048. X  if (! (hostentry = gethostbyname (SENDMAIL_HOST))) {
  30049. X    report_progress (report, "\nbuild_tcp_connection(): No such host", TRUE);
  30050. X    return -1;
  30051. X  }
  30052. X  if ((sock_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  30053. X    report_progress (report, "\nbuild_tcp_connection(): Could not create \
  30054. Xsocket", TRUE);
  30055. X    return -1;
  30056. X  }
  30057. X  sin.sin_family = AF_INET;
  30058. X  sin.sin_port = htons (PORT);
  30059. X  memcpy ((char *) &sin.sin_addr.s_addr, (char *) hostentry->h_addr,
  30060. X      hostentry->h_length);
  30061. X  memset (sin.sin_zero, EOS, sizeof (sin.sin_zero));
  30062. X  if (connect (sock_fd, (struct sockaddr *) &sin, sizeof (struct sockaddr_in))
  30063. X      < 0) {
  30064. X    report_progress (report, "\nbuild_tcp_connection(): Could not connect to \
  30065. Xport", TRUE);
  30066. X    close (sock_fd);
  30067. X    return -1;
  30068. X  }
  30069. X# ifdef NONBLOCKING_IO
  30070. X  if (fcntl (sock_fd, F_SETFL, (fcntl (sock_fd, F_GETFL, 0) | O_NDELAY)) < 0)
  30071. X    report_progress (report, "\nbuild_tcp_connection(): WARNING: timeout \
  30072. Xmechanism not functional", TRUE);
  30073. X# endif
  30074. X  return sock_fd;
  30075. X}
  30076. X
  30077. X/*
  30078. X  Queue up a file for later delivery.
  30079. X*/
  30080. X
  30081. Xvoid queue_up (char *file)
  30082. X{
  30083. X  FILE *id;
  30084. X  int id_no = 0;
  30085. X  char msg [MAX_LINE];
  30086. X
  30087. X  if ((id = fopen (IDF, "r")) != NULL)
  30088. X    fscanf (id, "%d\n", &id_no),
  30089. X    fclose (id);
  30090. X  mv (file, tsprintf ("%s/%d", QUEUE_DIR, ++id_no));
  30091. X  echo (tsprintf ("%d", id_no), IDF);
  30092. X  sprintf (msg, "File %s placed in the mail queue", file);
  30093. X  report_progress (report, msg, TRUE);
  30094. X}
  30095. X#endif
  30096. *-*-END-of-src/sysmail.c-*-*
  30097. echo x - src/tlock.c
  30098. sed 's/^X//' >src/tlock.c <<'*-*-END-of-src/tlock.c-*-*'
  30099. X/*
  30100. X  ----------------------------------------------------------------------------
  30101. X  |                        tlock UTILITY                      |
  30102. X  |                                                                          |
  30103. X  |                              Version 2.0                                 |
  30104. X  |                                                                          |
  30105. X  |                (or, when Computer Science gets to you)                   |
  30106. X  |                                                                          |
  30107. X  |                    Written by Anastasios Kotsikonas                      |
  30108. X  |                           (tasos@cs.bu.edu)                              |
  30109. X  |                                                                          |
  30110. X  | AGREEMENT: This software can be used and distributed freely only as a    |
  30111. X  | whole and not in parts, as long as you do not remove or alter the author |
  30112. X  | and copyright notices in the file defs.h; this notices are #define'd in  |
  30113. X  | the symbols VERSION and COPYRIGHT. Although you may alter the code         |
  30114. X  | provided for your personal use, you you may not alter the functions      |
  30115. X  | create_header(), create_multi_recipient_header() and main() in list.c,   |
  30116. X  | listserv.c and serverd.c (where applicable), and you may not redistribute|
  30117. X  | any changes you may have made. No part of the source code bearing a         |
  30118. X  | copyright notice can be included in commercial software systems without  |
  30119. X  | written permission by the author.                         |
  30120. X  | By using this software you are bound by this agreement.                  |
  30121. X  | This software comes with no warranties and cannot be sold for profit.    |
  30122. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  30123. X  | files when distributing this software.                                   |
  30124. X  | COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas               |
  30125. X  | Use, duplication or disclosure by the Federal Government is subject to   |
  30126. X  | the restrictions set forth in FAR 52.227-19(c), Commercial Computer      |
  30127. X  | Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1) |
  30128. X  | (ii).                                                                    |
  30129. X  |                                         |
  30130. X  | Enhanced by: Warren Burnstein.                         |
  30131. X  ----------------------------------------------------------------------------
  30132. X*/
  30133. X
  30134. X#include <stdio.h>
  30135. X#include <string.h>
  30136. X#ifndef unknown_port
  30137. X# ifndef __NeXT__
  30138. X#  include <unistd.h>
  30139. X# else
  30140. X#  include <libc.h>
  30141. X# endif
  30142. X#endif
  30143. X#include <fcntl.h>
  30144. X#include <errno.h>
  30145. X#ifdef unknown_port
  30146. Xextern int errno;
  30147. X#endif
  30148. X#include "defs.h"
  30149. X#include "struct.h"             /* global.h needs it */
  30150. X#include "global.h"             /* misc.c needs it */
  30151. X
  30152. XBOOLEAN tty_echo = TRUE;        /* ditto */
  30153. XFILE    *report  = NULL;        /* ditto */
  30154. X
  30155. Xextern void setup_string (char *, char *, char *);
  30156. Xextern char *locase (char *);
  30157. Xextern char *upcase (char *);
  30158. X
  30159. Xvoid main ();
  30160. Xint  check (char *);
  30161. Xint  gexit (int);
  30162. X
  30163. Xvoid main ();
  30164. X
  30165. Xchar *s[] = { 
  30166. X  SERVERD_LOCK_FILE, LIST_LOCK_FILE, SERVER_LOCK_FILE, PQUEUE_LOCK_FILE,
  30167. X  SERVER_MAIL_FILE, BATCH_FILE, NULL
  30168. X};
  30169. X
  30170. X/*
  30171. X  Test whether any locks exist on the above files plus the mail and moderated
  30172. X  files of each list by other processes.
  30173. X
  30174. X  USER CONTRIBUTED MODIFIED CODE: Warren Burnstein.
  30175. X*/
  30176. X
  30177. Xvoid main ()
  30178. X{
  30179. X#ifndef NO_LOCKS
  30180. X  char cmd[MAX_LINE], args[MAX_LINE], file[MAX_LINE], alias[MAX_LINE];
  30181. X  int i, locks = 0;
  30182. X  FILE *fp;
  30183. X
  30184. X  for (i = 0; s[i]; i++)
  30185. X    locks += check (s[i]);
  30186. X
  30187. X  if ((fp = fopen (CONFIG, "r")) == NULL) {
  30188. X    fprintf (stderr, "Cannot open %s\n", CONFIG);
  30189. X    gexit (1);
  30190. X  }
  30191. X
  30192. X  while (! feof (fp)) {
  30193. X    args [0] = RESET (cmd);
  30194. X    fscanf (fp, "%s", cmd);
  30195. X    if (cmd[0] == EOS)
  30196. X      continue;
  30197. X    fgets (args, MAX_LINE - 2, fp);
  30198. X    if (args [0] != EOS && args [strlen (args) - 1] == '\n')
  30199. X      args [strlen (args) - 1] = EOS;
  30200. X
  30201. X    if (strcmp (locase (cmd), "list") == 0 && sscanf (args, "%s", alias) == 1)
  30202. X      upcase (alias),
  30203. X      setup_string (file, alias, LIST_MAIL_FILE),
  30204. X      locks += check (file),
  30205. X      setup_string (file, alias, LIST_MODERATED_F),
  30206. X      locks += check (file);
  30207. X  }
  30208. X  fclose(fp);
  30209. X
  30210. X  if (!locks)
  30211. X    printf ("No files locked.\n"),
  30212. X    gexit (0);
  30213. X  gexit (locks + 1);
  30214. X#else
  30215. X  printf ("File locking mechanism not functional. This mechanism is turned off \
  30216. Xusually when\nfile locking is not supported over NFS. If this system is \
  30217. Xinstalled on a local\nfile system, you may consider undefining the symbol \
  30218. XNO_LOCKS in src/defs.h;\ncheck also with your system manuals to verify that \
  30219. Xfile locking over NFS is\nindeed not supported.\n");
  30220. X  gexit (-1);
  30221. X#endif
  30222. X}
  30223. X
  30224. X/*
  30225. X  Check whether a file is locked.
  30226. X
  30227. X  USER CONTRIBUTED FUNCTION: Warren Burnstein.
  30228. X*/
  30229. X
  30230. Xint check (char *s)
  30231. X{
  30232. X#ifndef NO_LOCKS
  30233. X  int fd, ret = 0;
  30234. X
  30235. X  if (lockf ((fd = open (s, O_RDWR)), F_TLOCK, 0))
  30236. X    if (errno != EBADF)
  30237. X      ret = 1,
  30238. X      printf ("Lock placed on %s\n", s);
  30239. X  close (fd);
  30240. X  return ret;
  30241. X#endif
  30242. X}
  30243. X
  30244. X/*
  30245. X  Required to avoid undefined symbols.
  30246. X*/
  30247. X
  30248. Xint gexit (int exitcode)
  30249. X{
  30250. X  exit (exitcode);
  30251. X}
  30252. *-*-END-of-src/tlock.c-*-*
  30253. echo x - redux
  30254. sed 's/^X//' >redux <<'*-*-END-of-redux-*-*'
  30255. X#!/bin/sh
  30256. X# Script to reduce the size of mboxes by removing unnecessary fields in
  30257. X# the header of each message.
  30258. X# Usage: redux [mbox-file] (default is ./mbox)
  30259. X
  30260. XFILE=$1
  30261. Xif [ $# = 0 ]; then
  30262. X  FILE=./mbox
  30263. Xfi
  30264. Xif [ ! -r $FILE ]; then
  30265. X  echo File $FILE not found.
  30266. X  exit
  30267. Xfi
  30268. Xecho Reducing $FILE\; reduced file in /tmp/reduced >&2
  30269. X/usr/bin/egrep -v "^Cc: |^          with BSMTP;|^Received: |^Status: |^Message-Id: |^Comment: |^Reply-To: |^Sender: |^To: |^Return-Path: |^    id " $FILE > /tmp/reduced
  30270. Xexit
  30271. *-*-END-of-redux-*-*
  30272. echo x - flocks
  30273. sed 's/^X//' >flocks <<'*-*-END-of-flocks-*-*'
  30274. X#include "/usr/server/src/defs.h"
  30275. Xrm -f SERVERD_LOCK_FILE
  30276. Xrm -f LIST_LOCK_FILE
  30277. Xrm -f SERVER_LOCK_FILE
  30278. Xrm -f PQUEUE_LOCK_FILE
  30279. *-*-END-of-flocks-*-*
  30280. echo x - ulock
  30281. sed 's/^X//' >ulock <<'*-*-END-of-ulock-*-*'
  30282. X#!/bin/sh
  30283. X# ulock - in conjunction with the file 'flocks', this utility removes all
  30284. X#        locked files.
  30285. X/lib/cpp flocks | /bin/sh
  30286. *-*-END-of-ulock-*-*
  30287. echo x - config
  30288. sed 's/^X//' >config <<'*-*-END-of-config-*-*'
  30289. X
  30290. X#        UNIX ListServer system configuration file
  30291. X#
  30292. X#                   version 6.0
  30293. X#
  30294. X#                    June 1993
  30295. X#
  30296. X# AGREEMENT: This software can be used and distributed freely as long
  30297. X# as you do not remove or alter the Copyright notice in the file defs.h;
  30298. X# this notice is #define'd in the symbol VERSION. Although you may alter
  30299. X# the code provided, you may not alter the functions create_header()
  30300. X# and create_multi_recipient_header() in list.c and listserv.c.
  30301. X# By using this software you are bound by this agreement.
  30302. X# This software comes with no warranties and cannot be sold for profit.
  30303. X# The AGREEMENT and COPYRIGHT notices should be included in all source
  30304. X# files when distributing this software.
  30305. X# COPYRIGHT: Copyright (c) 1991-93, Anastasios C. Kotsikonas
  30306. X# Use, duplication or disclosure by the Federal Government is subject to
  30307. X# the restrictions set forth in FAR 52.227-19(c), Commercial Computer
  30308. X# Software or, for Department of Defense Users, by DFAR 252.227-7013(c)(1)
  30309. X# (ii).
  30310. X#
  30311. X# Note: On SysV and BSD Unix systems 'sendmail' is located under /usr/lib/
  30312. X# but on SysVR4 it is located under /usr/ucblib/; also, check the path to
  30313. X# rmail if you are going to use it.
  30314. X
  30315. Xorganization Boston University         # define your site
  30316. Xlist venus venus@host onwer@domain venus1 -e -m 25
  30317. X         # define a list called 'venus' (echo to screen)
  30318. Xserver listserver@domain -e -r statistics -b get -a VENUS # define the server
  30319. X         # with restriction, owner approved subscriptions for
  30320. X         # list VENUS, and batch all 'get' requests
  30321. Xlist ermis ermis@domain owner@other-domain ermis1 -m 25 -e
  30322. X         # define a list called 'ermis'
  30323. Xlist herc herc@domain owner@domain herc1 -r -s -m 25
  30324. X         # define 'herc' w/ restricted mail and no subscription checking
  30325. Xheader ermis {     # define header lines to be preserved
  30326. X  X-Mailer:     # save the mailer string
  30327. X  X-Organization:
  30328. X  MIME-Version:
  30329. X}
  30330. Xarchive ermis /ftp/mailing-lists/ermis %y%m%d listserver/ermis &
  30331. Xjohny-be-good     # auto archive list ermis -- command spans two lines
  30332. Xarchive venus /ftp/mailing-lists/venus venus.%j listserver/venus - digest
  30333. Xarchive herc  /usr/server/archives/private/herc %v.%n listserver/herc
  30334. Xdefault ermis {     # define default mail mode and password for new subscribers
  30335. X mail = ack     # if not defined, the system default is NOACK
  30336. X address = fixed # other option is variable; system default is FIXED
  30337. X password = xxx  # if not defined, the system assigns a random password
  30338. X conceal = yes   # system default is NO
  30339. X}
  30340. Xdefault venus {  # define default mail mode for new subscribers; the system
  30341. X  mail = digest     # picks a password at random, does not conceal identities
  30342. X         # and the user may not reset his address
  30343. X}
  30344. Xceiling ermis 10 # limit the number of messages processed per day to 10
  30345. Xdigest ermis 5000 48
  30346. X                 # specify the max number of lines before a digest is forced out
  30347. X                 # followed by the frequency (hours) that digests are
  30348. X                 # distributed
  30349. Xdigest venus 1000 24
  30350. X         # these are the default settings
  30351. Xdigest herc 2000 72
  30352. X         # digests will go out every 3 days, or when they grow
  30353. X         # longer than 2000 lines
  30354. Xdisable herc statistics     # cannot get statistics for list herc
  30355. Xunix_cmd ermis pass1 dir '/bin/ls $*' #Syntax: dir [args]
  30356. X         # $* substitutes for all arguments
  30357. Xunix_cmd ermis pass1 swap '/bin/echo $2 $1' #Syntax: swap <arg1> <arg2>
  30358. X         # re-echo the two arguments in the opposite order
  30359. Xbatch 8 20     # batch requests between 8 am and 8 pm
  30360. Xfax /usr/bin/fax # Path to, and optional arguments to auto-faxing program
  30361. Xserverd -l 3 -e    -i 600
  30362. X         # the serverd program may be run with the -l option
  30363. X         # serverd will delay if the load average is above 3
  30364. X         # Note that the -1 flag is used by default by start
  30365. X         # Go into interactive mode also with a 10 minute duration
  30366. Xrestriction 20     # certain requests may not be serviced abover this # of users
  30367. Xmanager server     # email address of the manager of the system
  30368. Xpassword ellines # password for the 'restart', 'shutdown' and 'execute' requests
  30369. Xcomment server     #Actual comment must be preceded by a pound sign
  30370. Xcomment ermis     #Same here
  30371. Xcomment venus     #Venus Distribution List
  30372. Xfrequency 5     # how often to read mail (in seconds >= 0)
  30373. Xprecedence bulk     # Usually bulk, junk, first-class or none
  30374. Xlimit message 65536     # reject messages longer than 65536 bytes
  30375. X#limit files 65536     # split files over this limit
  30376. Xoption sysv_ps     # forces use of the SYS V ps command; other choice is bsd_ps
  30377. Xoption bsd_mail     # define it if BSD mail is available
  30378. Xoption post_mail # Post to news; other choice is gate_mail
  30379. X#option relaxed_syntax    # listserv does not complain for extra params to
  30380. X            # requests
  30381. X#option ignore_invalid_requests        # ignore invalid user requests
  30382. Xmailmethod system
  30383. X#mailmethod env_var LOGNAME /bin/rmail    # Valid 'mailmethod' options:
  30384. X                    # telnet
  30385. X                    # sendmail /usr/lib/sendmail -ba
  30386. X                    # sendmail /usr/lib/sendmail -t (IDA)
  30387. X                    # rmail /bin/rmail
  30388. X                    # binmail
  30389. X                    # env_var VARIABLE /bin/mail
  30390. X                    # env_var VARIABLE /usr/lib/sendmail -t
  30391. X                    # env_var VARIABLE /bin/rmail
  30392. X                    # env_var VARIABLE /usr/bin/mail
  30393. X#option bad_telnet # use this flag when a telnet session is not terminating
  30394. X
  30395. X# IMPORTANT NOTE:
  30396. X#
  30397. X# listserv also recognizes the requests 'restart' and 'shutdown' followed by
  30398. X# a password, that can be used to remotely restart and shutdown the server
  30399. X# system. The password is defined in the 'config' file using the 'password'
  30400. X# directive followed by the actual password.
  30401. X# This feature is not documented in the man page for obvious reasons.
  30402. X# The same password is used for the 'execute' request.
  30403. X
  30404. X# Below are some sample remote lists
  30405. Xremote rlist1 rlist1@remote-domain listserver@remote-domain 127.0.0.1 &
  30406. X  #Sex issues
  30407. Xremote rlist-2 rlist-2@remote-domain listserver@remote-domain &
  30408. X  #Fruit punch issues!!
  30409. Xremote cook cook@foo.com listserver@foo.com bar.foo.com 372     &
  30410. X  #Cooking issues
  30411. *-*-END-of-config-*-*
  30412. echo x - .awk
  30413. sed 's/^X//' >.awk <<'*-*-END-of-.awk-*-*'
  30414. X{
  30415. X  tabcol = 40;
  30416. X  l = 0;
  30417. X  if (length ($1) < tabcol)
  30418. X    l = int ((tabcol + 7 - length ($1)) / 8);
  30419. X  printf "%s", $1;
  30420. X  k = 8 - int ((length ($1) % 8));
  30421. X  for (i = 0; i < k; i++) printf (" ");
  30422. X  for (i = 0; i < l; i++) printf "        ";
  30423. X  if ($2 != "") printf " %s", $2;
  30424. X  if ($3 != "") printf " %s", $3;
  30425. X  if ($4 != "") printf " %s", $4;
  30426. X  if ($5 != "") printf " %s", $5;
  30427. X  if ($6 != "") printf " %s", $6;
  30428. X  print "";
  30429. X}
  30430. *-*-END-of-.awk-*-*
  30431. echo x - .stats
  30432. sed 's/^X//' >.stats <<'*-*-END-of-.stats-*-*'
  30433. X#!/bin/sh
  30434. X# For NeXT hosts replace cut with awk.
  30435. X
  30436. Xpth=$1
  30437. Xsubscribers=$2
  30438. Xheaders=$3
  30439. Xoutfile=$4
  30440. Xheaderscp1=/tmp/.hdr3.$$
  30441. Xheaderscp2=/tmp/.hdr4.$$
  30442. Xshift; shift; shift; shift
  30443. Xif [ $# = 0 -o "$1" = "" ]; then
  30444. X  if [ `cut -d" " -f1,4 $subscribers | grep -i ' NO$' | \
  30445. X    cut -d" " -f1 > emails` ]; then
  30446. X    echo $0: syntax error lines 12-13 >> $pth/.warning
  30447. X    exit 1
  30448. X  fi
  30449. Xelif [ "$1" = " -ALL " ]; then
  30450. X  cp $headers $headerscp1
  30451. X  grep -i ' YES ' $subscribers | cut -d" " -f1 | 
  30452. X    ( x="garbage"
  30453. X      reduced=3
  30454. X      while [ "$x" != "" ]; do
  30455. X    read x
  30456. X    if [ "$x" != "" ]; then
  30457. X      grep -i -v "^$x" $headerscp1 > $headerscp2
  30458. X      hdr=$headerscp1
  30459. X      headerscp1=$headerscp2
  30460. X      headerscp2=$hdr
  30461. X      if [ $reduced -eq 3 ]; then
  30462. X        reduced=4
  30463. X      else
  30464. X        reduced=3
  30465. X      fi
  30466. X    fi
  30467. X      done
  30468. X      exit $reduced
  30469. X    )
  30470. X  reduced=/tmp/.hdr$?.$$
  30471. X  if [ ! -f $reduced ]; then
  30472. X    echo $0: cannot open $reduced >> $pth/.warning
  30473. X   exit 1
  30474. X  fi
  30475. X  if [ `cat $reduced | tr '[a-z]' '[A-Z]' | sort | uniq -c | \
  30476. X    awk '{ print $2 " " $1 }' - | awk -f $pth/.awk - >> $outfile` ]; then
  30477. X    echo $0: syntax error lines 43-44 >> $pth/.warning
  30478. X    exit 1
  30479. X  fi
  30480. X  echo Total number of messages on file: `cat $headers | wc -l` >> $outfile
  30481. X  rm -f $headerscp1 $headerscp2
  30482. X  exit 0
  30483. Xelse
  30484. X  for user 
  30485. X  do
  30486. X    echo "$user" >> emails
  30487. X  done
  30488. Xfi
  30489. Xif [ `cat emails | $pth/.grep $headers > counts` ]; then
  30490. X  echo $0: syntax error line 57 >> $pth/.warning
  30491. X  exit 1
  30492. Xfi
  30493. Xif [ `paste emails counts | awk -f $pth/.awk - >> $outfile` ]; then
  30494. X  echo $0: syntax error line 61 >> $pth/.warning
  30495. X  exit 1
  30496. Xfi
  30497. Xecho Total number of messages on file: `cat $headers | wc -l` >> $outfile
  30498. Xrm -f counts emails 
  30499. Xexit 0
  30500. *-*-END-of-.stats-*-*
  30501. echo x - .grep
  30502. sed 's/^X//' >.grep <<'*-*-END-of-.grep-*-*'
  30503. X#!/bin/sh
  30504. Xf="k"
  30505. Xwhile [ "$f" != "" ]; do
  30506. X  read f
  30507. X  if [ "$f" != "" ]; then
  30508. X    grep -i "^$f" $1 | wc -l
  30509. X  fi
  30510. Xdone
  30511. *-*-END-of-.grep-*-*
  30512. echo x - .ignored
  30513. sed 's/^X//' >.ignored <<'*-*-END-of-.ignored-*-*'
  30514. X^server$
  30515. X^bin
  30516. X^sys
  30517. *-*-END-of-.ignored-*-*
  30518. echo x - queued
  30519. sed 's/^X//' >queued <<'*-*-END-of-queued-*-*'
  30520. X#!/bin/sh
  30521. X#
  30522. X# queued version 2.1
  30523. X#
  30524. X# Usage: queued <frequency>
  30525. X#
  30526. X# Daemon to process the mail queue periodically. The frequency is given
  30527. X# in seconds.
  30528. X
  30529. Xif [ $# -ne 1 ]; then
  30530. X  echo Usage: `basename $0` \<frequency\>
  30531. X  exit 3
  30532. Xfi
  30533. X
  30534. Xtrap 'rm -f $PID_QUEUED; kill -9 $$' 1 2 3 6
  30535. XPID_QUEUED=/usr/server/.pid.queued
  30536. Xwhile [ -f $PID_QUEUED ]; do    # kill previous queued
  30537. X  cat $PID_QUEUED | (read PID; kill -2 $PID > /dev/null 2>&1)
  30538. X  if [ $? -gt 0 ]; then
  30539. X    rm -rf $PID_QUEUED
  30540. X  fi
  30541. X  sleep 10
  30542. Xdone
  30543. Xecho $$ > $PID_QUEUED
  30544. X
  30545. XDIR=/usr/server/mqueue
  30546. XFREQ=$1
  30547. XMANAGER=`grep "^manager " /usr/server/config | awk '{ print $2 }'`
  30548. Xshift
  30549. Xif [ ! -d $DIR ]; then
  30550. X  echo $DIR directory missing
  30551. X  exit 3
  30552. Xfi
  30553. XMANAGER=`grep "^manager " /usr/server/config | awk '{ print $2 }'`
  30554. Xcd $DIR
  30555. XPWD=`pwd`
  30556. Xwhile [ 007 ]; do
  30557. X  for i in `\ls`
  30558. X  do
  30559. X    if [ ! -f /usr/server/pqueue ] && [ "$MANAGER" != "" ]; then
  30560. X      echo $0 aborts: pqueue not found | /bin/rmail $MANAGER
  30561. X      exit 1
  30562. X    fi
  30563. X    /usr/server/pqueue -e $PWD/$i
  30564. X    exit_status=$?
  30565. X    if [ $exit_status -gt 0 ]; then
  30566. X      echo $0 aborts: pqueue exit status $exit_status | /bin/rmail $MANAGER
  30567. X      exit $exit_status
  30568. X    fi
  30569. X  done
  30570. X  sleep $FREQ
  30571. Xdone
  30572. Xexit 0
  30573. *-*-END-of-queued-*-*
  30574. echo x - owners
  30575. sed 's/^X//' >owners <<'*-*-END-of-owners-*-*'
  30576. X# Example onwers file
  30577. X#
  30578. X# Syntax: email-address <list-alias | server> [preferences]
  30579. X#
  30580. X# valid preferences for owners are:
  30581. X#  CCSET, CCSUBSCRIBE, CCUNSUBSCRIBE, CCRECIPIENTS, CCINFORMATION,
  30582. X#  CCSTATISTICS, CCPRIVATE, CCRUN, CCERRORS, CCALL
  30583. X#
  30584. X# valid preferences for the manager are:
  30585. X#  CCGET, CCINDEX, CCLISTS, CCRELEASE, CCHELP, CCERRORS, CCALL
  30586. X#
  30587. X# Notice: only the primary of each list may be copied
  30588. X
  30589. Xtasos server CCERRORS CCLISTS
  30590. Xtasos ermis CCERRORS CCSUBSCRIBE CCSET
  30591. Xtasos venus CCALL
  30592. Xtasos herc
  30593. *-*-END-of-owners-*-*
  30594. echo x - unwanted.hosts
  30595. sed 's/^X//' >unwanted.hosts <<'*-*-END-of-unwanted.hosts-*-*'
  30596. X#
  30597. X# Sample unwanted.hosts file. List here all host names, IP addresses and/or
  30598. X# aliases which are not allowed to connect to your IUL server.
  30599. X# Each line may have multiple entries.
  30600. X#
  30601. X# If you want to allow access to some predetermined hosts only, create the file
  30602. X# priv.hosts (under this directory) and put the privileged host names and/or
  30603. X# IP addresses in it, in the same format a