L-Soft international, Inc.

 

Developers Guide

for

LISTSERV®, version 14.5

 

22 February 2006

LISTSERV 14.5 Release

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The reference number of this document is 0602-MD-02.

Information in this document is subject to change without notice.  Companies, names and data used in examples herein are fictitious unless otherwise noted. L-Soft international, Inc. does not endorse or approve the use of any of the product names or trademarks appearing in this document.

 

Permission is granted to copy this document, at no charge and in its entirety, provided that the copies are not used for commercial advantage, that the source is cited and that the present copyright notice is included in all copies, so that the recipients of such copies are equally bound to abide by the present conditions. Prior written permission is required for any commercial use of this document, in whole or in part, and for any partial reproduction of the contents of this document exceeding 50 lines of up to 80 characters, or equivalent. The title page, table of contents and index, if any, are not considered to be part of the document for the purposes of this copyright notice, and can be freely removed if present.

 

The purpose of this copyright is to protect your right to make free copies of this manual for your friends and colleagues, to prevent publishers from using it for commercial advantage, and to prevent ill-meaning people from altering the meaning of the document by changing or removing a few paragraphs.

 

 

Copyright © 1998-2006 L-Soft international, Inc.

All Rights Reserved Worldwide.

 

LISTSERV is a registered trademark licensed to L-Soft international, Inc.

L-SOFT and LMail are trademarks of L-Soft international.

LSMTP is a trademark of L-Soft international, Inc.

EASE and CataLIst are service marks of L-Soft international, Inc.

UNIX is a registered trademark of X/Open Company Limited.

AIX and IBM are registered trademarks of International Business Machines Corporation.

Alpha AXP, Ultrix and OpenVMS are trademarks of Digital Equipment Corporation.

OSF/1 is a registered trademark of Open Software Foundation, Inc.

Microsoft is a registered trademark and Windows, Windows NT and Windows 95 are trademarks of Microsoft Corporation.

HP is a registered trademark of Hewlett-Packard Company.

Sun is a registered trademark of Sun Microsystems, Inc.

IRIX is a trademark of Silicon Graphics, Inc.

PMDF is a registered trademark of Innosoft International.

Pentium and Pentium Pro are registered trademarks of Intel Corporation.

All other trademarks, both marked and not marked, are the property of their respective owners.

 

All of L-Soft's manuals for LISTSERV are available in ascii-text format via LISTSERV and in popular word-processing formats via ftp.lsoft.com.  They are also available on the World Wide Web at the following URL:

 

URL:  http://www.lsoft.com/manuals/index.html

 

L-Soft invites comment on its manuals. Please feel free to send your comments via e-mail to MANUALS@LSOFT.COM, and mention which manual you are commenting on.

 

"Hot fix" revisions to this and other L-Soft manuals are posted as they are made to the master document, on the announcement-only mailing list:

 

LSOFT-DOC-UPDATES@PEACH.EASE.LSOFT.COM

 

A word about formatting: This manual was written in Microsoft Word 2000, and originally formatted to be printed on 8-1/2"x11" paper on a Hewlett-Packard LaserJet 4M+. When printing the manual on a different type of printer, or converting to a different word-processing program, it is highly likely that the formatting and pagination will change and it will be necessary to update the table of contents and figures as well as the index prior to printing. The author has taken great pains to ensure that the pagination and formatting works properly with the particular printer mentioned above, and cannot be held responsible for what is, in the end, a limitation of the software used to produce the manual.

 

Reference Number 0602-MD-02


Table of Contents

 

1. LISTSERV's Archive Search Functions. 6

1.1. Preface. 6

1.2. A basic search session.. 6

1.3. Narrowing the search.. 7

1.4. The SEARCH command. 7

1.4.1. Basic search functions. 7

1.4.2. Date specifications. 10

1.4.3. Keyword search specifications. 10

1.4.4. Phonetic search. 12

1.4.5. What to do about "100 matches (more available).". 13

1.4.6. Specifying the last n posts as a range. 14

1.4.7. Exact syntax description. 14

2. LISTSERV "Commands-Job" Feature and CJLI Interpreter. 19

2.1. Introduction.. 19

2.2. Overview -- the JOB entity. 19

2.3. Control Cards -- general syntax rules. 20

2.4. The JOB control card. 22

2.5. The EOJ control card. 24

2.6. The DD control card. 24

2.7. The //*MSG control card. 24

2.8. Special considerations. 25

3. Relayed File Distribution and the DISTRIBUTE Command. 27

3.1. Introduction.. 27

3.2. What is Relayed File Distribution?.. 27

3.3. A technical description of Relayed File Distribution Requests. 28

3.4. Creating and sending a mail RFDR ("DISTRIBUTE") job.. 31

3.4.1. RFDR job options. 35

3.4.2. DISTRIBUTE Command Options. 37

3.5. Advanced LISTSERV applications using DISTRIBUTE.. 39

3.5.1. "List-free" bounce processing for one-shot lists (1.8d and following)40

4. DBMS and mail-merge support42

4.1. Overview.. 42

4.1.1. DBMS support42

4.1.2. Why require Oracle 8 or higher?. 43

4.1.3. Mail-merge. 43

4.2. Pre-installation tasks. 44

4.2.1. Selecting a suitable DBMS product45

4.3. Installation.. 47

4.3.1. Windows NT/2000/XP. 47

4.3.2. OpenVMS Alpha. 47

4.3.3. Unix. 48

4.3.4. Verification. 49

4.4. Post-installation tasks. 49

4.4.1. Mail-merge. 49

4.4.2. ODBC interface. 50

4.4.3. OCI interface. 50

4.4.4. CLI interface. 50

4.4.5. unixODBC (UODBC) interface. 50

4.4.6. Connecting to multiple simultaneous database sources. 51

4.4.7. Generic DBMS post-installation tasks. 52

4.4.8. Performance options. 53

4.5. Creating DBMS lists. 54

4.5.1. Configuring a list to use the DBMS. 54

4.5.2. Importing subscribers into a DBMS list55

4.5.3. ADD IMPORT benchmark. 55

4.5.4. Updating DBMS lists from an external application. 56

4.5.5. Format of the OPTIONS column. 57

4.5.6. Sample OPTIONS column settings. 58

4.5.7. Preserving options when migrating from non-DBMS to DBMS lists. 59

4.6. Using the mail-merge functions. 60

4.6.1. Using the web interface. 60

4.6.2. Sending DISTRIBUTE jobs to LISTSERV. 61

4.6.3. Using substitutions. 65

4.6.3.1. New substitutions available in LISTSERV 1.8e-2003a "level set" release. 68

4.6.4. Using conditional blocks. 69

4.7. Installing and configuring unixODBC with LISTSERV and MySQL.. 71

4.7.1. MySQL DBMS. 72

4.7.1. MyODBC Driver72

4.7.3. unixODBC. 72

4.7.4. Creating a unixODBC System DSN for LISTSERV. 73

4.7.5. Creating a MySQL User and Database/Schema for LISTSERV. 73

4.7.6. Configure LISTSERV support for unixODBC. 74

4.7.7. Connecting to External MySQL Databases. 74

4.7.8. References. 74

5. List Exits. 75

5.1. What is a "list exit"?.. 75

5.2. List Exit Points. 79

5.2.1. ADD/SUBSCRIBE exit points. 79

5.2.2. DELETE/SIGNOFF/CHANGE entry points. 80

5.2.3. Other exit points. 81

5.2.4. General remarks. 82

5.3. Local command definition (non-VM). 82

5.4. SPAM_EXIT (LISTSERV 14.3 and following). 83

5.4.1. Formal documentation. 83

5.4.2. Practical application. 84

5.5. A practical example: HAPPY99. 87

6. The LISTSERV TCPGUI interface. 91

6.1. Setting up the TCPGUI interface. 91

6.2. Running lcmdx.. 91

6.3. Sending LISTSERV commands directly from your application.. 92

6.4. Advanced TCPGUI Programming Issues. 93

6.4.1. Creating or replacing a list header94

6.4.2. Adding or replacing a password. 95

6.4.3. Bulk operations. 95

6.4.4. Commands that respond over e-mail95

6.4.5. Application-friendly commands. 96

6.4.6. Error handling. 97

6.5. LCMDX.C.. 98

Revision History. 102

Index. 103

 

 

 


1. LISTSERV's Archive Search Functions

 

DOCUMENTATION NOTE

 

The information in this chapter applies to the "SEARCH" command introduced in LISTSERV 1.8c. It does not contain information pertaining to the old VM "DATABASE" command syntax, nor to LISTSERV DBMS support introduced in version 1.8d.

 

1.1. Preface

 

This chapter is an introduction to the LISTSERV archive search functions first implemented in L-Soft's LISTSERV 1.8c and later. It is intended to be a referencedocument for general users with little or no knowledge of databasesystems. It does not contain any technical information that generalusers would have to worry about.

 

Note: For LISTSERV on VM only, this chapter can be used with current versions (1.8c or later) of LISTSERV. For 1.8b or earlier VM servers, the "INFO DATABase" command will retrieve the manual for the old command syntax. The old database documentation is also available at L-Soft's ftp site in the file

 

ftp://ftp.lsoft.com/documents/old-listdb.memo

 

This chapter will discuss the syntax and operational characteristics of the LISTSERV database subsystem. It is assumed that the reader is familiar with his or her e-mail client and familiar with sending commands to a LISTSERV server.

 

If you just need a "quick start", read the next two sections for basic instructions. If you want a detailed tutorial on how to use the SEARCH command itself, you might want to skim the next two sections and then start reading with the section entitled "The SEARCH Command".

 

1.2. A basic search session

 

Let's say that you are looking for messages in the EASE-HOME mailing list that pertain to the list header keyword "Digest=".

 

To search for the term "Digest=" in the EASE-HOME list on HOME.EASE.LSOFT.COM, create a new mail message addressed to LISTSERV@HOME.EASE.LSOFT.COM and in the body (not the subject) of the message, simply type:

 

Search 'Digest=' in EASE-HOME

 

LISTSERV might respond to you with the following:

 

  +--------------------------------------------------------------------+

  | > Search 'Digest=' in EASE-HOME                                    |

  | -> 10 matches.                                                     |

  |                                                                    |

  | Item # Date     Time    Recs Subject                               |

  | ------ ----     ----    ---- -------                               |

  | 000058 96/01/26 14:44   41   What happened                         |

  | 000059 96/01/26 18:14   38   Re: What happened                     |

  | 000066 96/02/02 22:51   31   Digest Problem                        |

  | 000074 96/02/03 15:01   75   Re: Digest Problem                    |

  | 000075 96/02/03 18:52   49   Re: Digest Problem                    |

  | 000076 96/02/03 16:27   52   Re: Digest Problem                    |

  | 000112 96/02/13 23:37   29   not receiving mail                    |

  | 000126 96/02/25 20:20   63   error/bounce msg posted to list How?  |

  | 000172 96/03/13 09:11   12   Digest Mailing Time                   |

  | 000483 96/06/22 17:36   34   Header Info                           |

  |                                                                    |

  | To order a copy of these postings, send the following command:     |

  |                                                                    |

  |             GETPOST EASE-HOME 58-59 66 74-76 112 126 172 483       |

  |                                                                    |

  | >>> Item #58 (26 Jan 1996 14:44) - What happened                   |

  |    I never touched the Limits= command or the notebook= All I did  |

  | was try and add: Digest= Yes,Daily                                 |

  |                  ^^^^^^^                                           |

  | I have tryed this several times with the same reply message:       |

  |                                                                    |

  | >>> Item #59 (26 Jan 1996 18:14) - Re: What happened               |

  | >   I never touched the Limits= command or the notebook= All I did |

  | >was try and add: Digest= Yes,Daily                                |

  |                   ^^^^^^^                                          |

  +--------------------------------------------------------------------+

Figure 1.1.Sample SEARCH output (further output deleted)

 

Note that LISTSERV includes excerpts from the indexed postings showing the context of the search term(s). We've deleted all but the first 2 in the example above to save space.

 

You would then use the GETPOST command to order the specific posts you wanted to read. For instance, we want to read posts numbered 66, 74 through 76, and 126. You would make another new message (or reply to the response from LISTSERV without quoting the text) and type in the body:

 

GETPOST EASE-HOME 66 74-76 126

 

LISTSERV would then respond with the desired postings. For the non-VM servers, GETPOST is analogous to the old database command "PRINT". There is no corresponding command for the old database command INDEX, since the response to a SEARCH command includes the index of matching postings.

 

1.3. Narrowing the search

 

It is possible to add further parameters to your search in order to narrow it. You can limit a search by date with a "since. . . " predicate. Likewise, you can limit by sender and/or by the subject line with a "where . . ." predicate. For instance:

 

Search 'Digest=' in LSTOWN-L since 94/01/01

Search 'Digest=' in LSTOWN-L where sender contains 'Thomas'

Search * in LSTOWN-L where sender is ERIC@SEARN

Search * in LSTOWN-L since 94/01/01 where subject contains 'Digest'

 

are all valid search commands that will (depending on how well you've crafted your predicate) dramatically reduce the number of entries returned to you.

 

1.4. The SEARCH command

 

This chapter will introduce the formal syntax of the SEARCH command. (Note: The minimum abbreviation of this command is "S".)

 

The syntax of this command is a bit complex, and will be introduced step by step.

 

 

1.4.1. Basic search functions

 

The two most important things you have to indicate when you search list archives are:

 

 1. The name of the list whose archives you want to search.

 

 2. What you want to search the individual documents for.

 

The name of the list to be searched is specified after the words or phrases to be sought and is prefixed with an IN keyword. For example, we might do this:

 

Search Rosemary in MOVIES

 

This would select all the entries from list "MOVIES" containing the string "ROSEMARY".

 

Now if you just wanted to see the list of all the movies you can see, you could have used an asterisk as search argument to select all the entries in the list:

 

Search * in MOVIES

 

Note that the mailing list name doesn't have to be uppercased.

 

If you want to "narrow" your previous search, i.e. perform additional tests on the documents that have been previously selected, you must omit the IN keyword. In that case, the search will be applied to the previous "hits" and will create a new "hit list".

 

But in most cases, we will want to search for something longer than one word, for example part of a "key" sentence.

 

Search Hardware problem with a 4381 in IBMFORUM

 

Another problem is that we might not remember the exact original sentence. This is not very important, since LISTSERV will search each word individually: in the above example, any entry that contained the words "hardware", "problem", "with", "a" and "4381" would have matched the search, even if the words appeared in a different order.

 

But what if the original document had "4381-13" in it, instead of "4381"? This is again no problem, as LISTSERV does not require the word to be surrounded by blanks to find a match. Case is also ignored when performing the search operation. That is, "problem" would have found a match on "problems"... and "with" would have found a match on "without" or "withstand"! This may sound like inconsistent behaviour, but you should keep in mind that it is always possible to "narrow down" a search operation. However, once a document has been excluded from the list of "hits", it is very difficult to bring it back.

 

Now what if I want to search for an exact string? For example, I am interested in the string "in C". It is very likely that just any document in the database will contain both a "in" and the letter C. But what I am interested in is things which have been written, or programmed, or implemented, "in C". In that case, it is possible to force LISTSERV to group words together by quoting them, as in:

 

Search 'in C' in UTILITY

 

This method can also be used to insert extra blanks between or before words: leading and trailing blanks are normally removed automatically, but they are preserved inside quoted strings. Please note that quotes must be doubled when specified inside quoted strings, as in:

 

Search 'Rosemary''s baby' in MOVIES

 

The search for 'in C' resulted in over fifty hits, because a match was erroneously found against "in clear", "in core", etc. However, I do not want to search for 'in C ' because there might be hits with "in C." or "in C," in the database and I don't want to miss them. If the search respected the capital C, it would no longer find all those irrelevant hits. To do this, you must enclose your search string in double-quotes instead of single quotes, for example:

 

Search "in C" in UTILITY

 

Note that single quotes should not be doubled inside double-quoted strings, and vice-versa. Only quotes of the same type as the string should be doubled.

 

It is important to understand the difference between the two types of quoting. If you request a search for 'TEXT', you will find a match on "TEXT", "Text", "text" or even "teXt". This is the same behaviour as unquoted text. However, if you request a search for "TEXT", it will only find a match on "TEXT", not on "text" or "Text".

 

Quoting is also the only way to search for a reserved keyword like "IN": if you tried "Search in in UTILITY", LISTSERV would report that database "IN" does not exist and would reject the command. This is because the keyword IN indicates the end of your search arguments. If you quote it, however, it will not be recognized and will be searched as you wanted it done. Similarly, if you want to search for an asterisk, you will have to quote it since

 

Search *

 

indicates that all entries should be selected.

 

Now the problem is that there may be sentences starting with a capital I, e.g. "In C, it would be coded this way:". How can I catch these sentences?

 

Actually, you have been using "complex search expressions" from the beginning without even being aware of it. When you specified a search on

 

Hardware problem with a 4381

 

, you had in fact been asking LISTSERV for: "Hardware NEAR problem NEAR with NEAR a NEAR 4381". The "NEAR" is implicit, but it may be overriden.

 

[Note that this is a change from the way the "locate" clause was implemented in 1.8b and earlier. Earlier versions used a default of "AND" instead of "NEAR" between discrete search terms. The difference is that

 

Search JOE SMITH in XYZ-L

 

looks for JOE and SMITH close to each other rather than simply looking for instances of both terms in the entire document. You can still use AND explicitly. Note that 'a NEAR b NEAR c' is defined as '(a NEAR b) AND (b NEAR c)', so the NEAR operator is not fully commutative.]

 

You may even use parenthesis if needed:

 

Search ("in C" or "In C") and program in UTILITY

 

The "NEAR" can still be implied, as in:

 

  +--------------------------------------------------------------------+

  | Search wooden chair (blue or green) in CHAIRS                      |

  | Search (wooden chair) or (plastic chair) in CHAIRS                 |

  | Search plastic chair (blue or green but not streaked) in CHAIRS    |

  |                                                                    |

  | The following commands are strictly equivalent:                    |

  |  Search (wooden chair) or (plastic chair not blue) in CHAIRS       |

  |  Search chair (wooden or (plastic not blue)) in CHAIRS             |

  |  Search chair (wooden or (plastic but not blue)) in CHAIRS         |

  |  Search chair NEAR (wooden OR (plastic AND NOT blue)) in CHAIRS    |

  +--------------------------------------------------------------------+

Figure 1.2.Sample  SEARCH  commands  using complex document search arguments

 

1.4.2. Date specifications

 

Since each document has been assigned a "date/time" field, it is possible to select documents based on this date field. This is accomplished by appending "date search rules" to the search expression, as in:

 

  +--------------------------------------------------------------------+

  | Search problem (serious or severe) in BBOARD since july            |

  | Search problem in BBOARD since oct 85                              |

  | Search symptom in BBOARD since 12/28                               |

  | Search error report from 12 january to august in BBOARD            |

  | Search user complaint until 18 sept in BBOARD                      |

  | Search data check since today 11:53 in EREP                        |

  +--------------------------------------------------------------------+

Figure 1.3.Sample SEARCH commands using date search arguments

 

The default values for omitted arguments are always chosen so as to exclude as few entries as possible. For example, "July" would mean "1 July 00:00:00" in a SINCE specification, and "31 July 23:59:59" in an UNTIL clause. The only exception is the year field, which always defaults to the current year.

 

1.4.3. Keyword search specifications

 

The last thing you may wish to search is the "keywords" list. For example, you might want to select those plastic chairs which cost less than 50 dollars. It is assumed that the price will vary often (maybe almost daily), and that it is therefore kept externally from the document describing the chair. Thus, you would have a "Price" keyword which you could search in the following way:

 

Search plastic chair in CHAIRS where price < 50

 

You may of course use complex expressions (with parenthesis) in the WHERE clause. There are new comparison operators available for this clause, like IS, CONTAINS, all the usual arithmetical comparison operators, and some more. However, the AND operation is no longer implied, but it can still be specified explicitly of course:

 

Search plastic chair in CHAIR where price < 50 and avail > 4

 

The problem now is that, as the search commands become more and more complex, they will no longer fit in a single line. To solve this problem, we begin the command with the string "// " (two front-slashes and a space) and follow it with the SEARCH command and the search specifications. Any database command ending in a comma indicates that more is to follow on the next line. This process can be repeated several times if desired.

 

  +--------------------------------------------------------------------+

  | // Search chair (wooden or (blue or green but not streaked)) ,     |

  |        in CHAIRS ,                                                 |

  |        where price < 50 & avail > 4                                |

  |                                                                    |

  | // Search chair (wooden or (blue or green but not streaked)) ,     |

  | in CHAIRS where price < 50 & avail > 4                             |

  |                                                                    |

  | // Search chair (wooden or ( ,                                     |

  | blue or green but not streaked) ,                                  |

  | ) ,                                                                |

  | in CHAIRS where price < 50 & avail > 4                             |

  +--------------------------------------------------------------------+

Figure 1.4.Sample SEARCH commands with continuation lines: All these commands are strictly identical, although the first one is obviously more legible. |

 

The only "trick" about this continuation line business is that you should always keep quoted strings on a single line. The process of identifying continuation lines and concatenating them afterwards may cause unwanted blanks to be inserted in the command line, which is no problem outside a quoted string since blanks are ignored, but might cause erroneous results in a quoted string.

 

If you want to search for several possible values in a given keyword, you do not have to repeat the keyword name and operator:

 

  +--------------------------------------------------------------------+

  | // Search * in BBOARD where ,                                      |

  | subject contains (PC or (Personal and computer))                   |

  |                                                                    |

  | is strictly equivalent to:                                         |

  |                                                                    |

  | // Search * in BBOARD where ,                                      |

  | subject contains PC or ,                                           |

  | (subject contains Personal and subject contains computer)          |

  +--------------------------------------------------------------------+

Figure 1.5.Sample use of "factorization"

 

However, it should be noted that this "factorization" is performed according to the rules of logic, which may not necessarily match those of English grammar. This removes any possible ambiguity as to the meaning of these clauses. Let's consider the following example:

 

machine does not contain (IBM and DEC)

 

This clause will get translated into:

 

machine does not contain IBM and machine does not contain DEC

 

In English you would probably say "machine contains neither IBM nor DEC" . This is how LISTSERV will understand it. However, if you read the clause aloud, you will probably not pronounce the parenthesis and will end up saying "machine does not contain IBM and DEC", in other words, "machine does not contain both IBM and DEC" , which is a totally different thing (and would most probably be true all the time). The "English meaning" could be obtained with the following clause:

 

not (machine contains (IBM and DEC))

 

In the former case, the negative "does not contain" operator is inserted inside the parenthesis. In the latter, only "contains" is moved, and the negation remains outside.

 

  +--------------------------------------------------------------------+

  | // Search gateway problem ,                                        |

  |   in BBOARD ,                                                      |

  |   since sept 86 ,                                                  |

  |   where sender contains (john or paul but not mick) ,              |

  |   and subject does not contain lost                                |

  |                                                                    |

  | -> 5 matches.                                                      |

  |                                                                    |

  | Item #   Date   Time  Recs   Subject                               |

  | ------   ----   ----  ----   -------                               |

  | 000012 87/10/18 13:09   12   The gateway has stopped working       |

  | 000017 87/08/24 09:18    9   Glory glory alleluja! Again!!!        |

  | 000018 87/10/18 13:09    8   You know what? It WORKS!!!            |

  | 000024 87/10/18 13:09    7   Guess what happened today?            |

  | 000205 87/10/04 16:59    9   Who's going to babysit it today?      |

  |                                                                    |

  |                                                                    |

  | You  might now wish to narrow your search down to exclude postings |

  | whose subject contains "work".  For instance,                      |

  |                                                                    |

  | // Search gateway problem ,                                        |

  |   in BBOARD ,                                                      |

  |   since sept 86 ,                                                  |

  |   where sender contains (john or paul but not mick) ,              |

  |   and subject does not contain (lost or work)                      |

  |                                                                    |

  | -> 3 matches.                                                      |

  |                                                                    |

  | Item #   Date   Time  Recs   Subject                               |

  | ------   ----   ----  ----   -------                               |

  | 000017 87/08/24 09:18    9   Glory glory alleluja! Again!!!        |

  | 000024 87/10/18 13:09    7   Guess what happened today?            |

  | 000205 87/10/04 16:59    9   Who's going to babysit it today?      |

  +--------------------------------------------------------------------+

Figure 1.6.Sample SEARCH commands with keyword search clauses

 

1.4.4. Phonetic search

 

There may be cases where you are looking for a certain value of a keyword, the exact spelling of which you cannot remember. In these cases, it may be useful to try a phonetic search. A phonetic search will yield a match for anything that "sounds like" your search string, as dictated by a predefined algorithm which is of course not perfect. It may give a hit for something which does not actually sound like your search string, or, more rarely, omit a keyword which did sound like what you entered. The main reasons for this are that the algorithm must be fast to execute on the machine and therefore not too sophisticated, and that the way a given word is pronounced depends on the idiom in which the word was written. For example, the phonetical transcription of the name "Landau" will be different in French, English, German and Russian. Thus, it is impossible to decide whether a word sounds like another if the language in which the words are pronounced is not known (and of course LISTSERV does not have, a priori, any way to know it).

 

Phonetic searches are performed through the use of the SOUNDS LIKE and DOES NOT SOUND LIKE operators, which are syntactically similar to CONTAINS and DOES NOT CONTAIN. That is, you could do something like:

 

Search * in PHONEBOOK where NAME sounds like WOLF

 

There is a little trick with the SOUNDS LIKE operator that you should be aware of. If your search string (WOLF in our above example) is a single word, it will be compared individually to all the words in the reference string (i.e. the data from the database), and will be considered a hit if it "sounds like" any of the words in the reference string. Thus, the search word "Ekohl" sounds like the reference string "Ecole Normale Superieure" because it matches the first word. If the search string contains more than one word, the search and reference strings will be compared phonetically as a whole (and "Ekohl Dzentrahll" will therefore not match "Ecole Normale Superieure"). Note that any search string containing more than a single word must be quoted, as explained in the previous sections of this chapter.

 

  +--------------------------------------------------------------------+

  | > Search * in BITEARN where site sounds like (COHRNEAL and         |

  | LAPORRADRY)                                                        |

  |                                                                    |

  | -> 3 matches.                                                      |

  |                                                                    |

  | Ref# Conn  Nodeid   Site name                                      |

  | ---- ----  ------   ---------                                      |

  | 0292 87/03 CRNLASSP Cornell University Cornell Laboratory of Atomic|

  | 0301 87/03 CRNLION  Cornell University Cornell Laboratory of Plasma|

  | 0307 87/06 CRNLNUC  Cornell University Laboratory of Nuclear Studes|

  |                                                                    |

  | > Search * in BITEARN where SITE sounds like HOPTIKK               |

  |                                                                    |

  | -> 2 matches.                                                      |

  |                                                                    |

  | Ref# Conn Nodeid Site name                                         |

  | ---- ---- ------ ---------                                         |

  | 0751 87/09 FRIHAP31 Assistance Publique - Hopitaux de Paris        |

  | 2120 87/04 UOROPT University of Rochester The Institute of Optics  |

  |                                                                    |

  | > Search * in BITEARN where SITE sounds like SCHIKAGO              |

  |                                                                    |

  | -> 1 match.                                                        |

  |                                                                    |

  | Ref# Conn Nodeid Site name                                         |

  | ---- ---- ------ ---------                                         |

  | 0140 86/03 BMLSCK11 Studiecentrum voor Kernenergie (SCK/CEN), Mol, |

  +--------------------------------------------------------------------+

Figure 1.7.Sample SEARCH commands involving phonetic match

 

In the figure above, the first command shows an example of accurate phonetic match, where the result is exactly what the user expected. In the second example, the user found what he was looking for ("Optics"), but an additional unwanted entry was selected. This is by far the most common case. The last command is a typical example of phonetic clash, where the algorithm did not translate the search string into phonetics as the user expected it, with the result that the desired name ("Chicago") was not found and that completely irrelevant entries were presented instead.

 

The phonetic matching algorithm used by LISTSERV is a slightly modified version of SOUNDEX -- a well-known algorithm that provides reasonably accurate matches at a very low CPU cost. Although it gives best results with the English language, for which it was originally designed, it is not too strongly tied to it and can still be used with other languages. It is of course absolutely impossible to write an program that would work for all the languages in the world, or even for the most widely used ones, since their interpretation of the most common combinations of letters are completely incompatible.

 

 

 

1.4.5. What to do about "100 matches (more available)."

 

LISTSERV limits the number of matching records in a given response to no more than 100. This is done primarily to stop hackers from tying up the server with SEARCH requests on lists with thousands of archived postings, but it also keeps the size of the response down to a manageable level. For instance, sending a "SEARCH *" command for an old, very large list could result in a response measuring in megabytes if not for the 100-record limitation.

 

There are a couple of different approaches to a solution:

 

·         (Preferred) Narrow your search parameters as explained in 1.3 and following.

 

·         Specify the first record for your search so that LISTSERV knows to start in a certain place. For instance, if you sent a search command like

 

search * in lstown-l where sender contains nathan@example.com

 

that resulted in more than 100 "hits", and the last four hits were something like

 

  +--------------------------------------------------------------------+

  | 007696 95/08/23 16:02   13   Re: How to send 'urgent' messages to  |

  | digest users?                                                      |

  | 007698 95/08/23 18:10   52   Re: Blocking expletives               |

  | 007699 95/08/23 20:00   41   Re: How to send 'urgent' messages to  |

  | digest users?                                                      |

  | 007716 95/08/25 10:34   33   Re: ignore subsequent lines to        |

  | listserv?                                                          |

  +--------------------------------------------------------------------+

 

you could send a followup search command using the following syntax:

 

search * in lstown-l.7716- where sender contains nathan@example.com

 

to get the next 100 hits starting with message number 7716. Note that it is important to include the trailing hyphen after the starting message number, as otherwise you will get back a response containing only a reference to the message number you specified.

 

1.4.6. Specifying the last n posts as a range

 

Starting with LISTSERV 1.8d it is possible to specify that your search criteria be applied to only the last n posts in the archive. For instance, say you are only interested in checking the last 50 postings of LSTOWN-L to see if nathan@lsoft.com posted. You would send

 

search * in lstown-l.last50- where sender contains nathan@lsoft.com

 

Again you would have to use the hyphen after the number. The number n can be any integer, but as with any other search, if LISTSERV finds more than 100 hits only the first 100 will be returned to you. Thus it would be possible for n to be 1000, or even 10,000, but you will still have to narrow your search if you want more hits.

 

1.4.7. Exact syntax description

 

This section describes the exact syntax of the "SEARCH" command in technical terms. You can skip it if you are not interested in learning about the details of this command.

 

General syntax

 

  +--------+-----------------------------------------------------------+

  |        |                                                           |

  | Search |  search-rules  <optional-rules>                           |

  |        |                                                           |

  |        |  Optional rules are:                                      |

  |        |                                                           |

  |        |    date-rules                                             |

  |        |    keyword-rules                                          |

  +--------+-----------------------------------------------------------+

 

The optional "date-rules" and "keyword-rules" arguments may appear in any order.

 

Date rules specification

 

You may optionally restrict the search to only those entries that lay within a given interval of time. This is accomplished by specifying one of the following date rules:

 

SINCE date-spec <time-spec>

FROM date-spec1 <time-spec1> TO date-spec2 <time-spec2>

UNTIL date-spec <time-spec>

 

The format of a "date-spec" is quite complex because of the number of different ways date/time specifications are usually expressed:

 

TODAY

yy

dd mm

<dd><->monthname<-><yy>

mm/yy

mm-yy

yy/mm/dd

yy-mm-dd

yyyymmdd      

 

(yyyymmdd is accepted by LISTSERV version 1.8d and following.)

 

Month names can be abbreviated to any length. If there is an ambiguity, the first month in chronological order is retained. For example, "J" would mean "January", "JU" would be "June" and "JUL" would unambiguously select "July".

 

The format of a "time-spec" is simply <hh:mm<:ss>>.

 

  +--------------------------------------------------------------------+

  | FROM 14 july TO oct 97                                             |

  | SINCE 96                                                           |

  | UNTIL 23-JUN-97                                                    |

  | SINCE today 11:30                                                  |

  +--------------------------------------------------------------------+

Figure 1.8.Sample date clauses

 

NOTE: Case is irrelevant in date specifications. The keywords (SINCE, UNTIL, etc) have been capitalized only for better legibility, and can be entered in lower case if desired.

 

Keyword rules specification

 

You may request the actual document search to take place only for those entries which match a set of "keyword comparison" rules. The syntax is the following:

 

 WHERE kwd-expression

 WITH kwd-expression

 

"kwd-expression" is, generally speaking, an mathematical expression of keyword/value comparisons, possibly bound by logical operators. Comparison operators have a higher precedence than logical operators, that is, "A>10 AND B=20" is interpreted as "(A>10) AND (B=20)". The available comparison operators are listed below. All the operators appearing on a given line are synonyms.

 

  +--------------------------------------------------------------------+

  | = IS                                                               |

  | ^= <> IS NOT                                                       |

  | >                                                                  |

  | <                                                                  |

  | >=                                                                 |

  | <=                                                                 |

  | SOUNDS LIKE                                                        |

  | DOES NOT SOUND LIKE                                                |

  | CONTAINS                                                           |

  | DOES NOT CONTAIN                                                   |

  +--------------------------------------------------------------------+

Figure 1.9.Comparison operators for WHERE clauses

 

All these operators are self-explanatory, except the last two which allow you to search the keyword value for a given "substring". That is, "Sender contains jeff" would be true if the value of the "Sender" keyword was "Jeff Smith" or "Jeffrey Donaldson". The case is ignored during the comparison unless the search operand is double-quoted.

 

If no valid comparison operator is specified between two arguments, "IS" (identity) is assumed.

 

The available logical operators are:

 

  +--------------------------------------------------------------------+

  | ^ NOT                                                              |

  | & AND BUT                                                          |

  | | / OR                                                             |

  +--------------------------------------------------------------------+

Figure 1.10.Logical (boolean) operators

 

Please note that the logical operators AND and OR have equal precedence and are evaluated left-to-right.

 

Finally, keywords and operators can be "factorized" when the same comparison is to be applied to a given keyword and a series of comparands. For example, you might enter:

 

Search * where sender contains ('CS Dept' and (Jack or Phil))

 

 This is internally expanded to:

 

// SEARCH * WHERE sender CONTAINS 'CS Dept' AND ,

   (sender CONTAINS Jack OR sender CONTAINS Phil)

 

Please note that the expression must always be enclosed in parenthesis, even if it is a simple one:

 

Search * where sender contains (Joe or Morris)

 

This stems from the fact that comparison operators have a higher priority than logical (boolean) ones.

 

  +--------------------------------------------------------------------+

  | WHERE Sender is "Arthur Dent" ,                                    |

  | and Subject does not contain tea                                   |

  |                                                                    |

  | WITH Refcode 8467272 and Location Roubaix                          |

  |                                                                    |

  | WITH (QTY > 100 | PRICE > 1000) & MAT = COPPER                     |

  |                                                                    |

  | Where Sender is (Atiaran@Land or Elena@Land) ,                     |

  | and Subject contains ('Be true' but not Ur-Lord)                   |

  +--------------------------------------------------------------------+

Figure 1.11.Sample WHERE clauses

 

Search rules specification

 

Finally, you must specify what is to be searched inside the document. If you do not want anything to be sought at all (e.g. if you are only selecting known items from the database), you can specify an asterisk as a placeholder to waive the search. Otherwise you must specify a mathematical expression where arguments are search strings, possibly bound by logical operators (see Figure 10 for a comprehensive list). The default operator is AND, so that a search for "INTERPRET STEM PROBLEM" will select all entries where "INTERPRET", "STEM" and "PROBLEM" can be found (not necessarily in the same line).

 

  +--------------------------------------------------------------------+

  | Search *                                                           |

  |                                                                    |

  | Search 'I/O' Error                                                 |

  |                                                                    |

  | // Search Interpret (performance or tips ,                         |

  | but not (bug or question))                                         |

  +--------------------------------------------------------------------+

Figure 1.12.Sample document-search clauses

 

Reserved words and quoting

 

When to quote strings

 

Keyword names and search arguments need not be quoted, unless:

 

·         They are formed of more than one word (search arguments only).

 

·         They contain leading or trailing blanks (search arguments only).

 

·         Their name matches one of the "reserved keywords" of the LISTSERV database system, and appears in a context where it can be mistaken for such. The "reserved keywords" are: FROM, IN, SINCE, TO, UNTIL, WHERE, WITH.

 

·         They contain a parenthesis, logical operator or comparison operator symbol. More generally, you should quote any string that contains one of the following characters:

 

( ) < > = | & ^ /

 

Any non-quoted word will be stripped of leading and trailing blanks and converted to uppercase before the search.

 

Single-quoted strings

 

Strings quoted in single-quotes (') are converted to upper case and cause case to be ignored during the search. That is, they behave in the same manner as un-quoted strings as far as the search algorithm is concerned. As a rule of thumb, any string can be single-quoted if desired, even if it does not have to.

 

Single quotes must be doubled inside single-quoted strings, but double quotes should not:

 

Search '"T''amo, ripetilo, si caro accento' in OPERA

 

Double-quoted strings

 

Strings quoted in double-quotes (") are not converted to upper case. They result in a case-sensitive search, which means that you should never double-quote a string unless you want case to be respected during the search.

 

Double quotes must be doubled inside double-quoted strings, but single quotes should not:

 

Search """T'amo, ripetilo, si caro accento" in OPERA

 

 


2. LISTSERV "Commands-Job" Feature and CJLI Interpreter

 

2.1. Introduction

 

The "Commands-Job" feature of LISTSERV was designed in an attempt to allow for powerful inter-LISTSERV (and more generally, program-to-LISTSERV) command transmission with message redirection and multi-line arguments capability, while still allowing inexpert users to send commands to LISTSERV for execution in a very simple, intuitive" way.

 

The implementation of Commands-Jobs has therefore been split into two different layers: the 'core' command job language interpreter, with its exacting, powerful but stern control cards syntax, and the 'outer' interface to the user which provides the required default control cards whenever they have been omitted, translating an "intuitive" series of commands to execute into an actual commands-job that can be processed by the 'core' interpreter.

 

Since this documentation is primarily intended for postmasters and LISTSERV applications programmers, it will be oriented towards a description of the 'core' interpreter. The work of the 'outer interface' will only be mentioned for better understanding. The 'core' interpreter will be referred to as 'Commands Job Language Interpreter' (CJLI) in the following discussion.

 

Warning: if you are familiar with MVS and JCL, you will probably notice some similarity between command job control cards and JCL. This similarity is purposeful and was intended to make CJLI easier to understand for JCL adepts and to make MVS users more comfortable with CJLI (MVS users who do not have any mailing system such as UCLA mail and have difficulties sending/receiving messages are often forced to use (basic) CJLI control cards to send commands to LISTSERV). However, there are a number of differences between CJLI and JCL and you should not assume that a given JCL card has the same meaning and syntax as its CJLI counterpart. Some JCL features which were deemed to be unnecessary (eg dataset concatenation with a blank DD card) have not been implemented, and new features have been implemented whenever required.

 

2.2. Overview -- the JOB entity

 

As soon as the 'outer' interface detects that a file contains commands (as opposed to a mail or non-mail file intended for redistribution to a list), it passes it to the CJLI for execution. This physical file will contain one or more logical 'JOB's with interspersed comment lines. Each 'JOB' will contain zero or more commands, start with a "// JOB" card and end with a "// EOJ" card. The 'outer' interface will provide these cards if omitted, but this will be detailed later on. Anything before the first "// JOB" card, after the last "// EOJ" or between "// EOJ" and "// JOB" cards is ignored. Notably, mail headers and "Acknowledge-To:" fields (at the bottom of the mail file) would be ignored. A physical job file containing two jobs might look like this:

 

(any number of header lines, ignored)

 //jobname1 JOB options

 .

 .

 .

 //jobname1 EOJ

(any number of lines, ignored)

 //jobname2 JOB options

 .

 .

 .

 //jobname2 EOJ

(any number of lines before EOF, ignored)

 

Each job in the physical file is a completely independent entity which contains commands and the 'dataset' definitions required to execute the commands properly. Jobs are executed in sequential order; if a job does not execute successfully, the other jobs in the physical file are still executed, unless the job has been terminated by a 'global' error (eg error reading the physical file), in which case the CJLI terminates after transferring the