~ PH_CLIENT.SAV% PH_CLIENT.SAV3BACKUP *.* OA$:[FTP.PH_CLIENT]PH_CLIENT.SAV/SAVE/LO SYSMANAGER GV5.5 _MEEVAX::  _$255$DUS6: V5.5-2 ~ #*[PH_CLIENT]AAAREADME.VMS;1+,<./ 4L0-0123KPWO56p7;89GHJJThis is the VAX/VMS distribution of ph v4.10. This version was sucessfullyJcompiled, linked, and run under VMS 5.3 with Wollongong WIN/TCP 5.1 headerJfiles and runtime libraries. Your mileage may obviously vary! The VMS portJimplementation notes at the front of ph.c may be helpful with other systemconfigurations as well.3The following files should exist in this directory:<AAAREADME.VMS;410 This very file you are now reading!LCOMPILE_PH.COM;410 Procedure to compile: crypt.c, cryptit.c, and ph.c.;CRYPT.C;410 Encryption routines (from 4.3 BSD)4CRYPTIT.C;410 Encryption routines for ph..LINK_PH.COM;410 Procedure to link ph.)PH-1.TXT;410 Man page for ph.,PH-INTRO.TXT;410 Introduction to ph.-PH.C;410 Main program for ph.3PROTOCOL.TXT;410 Ph protocol documentation.-REPLIES.H;410 Include file for ph.<TERMDEFS.H;410 Include file for VMS version of ph.KIf you have questions or problems installing the VMS version of ph, you mayAdirect them to me (Mark Sandrock) at sandrock@aries.scs.uiuc.edu.HGeneral ph questions and comments are best directed to the author of ph:#Steve Dorner, at s-dorner@uiuc.edu. Good luck, Mark Sandrock---HBITNET: sandrock@uiucscs Univ. of Illinois at Urbana-ChampaignLInternet: sandrock@aries.scs.uiuc.edu Chemical Sciences Computing ServicesFVoice: 217-244-0561 505 S. Mathews Ave., Urbana, IL 61801>"He who knows doesn't say. He who says doesn't know." -Lao Tse!*[PH_CLIENT]COMPILE_DEBUG_PH.COM;1+,./ 4DX-0123KPWO56ж*7.F89GHJ#$ cc/debug/noop/object=cryptd crypt'$ cc/debug/noop/object=cryptitd cryptitD$ cc/debug/noop/object=phd/define=("HOST=""ph-server.llnl.gov""", -: FALLBACKADDR=0x807312FD, -) "NSSERVICE=""ns""",FALLBACKPORT=105, - "ADMIN=""gp@llnl.gov""", -. "MAILDOMAIN=""llnl.gov""","CLIENT=""ph""") - ph 'p1'*[PH_CLIENT]COMPILE_PH.COM;4+,g./ 4>-0123KPWO56򒹲789GHJ $ cc crypt $ cc cryptit>$ cc /define=("HOST=""p.lanl.gov""",FALLBACKADDR=0x807312fd, -0 "NSSERVICE=""ns""",FALLBACKPORT=105, - "ADMIN=""lanl.gov""", -. "MAILDOMAIN=""lanl.gov""","CLIENT=""ph""") - ph 'p1'*[PH_CLIENT]CRYPT.C;1+,./ 4>-0123KPWO56pk7Ѓ89GHJ",/*#if defined(LIBC_SCCS) && !defined(lint)*/#ifdef LIBC_SCCS #ifndef lint;static char sccsid[] = "@(#)crypt.c 5.2 (Berkeley) 3/9/86";#endif#endif LIBC_SCCS and not lint/* * This program implements the* * Proposed Federal Information Processing * Data Encryption Standard.3 * See Federal Register, March 17, 1975 (40FR12134) *//* * Initial permutation, */static char IP[] = { 58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7,};/*" * Final permutation, FP = IP^(-1) */static char FP[] = { 40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25,};/*& * Permuted-choice 1 from the key bits * to yield C and D.' * Note that bits 8,16... are left out:( * They are intended for a parity check. */static char PC1_C[] = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36,};static char PC1_D[] = { 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4,};/*0 * Sequence of shifts used for the key schedule.*/static char shifts[] = {! 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,};/*/ * Permuted-choice 2, to pick out the bits from/ * the CD array that generate the key schedule. */static char PC2_C[] = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2,};static char PC2_D[] = { 41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32,};/*9 * The C and D arrays used to calculate the key schedule. */static char C[28];static char D[28];/* * The key schedule. * Generated from the key. */static char KS[16][48];/* * The E bit-selection table. */static char E[48];static char e[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10,11,12,13, 12,13,14,15,16,17, 16,17,18,19,20,21, 20,21,22,23,24,25, 24,25,26,27,28,29, 28,29,30,31,32, 1,};/*( * Set up the key schedule from the key. */ setkey(key) char *key;{ register i, j, k; int t; /*( * First, generate C and D by permuting' * the key. The low order bit of each2 * 8-bit char is not used, so C and D are only 28 * bits apiece. */ for (i=0; i<28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } /*, * To generate Ki, rotate C and D according) * to schedule and pick up a permutation * using PC2. */ for (i=0; i<16; i++) { /* * rotate. */ for (k=0; k * The combination of the key and the input, before selection. */static char preS[48];/* * The payoff: encrypt a block. */encrypt(block, edflag) char *block;{ int i, ii; register t, j, k; /*( * First, permute the bits in the input */ for (j=0; j<64; j++) L[j] = block[IP[j]-1]; /*- * Perform an encryption operation 16 times. */ for (ii=0; ii<16; ii++) { /* * Set direction */ if (edflag) i = 15-ii; else i = ii; /* * Save the R array, * which will be the new L. */ for (j=0; j<32; j++) tempL[j] = R[j]; /*. * Expand R to 48 bits using the E selector;, * exclusive-or with the current key bits. */ for (j=0; j<48; j++)" preS[j] = R[E[j]-1] ^ KS[i][j]; /*+ * The pre-select bits are now considered * in 8 groups of 6 bits each.( * The 8 selection functions map these+ * 6-bit quantities into 4-bit quantities * and the results permuted * to make an f(R, K).. * The indexing into the selection functions+ * is peculiar; it could be simplified by * rewriting the tables. */ for (j=0; j<8; j++) { t = 6*j; k = S[j][(preS[t+0]<<5)+ (preS[t+1]<<3)+ (preS[t+2]<<2)+ (preS[t+3]<<1)+ (preS[t+4]<<0)+ (preS[t+5]<<4)]; t = 4*j; f[t+0] = (k>>3)&01; f[t+1] = (k>>2)&01; f[t+2] = (k>>1)&01; f[t+3] = (k>>0)&01; } /* * The new R is L ^ f(R, K).1 * The f here has to be permuted first, though. */ for (j=0; j<32; j++) R[j] = L[j] ^ f[P[j]-1]; /*( * Finally, the new L (the original R) * is copied back. */ for (j=0; j<32; j++) L[j] = tempL[j]; } /*$ * The output L and R are reversed. */ for (j=0; j<32; j++) { t = L[j]; L[j] = R[j]; R[j] = t; } /* * The final output6 * gets the inverse permutation of the very original. */ for (j=0; j<64; j++) block[j] = L[FP[j]-1];}char *crypt(pw,salt) char *pw; char *salt;{ register i, j, c; int temp;" static char block[66], iobuf[16]; for(i=0; i<66; i++) block[i] = 0;" for(i=0; (c= *pw) && i<64; pw++){ for(j=0; j<7; j++, i++) block[i] = (c>>(6-j)) & 01; i++; }  setkey(block);  for(i=0; i<66; i++) block[i] = 0; for(i=0;i<2;i++){ c = *salt++; iobuf[i] = c; if(c>'Z') c -= 6; if(c>'9') c -= 7; c -= '.'; for(j=0;j<6;j++){ if((c>>j) & 01){ temp = E[6*i+j]; E[6*i+j] = E[6*i+j+24]; E[6*i+j+24] = temp; } } }  for(i=0; i<25; i++) encrypt(block,0);  for(i=0; i<11; i++){ c = 0; for(j=0; j<6; j++){ c <<= 1; c |= block[6*i+j]; } c += '.'; if(c>'9') c += 7; if(c>'Z') c += 6; iobuf[i+2] = c; } iobuf[i+2] = 0; if(iobuf[1]==0) iobuf[1] = iobuf[0]; return(iobuf);}*[PH_CLIENT]CRYPT.OBJ;4+,./ 4 -0123KPWO56 $7@P89GHJ 2CRYPTV1.011-FEB-1993 16:33VAX C V3.2-044P:2*" <4,$ >6.&@80( 91)! ;3+# =5-% ?7/'(08@ '/7?&.6>%- 5=$, 4<#+ 3;"* 2:!) 1991)! :2*" ;3+# <4,$?7/'>6.&=5-%      )4%/7(3-!0,1'8"5.*2$ `P         PP       P    P    P   P  P         P P    #P     8P    DP    UP    gP    tP  P       P    P    P   P    P    P   P    P  P    "P      =P    KP   ^P     mP   yP    P       P^VPUƜTRRBe\dRRBexTPSZRjTRTUjYYXWPUTedUTPWWQUTedUTQW/RRXP0SXXUTE0WH0QRRBadRRBgTWQPZSZP`RbR/P^TPUScRRBeðS?PXլXWXWPRb RPQ0WVF0U0ScRRBeUS/QPPSxPVC0QxQUSRB0QxQQQUSRB0QxQQQUSRB0QxQQQUSRB0QQUSRB0QxQQQUVUEĐUxPSxUQʏQQCSRxUQʏQQBSRxUQʏQQBSRˏUQQBP:QRbPP @@RQPRbRPXPSRcRcSPQ޼V@USeRRBİcUS?Q^VR`ScSARPQEP@* This software is Copyright (C) 1988 by Steven Dorner and theK* University of Illinois Board of Trustees, and by CSNET. No warranties ofB* any kind are expressed or implied. No support will be provided.H* This software may not be redistributed without prior consent of CSNET.9* You may direct questions to dorner@garcon.cso.uiuc.edu.G**********************************************************************/#define ROTORSZ 256#define MASK 0377 #ifdef VMS#include #else#include #include #endif#include #include #include /*# include #include */char t1[ROTORSZ];char t2[ROTORSZ];char t3[ROTORSZ];int Encrypting = 0; static int ccnt, nchars, n1, n2;char *Visible();crypt_start(pass) char *pass;{ n1 = 0; n2 = 0; ccnt = 0; nchars = 0; Encrypting = 1; crypt_init(pass);}char *decrypt(to, from) char *to; char *from;{ char scratch[4096]; char *sp; int count;B count = decode((unsigned char *)scratch, (unsigned char *)from);# for (sp = scratch; count--; sp++) {K *to++ = t2[(t3[(t1[(*sp + n1) & MASK] + n2) & MASK] - n2) & MASK] - n1; n1++; if (n1 == ROTORSZ) { n1 = 0; n2++; if (n2 == ROTORSZ) n2 = 0; } }* *to = '\0'; /* null-terminate */ return (0);} decrypt_end(){ Encrypting = 0;}/* single character decode */2#define DEC(c) (((unsigned char)(c) - '#') & 077)decode(to, from)unsigned char *to;unsigned char *from;{ int n; int chars; chars = n = DEC(*from++); while (n > 0) { /*7 * convert groups of 3 bytes (4 Input characters).  */0 *to++ = DEC(*from) << 2 | DEC(from[1]) >> 4;2 *to++ = DEC(from[1]) << 4 | DEC(from[2]) >> 2;- *to++ = DEC(from[2]) << 6 | DEC(from[3]); from += 4; n -= 3; } return (chars);}crypt_init(pw) char *pw;{ int ic, i, k, temp; unsigned random; char buf[13]; int seed; char *crypt();$ /* must reinitialize the arrays */ for (i = 0; i < ROTORSZ; i++) t1[i] = t2[i] = t3[i] = 0;" strncpy(buf, crypt(pw, pw), 13); seed = 123; for (i = 0; i < 13; i++) seed = seed * buf[i] + i; for (i = 0; i < ROTORSZ; i++) t1[i] = i; for (i = 0; i < ROTORSZ; i++) {" seed = 5 * seed + buf[i % 13]; random = seed % 65521; k = ROTORSZ - 1 - i;# ic = (random & MASK) % (k + 1); random >>= 8; temp = t1[k]; t1[k] = t1[ic]; t1[ic] = temp; if (t3[k] != 0) continue; ic = (random & MASK) % k; while (t3[ic] != 0) ic = (ic + 1) % k; t3[k] = ic; t3[ic] = k; } for (i = 0; i < ROTORSZ; i++) t2[t1[i] & MASK] = i;}H/************************************************************************ encrypts a string2* first byte of string is encoded length of string"* returns length of encoded stringH***********************************************************************/encryptit(to, from) char *to; char *from;{ char scratch[4096]; char *sp; sp = scratch; for (; *from; from++) {M *sp++ = t2[(t3[(t1[(*from + n1) & MASK] + n2) & MASK] - n2) & MASK] - n1; n1++; if (n1 == ROTORSZ) { n1 = 0; n2++; if (n2 == ROTORSZ) n2 = 0; } }- return (encode(to, scratch, sp - scratch));}/*B * * Basic 1 character encoding function to make a char printing.  */1#define ENC(c) (((unsigned char)(c) & 077) + '#')Eencode(out, buf, n) /* output a line of binary (up to 45 chars) * in */Eint n; /* a readable format, converting 3 chars to 4 */ char *buf; char *out;{ int i; char *outStart; outStart = out; *out++ = ENC(n);0 for (i = 0; i < n; buf += 3, i += 3, out += 4)9 threecpy((unsigned char *)out, (unsigned char *)buf); /* null terminate */ *out = '\0'; return (out - outStart);}threecpy(to, from)unsigned char *to;unsigned char *from;{ int c1, c2, c3, c4; c1 = *from >> 2;1 c2 = (*from << 4) & 060 | (from[1] >> 4) & 017;2 c3 = (from[1] << 2) & 074 | (from[2] >> 6) & 03; c4 = from[2] & 077; *to++ = ENC(c1); *to++ = ENC(c2); *to++ = ENC(c3); *to = ENC(c4);}*[PH_CLIENT]CRYPTIT.OBJ;4+,b ./ 4 -0123KPWO56@k7N{IJ89GHJ 4CRYPTITV1.011-FEB-1993 16:33VAX C V3.2-044P^R|bԢ  CRYPT_INIT^VWURݬDECODETPQPSQlPЬQ֬dPPʏP@eP PʏP@fP¢ PʏP@gP¢PPa֢ѢԢ֢ Ѣ Ԣ TSPSPP^ <^ЬR֬bR#RˏRTTUT1ЬS֬ЬRbP#PʏPxPQP#PʏPPPPQcЬS֬P#PʏPxPQP#PʏPPPPQcЬS֬P#PʏPxPQP#PʏPPQcRT1eUP^UZVTeSRPcb`SRPT ݬݬCRYPTP߭STRNCPY{WTScRWRTRWS TPSPcSPYWSzYP{ PQPPRBRSRWzWP{PQPPXYTˏXSTRQSPRRRPRQPQP{RPPQXXDfRAfDfRAfDeVˏXRQRPTRRRPRQPQ{RPPQQSCePSRzRP{TPQPPSCeSDeTCeY$PTdRR2RSPCjTPP|^UVTRShPSQSPPʏP@dP PʏP@eP¢ PʏP@fP¢PPa֢ѢԢ֢ Ѣ Ԣ ֬PPS~ݚRCRYPTIT crypt_start((decrypt decrypt_end decode crypt_init8 encryptit encodeX@threecpy  C$V_CTYPEDEFS CRYPT_INITDECODESTRNCPYCRYPTENCODETHREECPY  CRYPT_START (DECRYPT DECRYPT_END <DECODE  CRYPT_INIT 8| ENCRYPTIT ENCODE @<THREECPY$CODE$DATASTDINSTDOUTSTDERR_CTYPE_T1T2T3 ENCRYPTING1ENCODE^ЬPPTPQPެ ScPʏP#PPaRcPݬݬTHREECPYRRcЬPTP<^ЬRbPPPxPUxPSʏSQxQPʏPPSxQQʏQTTPxPPʏPPQʏTЬR֬UPPPʏP#PPbЬR֬SPPPʏP#PPbЬR֬QPPPʏP#PPbTPPPʏP#PP*[PH_CLIENT]DBGERR.LOG;1+,  ./ 4h-0123KPWO567%$89GHJ ?!Logging enabled - this is being written to log file DBGERR.LOG!C!The following information may be helpful to the DEBUG maintainers.!3!If you wish to report this problem please include:!$! o The stack dump that follows.$! o The debugger version number.:! o The program being debugged, both source and image.?! o The last, if not all, commands entered to the debugger.2! o Any other information that may be helpful.!&!The base address of DEBUG is 0005FE00)!The base address of DEBUGSHR is 00000000;!The version of the debugger is: VAX DEBUG Version V5.3-017!N! module name routine name line rel PC abs PCO! 00000000 00000000O! 00000000 0003CAB4O! 00000000 0003D4F9>!----- above condition handler called with exception 0000000C:h!%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000000B, PC=0002FDD3, PSL=03C00009!----- end of exception messageO! 00000000 0002FDD3O! 00000000 00001263O! 00000000 000010B2O! 00000000 00000FEBO! 00000000 00000DFBO! 00000000 000006E8O! 00000000 00052128O! 00000000 0003D2E7O! 00000000 000003DEO! 00000000 00000D14O! 00000000 000008A4O! 00000000 00000293O! 00000000 7FF5BED7*[PH_CLIENT]LINK_DEBUG_PH.COM;1+,./ 4;x-0123KPWO56 e7p 89GHJ7$ link /exe=phd/debug phd,cryptitd,crypt,SYS$INPUT:/opt;multinet_socket_library/share,sys$library:vaxcrtl.exe/share*[PH_CLIENT]LINK_PH.COM;1+, ./ 4;l-0123KPWO560789GHJ+$ link 'p1' ph,cryptit,crypt,SYS$INPUT:/opt;multinet_socket_library/share,sys$library:vaxcrtl.exe/share*[PH_CLIENT]PH-1.TXT;1+,./ 4-0123KPWO560m7%m89GHJ APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L) NNAAMMEE; ph -- access to the CSO Nameserver (on-line phone book)SSYYNNOOPPSSIISS. pphh [--ss server] [--pp port] query1 pphh [--ss server] [--pp port] [--nn]!DDEESSCCRRIIPPTTIIOONN? _P_h queries the CSO Nameserver, a database of University> faculty, students and staff. The database contains nearlye all the information in the _S_t_u_d_e_n_t/_S_t_a_f_f _D_i_r_e_c_t_o_r_y (the9 University phone book), as well as other information,( including electronic mail addresses.: _P_h may be used in two ways; interactively, or with command-line arguments.? If given arguments, it will treat the arguments as a query,6 and return the results of the query. For example, ph steven dornerC would return the entry for the author of _p_h, Steven Dorner.? For more information on what types of queries you may make,0 see the _Q_u_e_r_i_e_s section below.D If given no arguments, _p_h will enter interactive mode, print> a prompt, and wait for commands. Interactive mode will be discussed in detail below.? _P_h is not intended for the generation of mailing lists.A Therefore, it will refuse any requests resulting in more than7 a small number of matches. This is not negotiable.OOPPTTIIOONNSS, _P_h recognizes the following options:G -n Do not read the ..nneettrrcc file. This option hasE meaning only when using _p_h in interactive mode (see; below for descriptions of the .netrc file and interactive mode.) -s _s_e_r_v_e_rI Use _s_e_r_v_e_r as a Nameserver host, instead of the default host. -p _p_o_r_tH Use _p_o_r_t as the tcp port to connect to, instead of the default port.APage 1 (printed 10/11/89)APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L)QQUUEERRIIEESS< The Nameserver's database containes over 60,000 entries.K Each entry is comprised of multiple _f_i_e_l_d_s, each containing? information about the entry. Each field has a name that is< descriptive of what the field contains; for example, theV field named _m_a_i_l__a_d_d_r_e_s_s contains the office mail address of? the person in question (for more information on fields, see^ the description of the ffiieellddss command in the _I_n_t_e_r_a_c_t_i_v_e section below).I By default, queries are assumed to refer to the _n_a_m_e field ofM the entry. Therefore, saying ''pphh jjoohhnn ddooee'' looks for; entries whose name field contains ''john'' and ''doe.''C Fields other than the _n_a_m_e field must be specified; for pd- a~ PH_CLIENT.SAV[PH_CLIENT]PH-1.TXT;1,example, ph dorner address=DCL; would return entries with name ''dorner'' whose address contained ''DCL.''A Matching in _p_h is done on a word-by-word basis. That is,> both the query and the entry are broken up into words, and: the individual words are compared. Although _p_h is= insensitive to case, it otherwise requires words to matchB exactly, with no characters left over; ''john'' does nnoott9 match ''johnson,'' for example. This behavior may beA overriden by the use of normal shell metacharacters (''?'' to; match any single character, ''*'' to match zero or moreA characters, and ''[]'' to match a single character from a set of characters).@ _P_h will display only entries that match aallll of the. specifications in the query. For example, ph steven dornerG will return all entries with bbootthh ''steven'' and ''dorner'' in the _n_a_m_e field.= _P_h returns a certain set of fields by default. It is= possible to ask for different fields in a query. This isJ done by specifying the ''_r_e_t_u_r_n'' keyword, and listing the% fields of interest. For example,' ph steven dorner return emailA would print only the electronic mail address of the author ofC _p_h. You may also ask for all fields in the entry, by using@ ``all'' as a field name. This will show you every field you+ are allowed to see in the user's entry.APage 2 (printed 10/11/89)APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L)L All output from _p_h is sent through _m_o_r_e (or whatever program; specified in the _P_A_G_E_R environment variable)..IINNTTEERRAACCTTIIVVEE MMOODDEE@ If _p_h is given no arguments, it enters interactive mode,? where it prompts for, executes, and displays the results of= Nameserver commands. Interactive mode provides access to> more Nameserver features than mere queries. Some of theseC features require the user to identify him/her self to _p_h byG use of the _l_o_g_i_n command; others do not. Commands may be8 abbreviated, provided enough characters are given to) distinguish them from other commands.- TThhee ..nneettrrcc ffiilleeC _P_h reads the same .netrc file as does ftp (see ftp(1)). IfH it finds a _m_a_c_h_i_n_e named ``ph'' that has a login and aL password specified for it, _p_hwill automatically do a _l_o_g_i_n@ command, using the values from the .netrc file. _P_h willA silently refuse to use a .netrc file that has any permissions& for group or other (see chmod(1))./ PPuubblliicc CCoommmmaannddss? The following commands do not require the user to be logged in to the Nameserver: hheellppH _H_e_l_p provides explanations of Nameserver commands. Given noG arguments, _h_e_l_p lists the available help topics. Given oneI of these topics as an argument, _h_e_l_p will print help for thatA topic. A list of commands and a one-line description of eachM command may be obtained by requesting the topic _c_o_m_m_a_n_d_s. qquueerryyG _Q_u_e_r_y performs Nameserver queries, and works exactly likeE non-interactive _p_h, except that metacharacters do not have to be quoted. ffiieellddssK _F_i_e_l_d_s lists the fields currently in use in the Nameserver.A For each field a display like the following (admittedly ugly) is produced:9 -200:2:email:max 64 Lookup Public Default Change Turn3 -200:2:email:Preferred electronic mail address.@ The leading number is a reply code form the Nameserver. The@ next number is the field number. Following the field number> is the name of the field, the maximum length of the field,9 and the flags for the field. The second line has, inA addition to repeated reply code, number, and name, a one-line description of the field.APage 3 (printed 10/11/89)APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L)J The flags determine how a field may be used. _L_o_o_k_u_p meansJ the field may be searched in a query. _I_n_d_e_x_e_d means theO field is indexed (at least one _I_n_d_e_x_e_d field must be includedK in every query). _D_e_f_a_u_l_t means the field is displayed byU default. _C_h_a_n_g_e means that users may change the field. _T_u_r_nA means that display of the field may be inhibited by beginning the field with a ''*''. sseett option[==value]E _S_e_t allows Nameserver options to be set. These options are for future use. qquuiitt Exits _p_h. llooggiinn aliasK This command identifies the user to the Nameserver. _A_l_i_a_s is7 your Nameserver alias, a unique name for you in theE Nameserver; it is the first field printed in _p_h queries. YouE will be prompted for your Nameserver password. This is nnoott? the same as your system password. The only way to discover/ your Nameserver password is to send mail to nameserv@uxg.cso.uiuc.edu.? You are allowed to change your Nameserver alias; there are,A however, restrictions on Nameserver alia; they must be uniqueA within the Nameserver, they cannot be common names (''david''= is right out), and they can only contain letters, digits, dashes (-) and periods (.).H CCoommmmaannddss RReeqquuiirriinngg LLooggiinn? The following commands require that the user executing them# be logged in to the Nameserver.$ ppaasssswwoorrdd [alias]? This command changes your Nameserver password. You will beC asked to type your new password twice. _P_h will complain if8 your password is too short, or contains only numbers> (although it does allow such passwords). Privileged usersA may change the passwords of certain other users by specifyingQ the alias of the other user when giving the _p_a_s_s_w_o_r_d command. mmee< This command lists the nameserver entry of the currently logged-in user. eeddiitt field [alias]D This command allows _p_h users to change those fields in theirT entry that have the _C_h_a_n_g_e flag set. _E_d_i_t will retrieve the@ value of the named field (if a value exists), and will allowW the user to edit the value with /_u_s_r/_u_c_b/_v_i (the _E_D_I_T_O_RD environment variable may be used to override the use of _v_i).APage 4 (printed 10/11/89)APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L)@ The changed value will then be reinserted in the Nameserver. aadddd9 Adds entries to the Nameserver. This is a privileged command. ddeelleettee> Deletes entries from the Nameserver. This is a privileged command. llooggoouutt4 Undoes the effects of a _l_o_g_i_n command.(QQUUEERRYY EEXXAAMMPPLLEESSC Here are some examples to clarify _p_h queries. Each example> is preceded by the effect desired. It is assumed that theD queries are being done with _p_h from the command line, rather; than by using the interactive mode of _p_h. The only@ difference for interactive mode is that metacharacters would% not have to be quoted or escaped., Find the _p_h entry for Steven Dorner: ph steven dorner@ Find the ph entry for S. Dorner, where the rest of the first name is not known: ph s\* dorner. Find Alonzo Johnson (or is that JohnsEn?): ph alonzo johns\?n or ph alonzo johns\[eo\]n? Find Steven D., where the rest of the last name is unknown: ph steven d\*A The last query fails because it matches too many entries. It? is therefore necessary to narrow the search. Suppose is is. known that Steven D. has an office in DCL:# ph steven d\* address=DCLA Alternately, suppose Steven D. works for CSO. You might try:& ph steven d\* department=CSO1 When that failed, a good next guess would be:APage 5 (printed 10/11/89)APH(1L) UNIX 4.3 BSD (27 Aug 89) PH(1L), ph steven d\* department=computingE The moral of the story is that fields in _p_h generally containA whatever the user wishes them to contain, and hence there may8 be many different spellings and abbreviations of any? particular field (some fields are exceptions, including theF _n_a_m_e field, which is always the full name, as known to theA University, of the person involved). It pays to make liberal> use of metacharacters and creativity when searching fields other than _n_a_m_e.? Suppose all that is wanted is full name and electronic mail address of S. Dorner:) ph s\* dorner return name email BBUUGGSS@ Separate words in a query are allowed to match the same word@ in the entry; ''ph s\* smith'' is functionally equivalent to8 ''ph smith,'' because the ''s*'' is allowed to match ''smith.''? There is no way to turn off the reading of the .netrc file.$DDIISSTTRRIIBBUUTTIIOONN; Source code for _p_h is available by anonymous ftp to> uxc.cso.uiuc.edu, in the net/ph subdirectory. This source> works on 4.[23]bsd Unix systems. Any troubles encountered@ porting _p_h to a particular system are of interest to theC author of _p_h, as are ports done to other operating systems.SSEEEE AALLSSOOu _T_h_e _C_S_O _N_a_m_e_s_e_r_v_e_r, _A_n _I_n_t_r_o_d_u_c_t_i_o_n, by Steven Dorner _T_h_e _C_S_O _N_a_m_e_s_e_r_v_e_r, _S_e_r_v_e_r-_C_l_i_e_n_t _P_r_o_t_o_c_o_l, by Steven Dorner qi(8)AAUUTTHHOORR Steve Dorner4 University of Illinois Computing Services Office s-dorner@uiuc.eduAPage 6 (printed 10/11/89)APage 7 (printed 10/11/89)*[PH_CLIENT]PH-DECNET.COM;1+,N./ 4<J-0123KPWO56c7ۀ89GHJ$ If "''P1'" .EQS. ""$ Then.$ Write SYS$OUTPUT "You must specify a query!" $ Exit$ EndIf<$ Query = "''P1' ''P2' ''P3' ''P4' ''P5' ''P6' ''P7' ''P8'" &$ Open/read/write net icaen::"task=ph"$ Write net query$Loop:!$ read/time=15/End=Done net reply$ Write sys$output reply $ GoTo Loop$Done: $ close net*[PH_CLIENT]PH-INTRO.TXT;1+,y.!/ 4!!8-0123KPWO"56|n7P6n89GHJBL TThhee CCSSOO NNaammeesseerrvveerrF AAnn IInnttrroodduuccttiioonn8 by Steven Dorner, Computing Services Office % ph steven dorner -201 1:Database ready.- ---------------------------------------- alias: sdorner$ name: dorner steven c, email: dorner@uxg.cso.uiuc.edu. phone: (W) 333-3339 (H) 356-88923 address: 189 DCL, 1304 W Springfield, U* address: 1201 W. Washington, C. department: computing services office( title: research programmer mailcode: 256 hours: weekdays( project: CSO Nameserver (Ph)- ----------------------------------------R WWhhaatt iiss iitt?? The CSO Nameserver could be considered a data-? base containing information about people and things at the< University of Illinois. It is designed to be extremely? flexible in what information it keeps, and also to provideA fast access to that information. Currently, most of the in-W formation in it comes from the University _S_t_u_d_e_n_t_/_S_t_a_f_f_2 _D_i_r_e_c_t_o_r_y (the phone book).@ The CSO Nameserver could also be considered to be a pair of@ programs; one that manages the actual data (this program isi called _q_i, for __q_u_e_r_y __i_n_t_e_r_p_r_e_t_e_r), and another one that han-= dles user requests (the program CSO provides for this isS called _p_h, for __p__h_o_n_e _b_o_o_k). To most people, the CSOE Nameserver will be exactly this second program, _p_h, the pro-O gram that gives them access to the University _D_i_r_e_c_t_o_r_y.S WWhheerree iiss iitt?? The database for the Nameserver resides on a= CSO minicomputer (a VAXServer 3500) that runs the UnixTM3 operating system; the name of this computer is@ garcon.cso.uiuc.edu. The program that manages the databaseF (_q_i) runs on this machine. _Q_i allows programs running on@ other computers to access the database by serving as an in-A termediary between them and the actual database. It commun-O icates with such programs using the campus network, _U_I_U_C_n_e_t.I _P_h (the program that is usually used to communicate with _q_i)= is installed on all of CSO's UNIXTM computers. A simple versionC of _p_h is also available on CSO's main IBM computer, a 3081C which uses a proprietary IBM operating system. _P_h is also; installed on many non-CSO computers across the campus;A later, I'll discuss how you can get _p_h installed on your system.` WWhhaatt iiss iitt ggoooodd ffoorr?? The Nameserver is good for looking up@ phone numbers and addresses of University faculty, studentsm or staff members, just like the _S_t_u_d_e_n_t_/_S_t_a_f_f__D_i_r_e_c_t_o_r_y; but= the Nameserver is good for more than just that. For one@ thing, the Nameserver knows the electronic mail address for? thousands of faculty, students and staff; this informationi is not present in the _S_t_u_d_e_n_t_/_S_t_a_f_f__D_i_r_e_c_t_o_r_y. For someA people, it knows other things, such as office hours or vaca- tion plans.A A key thing to know about the Nameserver is that, if you useC a computer that has _p_h installed on it, you can change the< information the Nameserver keeps about you. That means? that, if you change offices in the middle of the year, you9 can put your correct address and phone number in theB Nameserver immediately, so that people can use _p_h to find& up-to-date information about you.] WWhhaatt iissnn''tt iitt ggoooodd ffoorr?? There are some things the= Nameserver is not meant to do. One thing that should be@ mentioned right away is that the Namesever can't be used toA generate mailing lists for junk mail; you don't have to wor-9 ry about getting junk mail because you appear in the Nameserver's database.@ Another thing it isn't good for is notifying the UniversityA of changes of address. Changes you make to your informationA in the Nameserver are not automatically sent to your depart-? ment, or the Office of Admissions and Records, or Payroll,< or anywhere else; you must still notify these places of changes in your address. HHooww ccaann II hhaavvee pphh iinnssttaalllleedd oonn mmyy ccoommppuutteerr?? If one of the= computers you use runs UNIXTM or VMS and is connected toS _U_I_U_C_n_e_t, you can probably have _p_h installed on it. Tell the@ person who manages your computer that he can get the sourceA code for _p_h by anonymous ftp to uxc.cso.uiuc.edu, in the: net/ph subdirectory (don't worry-he'll know what that means).Z HHooww ddoo II uussee pphh?? There are two different ways to use _p_h.> One way is good for finding information about people, and the> other is good for changing the information the Nameserver? keeps about you. I will give you a brief idea of how both? these ways work; for more detailed information, you shouldE read the ``manual page'' for _p_h, which you can read (if your= computer runs UnixTM) by typing the command, ``man ph''.B To use _p_h to find out information, you should type ``ph''C and the name of the person you want to know about; _p_h will0 respond with information about that person: % ph steven dorner -201 1:Database ready.- ---------------------------------------- alias: sdorner$ name: dorner steven c, email: dorner@uxg.cso.uiuc.edu. phone: (W) 333-3339 (H) 356-88923 address: 189 DCL, 1304 W Springfield, U* address: 1201 W. Washington, C. department: computing services office( title: research programmer mailcode: 712 hours: weekdays( project: CSO Nameserver (Ph)- ----------------------------------------= If there are a lot of people who have the name you askedB for, _p_h will let you view the list a screenful at a time;6 just hit the spacebar to move to the next screen.@ You don't have to know the exact spelling of a name to find= information; you can put special symbols in the name for= which you are searching that tell the Nameserver to findA names that you only know a few letters of. I won't say any-? thing more about that here; look in the manual page if you# are interested in the details.A Sometimes, you will ask ph for a name, and it will refuse to< give you information, because too many people have that name: % ph smith -201 1:Database ready.) 502:Too many entries to print (373).D _P_h does this so that no one can use it to get mailing lists> for junk mail or other nefarious purposes. If you really= want to find the person, you will have to know something else> about them, like part of their first name, or their phone number? If you want to change the information the Nameserver keepsD about you, you should just type ``ph''. _P_h won't look up a> name, but will instead give you a prompt. There are manyD possible commands you can type to _p_h; they are described in@ full in the _p_h manual page. You will only need to knowI three commands to change your information, however; _l_o_g_i_n,U _e_d_i_t, and _q_u_i_t. Before actually using _p_h for this, you will$ have to make some preparations.; The first thing you have to do is find your NameserverC _a_l_i_a_s. This is a unique name assigned to you by the> NameServer. It will be your first initial, followed by aA dash, followed by your last name. If there is more than one? person with the same first initial and last name as yours,@ there may be number tacked onto the end of your alias. The= easiest way to find your alias is simply to look up your; name with ph; it will be obvious to you which entry is yours.9 Once your know your alias, you need to find out your> Nameserver password. To do this, send electronic mail to> nameserv@uxg.cso.uiuc.edu. You will receive (in a day or. two) a reply that contains your password.C Now, it's time to use _p_h to change your information. Type? ``ph'' and a return. You will get a ``ph>'' prompt. Now,@ type ``login alias'' (but use your real alias, not the wordB ``alias''!) and a return. _P_h will ask for your password;@ type your password and a return. You should get a greeting- from the Nameserver, and another prompt. % ph; $Header: ph.c,v 2.10 88/03/09 09:59:32 dorner Locked $) Please mail questions or comments to dorner@uxg.cso.uiuc.edu. ph> login sdorner -201 1:Database ready._ Enter nameserver password: _t_y_p_e _y_o_u_r _p_a_s_s_w_o_r_d _h_e_r_e 200:sdorner:Hi how are you? ph>A You are now ready to change your information. Your informa-= tion is organized into ``fields'', each one containing a? different piece of information. There is a field for your name,A your address, your phone numbers, etc. To change a particu-> lar field, type ``edit field'' and a return, substitutingA the name of the field you wish to change for ``field''. For< example, if you want to change your phone numbers, type> ``edit phone''. You will be placed in your favorite UNIX@ editor, with the contents of the field you asked for as the@ text. Make whatever changes you wish, and exit the editor.5 _P_h will then change the information for you.A Some information cannot be changed; the ``name'' field, for? example, cannot be changed. If you need to change one of* these fields, you should send mail to< nameserv@uxg.cso.uiuc.edu and arrangements can be made.? Once you are done changing your information, type ``quit'' and a return. SSuuppppoossee II ccaann''tt uussee pphh ffrroomm mmyy ccoommppuutteerr?? If your computer? doesn't have ph installed on it, but you would like to use@ ph to look up addresses or change your information, you can@ still do so. Connect to CSO's staff Pyramid, uxe, by using> telnet (telnet uxe.cso.uiuc.edu), sytek (call 12ee) or by> dialup (333-4008, class duxe). When you are prompted forA login:, type ``phones'' and a return. When you are prompted: for Password:, type another return. You will then beA prompted for your terminal type. If you have a vt100 termi-A nal or terminal emulator, you can just type a return; if youA have some other terminal, type its name. You will receive a ph> prompt, and can use ph.z WWhheerree ccaann II ffiinndd mmoorree iinnffoorrmmaattiioonn?? More information can beA found by reading the manual page on _p_h. Programmers whoA wish to access the Nameserver from their programs should ob-~ tain the document _N_a_m_e_s_e_r_v_e_r__S_e_r_v_e_r_/_C_l_i_e_n_t__L_a_n_g_u_a_g_e, avail-A able in the file ``language.troff'' in the same directory on0 uxc.cso.uiuc.edu as the _p_h source code.e WWhhaatt iiff II hhaavvee ttrroouubbllee?? If you have problems or questionsE that are not resolved by reading this document, the _p_h manu-~ al page, or _N_a_m_e_s_e_r_v_e_r__S_e_r_v_e_r_/_C_l_i_e_n_t__L_a_n_g_u_a_g_e, feel free to; ask me by sending mail to ``dorner@uxg.cso.uiuc.edu''.y AAppppeennddiixx -- AA RRaannkk BBeeggiinnnneerr''ss GGuuiiddee ttoo VVII? This page describes a few vi commands to accomplish simple> editing tasks. Full documentation for vi can be found in _T_h_e _U_N_I_X _U_s_e_r'_s _M_a_n_u_a_l _S_u_p_p_l_e_m_e_n_t_a_r_y _D_o_c_u_m_e_n_t_s, chapter 15A (really advanced users should read chapter 16 as well). Two< thing to keep in mind: First, the editor is pronounced? ``vee eye''; if you pronounce it, ``vie,'' UNIX gurus will8 laugh at you, though not out loud. Secondly, vi is@ case-sensitive; be sure to use upper or lower case commands as appropriate.I MMooddeess.. Vi is a modal editor; what you can do depends on? what mode you are in. The two modes of interest to us areW _c_o_m_m_a_n_d mode and _i_n_s_e_r_t mode. You type most commands in? command mode; all you do in insert mode is type your text.L You get out of insert mode by typing _e_s_c_a_p_e, usually marked= ``esc'' on keyboards; on some keyboards, you may have to> hold down the control or alt key and press ``[''. If you@ type escape in command mode, vi will beep at you; so if you? get confused, just type escape until vi beeps; then you'll be back in command mode.Y MMoovviinngg AArroouunndd.. Here are some motion commands in vi. They? are typed in command mode, and leave the editor in command mode.B CCoommmmaanndd WWhhaatt iitt ddooeessI control-h Moves the cursor lleefftt ([[]]) one character.I h Moves the cursor lleefftt ([[]]) one character.D j Moves the cursor ddoowwnn ([[]]) one line.> k Moves the cursor uupp ([[]]) one line.L l Moves the cursor rriigghhtt ([[]]) one character.N w Moves the cursor ffoorrwwaarrdd to the beginning of" the next word.Q b Moves the cursor bbaacckkwwaarrdd to the beginning of& the previous word.] DDeelleetteeiinngg TTeexxtt.. Here are some commands to get rid of stuff.= Type them in command mode; they will leave the editor in command mode.B CCoommmmaanndd WWhhaatt iitt ddooeess- dd Deletes the current line.< x Deletes the character at the cursor, and@ moves the rest of the line to fill the hole.W AAddddiinngg TTeexxtt.. The following commands all put you into insert? mode and let you type text. Type escape when you are fin-A ished adding text, and you will be returned to command mode.B CCoommmmaanndd WWhhaatt iitt ddooeessA i Start inserting characters before the charac-) ter the cursor is on.A O Create a new line above the cursor, and start< inserting at the beginning of that line.L Note that this command is a _c_a_p_i_t_a_l ``O''.V GGeettttiinngg OOuutt.. The following commands exit vi. They work in command mode.B CCoommmmaanndd WWhhaatt iitt ddooeess@ ZZ Exit vi, and save the changes you have made.D Those are _c_a_p_i_t_a_l Z's, by the way.B :q!o/ Exit vi, but don't save changes (the ``o/''* means to type return).*[PH_CLIENT]PH.C;1+,X.r/ 4grp8-0123KPWOs56|47∟89GHJI/***********************************************************************/F/*********************************************************************>* This software is Copyright (C) 1988 by Steven Dorner and theK* University of Illinois Board of Trustees, and by CSNET. No warranties ofB* any kind are expressed or implied. No support will be provided.H* This software may not be redistributed without prior consent of CSNET.9* You may direct questions to dorner@garcon.cso.uiuc.edu.G**********************************************************************/H/***********************************************************************H* This is a client program for CSO's nameserver. It attempts to contactC* the nameserver running on garcon.cso.uiuc.edu, and query it aboutI* entries. The following entries in /etc/hosts (if you're using one) and"* /etc/services will help matters:* * /etc/hosts:** 128.174.5.58 garcon.cso.uiuc.edu garcon* * /etc/services:0* ns 105/tcp ns # CSO nameserverJ*************************************************************************/ #ifdef VMS/* P H for V A X / V M SC Ported to VAX/VMS Version 5.3 using VAXC 3.2 and TGV MultiNet 3.0G by Mark Sandrock, UIUC School of Chemical Sciences Computing Services? and R. Kevin Oberman, Lawrence Livermore National Laboratory. VMS 4.4 implementation notes:? 1) VAXCRTL does not supply the following routines used by PH:? a) fork -- SYS$CREPRC or LIB$SPAWN should be used instead.D b) execlp -- VAXCRTL does provide execl, but it is too limited.; c) popen/pclose -- VAXCRTL does provide "pipe" instead.I d) index/rindex -- VAXCRTL "strchr/strrchr" functions are equivalent., e) getpass -- implemented in this file.9 f) unlink -- VAXCRTL does provide "delete" function.A 2) VAX/VMS does not provide the following utilities used by PH:6 a) /usr/ucb/more -- VMS PH does not do paging yet.8 b) /usr/ucb/vi -- EDT or TPU should be used instead.]uRE~ PH_CLIENT.SAVX[PH_CLIENT]PH.C;1grC 3) The VAXCRTL "getenv" function does not recognize the followingE environment names. SYS$TRNLNM could be used instead, if need be:C a) PAGER: specifies "pager" other than the default (TYPE/PAGE).= b) EDITOR: specifies editor other than the default (EDT).A 4) The SOCKET INTERFACE implemented by TGV MultiNet 3.0 returnsF a channel number rather than a standard file descriptor, and thusH is not compatible with the UNIX-style i/o functions such as fdopen,H read and write. Instead MultiNet provides special versions of read/; write called socket_read/socket_write for network i/o.H 5) The VMS VAXC include files are used wherever possible, with severalJ exceptions as noted in the MultiNet Programmer's Guide. The followingI include files do not exist under VMS VAXC 3.2 and were simply copied over from uxc (4.3 bsd): a) #include  b) #include Change log:D 05-May-1988 12:09 MTS Initial port of ph.c,v 2.1x5 to vms_ph.c./ Initial port of cryptit.c to vms_cryptit.c.@ 13-Feb-1991 16:08 MTS Has it really been that long? Re-ported+ ph v4.10 under VMS 5.3 and WIN/TCP 5.1.; 15-Oct-1991 14:44 RKO Modified for MultiNet V3.0./*L***************************************************************************/Ostatic char *rcsid = "VAX/VMS: ph.c,v 4.10 91/10/15 14:44:00 sandrock-oberman";#include stdio#include signal6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h" #include file #include stat7#include "multinet_root:[multinet.include.netinet]in.h"2#include "multinet_root:[multinet.include]netdb.h"#include ctype/* #include */8#include descrip /* VMS descriptor structures defs */6#include iodef /* VMS I/O function definitions */7#include ssdef /* VMS System Status definitions */6#include ttdef /* VMS terminal characteristics */=#include "termdefs.h" /* VMS defs for setterm() function */#elseCstatic char *rcsid = "$Date: 91/02/06 07:24:53 $$Revision: 4.10 $";>static char *srcid = "$Source: /nameserv/Src/Ph/RCS/ph.c,v $";#include #include #include #include #include #include #include #include #include #include #include #ifdef hpux#include :#define bcopy(source,dest,count) memcpy(dest,source,count)*#define index(string,ch) strchr(string,ch),#define rindex(string,ch) strrchr(string,ch)#else #ifndef NeXT void bcopy();#endif#endif#endif#include "replies.h"H/************************************************************************ vital definesH***********************************************************************/1#define MAXSTR 2048 /* max string length */2#define MAXVAL 14000 /* max value length */3#define DELIM " \t\n"/* command delimiters */I#define MAXARGS 20 /* maximum # of arguments in PH environ var. */H/***********************************************************************/* declarations for a couple of useful functionsH***********************************************************************/char *GetValue();char *strtok();char *getenv(); #ifdef VMS;char *strchr(); /* VMS equivalent of "index" */<char *strrchr(); /* VMS equivalent of "rindex" */#define index(a,b) strchr(a,b) #define rindex(a,b) strrchr(a,b)#define GetQValue(aLine) \) (strchr(strchr(aLine,':')+1,':')+1)#elseFILE *popen();#define GetQValue(aLine) \' (index(index(aLine,':')+1,':')+1)#endifchar *malloc();char *getpass();void exit(), free(), perror();char *makestr();I/************************************************************************. * declarations for the functions in this fileJ ************************************************************************/ int main();char *issub();int ContactQI(); int DoId();int PrintResponse();int GetGood();void EnvOptions();void ComplainAboutService();void ComplainAboutHost();void Interactive();int DoCommand();int DoOtherWPage();int DoOther(); #ifdef MACCint DoFields();#endif int DoHelp();int DoQuery();/* int DoLogin(); */ int DoQuit(); int DoEdit(); int DoMake();int EditValue();int UpdateValue();int DoFields(); int DoMe();/* int DoPassword();int DoLogout();void VetPassword(); */int AllDigits();int PrintQResponse();/* void DoAutoLogin(); */void SkipMacdef();/* int TryLogin(); */void EmailLine();void NotRegisteredLine();FILE *OpenPager();int DoSwitch();H/************************************************************************* These are external for convenience' sakeH***********************************************************************/#ifdef MACC_ECHOint maccecho =0;#endif #ifdef VMS<int ToQI; /* write to this to tell the nameserver stuff */7int FromQI; /* read nameserver responses from here */char ToQIBuf[MAXSTR]; int ToQILen;#define qprintf \ { \ char *ToQI=ToQIBuf; \ sprintf#define qflush(foobar) \ ToQILen = strlen(ToQIBuf); \ } \$ socket_write(ToQI,ToQIBuf,ToQILen)#else?FILE *ToQI; /* write to this to tell the nameserver stuff */:FILE *FromQI; /* read nameserver responses from here */#define qprintf fprintf#define qflush fflush#endif7char MyAlias[MAXSTR]; /* currently logged-in alias */+char *Me; /* the name of this program */@char *MyPassword=NULL; /* password read from .netrc (if any) */I/************************************************************************ * switchesJ ************************************************************************/+int NoNetrc = 0; /* -n don't read .netrc */6char *UseHost = 0; /* -s use server on what machine */$int UsePort = 0; /* -p use port # */6int NoReformat=1; /* -i don't reformat email fields */(int NoPager=0; /* -m don't use pager */0int NoBeautify=0; /* -b don't beautify output */*int NoLabels=0; /* -l don't use labels */%int Confirm=0; /* -c confirm Edit */6char *DefType=0; /* -t prepend this type to queries */4char *ReturnFields=NULL;/* -f give list of fields */H/************************************************************************ and the fun begins...H***********************************************************************/int main(argc, argv) int argc; char **argv;{ int theCode=LR_ERROR; int optionsCount; char buffer[4096];#ifdef MACC_ECHO int margc=0;#endif #ifdef VMS(char *temps; /* temp strings */#endif /*+ * figure out what this program is called */ #ifdef VMS Me = " ph";#else Me = rindex(*argv,'/');#endif if (Me) Me++; else Me = *argv; EnvOptions(CLIENT); if (strcmp(CLIENT,Me)) { sprintf(buffer,"-t %s",Me); (void) OptionLine(buffer); EnvOptions(Me); }/ optionsCount = ProcessOptions(--argc,++argv); argc -= optionsCount; argv += optionsCount;  if (!ContactQI()) {< fputs("Sorry--phone book not available now.\n", stderr); #ifdef VMS exit(SS$_CONNECFAIL);#else exit(1);#endif } /* * identify ourselves *// if ((theCode=DoId())>=400) exit(theCode/100); if (argc==0)< Interactive(); /* no arguments--interactive mode */ else {+ /* make a query out of the arguments */ strcpy(buffer,"query "); for (; argc; argc--, argv++) { strcat(buffer,*argv); if (argc > 1) strcat(buffer," "); } strcat(buffer,"\n"); theCode = DoCommand(buffer); qprintf(ToQI,"\nquit\n"); qflush(ToQI); } #ifdef VMS exit(SS$_NORMAL);#else( exit(theCode > 299 ? theCode/100 : 0);#endif}H/***********************************************************************! * contact the central nameserverI ***********************************************************************/int ContactQI(){& int sock; /* our socket */F static struct sockaddr_in QI; /* the address of the nameserver */> struct servent *theNs; /* nameserver service entry */B static struct hostent *theHost; /* host entry for nameserver */ char host[80]; char *baseHost; int backupNum=0; int mightBackup; /* create the socket */) sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) return (0); QI.sin_family = AF_INET; /* find the proper port */ if (UsePort) QI.sin_port = UsePort;3 else if (theNs = getservbyname(NSSERVICE, "tcp")) { QI.sin_port = theNs->s_port; } else { ComplainAboutService();& QI.sin_port = htons(FALLBACKPORT); } /* find the proper host */& baseHost = UseHost ? UseHost : HOST;# if (mightBackup=(*baseHost=='.')), sprintf(host,"%s%s",NSSERVICE,baseHost); else strcpy(host,baseHost); for (;;) { /* create the socket */+ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) return (0); QI.sin_family = AF_INET;& if (theHost = gethostbyname(host)) {> bcopy(theHost->h_addr, (char *) &QI.sin_addr.s_addr, 4); } else if (!backupNum) { ComplainAboutHost(host);/ QI.sin_addr.s_addr = htonl(FALLBACKADDR);? theHost = gethostbyaddr(&QI.sin_addr.s_addr, 4, AF_INET); } else {2 fprintf(stderr,"No more backups to try.\n"); return(0); } # /* connect to the nameserver */> if (connect(sock, (struct sockaddr *)&QI, sizeof(QI)) < 0) { perror(host); if (mightBackup) { backupNum++;5 sprintf(host,"%s%d%s",NSSERVICE,backupNum,baseHost); } else return (0); } else break; } if (backupNum)V fprintf(stderr,"WARNING--backup host %s; information may be out of date.\n",host); /* open path to nameserver */ #ifdef VMSB ToQI = sock; /* copy socket channel for netwrite calls */9 FromQI = sock; /* ditto for netread calls */#else) if ((ToQI = fdopen(sock, "w")) == NULL) { perror("to qi"); return (0); }! /* open path from nameserver */+ if ((FromQI = fdopen(sock, "r")) == NULL) { perror("from qi"); return (0); }#endif UseHost = theHost->h_name; UsePort = QI.sin_port; return (1);}H/***********************************************************************&* identify ourselves to the nameserverH***********************************************************************/ int DoId(){# qprintf(ToQI,"id %d\n",getuid()); qflush(ToQI); return (PrintResponse(-1));}H/***********************************************************************9 * print what the QI (Query Interpreter; nameserver) says@ * read replies from nameserver until code indicates a completedE * command. This routine does not beautify the responses in any way., * if doPaging is 1, the pager will be used.+ * if doPaging is 0, no pager will be used.> * if doPaging is -1, the response will not be printed at all.I ***********************************************************************/int PrintResponse(doPaging)(int doPaging; /* use the pager? */{* char scratch[MAXSTR]; /* some space */3 int code=LR_ERROR; /* the reply code */ FILE *theOutput;" theOutput = OpenPager(doPaging);9 while (GetGood(scratch, MAXSTR, FromQI)) /* read it */ { code = atoi(scratch);N if (doPaging!= -1 || code>=400) fputs(scratch, theOutput); /* echo it */ if (code >= LR_OK) break; } #ifdef VMS#else if (theOutput != stdout) pclose(theOutput);#endif: return (code); /* all done. return final code */}H/***********************************************************************&* get a non-comment line from a stream-* a comment is a line beginning with a # signH***********************************************************************/)int GetGood(theString, maxChars, theFile)6char *theString; /* space to put the chars */4int maxChars; /* max # of chars we want */ #ifdef VMS4int theFile; /* stream to read them from */{(static char Qbuf [MAXSTR+4] = { '\0' } ;8static int pos = {0}, end = {0}, len = {0}, tend = {0}; char *linp; for (;;) { if (pos >= len) {/ len = socket_read(theFile,Qbuf,maxChars); if (len <= 0) return (0); Qbuf [len] = '\0'; pos = 0; }> linp = index(Qbuf+pos, '\n'); /* find next newline char */ if (linp == NULL) {F strncpy(theString, Qbuf+pos, len-pos+1); /* Copy what we have */; end = len-pos; /* no newline chars left */6 pos = 0; /* Start at the beginning *// len = socket_read(theFile,Qbuf,maxChars); if (len <= 0) return (0); Qbuf [len] = '\0'; linp = index(Qbuf, '\n');0 strncpy(theString+end, Qbuf, linp-Qbuf+1); tend = linp + end - Qbuf;% *(theString+tend-pos+1) = '\0'; end = tend - end; } else {@ end = linp - Qbuf; /* convert pointer to index */. strncpy(theString, Qbuf+pos, end-pos+1);$ *(theString+end-pos+1) = '\0'; }G pos = end + 1; /* save new position for next time */#else :FILE *theFile; /* stream to read them from */{ for (;;) {/ (void) fgets(theString, maxChars, theFile);#endif if (*theString != '#')3 return (1); /* not a comment; success! */ else if (!*theString)7 return (0); /* empty string==end of stream */ }}H/***********************************************************************<* complain that there isn't an entry for ns in /etc/servicesH***********************************************************************/void ComplainAboutService(){N fprintf(stderr, "Warning--there is no entry for ``%s'' in /etc/services;\n", NSSERVICE);E fputs("please have your systems administrator add one.\n", stderr);*O fprintf(stderr, "I'm going to use port %d in the meantime.\n", FALLBACKPORT);*}H/***********************************************************************=* complain that there isn't an entry for garcon in /etc/hostsH***********************************************************************/void ComplainAboutHost(name) char *name;t{iB fprintf(stderr, "Warning--unable to find address for ``%s''.\n", name);E fprintf(stderr, "I'm going to use address 0x%x in the meantime.\n",* FALLBACKADDR);}*H/***********************************************************************'* the interactive portion of the clientoH***********************************************************************/typedef struct command Command;nstruct command{ 5 char *cName; /* the name of the command */a5 int cLog; /* must be logged in to use? */u: int (*cFunc) (); /* function to call for command */};Command CommandTable[] ={* "help", 0, DoHelp, "?", 0, DoHelp,* "query", 0, DoQuery, #ifndef MACC CLIENT, 0, DoQuery,  "me", 1, DoMe, "edit", 1, DoEdit, "make", 1, DoMake,/* "password", 1, DoPassword, "passwd", 1, DoPassword, "login", 0, DoLogin, "logout", 1, DoLogout, */n#endif #ifdef MACC r "fields", 0, DoFields,#elseM "fields", 0, DoOtherWPage, "switch", 0, DoSwitch,#endif #ifndef MACC "add", 1, DoOther, "delete", 1, DoOther,C "set", 0, DoOther,#endif "quit", 0, DoQuit, "bye", 0, DoQuit,o "exit", 0, DoQuit, 0, 0, 0.};H/************************************************************************ the main looptH***********************************************************************/>int LastCode = 0; /* the response from the previous command */void Interactive(){S9 char inputLine[MAXSTR]; /* space for an input line */ char *spot;o5 *MyAlias = 0; /* nobody logged in yet... */- #ifndef MACC puts(rcsid);W/* printf("Send mail to %s to get your password (see \"help password\").\n",PASSW); */r< printf("Mail other questions or comments to %s.\n",ADMIN);#else); printf("Lookup - ELECTRONIC MAIL DIRECTORY SERVICE\n\n");= printf("Please mail questions or comments to %s.\n",ADMIN);#endif /* * print database status */l# LastCode = DoOther("status\n",0);m /* * autologin if possible */ /* #ifndef MACC  if (!NoNetrc) DoAutoLogin(); #endif */t puts(" "); while (1)n {t# (void) signal(SIGPIPE,SIG_IGN);v#ifdef MACC_ECHO if (!maccecho) printf("%s> ",Me);#elset printf("%s> ",Me);#endif( (void) fflush(stdout); /* prompt */ spot=inputLine;c do {7 if (!fgets(spot, MAXSTR-(spot-inputLine), stdin)) return; /* read line */n- spot = inputLine + strlen(inputLine)-2;o% if (*spot=='\\') *spot++ = ' ';l else spot=inputLine-1; }o while (spot>=inputLine);#ifdef MACC_ECHO if (maccecho)$ printf("%s> %s",Me,inputLine);#endifJ if (!(LastCode=DoCommand(inputLine))) /* is it a command we know? */B LastCode = DoOther(inputLine); /* unrecognized command */ }}5H/***********************************************************************E* look at input line, and if we have a specific command for it, do itcH***********************************************************************/int DoCommand(inputLine).char *inputLine; /* the input line */{d* char scratch[MAXSTR]; /* some space */= char *theToken; /* a token from the command line */i0 Command *theCommand; /* the command name */ Command *doMe; int len;B /* make a safe copy of the input line, so we can play with it */ strcpy(scratch, inputLine);r+ if (!(theToken = strtok(scratch, DELIM)))*- return (LR_ERROR); /* blank line */f% /* search command table linearly */ doMe = NULL; len = strlen(theToken);cB for (theCommand = CommandTable; theCommand->cName; theCommand++)3 if (!strncmp(theCommand->cName, theToken, len))2 {2@ if (doMe) /* we found 2 commands that match (bad) */ {/( printf("%s is ambiguous.\n", theToken); return (LR_ERROR);c }/? doMe = theCommand; /* we found a command that matches */u }/: if (doMe) /* found one and only one command */ {e /* expand command name */' theToken = strtok((char *)0, "\n");uI sprintf(inputLine, "%s %s\n", doMe->cName, theToken ? theToken : ""); /* execute command */h if (doMe->cLog && !*MyAlias)? printf("You must be logged in to use %s.\n",doMe->cName);e else) return((*doMe->cFunc) (inputLine));* return (LR_ERROR); }** return (0); /* didn't find it */}iH/***********************************************************************B* execute a command for which we do nothing special; use the pagerH***********************************************************************/int DoOtherWPage(inputLine)Achar *inputLine;{m4 qprintf(ToQI,"%s",inputLine); /* send command */ qflush(ToQI);*0 return (PrintResponse(1)); /* get response */}tH/***********************************************************************D* execute a command for which we do nothing special; don't use pagerH***********************************************************************/int DoOther(inputLine)char *inputLine;{ 4 qprintf(ToQI,"%s",inputLine); /* send command */ qflush(ToQI);,0 return (PrintResponse(0)); /* get response */}a #ifdef MACCint DoFields(inputLine)ichar *inputLine;{s* printf("Field Name Description\n"); - printf("------------------------------\n");)( printf("name Person Name\n");> printf("email Electronic Mail Address if exists\n");1 printf("phone Telephone Number One\n");*1 printf("phone2 Telephone Number Two\n");n; printf("address Street Address of the Building\n");** printf("building Building Name\n");< printf("department Department Number One of Person\n");< printf("department2 Department number Two of Person\n");H printf("appointment Appointment Classification Code Number One \n");G printf("appointment2 Appointment Classification Code Number Two\n");& printf("title Title One\n");& printf("title2 Title Two\n");W printf("alias Unique Name built from First Letter of First Name, Last\n"); n1 printf(" Name and a Number\n\n");  return(LR_OK);}/#endifH/************************************************************************ execute a query request*H***********************************************************************/int DoQuery(inputLine)char *inputLine;{* char scratch[4096];* char *args;*! int noReformatWas = NoReformat;i int code;*1 if (ReturnFields && !issub(inputLine,"return"))* {*' args=inputLine+strlen(inputLine)-1;o. sprintf(args," return %s\n",ReturnFields);2 for (;*args;args++) if (*args==',') *args=' '; }r! if (!NoBeautify && !NoReformat)* {h* char *ret = issub(inputLine,"return");. if (ret) NoReformat = !issub(ret,"email"); } + if (!DefType || issub(inputLine,"type="))I { 7 qprintf(ToQI,"%s",inputLine); /* send command */, qflush(ToQI); }* else {t strcpy(scratch,inputLine);! args = strtok(scratch," \t");d args = strtok(0,"\n"); if (args)  { O qprintf(ToQI,"query type=\"%s\" %s\n",DefType,args); /* send command */g qflush(ToQI);r }  else {h# qprintf(ToQI,"%s",inputLine);; qflush(ToQI);o }c }a ? code = (NoBeautify ? PrintResponse(1) : PrintQResponse(1,0));* NoReformat = noReformatWas;* return (code);}*H/************************************************************************ execute a login requestsH***********************************************************************/int DoLogin(inputLine)char *inputLine;{m8 char encryptMe[MAXSTR]; /* string from nameserver */; char encrypted[MAXSTR]; /* string from ns, encrypted */a: char *password; /* user's nameserver password */ int code; char scratch[MAXSTR];e strcpy(scratch,inputLine);C (void) strtok(scratch,DELIM); /* the login part of the command */*1 if (!strtok(0,DELIM)) /* check for an alias */* { C printf("Enter nameserver alias: "); /* ask for missing alias */*) fgets(scratch,sizeof(scratch),stdin);a$ if (!*scratch) return(LR_ERROR);* sprintf(inputLine,"login %s",scratch); }: qprintf(ToQI,"%s",inputLine); /* send login request */ qflush(ToQI);r+ for (;;) /* read the response */  { , if (!GetGood(encryptMe, MAXSTR, FromQI)) {i8 fprintf(stderr, "Whoops--the nameserver died.\n"); exit(1); } code = atoi(encryptMe);*B if (code != LR_LOGIN) /* intermediate or strange response */ fputs(encryptMe, stdout); . if (code >= LR_OK) /* final response */ break; }u if (code == LR_LOGIN)+ {)/ /* the nameserver has issued a challenge */u( password = MyPassword ? MyPassword :+ getpass("Enter nameserver password: ");  crypt_start(password);1 /* encrypt the challenge with the password */ D encryptMe[strlen(encryptMe) - 1] = '\0'; /* strip linefeed */F encrypted[encryptit(encrypted, index(encryptMe, ':') + 1)] = '\0';' /* send the encrypted text to qi */, qprintf(ToQI, "answer %s\n", encrypted); qflush(ToQI);e /* get the final response */ for (;;) { . if (!GetGood(encryptMe, MAXSTR, FromQI)) {(3 fprintf(stderr, "Whoops--the nameserver died.\n");h exit(1);o }f code = atoi(encryptMe);n fputs(encryptMe, stdout);i. if (code >= LR_OK) /* final response */ break;2 }e }1) if (code == LR_OK) /* logged in */* {*/ strcpy(MyAlias, index(encryptMe, ':') + 1);c *index(MyAlias, ':') = '\0';B VetPassword(password); /* make sure password is reasonable */ } else *MyAlias = '\0'; return(code);o}sH/************************************************************************ execute a quit requestH***********************************************************************/int DoQuit(inputLine)nchar *inputLine;{s DoOther("quit\n"); #ifdef VMS exit(SS$_NORMAL);i#elseu@ exit(LastCode=LR_MORE ? LastCode/100 : 0);#endif}H/************************************************************************ edit a fieldH***********************************************************************/int DoEdit(inputLine))char *inputLine;{r char *theField;  char *theAlias;  char *theValue;) int theCode=LR_OK; char confirm[10];7 (void) strtok(inputLine, DELIM); /* skip ``edit'' */?. if (!(theField = strtok((char *) 0, DELIM))) {$ (void) DoCommand("help edit\n"); return(LR_ERROR);t }h. if (!(theAlias = strtok((char *) 0, DELIM))) theAlias = MyAlias;kG if ((theValue = GetValue(theAlias, theField)) && EditValue(theValue)) { 9 for (theCode=UpdateValue(theAlias,theField,theValue);o& 400<=theCode && theCode<=499;2 theCode=UpdateValue(theAlias,theField,theValue)) {! if (!isatty(0)) break;* printf("Shall I try again [y/n]? ");+ fgets(confirm,sizeof(confirm),stdin);e0 if (*confirm!='y' && *confirm!='Y') break; } 1 if (theCode<300 && !strcmp(theField,"alias"))p strcpy(MyAlias,theValue); } return(theCode);} H/***********************************************************************.* get the value of a field from the nameserverH***********************************************************************/"char *GetValue(theAlias, theField)char *theAlias; char *theField; {= static char theValue[MAXVAL]; /* will hold the value */" char *vSpot; char scratch[MAXSTR]; int code;,$ if (!strcmp(theField, "password")) {d4 puts("Use the ``password'' command, not edit."); return (NULL); }r /* do the query */B qprintf(ToQI, "query alias=%s return %s\n", theAlias, theField); qflush(ToQI);  *theValue = '\0';;J /* read qi response lines, concatenating the responses into one value */1 for (vSpot = theValue;; vSpot += strlen(vSpot))r {"* if (!GetGood(scratch, MAXSTR, FromQI)) {H8 fprintf(stderr, "Ding-dong the server's dead!\n"); exit(0); }*) if ((code = atoi(scratch)) == -LR_OK)*M strcpy(vSpot, index(GetQValue(scratch), ':') + 2); /* part of value */* else if (code >= LR_OK)( break; /* final response */ else) fputs(scratch, stdout); /* ??? */( }R% if (code != LR_OK) /* error */* fputs(scratch, stdout);*+ return (code == LR_OK ? theValue : NULL);u} H/************************************************************************ Edit a valueH***********************************************************************/int EditValue(theValue)t1char *theValue; /* the value to edit */e{i8 char *theFileName; /* name of temp file to use */ char *mktemp();* #ifdef VMS$ struct dsc$descriptor_s cli_input;7 char template[28], f1[28], f2[28], edit_command[64];  int istat;#elset char template[20];r#endif7 int fd; /* file descriptor for temp file */ 3 static char newValue[MAXVAL]; /* new value */h7 char *editor; /* editor program to use */ 8 int bytes; /* numnber of bytes in file */ register char *from, *to;-< int badChar; /* did we find a bad character? */ int junk;R char scratch[80]; & /* put the value into a temp file */ #ifdef VMS/ strcpy(template, "SYS$SCRATCH:PHXXXXXX.TMP"); ! theFileName = mktemp(template);d strcpy (f1, theFileName);* strcpy (f2, theFileName);*C strcat (f1, ";1"); /* versions needed for delete function */  strcat (f2, ";2");' if ((fd = creat(theFileName, 0)) < 0)*#else*$ strcpy(template, "/tmp/phXXXXXX");! theFileName = mktemp(template);h; if ((fd = open(theFileName, O_RDWR | O_CREAT, 0777)) < 0) #endif {  perror(theFileName); return (0);n }0 if (write(fd, theValue, strlen(theValue)) < 0) {f perror(theFileName); (void) close(fd);} return (0);o }0 (void) close(fd);,& /* run an editor on the temp file */ #ifdef VMS# if (!(editor = getenv("EDITOR")))o editor = "EDIT/TPU"; strcpy(edit_command, editor);n strcat(edit_command, " ");$ strcat(edit_command, theFileName);L cli_input.dsc$w_length = strlen(edit_command); /* descriptor for spawn */) cli_input.dsc$a_pointer = edit_command;,( cli_input.dsc$b_class = DSC$K_CLASS_S;( cli_input.dsc$b_dtype = DSC$K_DTYPE_T;5 if( (istat = LIB$SPAWN(&cli_input)) != SS$_NORMAL )  {n (void) delete (f1);t exit(istat); }h#else# if (!(editor = getenv("EDITOR"))) #ifdef hpux= editor = "/usr/bin/vi";u#else) editor = "/usr/ucb/vi";n#endif if (fork()) % (void) wait((union wait *)&junk);( else {d5 (void) execlp(editor, editor, theFileName, NULL); : fprintf(stderr,"Whoops! Failed to exec %s\n",editor); exit(1); }#endif% /* does the user want the value? */  if (Confirm) {  do { ' printf("Change the value [y]? ");* gets(scratch); }i0 while (*scratch && !index("yYnN",*scratch)); }   /* read the value back out */& if ((fd = open(theFileName, 0)) < 0) {h perror(theFileName); #ifdef VMS#else (void) unlink(theFileName);m#endif return (0);l } #ifdef VMS#else  (void) unlink(theFileName);r#endif3 if ((bytes = read(fd, newValue, MAXSTR - 1)) < 0)* {* perror(theFileName); (void) close(fd);n #ifdef VMS4 (void) delete (f1); /* delete 1st temp file */4 (void) delete (f2); /* delete 2nd temp file */#endif return (0);e }( (void) close(fd);e #ifdef VMS4 (void) delete (f1); /* delete 1st temp file */4 (void) delete (f2); /* delete 2nd temp file */#endif newValue[bytes] = 0; /* did the value change? */g> if (Confirm && *scratch && *scratch!='y' && *scratch!='Y' ||" !strcmp(newValue, theValue)) return (0);*9 /* copy new value into old, stripping bad characters */o badChar = 0;5 for (to = theValue, from = newValue; *from; from++)* if (*from == '"')d {i *to++ = '\\';r *to++ = '"'; }e else% if (*from >= ' ' && *from <= '~')n *to++ = *from; else if (*from == '\t') {x *to++ = '\\';* *to++ = 't'; } else if (*from == '\n') {*> if (*(from + 1)) /* skip terminating newline from vi */ {o *to++ = '\\'; *to++ = 'n';* }* }* else badChar = 1; *to = 0;? if (badChar) /* complain if we found bad characters */n {fD fputs("Illegal characters were found in your value.\n", stderr);Q fputs("Please use only printable characters, newlines, and tabs.\n", stdTD~ PH_CLIENT.SAVX[PH_CLIENT]PH.C;1gr\Cerr);n> fputs("The offending characters were removed.\n", stderr); }0 return (1);e}AH/***********************************************************************,* update a nameserver field with a new valueH***********************************************************************/-int UpdateValue(theAlias, theField, theValue)Dchar *theAlias; char *theField;rchar *theValue; {DR qprintf(ToQI, "change alias=%s make %s=\"%s\"\n", theAlias, theField, theValue); qflush(ToQI); return(PrintResponse(0)); }eH/************************************************************************ print info on current userH***********************************************************************/ /*ARGSUSED*/int DoMe(inputLine)*char *inputLine;{0 if (!*MyAlias) {t return(DoHelp("help me")); }i8 qprintf(ToQI, "query alias=%s return all\n", MyAlias); qflush(ToQI);*> return(NoBeautify ? PrintResponse(0) : PrintQResponse(0,0));}nH/************************************************************************ set command-line switchesSH***********************************************************************/int DoSwitch(inputLine)Echar *inputLine;{Y& inputLine = strtok(inputLine,DELIM);" if (!OptionLine(strtok(0,"\n"))) {G printf("The following things can be changed with \"switch\":\n\n");"A printf(" Paging is %s; use \"switch -%c\" to turn it %s.\n",d NoPager ? "OFF" : "ON", NoPager ? 'M' : 'm',  NoPager ? "on" : "off"); M printf(" Email reformatting is %s; use \"switch -%c\" to turn it %s.\n",  NoReformat ? "OFF" : "ON",  NoReformat ? 'R' : 'r', NoReformat ? "on" : "off");O printf(" Query beautification is %s; use \"switch -%c\" to turn it %s.\n",n NoBeautify ? "OFF" : "ON",r NoBeautify ? 'B' : 'b', NoBeautify ? "on" : "off");I printf(" Label printing is %s; use \"switch -%c\" to turn it %s.\n", NoLabels ? "OFF" : "ON",i NoLabels ? 'L' : 'l', NoLabels ? "on" : "off");L printf(" Edit confirmation is %s; use \"switch -%c\" to turn it %s.\n", Confirm ? "ON" : "OFF", Confirm ? 'c' : 'C',  Confirm ? "off" : "on");J printf(" Default entry type is %s; use \"switch -%c%s\" to %s %s.\n", DefType ? DefType : "OFF",f DefType ? 'T' : 't', $ DefType ? "" : " name-of-type",' DefType ? "turn it" : "set it to",*' DefType ? "off" : "\"name-of-type\""); M printf(" Default field list is %s; use \"switch -%c%s\" to %s to %s.\n", 0 ReturnFields ? ReturnFields : "default", ReturnFields ? 'F' : 'f',+ ReturnFields ? "" : " field1,field2,... ",$ ReturnFields ? "revert" : "set it",5 ReturnFields ? "default" : "\"field1,field2,...\"");hL printf("\nThe following things cannot be changed with \"switch\":\n\n");E printf(" Connected to server %s at port %d\n", UseHost,UsePort); E printf(" The .netrc file was %sread.\n", NoNetrc ? "not " : ""); }  return(LR_OK);}TH/***********************************************************************,* change a field value from the command lineH***********************************************************************/int DoMake(inputLine)char *inputLine;{  int theCode=LR_ERROR;o if (!*MyAlias) DoHelp("help make"); else { 9 qprintf(ToQI,"change alias=%s %s",MyAlias,inputLine);  qflush(ToQI);o theCode = PrintResponse(0);r }c return(theCode);}p H/************************************************************************ change passwordhH***********************************************************************/int DoPassword(inputLine)char *inputLine;{( char password[80];e char *confirm; char *theAlias;e int theCode=LR_ERROR;' if (!*MyAlias) {*$ return(DoHelp("help password")); }* /* which alias to use? */t" (void) strtok(inputLine, DELIM);. if (!(theAlias = strtok((char *) 0, DELIM))) theAlias = MyAlias;* /* get the password */4 strcpy(password, getpass("Enter new password: "));# if (!*password) return(LR_ERROR); ' confirm = getpass("Type it again: ");r if (strcmp(confirm, password)) {t8 fprintf(stderr, "Sorry--passwords didn't match.\n"); return(theCode); }tH VetPassword(confirm); /* complain if we don't like the password */% /* encrypt and send the password */*0 password[encryptit(password, confirm)] = '\0';J qprintf(ToQI, "change alias=%s make password=%s\n", theAlias, password); qflush(ToQI);e$ /* see what the nameserver says */G if ((theCode=PrintResponse(0)) == LR_OK && !strcmp(theAlias,MyAlias))s crypt_start(confirm);D return(theCode);}nH/************************************************************************ log out the current userH***********************************************************************/int DoLogout(inputLine)rchar *inputLine;{e *MyAlias = '\0'; return(DoOther(inputLine));e}AH/***********************************************************************(* complain about passwords we don't likeH***********************************************************************/void VetPassword(thePassword)pchar *thePassword;{C3 if (strlen(thePassword) < 5 || /* too short */m- AllDigits(thePassword)) /* digits only */nG fputs("That is an insecure password; please change it.\n", stderr);}rH/************************************************************************ is a string all digitsH***********************************************************************/int AllDigits(theString)register char *theString;*{*! for (; *theString; theString++)* if (!isdigit(*theString))* return (0);* return (1);*}*H/************************************************************************ print the response to a querya1* this strips out all the nameserver reply codes.sH***********************************************************************/+int PrintQResponse(reformatEmail,amHelping)nint reformatEmail;int amHelping;{a char theLine[MAXSTR]; int theCode=LR_ERROR;e int currentPerson = 0; int thePerson; register char *cp; FILE *theOutput; char nickname[MAXSTR];( char alias[MAXSTR]; char email[MAXSTR]; int copiedEmail=0; theOutput = OpenPager(1);,O *alias = *email = *nickname = 0; /* haven't found an alias or nickname yet */=" if (NoReformat) reformatEmail=0; /* get the response */* while (GetGood(theLine, MAXSTR, FromQI)) {% theCode = atoi(theLine); if (theCode == LR_NUMRET)T { #ifdef MACCl cp = strchr(theLine,':'); if ( cp != 0)Q fprintf(theOutput,"\n%s\n",cp+1); /* strchr returns pointer to : then add one */1 #endif MACCp }0 elseJ if (theCode == -LR_OK || theCode == -LR_AINFO || theCode == -LR_ABSENT || theCode == -LR_ISCRYPT) {*0 thePerson = atoi(index(theLine, ':') + 1); /* output a delimiter */% if (thePerson != currentPerson)( {) if (*alias && !*email)& NotRegisteredLine(alias,theOutput); else if (*email)  {# EmailLine(email,alias,nickname);n% fputs(GetQValue(email),theOutput);  *email = 0; }@ fputs("----------------------------------------\n", theOutput); currentPerson = thePerson;v copiedEmail=0;c }  if (reformatEmail) {* cp = GetQValue(theLine);/ while (*cp && *cp==' ') cp++; if (!strncmp("alias",cp,5)) { copiedEmail = 0;i strcpy(alias,theLine);a continue; }! else if (!strncmp("email",cp,5))r { strcpy(email,theLine);L copiedEmail = 1;h continue; }$ else if (!strncmp("nickname",cp,8)) { copiedEmail = 0;T strcpy(nickname,theLine); continue; }" else if (*cp==':' && copiedEmail) continue; else) copiedEmail = 0;t }  /* output the line */\! if (NoLabels && !amHelping)o: fputs(index(GetQValue(theLine),':')+2, theOutput); else- fputs(GetQValue(theLine), theOutput);u }  else if (theCode != LR_OK)- fputs(theLine, theOutput); /* error */= if (theCode >= LR_OK)e {r if (*alias && !*email)$ NotRegisteredLine(alias,theOutput); else if (*email) {e! EmailLine(email,alias,nickname);a /* output the line */ if (NoLabels && !amHelping)3 fputs(index(GetQValue(email),':')+2, theOutput);; elses& fputs(GetQValue(email), theOutput); }e break; }: }1 /* final "delimiter" */  if (currentPerson)C fputs("----------------------------------------\n", theOutput); #ifdef VMS#elser if (theOutput != stdout) (void) pclose(theOutput);t#endif return(theCode);}f #ifndef NeXTH/***********************************************************************E* break a string into tokens. this code is NOT lifted from sysV, butO* was written from scratch.eH***********************************************************************//*I * function: strtok purpose: to break a string into tokens parameters:;L * s1 string to be tokenized or 0 (which will use last string) s2 delimitersJ * returns: pointer to first token. Puts a null after the token. returns * NULL if no tokens remain. * */*char *strtok(s1, s2)char *s1, *s2;{* static char *old = 0;* char *p1, *p2; if (!(s1 || old))o return (NULL); p1 = (s1 ? s1 : old);o) while (*p1 && (index(s2, *p1) != NULL))R p1++;s if (*p1) {d p2 = p1;+ while (*p2 && (index(s2, *p2) == NULL)) p2++;* if (*p2) {* *p2 = '\0';* old = ++p2;* }d else old = 0; return (p1); }* else return (NULL);}*#endif #ifdef VMS/* setterm.cL * * module in termlib  *, * contains routines to set terminal mode *1 * V1.0 19-jul-84 P. Schleifer Initial drafto */usetterm(characteristic, state)long *characteristic, *state;{  int status; long efn; long new_state; short term_chan; struct char_buff mode;= struct mode_iosb term_iosb; $DESCRIPTOR(term_desc, "TT:"); /* get event flag */ status = lib$get_ef(&efn);. if ( status != SS$_NORMAL ) return (status); /* get channel to terminal */ 4 status = sys$assign(&term_desc, &term_chan, 0, 0);, if (status != SS$_NORMAL) return (status);Q /* if characteristic is BROADCAST, ECHO, or TYPEAHEAD, state must be toggled */,^ if (*characteristic == BROADCAST || *characteristic == ECHO || *characteristic == TYPEAHEAD) new_state = !(*state); else new_state = *state;t /* get current mode */\ status = sys$qiow(efn, term_chan, IO$_SENSEMODE, &term_iosb, 0, 0, &mode, 12, 0, 0, 0, 0);g if (status != SS$_NORMAL || term_iosb.stat != SS$_NORMAL) { sys$dassgn(term_chan); return (status); }*% /* change characteristics buffer */i if (new_state == ON)' mode.basic_char |= *characteristic;h else* mode.basic_char &= ~(*characteristic);1 /* $ SET TERM/... and then deassign channel */,Z status = sys$qiow(efn, term_chan, IO$_SETMODE, &term_iosb, 0, 0, &mode, 12, 0, 0, 0, 0); sys$dassgn(term_chan); lib$free_ef(&efn);, if (status != SS$_NORMAL) return (status); else return (term_iosb.stat);f}hH/************************************************************************ get password from stdina* <* implement for VMS, since VAXCRTL lacks getpass() function.H***********************************************************************/char *getpass(prompt) char *prompt; {xstatic char line [12];1static int echo = {ECHO}, off = {OFF}, on = {ON};t< printf(prompt); (void) fflush(stdout); /* prompt */ setterm(&echo, &off);R gets(line);a setterm(&echo, &on); puts("");l return(line);c}c#endifH/***********************************************************************0* use .netrc to login to nameserver, if possibleH***********************************************************************/void DoAutoLogin(){' FILE *netrc; /* the .netrc file */*3 char pathName[1024];/* pathname of .netrc file */d< struct stat theStat;/* permissions, etc. of .netrc file */; char key[80], val[80]; /* line from the .netrc file */tG char *token; /* token (word) from the line from the .netrc file */_, char *alias=NULL; /* the user's alias */- char *pw=NULL; /* the user's password */h /*7 * manufacture the pathname of the user's .netrc filer */m/ sprintf(pathName,"%s/.netrc",getenv("HOME"));* /*% * make sure its permissions are oke */r if (stat(pathName,&theStat)<0) return;n if (theStat.st_mode & 077)3 return; /* refuse insecure files */  /* * try to open itr */ # if (!(netrc=fopen(pathName,"r"))) return;v /*( * look for a ``machine'' named ``ph'' */"* while (2==fscanf(netrc,"%s %s",key,val)) {e6 if (!strcmp(key,"machine") && !strcmp(val,CLIENT)) {F /*9 * found an entry for ph. look now for other itemsu */. while (2==fscanf(netrc,"%s %s",key,val)) {<2 if (!strcmp(key,"machine")) /* new machine */ {) if (alias) {free(alias);alias=NULL;} if (pw) {free(pw);pw=NULL;} break;  } else if (!strcmp(key,"login"))e7 alias=strcpy(malloc((unsigned)strlen(val)+1),val);t" else if (!strcmp(key,"password"))4 pw=strcpy(malloc((unsigned)strlen(val)+1),val);3 else if (!strcmp(key,"macdef")) SkipMacdef(netrc);t' if (alias && pw && TryLogin(alias,pw))( goto done;( }) } 6 else if (!strcmp(key,"macdef")) SkipMacdef(netrc); }tdone:_ if (alias) free(alias);i if (pw) free(pw);e return;n}.H/***********************************************************************"* skip a macdef in the .netrc fileH***********************************************************************/void SkipMacdef(netrc) FILE *netrc;{n int c, wasNl;A 4 for (wasNl=0;(c=getc(netrc))!=EOF;wasNl=(c=='\n')) if (wasNl && c=='\n') break;}EH/*********************************************************************** * try a login alias and passwordH***********************************************************************/int TryLogin(alias,password) char *alias;char *password;e{" char loginLine[80];  int success; /* * construct a login linee */s( sprintf(loginLine,"login %s\n",alias); /* * set our passwordf */e MyPassword=password; /* * try the login */l! success = DoLogin(loginLine,0);c /* * reset our passwordu */o MyPassword = NULL;& while (*password) *password++ = 'x'; /*$ * return our success (or failure) */n return(success);}fH/************************************************************************ execute a help requestH***********************************************************************/int DoHelp(inputLine)ichar *inputLine;{l char scratch[256]; char *token;  strcpy(scratch,inputLine);< token = strtok(scratch+4,DELIM); /* the word after help */E if (token && !strcmp(token,"native")) /* looking for native help */f= strcpy(scratch,inputLine); /* leave the command alone */e elseM sprintf(scratch,"help %s %s",CLIENT,inputLine+4); /* insert identifier */c 2 qprintf(ToQI,"%s",scratch); /* send command */ qflush(ToQI);? return (NoBeautify ? PrintResponse(0) : PrintQResponse(0,1));h}cI/************************************************************************+5 * reformat an email line to include an alias addressrJ * this is kind of a hack since we're working on an already-formatted lineJ ************************************************************************/$void EmailLine(email,alias,nickname) char *email; char *alias;char *nickname;{  char scratch[MAXSTR];i1 char *emSpot; /* beginning of email account */=4 char *alSpot; /* beginning of nameserver alias */2 char *niSpot; /* beginning of nickname field */  if (*nickname) { . emSpot = index(GetQValue(email), ':') + 2;1 niSpot = index(GetQValue(nickname), ':') + 2;  *index(niSpot,'\n') = 0; *index(emSpot,'\n') = 0; /* * overwrite the email label */t3 strcpy(niSpot-2-strlen("email to"),"email to");e> niSpot[-2] = ':'; /* strcpy clobbered the colon; repair */( sprintf(scratch,"@%s\n",MAILDOMAIN); strcat(nickname,scratch);*? strcpy(email,nickname); /* leave it in the "email" line */n4 *nickname = 0; /* we're done with the alias */ }i else if (*alias) {. emSpot = index(GetQValue(email), ':') + 2;. alSpot = index(GetQValue(alias), ':') + 2; *index(alSpot,'\n') = 0; *index(emSpot,'\n') = 0; /* * overwrite the email label */*3 strcpy(alSpot-2-strlen("email to"),"email to");s> alSpot[-2] = ':'; /* strcpy clobbered the colon; repair */( sprintf(scratch,"@%s\n",MAILDOMAIN); strcat(alias,scratch);< strcpy(email,alias); /* leave it in the "email" line */1 *alias = 0; /* we're done with the alias */, }i};I/************************************************************************(/ * put out a ``not registered'' line with alias*J ************************************************************************/'void NotRegisteredLine(alias,theOutput)* char *alias;FILE *theOutput;{h char scratch[MAXSTR];u register char *cp;  strcpy(scratch,alias);% cp = index(GetQValue(scratch),':'); strcpy(cp-8,"email to:");h, strcpy(cp+1," (no address registered)\n"); /* output the line */s if (NoLabels)c6 fputs(index(GetQValue(scratch),':')+2, theOutput); else) fputs(GetQValue(scratch), theOutput);f' *alias = 0; /* done with alias */ } I/************************************************************************  * process a set of options J ************************************************************************/int ProcessOptions(argc,argv)" int argc;B char **argv;{  int count = 0; /* * options processingt */o3 for (;argc && **argv=='-'; argc--,argv++,count++)  {t& for ((*argv)++; **argv; (*argv)++) {O switch(**argv) {L! case 'r': NoReformat = 1; break;f! case 'R': NoReformat = 0; break;o case 'n': NoNetrc = 1; break; case 'N': NoNetrc = 0; break; case 'm': NoPager = 1; break; case 'M': NoPager = 0; break;! case 'b': NoBeautify = 1; break;r! case 'B': NoBeautify = 0; break;t case 'l': NoLabels = 1; break;y case 'L': NoLabels = 0; break;: case 'C': Confirm = 1; break; case 'c': Confirm = 0; break; case 's': if (argv[0][1]) { if (UseHost) free(UseHost);" UseHost = makestr(*argv + 1); goto whilebottom; } else if (argc>1)n { if (UseHost) free(UseHost); UseHost = makestr(argv[1]); argc--,argv++,count++;. goto whilebottom; } elsetK fprintf(stderr,"-%c option given without server hostname.\n", **argv); break;h case 't': if (argv[0][1]) { if (DefType) free(DefType);" DefType = makestr(*argv + 1); goto whilebottom; } else if (argc>1)d { if (DefType) free(DefType); DefType = makestr(argv[1]); argc--,argv++,count++;* goto whilebottom; } elseeF fprintf(stderr,"-%t option given without entry type.\n", **argv); break;* case 'f': if (argv[0][1]) {* if (ReturnFields) free(ReturnFields);' ReturnFields = makestr(*argv + 1);  goto whilebottom; } else if (argc>1)o {* if (ReturnFields) free(ReturnFields);% ReturnFields = makestr(argv[1]);o argc--,argv++,count++;o goto whilebottom; } else*F fprintf(stderr,"-%t option given without field list.\n", **argv); break;* case 'F':( if (ReturnFields) free(ReturnFields); ReturnFields = 0; break;h case 'T': if (DefType) free(DefType); DefType = 0;r break; case 'p': if (isdigit(argv[0][1])) {& UsePort = htons(atoi(*argv + 1)); goto whilebottom; }( else if (argc>1 && isdigit(*argv[1])) {$ UsePort = htons(atoi(argv[1])); argc--,argv++,count++;A goto whilebottom; } elserG fprintf(stderr,"-%c option given without port number.\n", **argv);o break;L default:3 fprintf(stderr,"Unknown option: -%c.\n",**argv);p }  }d whilebottom:;t }e return(count);} I/************************************************************************* * Process a lineful of optionssJ ************************************************************************/OptionLine(line) char *line;i{( int argc;  char *argv[MAXARGS]; char *token;  if (!line || !*line) return; J for (argc=0,token=strtok(line,DELIM);token;argc++,token=strtok(0,DELIM)) argv[argc] = token;s argv[argc] = 0;o $ return(ProcessOptions(argc,argv));}*I/************************************************************************ + * OpenPager - open the user's chosen pager*J ************************************************************************/FILE *OpenPager(doPaging)= int doPaging;n{O char *thePager; FILE *theOutput; #ifdef VMS@ return(stdout); /* simpler to skip paging for right now */#else  if (NoPager || doPaging!=1)* return(stdout);* else {*- if ((thePager = getenv("PAGER")) == NULL)p #ifdef hpuxP! thePager = "/usr/bin/more";o#else ! thePager = "/usr/ucb/more";t#endif3 if ((theOutput = popen(thePager, "w")) == NULL)e theOutput = stdout;e return(theOutput); }*#endif}*I/************************************************************************i4 * makestr - make a copy of a string in malloc-spaceJ ************************************************************************/char *makestr(str) char *str;{i char *copy;( int len;  len = strlen(str); if (copy=malloc(len+1)) strcpy(copy,str);* return(copy);*}*I/************************************************************************u0 * issub - is one string a substring of another?J ************************************************************************/char *issub(string, sub)char *string;m char *sub;{n int len; len = strlen(sub); for (; *string; string++) # if (!strncmp(string, sub, len))o return (string); return (0);O}uH/***********************************************************************6 * EnvOptions - grab some options from the environmentI ***********************************************************************/evoid EnvOptions(name)m char *name;m{= char buffer[80]; register char *np,*bp;) for (np=name,bp=buffer; *np; np++,bp++) , *bp = islower(*np) ? toupper(*np) : *np; *bp = 0; OptionLine(getenv(buffer));i}'*[PH_CLIENT]PH.EXE;4+,bG.3/ 434-0123 KPWO456Z7`89GHJ0D`0205h.PHV1.0%05-13 : A JPk , ?0!MULTINET_SOCKET_LIBRARY_001! LIBRTL_001 ! VAXCRTL_001O! MTHRTL_001VAX/VMS: ph.c,v 4.10 91/10/15 14:44:00 sandrock-oberman phphph-t %sSorry--phone book not available now. query quit nstcpp.lanl.gov%s%snsNo more backups to try. %s%d%snsWARNING--backup host %s; information may be out of date. id %d Warning--there is no entry for ``%s'' in /etc/services; nsplease have your systems administrator add one. I'm going to use port %d in the meantime. Warning--unable to find address for ``%s''. I'm going to use address 0x%x in the meantime. help?queryphmeeditmakefieldsswitchadddeletesetquitbyeexitMail other questions or comments to %s. lanl.govstatus %s> %s is ambiguous. %s %s You must be logged in to use %s. %s%sreturn return %s returnemailtype=%s query type="%s" %s %s Enter nameserver alias: login %s%sWhoops--the nameserver died. Enter nameserver password: answer %s Whoops--the nameserver died. quit help edit Shall I try again [y/n]? aliaspasswordUse the ``password'' command, not edit.query alias=%s return %s Ding-dong the server's dead! SYS$SCRATCH:PHXXXXXX.TMP;1;2EDITOREDIT/TPU Change the value [y]? yYnNIllegal characters were found in your value. Please use only printable characters, newlines, and tabs. The offending characters were removed. change alias=%s make %s="%s" help mequery alias=%s return all The following things can be changed with "switch": Paging is %s; use "switch -%c" to turn it %s. ONOFFoffon Email reformatting is %s; use "switch -%c" to turn it %s. ONOFFoffon Query beautification is %s; use "switch -%c" to turn it %s. ONOFFoffon Label printing is %s; use "switch -%c" to turn it %s. ONOFFoffon Edit confirmation is %s; use "switch -%c" to turn it %s. OFFONonoff Default entry type is %s; use "switch -%c%s" to %s %s. OFF name-of-typeset it toturn it"name-of-type"off Default field list is %s; use "switch -%c%s" to %s to %s. default field1,field2,... set itrevert"field1,field2,..."default The following things cannot be changed with "switch": Connected to server %s at port %d The .netrc file was %sread. not help makechange alias=%s %shelp password Enter new password: Type it again: Sorry--passwords didn't match. change alias=%s make password=%s That is an insecure password; please change it. ---------------------------------------- aliasemailnickname---------------------------------------- TT:%s/.netrcHOMEr%s %smachineph%s %smachineloginpasswordmacdefmacdeflogin %s nativehelp %s %sph%semail toemail to@%s lanl.govemail toemail to@%s lanl.govemail to: (no address registered) -%c option given without server hostname. -%t option given without entry type. -%t option given without field list. -%c option given without port number. Unknown option: -%c. :2*" <4,$ >6.&@80( 91)! ;3+# =5-% ?7/'(08@ '/7?&.6>%- 5=$, 4<#+ 3;"* 2:!) 1991)! :2*" ;3+# <4,$?7/'>6.&=5-%      )4%/7(3-!0,1'8"5.*2$                                                                                                                                     h lĨ"Ĩ)Ĩ-26|eq~ PH_CLIENT.SAVbG[PH_CLIENT]PH.EXE;43H|Τ^6uUVaTޤ8eeмeߤ<+eߤ?~6PdeߤBͬ6ͬC>S> ݮ6PRRCSB 6PRC߭S_&ev+ݬ׬ݬB&PxPPPPI6ߤH5< ~6PǏdP~6լ T1ߤnͬ5լ/5RPݼͬbѬ ߤuͬb׬լߤwͬX5ͬfRߤyRj5f95Pf4X5P^YU5V&`SgkRU[4PPii\PÃÀU4P @P7f4f:4i~kf4i~3PH\\TÇTTW\g.\\XW×Ò߭^4 W߭ 43PTP߭3PP\ݼq3_PUH߭Öf3ݏsf3ݏs<3P:3PÚf3PT 3P-߭3XUWUúó߭|31)PU߭ýfY3T Tв<2P ^S6^\cR2PR3c2PcW2Џ~^[T<R2Sd<~XPMi2PRѬ R Sn2Rd<~ PRPP^hR$'ݬߢݬ 1P$P$P@ ޢPP~!2PT1$PPPޢPP~ݬ1$ ݬߢݬ 1P$P$P@ ߢ1PSޢPPSPPPߢ ~H1 SޢPPS((PPP` ( ;ޢPPT  PPPޢPP~ݬ0 PPP` ޼P`#P`1PP^%1R[\7b0b:0i~kݢ0^[Rݬ–00ݏs0}0^VW0U0Sc[TRbf40d;10mPfu0 0gw/e/Rc\\R\\~R/P\/P\\Rb\  \\R\R\Pf1nGPf1]|^oZSݬ(/|q/PT<PVT /PURb3UTb.PVTÀ.<PRV RbV\Ò /PPRÛRRfÔݬ.զJP`fÜ. Pݬ<PPP ^5SYRcPݬ¾Pf.ߣ4.P -U ^S*YRcPݬP.ߣ-PN-^wY|XuWjZXUi[U}ЬR ޮ Tݮ g-PSbSݮR6-PRP RbPP:ݬ2-PPRR?-bPb, bRb1i1ЬRޮTݮ,PSbSݮ R,PRP RbPPTJTRޮVݮ,PSbSݮRb,PRP RbPRPRRiAЬRnnTnD,PSbSݮR,PRP RbPP0gRݬR-,g+Phhgj|+1ݬ+,PS ,PS6gRSSR+g+Phhgj+/PgRݬR+gd+Phhgj*PSPPSSR[iRP^[ZVf+YS+XP+WVR^aTݬ* +  +P?*+<~*<P*ݬ*jPݬ3P*j\*Pkkj')f<~P6hE*`*)PSS- g *SS-1PPUNT)g)ĠuĜuĐu)ĤuĜu² )ĐuUUnnwp)P@:)PP"@jPpP\)j+)Pkݫ(f<~P{h),)(PSg(SSw:(PP`(:Q(`nUU(P(UQaaPPP@iP PQaPPh Z( P`SPP^YSRV(^e(W.SRSŸݬ;(£.(PV§<P² (PTlTVTPU1UP1UVTPSяSaSXP?'PI¶t'g ߭N'yY"UVTcPSяS SS, V&PU&SP^ZV!'W'XQS,]Yݬ&P&PjRݬݬR&jt&PICj7%,Rb,Tf<~P!gI&d&&PUU81:::5&RbPPbPPbP~T%Uh%T%PT1gPU h%UT,TTPP^%WPT[V?߭؞O%Rb߭ %PUU߭bU߭bX߭$%[߭%U$PR UM%Pݬ$PݬR$PU%%R$PR$^$PReRR`$n`$U`$`{$P`$PRR߭!$R$0pU$6$~ćL$PU#PS U?$P<~>S#PR)U$S#߭#߭#PSw#߭q#߭g#B>,R RyRYݬ>Y#PPUЬQ>P`\P`SS"\QRQ"b=PS  S~S+S  \tS PRb\nUP`aU"gČ"Rbgĺbgb2P ^SMRcPݬ ݬݬP"c"Pd^ߣQ"^9TMR P` ;wdPCPP"d"Pd!:PS |~CPSSP^MT^ݬ"Pb"PUGeCS> U!PRPRCSB !PRC߭SPRR1dw!XhS UPUUS MRPmRR~S SPSSęhS UPUUS RRPrRR~S SPSShxS mUPiUUS BRPbRR~S eSPbSS#h4S ĴUPİUUS LRPlRR~S ĬSPĩSSphS UPUUS cRPCRR~S SPSSķhQ oWP`WWQ XVPNVVQ MUP?UUQ TRPtRR~QQS;SShHQ WPWWQ VPVVQ UPĸUUQ FRPfRR~QQSİSSshh0huRtRRUh<P^SIR<TnP` z JcPݬP„Pc~PSMcAPTTPP^YXU_ISTRi ×P åݬYéLPWiWí ? uœu u¤uœuò u߭<P uœuum¤uœuò [uV߭V&P|=<PVTT P+TQaPaPPP@eP PQaPP- V߭@hP߭WPhPqkh_PTTiWTP VOTPP^P`% ^RNGSݬP+ЬQaPaPPP@bP PQaPP5 ^)RЬP``QQQAbPP`2P^FT<WԮYVSPRb`c6Ԭ <~P1*rUCX Z[ PWWf1W8W W W1z:ePP PSSfV/ <5V::ePPePPhRbVE hSYլ1::ePPePRbb PRbb Ro jPYk1jPRu jPkY1HR{ jPYk1)b:Y1Y|.լ)V:::ePPePPeP~h5PV::ePPePPhPW VhW1V1P1 8լ3V:::ߞ-RbPPbPPbP~KPV::PPPP PN<~ZP1gծ VĄ WP^NTլ ČuPЬPPRPČuRRSc+c~ݬkPPScc~ݬQPcISRb)b~ݬ5PRbb~ݬPb bRRČuPČuSPP(^BRڐܐ® ߭@P|~?PPмPP PPPռPPTмT|~|~ |~'2~ݭ PSS 2PP2~SPTˏSȼSSˏSҼPSSSPSS|~|~ |~#2~ݭ PS2~߭XSSP2P ^ASMRݬ uœuuh¤uœuò VuP^[AU|WŽ UPų 4PRݬ ߭*ЬSS߭PQcPЬP֬x`QP^T=Rݬ PP~P! PtPݬf~  |dP# Phd7P dRPSYPSSPP|^=UЬ Vf1:::ݬTdPPdPPdPR:::VdPPdPPdPS Sd` Rd`/ SR& pPR~]:= 8 vV=Vݬ-fPЬVf1:::ݬRTdPPdPPdPR:::VdPPdPPdPS Sd` Rd`O SRF PR~:] X VVݬ{f<^;Sݬ]Td:::UePPePPePRf R~dp RRd.ݬ:::ePPePPeP~ #Pݬ::ePPePP$^YbZ[|WVfX:UԮլ1޼R-1h P<ЬRb1P޼RPPB2TTTTTTTTTT|TTTTTTTTTTTTTTTTTTTTTTTt1P?Pg1Pg1Ph1Ph1Pk1Pk1P91P.1P%1P1P1P1PЬTdP0ff SSPPPRSRRf1PѬ>ff ЬPРSSPPPRSRRf׬֮1 ~Ŋ 1PЬTdP0jj SSPPPRSRRj1Ѭ>jj ЬPРSSPPPRSRRj׬֮1u~ŵ j 1QPЬTdP0ii SSPPPRSRRi1 Ѭ>ii ЬPРSSPPPRSRRi׬֮1~ 1Pii i1jj j1ЬScPPPP@ c~PPtѬ6УRbPPP@j !RPP׬S֮9~ . ޼R~(  ЬP`1x׬֮լ ޼R-1LP^6TЬRbS> ݬ PRPRCSB  PRCͬͬSa^} PP^ݬ PPB PR ݬR RP ^ެSc PR!PRcݬ PЬP֬PP|X^ V5UЬR\Sb0PbTTPPP@fT~ PQTQQcRSbҔc\ PTAd=S> T PRRCSB l PRC߭S;^R|bԢ^VWUڵRݬTPQPSQlPЬQ֬dPPʏP@eP PʏP@fP¢ PʏP@gP¢PPa֢ѢԢ֢ Ѣ Ԣ TSPSPP^ɽ<^ЬR֬bR#RˏRTTUT1ЬS֬ЬRbP#PʏPxPQP#PʏPPPPQcЬS֬P#PʏPxPQP#PʏPPPPQcЬS֬P#PʏPxPQP#PʏPPQcRT1eUP^%UZVTeSRPcb`SRPT ݬݬP߭{WTScRWRTRWS TPSPcSPYWSzYP{ PQPPRBRSRWzWP{PQPPXYTˏXSTRQSPRRRPRQPQP{RPPQXXDfRAfDfRAfDeVˏXRQRPTRRRPRQPQ{RPPQQSCePSRzRP{TPQPPSCeSDeTCeY$PTdRR2RSPCjTPP|^UVTʲRShPSQSPPʏP@dP PʏP@eP¢ PʏP@fP¢PPa֢ѢԢ֢ Ѣ Ԣ ֬PPS~^ЬPPTPQPެ ScPʏP#PPaRcPݬݬRRcЬPTP<^ЬRbPPPxPUxPSʏSQxQPʏPPSxQQʏQTTPxPPʏPPQʏTЬR֬UPPPʏP#PPbЬR֬SPPPʏP#PPbЬR֬QPPPʏP#PPbTPPPʏP#PP^)VPUƜTRRBe\dRRBexTPSZRjTRTUjYYXWPUTedUTPWWQUTedUTQW/RRXP0SXXUTE0WH0QRRBadRRBgTWQPZSZP`RbR/P^1TPUScRRBeðS?PXլXWXWPRb RPQ0WVF0U0ScRRBeUS/QPPSxPVC0QxQUSRB0QxQQQUSRB0QxQQQUSRB0QxQQQUSRB0QQUSRB0QxQQQUVUEĐUxPSxUQʏQQCSRxUQʏQQBSRxUQʏQQBSRˏUQQBP:QRbPP @@RQPRbRPXPSRcRcSPQ޼V@USeRRBİcUS?Q^VR`ScSARPQEP@$ EnvOptions <   1 lCRYPTIT crypt_start(decrypt decrypt_end decodex crypt_init encryptit encodeX threecpy  CRYPT setkeyencrypt tcryptlw P *[PH_CLIENT]PH.HLP;1+,{./ 4ID-0123KPWO56ƫ789GHJ 1 PhD Ph will return LLNL personnel information on any person in the LLNL9 central "people" database. The format of the command is:+ Ph [-s server] query [RETURN field|ALL]I where query is usually the name of the person about whom you wish to get information.2 query3 Query is a field=string where field may be one of:3 Name, Alias, Email, Phone, Nickname, and Empl_no' If no field is given, name is assumed.2 RETURN= The RETURN keyword is used to specify that only the field orA fields following are to be returned. If RETURN is not specified,& a standard set of fields is returned.3 ALL> The RETURN field of ALL results in all non-blank, unencrypted fields being returned2 serverE An alternate server may be specified in the form ph -s server query.4 e.g. ph -s apple.beta.com rob* richards return all 2 Examples $ Ph oberman ) ----------------------------------------$ name: R Kevin Oberman  phone: 26955! fax: 1 510 422 2495# office_location: Bld.131 Rm.2623A mailcode: 156 department: EE-Engr Serv< email to: oberman@llnl.gov (oberman@icaen.llnl.gov)) ---------------------------------------- $ Ph Jo* Gross) ---------------------------------------- name: John S Gross  phone: 31650" office_location: Bld.131 Rm.2623 mailcode: 156 department: EE-Engr Serv9 email to: gross2@llnl.gov (gross@icaen.llnl.gov)) ---------------------------------------- $ Ph nuckolls jo* return all) ---------------------------------------- alias: nuckolls2% name: John H Nuckolls  phone: 25435% office_location: Bld.111 Rm. 501P mailcode: 001) department: Director Admin Staff pr_account: 9500 empl_no: 659700) ----------------------------------------- $ Ph alias=bailey4 return empl_no pr_account) ---------------------------------------- empl_no: 036950 pr_account: 9704) ----------------------------------------*[PH_CLIENT]PH.OBJ;4+,v.0/ 4006 -0123KPWO156xŲ7  ֲ89GHJ(/PHV1.011-FEB-1993 16:33VAX C V3.2-044PVAX/VMS: ph.c,v 4.10 91/10/15 14:44:00 sandrock-obermanPP8P ph |P P%s is ambiguous. P P%s %s PYou must be logged in to use %s. P%sP%sPreturnP return %s PreturnPemailPtype=P%sP P Pquery type="%s" %s P%s P  P PEnter nameserver alias: *Plogin %s3P%s6PWhoops--the nameserver died. TPEnter nameserver password: pPanswer %s {PWhoops--the nameserver died. Pquit P P Phelp edit P PShall I try again [y/n]? PaliasPpasswordPUse the ``password'' command, not edit.Pquery alias=%s return %s !PDing-dong the server's dead! ?PSYS$SCRATCH:PHXXXXXX.TMPXP;1[P;2^PEDITORePEDIT/TPUnP pPChange the value [y]? PyYnNPIllegal characters were found in your value. PPlease use only printable characters, newlines, and tabs. PThe offending characters were removed. Pchange alias=%s make %s="%s" ;Phelp meCPquery alias=%s return all ^P bP dPThe following things can be changed with "switch": P Paging is %s; use "switch -%c" to turn it %s. PONPOFFPoffPonP Email reformatting is %s; use "switch -%c" to turn it %s. PONPOFFPoff Pon#P Query beautification is %s; use "switch -%c" to turn it %s. bPONePOFFiPoffmPonpP Label printing is %s; use "switch -%c" to turn it %s. PONPOFFPoffPonP Edit confirmation is %s; use "switch -%c" to turn it %s. POFFPONPonPoffP Default entry type is %s; use "switch -%c%s" to %s %s. ;POFF?P name-of-typeNPset it toXPturn it`P"name-of-type"oPoffsP Default field list is %s; use "switch -%c%s" to %s to %s. PdefaultP field1,field2,... Pset itPrevertP"field1,field2,..."PdefaultP The following things cannot be changed with "switch": 0P Connected to server %s at port %d UP The .netrc file was %sread. uPnot zPhelp makePchange alias=%s %sPhelp passwordP P PEnter new password: PType it again: PSorry--passwords didn't match. Pchange alias=%s make password=%s  PThat is an insecure password; please change it. E P---------------------------------------- o Paliasu Pemail{ Pnickname P----------------------------------------  PTT:uPuP P%s/.netrc PHOME Pr P%s %s Pmachine Pph P%s %s Pmachine Plogin C$V_CTYPEDEFS OPTIONLINEPROCESSOPTIONSSETTERMSTRTOKPRINTQRESPONSEDOLOGINDOOTHER DOCOMMANDGETGOOD PRINTRESPONSEDOSWITCH OPENPAGERNOTREGISTEREDLINE EMAILLINE SKIPMACDEFPRINTQRESPONSE ALLDIGITSDOME UPDATEVALUE EDITVALUEDOMAKEDOEDITDOQUITDOQUERYDOHELPDOOTHER DOOTHERWPAGE DOCOMMAND INTERACTIVECOMPLAINABOUTHOSTCOMPLAINABOUTSERVICE ENVOPTIONSGETGOOD PRINTRESPONSEDOID CONTACTQIISSUBMAKESTRPERRORFREEEXITGETPASSMALLOCSTRCHRGETENVSTRTOKGETVALUETOUPPER GETSERVBYNAME GETHOSTBYADDR GETHOSTBYNAMESIGNALFFLUSHSPRINTFPRINTFFPRINTFFSCANFPUTSFPUTSGETSFGETSFGETCFOPEN SOCKET_WRITESTRLENSTRCATSTRCPYPROCESSOPTIONS OPTIONLINESTRCMPCONNECTHTONLBCOPYSTRCPYHTONSSOCKET SOCKET_WRITESTRLENGETUIDATOISTRNCPY SOCKET_READSTRLENSTRNCMPSTRLENSTRCPY SOCKET_WRITESTRLEN SOCKET_WRITESTRLENSTRCPY SOCKET_WRITESTRLEN VETPASSWORD ENCRYPTIT CRYPT_STARTATOI SOCKET_WRITESTRLENSTRCPYSTRCPYSTRCMPISATTYSTRCPYATOI SOCKET_WRITESTRLENSTRCMPSTRCMPREADOPENDELETE LIB$SPAWNCLOSEWRITESTRLENCREATSTRCATSTRCPYMKTEMP SOCKET_WRITESTRLEN SOCKET_WRITESTRLEN OPTIONLINE SOCKET_WRITESTRLEN CRYPT_START SOCKET_WRITESTRLEN ENCRYPTIT VETPASSWORDSTRCMPSTRCPYSTRLENSTRCPYSTRNCMPATOI LIB$FREE_EF SYS$DASSGNSYS$QIOW SYS$ASSIGN LIB$GET_EFTRYLOGIN Ppassword Pmacdef Pmacdef Plogin %s  P  Pnative Phelp %s %s Pph# P%s& Pemail to/ Pemail to8 P@%s = Planl.govF Pemail toO Pemail toX P@%s ] Planl.govf Pemail to:p P (no address registered)  P-%c option given without server hostname.  P-%t option given without entry type.  P-%t option given without field list.  P-%c option given without port number. ( PUnknown option: -%c. > P B P P|Τ^ C$MAIN_ARGS U VTޤ8eeмeߤ< ENVOPTIONSeߤ?STRCMPPdeߤBͬSPRINTFͬC>S> ݮSTRTOKPRRCSB STRTOKPRC߭SPROCESSOPTIONSe ENVOPTIONSݬ׬ݬPROCESSOPTIONSPxPPP CONTACTQIPߤHFPUTS< ~EXITDOIDPǏdP~EXITլ INTERACTIVE1ߤnͬSTRCPYլ/STRCATRPݼͬbѬ ߤuͬb׬լߤwͬSTRCATͬ DOCOMMANDfRߤyRSPRINTFfSTRLENP  f SOCKET_WRITEEXITP^YVSRUSOCKETPPii\PÃÀ GETSERVBYNAMEP @P7fFPRINTFf:FPUTSi~kfFPRINTFi~HTONSP\\TÇTTW\g.\\XW×Ò߭SPRINTF W߭STRCPYSOCKETPTP߭ GETHOSTBYNAMEPP\ݼBCOPY_PUH߭ÖfFPRINTFݏsfFPRINTFݏsHTONLP GETHOSTBYADDRPÚfFPRINTFPTCONNECTP-߭PERRORXUWUúó߭SPRINTF1)PU߭ýfFPRINTFTTв<2P ^ S\cRGETUIDPRSPRINTFcSTRLENP  c SOCKET_WRITEЏ~ PRINTRESPONSE^T<RSd<~GETGOODPMATOIPRѬ R SFPUTSRd<~GETGOODPRPP^R$'ݬߢݬ  SOCKET_READP$P$P@ ޢPP~STRCHRPT1$PPPޢPP~ݬSTRNCPY$ ݬߢݬ  SOCKET_READP$P$P@ ߢSTRCHRPSޢPPSPPPߢ ~STRNCPY SޢPPS((PPP` ( ;ޢPPT  PPPޢPP~ݬSTRNCPY PPP` ޼P`#P`1PP^R\7bFPRINTFb:FPUTSi~kݢFPRINTF^Rݬ–FPRINTFݏsFPRINTF^V WUST RbPUTSd;PRINTFmDOOTHERPfuPUTS SIGNALgwPRINTFeFFLUSHRc\\R\\~RFGETSP\STRLENP\\Rb\  \\R\R\ DOCOMMANDPf1nDOOTHERPf1]|^SݬSTRCPY|STRTOKPT<PVTSTRLENPURb3UTbSTRNCMPPVTÀPRINTF<PRV RbV\ÒSTRTOKPPRÛRRfÔݬSPRINTFզ P`fÜPRINTF Pݬ<PPP ^ SRcPݬ¾PSPRINTFߣSTRLENP   SOCKET_WRITE PRINTRESPONSE ^ SRcPݬPSPRINTFߣSTRLENP   SOCKET_WRITE PRINTRESPONSE^Y X WZUi[}ЬR ޮ Tݮ STRLENPSbSݮRSTRNCMPPRP RbPP:ݬSTRLENPPReRSPRINTFbPb, bRb1i1ЬRޮTݮSTRLENPSbSݮ RSTRNCMPPRP RbPPTJTRޮVݮSTRLENPSbSݮRSTRNCMPPRP RbPRPRRiAЬRnnTnSTRLENPSbSݮRSTRNCMPPRP RbPP0gRݬRSPRINTFgSTRLENPhhgj SOCKET_WRITE1ݬSTRCPYSTRTOKPSSTRTOKPS6gRSRSPRINTFgSTRLENPhhgjs SOCKET_WRITE/PgRݬRSPRINTFgSTRLENPhhgj SOCKET_WRITE PRINTRESPONSEPSPPRINTQRESPONSEPSSR[iRP^ [ ZVYXWRTݬSTRCPY STRTOK STRTOKP?PRINTF<~FGETS<P*ݬSPRINTFjPݬ3PSPRINTFjSTRLENPkkj SOCKET_WRITEf<~GETGOODP6hFPRINTFEXITATOIPSS- gFPUTSSS-1 PPUNTPRINTFgFFLUSHĠuĜu~ PH_CLIENT.SAVv[PH_CLIENT]PH.OBJ;40(SETTERMĐuGETSĤuĜuSETTERM² PUTSĐuUUnn CRYPT_STARTSTRLENP@:STRCHRPP ENCRYPTIT@jPpPSPRINTFjSTRLENPkݫ SOCKET_WRITEf<~GETGOODP{hFPRINTFEXITATOIPSgFPUTSSSw:STRCHRPP STRCPY:  STRCPYSTRLENSTRCMPSTAT SOCKET_WRITESTRLENSTRCMPSTRCPYSTRCATSTRCPYSTRLENSTRCPYHTONSATOISTRCPYSTRLENSTRNCMPSTRLEN |MAIN  CONTACTQI  DOID  PRINTRESPONSE GETGOOD COMPLAINABOUTSERVICE <COMPLAINABOUTHOST t INTERACTIVE | DOCOMMAND l DOOTHERWPAGE  DOOTHER  DOQUERY DOLOGINSTRCHR`nUUSTRLENP(UQaaPPP@iP PQaPPh FPUTS  P`SPP^RDOOTHEREXIT^WRSŸݬSTRTOK£STRTOKPV§ DOCOMMAND<P²STRTOKPT TVTGETVALUEPU1U EDITVALUEP1UVT UPDATEVALUEPSяSaSXPISATTYPI¶PRINTFg ߭FGETSꑭyY"UVT UPDATEVALUEPSяS SS, VSTRCMPPU STRCPYSP^ ZVWXSYݬSTRCMPPPUTSPjRݬݬRSPRINTFjSTRLENP  j SOCKET_WRITE,Rb,Tf<~GETGOODP!gFPRINTFEXITATOIPUU81:::STRCHRRbPPbPPbP~TSTRCPYUhFPUTSTSTRLENPT1gPU hFPUTSUT,TTPP^WTV?߭؞SSTRCPYRb߭MKTEMPPUU߭bU߭bX߭STRCAT[߭STRCATUCREATPR UPERRORPݬSTRLENPݬRWRITEPUPERRORRCLOSEPRCLOSE^GETENVPReRR`STRCPYn`STRCATU`STRCAT`STRLENP` LIB$SPAWNPRR߭DELETEREXIT0pPRINTFGETS~ćSTRCHRPUOPENPS UPERRORP<~>SREADPR)UR PH main ContactQI DoId` PrintResponseGetGoodYComplainAboutServiceD<ComplainAboutHost8t Interactive DoCommandl DoOtherWPageXDoOtherX DoQuery DoLogin DoQuit# DoEdit+GetValueaP EditValuePERRORSCLOSE߭DELETE߭DELETEPSCLOSE߭DELETE߭DELETEB>R RyRYݬ>STRCMPPPUЬQ>P`\P`SS"\QRQ"b=PS  S~S+S  \tS PRb\nUP`aU"gČFPUTSRbgĺbgb2P ^ SRcPݬ ݬݬPSPRINTFcSTRLENP  ߣ SOCKET_WRITE PRINTRESPONSE^ TR P` ;DOHELPdP CPSPRINTFdSTRLENP  d SOCKET_WRITE PRINTRESPONSEPS |~PRINTQRESPONSEPSSP^T^ݬSTRTOKPbSTRTOKPUGeCS> USTRTOKPRPRCSB STRTOKPRC߭SPROCESSOPTIONSPRR1dPRINTFXhS UPUUS MRPmRR~S SPSSęhS UPUUS RRPrRR~S SPSShS mUPiUUS BRPbRR~S eSPbSS#hS ĴUPİUUS LRPlRR~S ĬSPĩSSphS UPUUS cRPCRR~S SPSSķhQ oWP`WWQ XVPNVVQ MUP?UUQ TRPtRR~QQS;SShQ WPWWQ VPVVQ UPĸUUQ FRPfRR~QQSİSSshh0huRtRRUh<P^ SR<T P` zDOHELPJcPݬ „PSPRINTFcSTRLENP  c SOCKET_WRITE PRINTRESPONSEPTTPP^ Y XUSRi ×DOHELPåݬSTRTOKéSTRTOKPWiWíPRINTFFFLUSH uœuSETTERMuGETS¤uœuSETTERMò PUTSu߭STRCPY<PPRINTFFFLUSH uœuSETTERMuGETS¤uœuSETTERMò PUTSuV߭VSTRCMPPFPRINTF<PVTTSTRLENP+TQaPaPPP@eP PQaPP FPUTSV߭ ENCRYPTIT@hP߭WPSPRINTFhSTRLENP  h SOCKET_WRITE PRINTRESPONSEPTTiWSTRCMPP V CRYPT_STARTTPP^ P`DOOTHER ^RSݬSTRLENP+ЬQaPaPPP@bP PQaPP FPUTS^RЬP``QQQAbPP`2P^T<WԮYVSPRb`cԬ<~GETGOODP1ATOISTRCHRUFPUTSXSTRNCMPZSTRCPY[ PWWf1W8W W W1z:ePP PSSfVNOTREGISTEREDLINE<5 EMAILLINEV::ePPePPhRbVE hSYլ1::ePPePRbb PRbb Ro jPYk1jPRu jPkY1HR{ jPYk1)b:Y1Y.լ)V:::ePPePPeP~h5PV::ePPePPhPW VhW1VNOTREGISTEREDLINE1P1 EMAILLINE8լ3V:::ߞSTRCHRRbPPbPPbP~FPUTSKPV::STRCHRPPSTRCHRPPFPUTS P<~GETGOODP1gծ VĄ FPUTSWP^Tլ ČuPЬPPRPČuRRSc+c~ݬSTRCHRPPScc~ݬSTRCHRPcISRb)b~ݬSTRCHRPRbb~ݬSTRCHRPb bRRČuPČuSPP(^Rڐܐ® ߭ LIB$GET_EFP|~? SYS$ASSIGNPмPP PPPռPPTмT|~|~ |~'2~ݭ SYS$QIOWPSS 2PP2~ SYS$DASSGNSPTˏSȼSSˏSҼPSSSPSS|~|~ |~#2~ݭ SYS$QIOWPS2~ SYS$DASSGN߭ LIB$FREE_EFSSP2P ^SRݬPRINTFFFLUSH uœuSETTERMuGETS¤uœuSETTERMò PUTSuP^U|WŽ GETENVPų SPRINTFSTATPff ЬPРSSPPPRSRRf׬1 ~Ŋ 1PЬTdP0jj SSPPPRSRRj1Ѭ>jj ЬPРSSPPPRSRRj׬֮1u~ŵ DOQUIT DOEDIT GETVALUE P EDITVALUE  UPDATEVALUE hDOME DOSWITCH DOMAKE  DOPASSWORD DOLOGOUT  VETPASSWORD  ALLDIGITS 0PRINTQRESPONSE `STRTOK SETTERM 4 GETPASS  DOAUTOLOGIN d# SKIPMACDEF # TRYLOGIN $DOHELP $| EMAILLINE P&<NOTREGISTEREDLINE 'PROCESSOPTIONS 1QPЬTdP0ii SSPPPRSRRi1 Ѭ>ii ЬPРSSPPPRSRRi׬֮1~ 1Pii i1jj j1ЬScPPPP@c~PPtѬ6УRbPPP@!RPP׬S֮9~ ޼R~( ЬP`1x׬֮լ ޼R-1LP^TЬRbS> ݬSTRTOKPRPRCSB STRTOKPRCͬͬS'ProcessOptionsDH+ OptionLine\+ OpenPager +makestr/ +issub>$, EnvOptions <   1PROCESSOPTIONS^PP^ݬSTRLENPPMALLOCPR ݬRSTRCPYRP ^ެScSTRLENPR!PRcݬSTRNCMPPЬP֬PP|X^VUЬR\Sb0PbTTPPP@fT~TOUPPERPQTQQcRSbҔc\GETENVPTAd=S> TSTRTOKPRRCSB STRTOKPRC߭SPROCESSOPTIONS'PTTTTTTTTTT|TTTTTTTTTTTTTTTTTTTTTTTtPDOHELPP l!T H+ OPTIONLINE + OPENPAGER +MAKESTR + ISSUB $,| ENVOPTIONS C$MAIN_ARGS,$CODEu$DATAF $CHAR_STRING_CONSTANTSSTDINSTDOUTSTDERR_CTYPE_TOQIFROMQITOQIBUFTOQILENMYALIASME MYPASSWORDNONETRCUSEHOSTUSEPORT NOREFORMATNOPAGER NOBEAUTIFYNOLABELSCONFIRMDEFTYPE< RETURNFIELDS COMMANDTABLELASTCODEDOHELP PDOQUERY,PDOQUERY8PDOMEDPDOEDITPPDOMAKE\P DOOTHERWPAGEhPDOSWITCHtPDOOTHERPDOOTHERPDOOTHERPDOQUITPDOQUITPDOQUITE EMAILLINEV::ePPePPhRbVE hSYլ1::ePPePRbb PRbb Ro jPYk1jPRu jPkY1HR{ jPYk1)b:Y1Y.լ)V:::ePPePPeP~h5PV::ePPePPhPW VhW1VNOTREGISTEREDLINE1P1 EMAILLINE8լ3*[PH_CLIENT]PROTOCOL.TXT;1+,P./ 4(-0123KPWO56to7P p89GHJ0o NNaammeesseerrvveerr SSeerrvveerr--CClliieenntt LLaanngguuaaggee( by Steven Dorner- Computing Services Office+ University of Illinois# 6/1/89$IInnttrroodduuccttiioonnNThe language (or _p_r_o_t_o_c_o_l, if you prefer) used between the CSOANameserver and its clients is meant to be relatively easy to gen->erate and to parse, so that it can be used by programs. It is<also meant to be not too onerous for use by humans directly.(GGeenneerraall FFoorrmmaattAThe general format of the language is a request/response language?like that of FTP. The conversation is in netascii, with a car-<riage return-linefeed pair separating the lines. The client?makes requests, and the server responds to them. This allows aL_t_e_l_n_e_t client to connect to the Nameserver so that users may use<the Nameserver without any intervening client, if they wish.?A request begins with a keyword, and may have zero or more key-Awords or values, separated by spaces, tabs, or newlines, and fol-<lowed by a carriage return-linefeed pair. Values containingHspaces, tabs or newlines should be enclosed in _d_o_u_b_l_e quotesA(``"''). Any printable characters may be used in the string (ex-=cept ``"''). In addition, the sequences ``0' and ``'' may be+used to mean newline and tab, respectively.7Like FTP, numerical values will be used to indicate the<NameServer's response to requests. Unlike FTP, data will be:passed on the same connection as commands. The format forresponses will be as follows:5 _n_u_m_b_e_r:_r_e_s_p_o_n_s_e?Multiline responses should preface the number with a minus sign2(``-'') on all lines of the response but the last.ANotice that since more than one specific piece of information may@be manipulated by a particular command, it is possible for parts>of a command to succeed, while other parts of the same command@fail. This will be handled as a single continued response, with?the result code changing as appropriate. Also, if a particularAfield in the request is objectionable, that field should be iden-Atified after the colon following the result code. The field name>should be separated by a colon from the text of the error mes->sage. The text of the message is primarily for human consump-0tion, and may vary from the examples given here.=As for FTP, numerical responses will be in the range 100-599,7where the leading digit has the following significance: 1: In progress 2: Success 3: More information needed 4: Temporary failure 5: Permanent failure=Specific numbers have meanings to some commands; all commandsobey the general scheme.=In practice, almost every command will generate more than one>line of response; every client should be prepared to deal with@such continued responses. It is worthwhile to note that no com-@mand is finished unless the result code (treated as a signed in-'teger) is greater than or equal to 200."TThhee CCoommmmaannddssrqquueerryy [[ffiieelldd==]]vvaalluuee...... [[rreettuurrnn ffiieelldd......]]? This is the basic client request. It does not require (in> the common case) any identification from the client. En-A tries whose fields match the given values will be found, andA the requested fields printed. If no query fields are speci-> fied, the name field is assumed. If no return fields are= specified, default fields will be returned. Fields fromA each entry will be prefaced with a sequence number, a colon,' the field name, and another colon.@ Note that to view some sensitive fields, it is necessary toA login to the Nameserver. Values containing newlines will be9 broken into lines and printed one line per response. Examples: qquueerryy nnaammee==ddoorrnneerr pphhoonnee==33--33333399 rreettuurrnn aalliiaass 200:1:alias:sdornerA qquueerryy aalliiaass==ssddoorrnneerr# -200:1:name:Steven Dorner -200:1:alias:sdorner -200:1:phone:333-3339 200:1:address:189 DCL+ 200:1:address:1304 W. Springfieldr qquueerryy ddoorrnneerr rreettuurrnn aalliiaass ""hhoommee pphhoonnee"" 200-:1:alias:adorner6 -508:1:home phone:This field is not present.$ -200:2:alias:anotherdorner$ -200:2:home phone:555-1212 -200:3:alias:sdorner5 508:3:home phone:This field is not present.g qquueerryy aalliiaass==ssddoorrnneerr rreettuurrnn uunniivviiddA 503:univid:You are not authorized for this information. qquueerryy nnaammee==ddoorrnneerr ""vvmmss lloovvee""==hhiigghh rreettuurrnn aalliiaass 501:No matches.{cchhaannggee [[ffiieelldd==]]vvaalluuee...... mmaakkee ffiieelldd==vvaalluuee......A Change looks much like query. The entries to be changed are< specified as in query. They keyword make separates the= search criteria from the fields to be changed. The user@ must be logged in for change to work, and must have the au-@ thority to change the fields in the entries selected by the> query portion. If it is desired delete a field, AdjacentE double quotes (``""'') should be used. Fields marked _e_n_-G _c_r_y_p_t_e_d must be encrypted before transmission to the? Nameserver. This encryption should be done with the pass- word of the logged in user. Examples: cchhaannggee aalliiaass==ssddoorrnneerr mmaakkee aalliiaass==ddrrddeeaatthh eemmaaiill==uuxxqq 200:Oky cchhaannggee aalliiaass==ssddoorrnneerr mmaakkee aalliiaass==ddrrddeeaatthh( 506:change: must be logged in.h cchhaannggee sstteevveenn ddoorrnneerr mmaakkee hhoouurrss=="""" 200:Okr cchhaannggee nnaammee==iikkeennbbeerrrryy pphhoonnee==333333--333333996 510:ikenberry:You may not change this entry.llooggiinn aalliiaassaannsswweerr ccooddee> This is used to identify the user of a particular connec-@ tion. The NameServer will respond with a random challenge,> which must be returned in encrypted form. The encryption@ key will be a password known to both the NameServer and the? user (or user's trusted host). Note that this scheme pre-? cludes the use of login through a direct telnet connection7 (unless the user is very good at encrypting text). Examples:2 llooggiinn ss__ddoorrnneerr" 301:dkeiigjasdvvnmnmeighY aannsswweerr eewwiittuueeggnnddvvbbnnggkkggddffkkggll 200:Hello s_dorner!2 llooggiinn ss__ddoorrnneerr& 301:eiituerwbfncvkfdk;efdgi;Y aannsswweerr eewwiittuueeggnnddvvbbnnggkkggddffkkggll 500:Die, hacker scum!llooggoouuttA Any user identity established with a previous login will be7 forgotten. The connection is not closed, however. Examples: llooggoouutt 200:Ok1ffiieellddss [[ffiieelldd......]]? With no arguments, echoes the contents of the NameServer's> fields.config file. Otherwise, descriptions of the named fields are given. Examples: ffiieellddss) 200:4aadddd ffiieelldd==vvaalluuee......A Creates a nameserver entry with the given fields. Only cer-7 tain users will be allowed to execute this command Examples:z aadddd nnaammee==""ddoorrnneerr sstteevveenn cc"" aalliiaass==ssddoorrnneerr 200:Ok.; aadddd aalliiaass==ssddoorrnneerr- 509:"sdorner":Alias already in use.; aadddd aalliiaass==ccddoorrnneerr4 511:You are not authorized to add entries.Cddeelleettee [[ffiieelldd==]]vvaalluuee......A Deletes one or more nameserver entries. Most people may not% delete (even their own) entries. Examples:D ddeelleettee aalliiaass==ssddoorrnneerr 200:Ok.D ddeelleettee aalliiaass==ssddoorrnneerr. 513:sdorner:You may not delete this.=sseett ooppttiioonn[[==vvaalluuee]]......0 Sets an option for this nameserver session. Examples:/ sseett tteerrssee==ooffff 200:Ok., sseett mmaaxx==22000000& 512:max:Value out of bounds. qquuiitt Ends a nameserver session. Examples: qquuiitt 200:Bye!- Appendix A-Command Summaryrqquueerryy [[ffiieelldd==]]vvaalluuee...... [[rreettuurrnn ffiieelldd......]]{cchhaannggee [[ffiieelldd==]]vvaalluuee...... mmaakkee ffiieelldd==vvaalluuee......llooggiinn aalliiaassaannsswweerr ccooddeellooggoouutt1ffiieellddss [[ffiieelldd......]]4aadddd ffiieelldd==vvaalluuee......Cddeelleettee [[ffiieelldd==]]vvaalluuee......=sseett ooppttiioonn[[==vvaalluuee]]...... qquuiitt, Appendix B-Result Codes% 100 In progress (general).' 101 Echo of current command.! 200 Success (general).- 201 Database ready, but read only.* 300 More information (general).# 301 Encrypt this string.) 400 Temporary error (general).) 500 Permanent error (general).# 501 No matches to query.) 502 Too many matches to query.8 503 Not authorized for requested information.< 504 Not authorized for requested search criteria.8 505 Not authorized to change requested field.2 506 Request refused; must be encrypted.$ 507 Field does not exist.7 508 Field is not present in requested entry.$ 509 Alias already in use.3 510 Not authorized to change this entry.- 511 Not authorized to add entries. 512 Illegal value. 513 Unknown option. 514 Unknown command.) 515 No indexed field in query., 516 No authorization for request.> 517 Operation failed because database is read only.; 518 Too many entries selected by change command. 599 Syntax error.*[PH_CLIENT]REPLIES.H;1+,./ 4I-0123KPWO56pz7{89GHJ I/***********************************************************************/F/*********************************************************************>* This software is Copyright (C) 1988 by Steven Dorner and theA* University of Illinois Board of Trustees. No warranties of any>* kind are expressed or implied. No support will be provided.A* This software may not be redistributed for commercial purposes.8* You may direct questions to dorner@garcon.cso.uiuc.eduG**********************************************************************/#ifndef REPLIES_H#define REPLIES_HH/*********************************************************************** * Reply codesH***********************************************************************/)#define LR_PROGRESS 100 /* in progress */&#define LR_ECHO 101 /* echoing cmd */?#define LR_NUMRET 102 /* how many entries are being returned */ #define LR_OK 200 /* success */;#define LR_RONLY 201 /* database ready in read only mode */)#define LR_MORE 300 /* need more info */.#define LR_LOGIN 301 /* encrypt this string */*#define LR_TEMP 400 /* temporary error */@#define LR_INTERNAL 401 /* database error, possibly temporary */B#define LR_LOCK 402 /* lock not obtained within timeout period */.#define LR_ERROR 500 /* hard error; general */2#define LR_NOMATCH 501 /* no matches to request */8#define LR_TOOMANY 502 /* too many matches to request */1#define LR_AINFO 503 /* may not see that field */9#define LR_ASEARCH 504 /* may not search on that field */1#define LR_ACHANGE 505 /* may not change field */-#define LR_NOTLOG 506 /* must be logged in */(#define LR_FIELD 507 /* field unknown */6#define LR_ABSENT 508 /* field not present in entry */<#define LR_ALIAS 509 /* requested alias is already in use */0#define LR_AENTRY 510 /* may not change entry */-#define LR_ADD 511 /* may not add entries */(#define LR_VALUE 512 /* illegal value */*#define LR_OPTION 513 /* unknown option */,#define LR_UNKNOWN 514 /* unknown command */:#define LR_NOKEY 515 /* no indexed field found in query */7#define LR_AUTH 516 /* no authorization for request */E#define LR_READONLY 517 /* operation failed; database is read-only */?#define LR_LIMIT 518 /* too many entries selected for change */C#define LR_HISTORY 519 /* history substitution failed (obsolete) */,#define LR_XCPU 520 /* too much cpu used */?#define LR_ADDONLY 521 /* addonly option set and change command& applied to a field with data */<#define LR_ISCRYPT 522 /* attempt to view encrypted field */B#define LR_NOANSWER 523 /* "answer" was expected but not gotten */(#define LR_SYNTAX 599 /* syntax error */#endif*[PH_CLIENT]TERMDEFS.H;1+,./ 4Tb-0123KPWO56{7{89GHJ /* termdefs.h *H * contains definitions required for use of functions which sense or set2 * terminal characteristics (contained in TERMLIB) *, * V1.0 19-jul-84 P. Schleifer Initial draft *9 * no privileges are needed to run any routine in TERMLIB */ #define OFF 0 #define ON 1#define BROADCAST TT$M_NOBRDCST#define ECHO TT$M_NOECHO#define EIGHTBIT TT$M_EIGHTBIT#define FORMFEEDS TT$M_MECHFORM#define HOSTSYNC TT$M_HOSTSYNC#define PASSALL TT$M_PASSALL#define READSYNC TT$M_READSYNC#define TABS TT$M_MECHTAB #define TYPEAHEAD TT$M_NOTYPEAHD/* termmode.h *T * header file for modules in termlib - setting and sensing terminal characteristics *, * V1.0 19-jul-84 P. Schleifer Initial draft */ /* iosb.h *$ * structs for VMS I/O status blocks *, * V1.0 10-jul-84 P. Schleifer Initial draft *//* general I/O status block */typedef struct iosb_struct {, short status; /* I/O completion status */9 short transfer_count; /* # bytes actually transfo~ PH_CLIENT.SAV[PH_CLIENT]TERMDEFS.H;1Tered */; long device_dependent_data; /* device dependent data... */ } iosb;/* terminal read iosb */struct term_read_iosb {, short status; /* I/O completion status */ short offset_to_terminator; short terminator; short terminator_size;};/* terminal write iosb */struct term_write_iosb { short status; short byte_count; short line_count; unsigned char column_position; unsigned char line_position;};!/* iosb for IO$_SENSE(SET)MODE */struct mode_iosb { int stat:16; unsigned xmit_speed:8; unsigned recv_speed:8; unsigned cr_fill:8; unsigned lf_fill:8; unsigned parity_flgs:8; unsigned fill:8;};struct char_buff { unsigned class:8; unsigned type:8; unsigned buffer_size:16; unsigned basic_char:24; unsigned page_len:8; unsigned long extended_char;};xn ~ PH_CLIENT.SAVS>] vpy;1_:G{[ DPdiTOE H>_[؜C8pw*i5O?o>޻\YCyD z/j2D`de%#%76KBRѮ1h4] 2H?EuIc_C6A{p[UJ (WO}CӢד;^OD6)NhN'l&TCCrAFPkw!hy7Ӆ/ξ"Miabw:4Nea T@Q;sդ9ԥAR^"bu;qӎȓ rsEoCtnirj0~NSXw f~2ӀR/F+JiAaA:%?s5*e~lE''/G{ղH=DP, ki6q)PNr8Cfnǀ(mm-$|ڤ.mOf*-ܷk ʅA0r'A)ioYͫq˟y !Ѫok`"\`.F;s( AaNK1Ҵғ09/9 " {҂G,TwWc c_TCY9:vSģ⿏v> _=*D{6u>zmV|LD%9Ԉo 'BJW@6jSQM @XJߔ-.Y)'^(4W NH禎Inb;%nȐyo47ԸwSg f&Weu4>lS p |[ ;LYf!Yj1S 1w[V*뗛ӟI g BWaeorHM!w\i7,ip,І8S; aqp Z;H$or6+2:uYU.'+{7_q қP'gn+$w4CeKkeu7 WȊ(mezeVe`m-˚əOR:PA# _j݁ @DM>A+Ga4*acH]s3lx}8șwm pM6-CMжy?7Gwl!}^cqdl 1VHs>'`SOO˨$60p@`^b9m9,pA 1K +_Uqwد1oXש+NDiP`8̴8;&qyc(TU{ +lm,O'>~bF6Ibˮezm8SsDHqi %k#sMKƛc0"2ң])q{W5zR`;~AD pLؼ^| y6A0 0\qƳQa L%3kՃql`Y$o"5x j֭Oy*&h8$:x2wsb`ouuVTZܼ;eSԠ9G% }Ug{T;3[0ro9 0z`^yF=Ý4~qv ô=H4E K2O^lARdѳt)kъxW^{VbW"w;}$YB7 +077"OڥXc߶tbG_Fi!qruE3s?Mu4l_ sǬ:R =!944ش;zvbyy">lig@)˟y` 7x+"z܋^*T1;uWQ-f9x3yk")n c&F ~q<8H ׊ [1"aN #1J||n$0m΋&dڨ;{CD"tX>aDYƥqoN@wxZ#Бb[!zL(`+˕H.0Z ``IYOB}/-~Xxp0V eǀi2 D%LSlXE <8A lyMd{A gbՀbfk07AGuSۍ8&)^k4d耂W1sl3NNn0/}]D`ZkVm=bo/kNt]:,#sTܿ.#>,*q7(^VmW#~ hq X~ v!w\oYXٗo*lJ0ދVyw\/`i1B;ibod!yjb@]yZ"<ˢk4w9F4$x$ #O!1aWlo00`|*^c:Z7Eol0*hnBtRq2!W|M_#@ԛL #4\Ses=)P~EDgq-ޮtA 8fc$jm;3/ Euc_A56;Рzf=[m6Iquw ˖Q` K3 ' L h#$y4aPPc<AH@ dT{N˘ྶ/N8ySb}G?,uxHiKi V'I8Ɂ;@&ݤ[sEQuS`Lc̫>Y|Ds2d}$-ʕG+'LmG!t-H¦zaNLm$VXo5?7wUnW=)G6: vֹ_R!EA)|fà4s+'Fs|D;(=:c+ZDmߧqL»}`*uAsr_lQID[OSt̗e!th|?sZ%0ۏ뒂!6leAץ$'W}-8b >&Y XOl,n9VR!m1WHQɬy!!MϨse@$nϜٛ BwԸG-G;z)x"ٷ+o59Ar/MFtqFzM&TPo[3oiG%QD4sYEFّWM}(LH&bԉs[lOK_j>1M2̾gPLq2JP$en@Bh5{WXc0LbX^]!Ha T ٹ V$_I/s<:KQƅCX3"_cޘ0W^H&Ӷ"fTSDt/d3se͸h[nޜiו51bQd J  U:z;O!Մ ]lCnCƄ;2C#ÒK2DWIR`/C4Ӡ"X$ T'ZS͑9ء t=3 TCz&A6r]d?[*Iґh):AjF+D`֐tlx+̒_G"FD}Y4 aUR+ LP"V\bu^mlyXL~DS܁5al,Z`vj/JA /c#\D Feǰ7Tz!9Mx$^_$4Cԏ})AФ2n2?ؼ!6qSH}QO*_{(񣟧` c{!LUk)AGjݫ\ iAuR:eפDtH{'>Y s/XB\ r:}F/a R rO%'=,_i?[)8%q=nEhp ޲cAw@D\x#bGCma? 1 GNJ.ʹS(FW_V KY_i[_3_{LV+䰟;%XY/@*:V4mB_{ B>2 .aUQ򻞌BdD:$o.X1yȓR4{N@|k$$'i*>l;:E.  ?.8õ.S[i4")R:ť 2Uˤ6e:DzIC] `=ieN{Yx`J2\* R3 ָFi2Q b W>nν833Sl]>wo ->}WPW. h&fr*`-c0Q2-Y^6R ^RN==-"8JV!vbEM$ -x+%MY p`I3̬mb;6{v޾ǹge/(?4gvdΥ-u؜9cBΆ/*kGH'sX]r 2-E^Z䯮=įe|nfB>@6 +jT[I5BCcHFcX6T]k A|?J"p~&~X$g`! %:Mwy-f[s_ZRo=A %CO;IE{NUQ*}*q _7&gx&X{!Qq Ig[<"&u^0ZKj PcK(]v]LHXo3na -)UC@rtڮ cUaIg|%]J;MBߑ);'e#qct#g7+@J@3{˥bdd"7wB]CaY&oq֣tRһx_<4Ncv+^k%LL 1 Q9R _64 œ/VldQ %Qn ~(kmWNaNf ?WG?b6Ҫ_tTrVs$_th)zQGDܨT߇f& ~6C];[4V[jG^;},l' JUӲ7Ϛ2t׀}|pR67d_& 6UoIF^ɱ>8LFEH^!_yrXDL@Y߲RC9Xa%TZ[%L7,bx3I%֙wqu^ N%T5.cu 'jE.IcQ/6(& N+s3ϲ+5tg6;jpGD4هwotlYA[<YD#=r?,1 et7.pڞʝ%A,TXdWl~"-Гminvak4PD\;: i'zveǣy^ 3^ۂ a:<lm2y3:}g@ (. oObAJQHգϿ=-*헥5D[填$E0lR#>#;&>:jlW9xDm@:PB{y@(_<6 nxE;Zd5A|z;_UKd6]&B(}E)\Ɲ01a|mPmeaGKbWo%"*ˉȏ2uΰpq^=<7 jE;F͖g٧Džm%,!QEnL HȢZ*VDYWaI*C&6;2^W6\eF95D/8F VE |Z6"39kH1ܯ;]`mOҠZ ;觴sS9bqh=35Dtrv Tu,A9RD@Y>rI&:$j#yTe ։:;=:)hX?;ĥc0ktZckLh1C;O2}m,=nZ5$rVimuf!:,xmRr.ēx?]%mƥu3\4 贞By8}r]%!|Q#D%o5#|x퍶 `;?~X3V؜KMbf{,X.mx߇RrD/]*Id"t|0!MГ&Ӎfq4M R{a@CG@k2$!q|[Q4g~Qh "ʫfbd 2#~&kH?=AmmXpLBVzלFhY3!BǠWF. (HU?EL!<' WqH]:D6Fw$i7 gc-v'zI6-1@1`;bf`d+zf1~8 p!9T};%*R +`Ffj3ըڒqqFq ]`g,f8YKkfFf܎l3ݓjqWۈVMc&6(9Ç7 ;tᆚѕOhDj}-%ujF>MhEsfM&CX_Gowⰿ2t'ʒނR a*yR۴wJ_=-PʹAp_Pж)Lcea2_tuAE.K3c×MqZ%MFUKkb@>ڐ4GgJrJۤ-̡שX=V~;^ ,K=୙q.|1!i6#d;G]Tw* j !#tOSB~mF> Wze,Unq-.e3EV)?]w78sN!ԬuQ\>50q`ӑ V(hiF‘s9+u Xp3pqHL2J9ϗjIObW8VJ6$X0qZwЅ=DA۷w!9>Ul;(O>}ѳi`(+T NB/AdԽݳ-[*cTwG\olȢNH 18A# _j<Y 7qU|Fڶzi$KAvMZhB5h_fbP6r}C7+gx!*KQά@JfqT^ )]uDO4"_Xn<p-J jfb1.HaC֥B:}3<ԁJmޖi:Zm̟q{Av͈5.s=JТa ""?QƼSy.)uVB`(0ݐpIT&2ğ!eY:ᾧeqa@+4=W|ߨvIzZHL%om8z}xyŒ!H'Gw(2 6Í4K>eO*Z9n{8K^_ $P:@$ 2^v4gswգa"4DhaЬyaMnwl;]H04AU8n~0)#uzO+AuR5ʘnɜc5$Sٷlz_pw\FOShl iH,$&Q :<̿4U&/Ob{2:vu݃'P) D"1,t\IK)g5)R7@]+QU?K7^ooxxK mY-w &•PS+Ϥ[uFʙ}YP+J8@cuFks嬐{מ{_+6'I !_\qr{(849>4ɢ ;/ (+7^-'IɄxm)⭘@[GϐB.l@k?c4;R&n;gQ:LGcCrpqwYl@mSI'mKn~~ kFR&Yq)sksrɤ3/ )hIObolrc{g/}nC>g0si725{!.$1`i~L(#r[1X;dt5G-4Az#05CxE%o6Uj$Z+]mcB +SthdB4G>"zjbrstTsZ`| =f;j~Lx,+ ?*$w- 6yٰtL}РvX aBhFxuL xQleP1xj:(|P~ C'bаYѸ4(%K&)0kEk*14` oWSIC=~z&e/K'SRHt&lZ* +cA|зKC1<"P&<v{)I?&l 58_ 26Ic'd@vHQFpF`x^}. )tHO0x+ G[_?WKnZ0FG Y7]G &|M{HM.N_}HLBmKMD$uxuwI5Jw#p| s0 &)YH/qL3|S!C1V`q={Nͤb(l7)KjiD^ls2 uw'|A=9iVu"A3_᧾>$|O Recz,e<&)/bn7\Ywt5LU^,m.<|i|Y&)Gwr2tr??%8nKCQJ+P4G <6aG'L=$A`YPgo+2*W2a*Ee2N}a?8&vJ:}v;k@G[T+'lK5?C-T UpmrTF:gi[SM0 O͙"#0[ ]A# B!_D> f;`{**;H"\NIZoD7WMdHdQ i=3??) .WEn/KɧVEV3NU5 ht&g#;$ 3d3GS@~&U?+{hgX,8UYe]Q VGUDb8"^oq>JX'O. l]:$G_t ^j^ %oa60#*hDNs6Y`^Kx^ oc5ih{YJVdgJ_vX^*`ov"!v%oJ\%96r(Sp28j4#Y5 6]0AhEg;%9V`Mpg?&uYZu?Qc4d*ƀ svVZ_H]XoZԺO&*[wle=-x <љRw))}B5%]#"8KՄW;(_O(l*_#6('n{80djc9zdznSuOƚImٙTq&Cqݗq:gׇ֘ukc. q,&ԪQY.< |c<:@s'0V*r*t{{g7ȕ ڃ9j&s(v~ ꮠhTlx)XHK,D缝01+E >u8%] ub:6U@,MQn9]ʧvi4x4~*ɿ+?WkN2goWɗ+!v%1chls"d;~35,O,Y zeР}㠘hwe;V -nu"?LKikÂl*7Hw::՝2wtkb00Um2'Dzldn LR3Õ52؋jBLgKa^v jaIxt ڦ2AMHB_$|hn2]PRZ:G6u<r͘{7sv`ubi;h؃xɉ- "tk4_a+'.={P .;8EOc4[.'n4r۬X]ʿD2v,v}]ҿﹷI9m s,n57U;ʛi^MD'1v~~!|VHcve-6`--99g5¼gt"OPL )kgGSuZ&HI‰kϪ",ڐ\QCX君Mf*Ŷ'NԐu>7xa@@쨾Ub6OO7$N/7jJ넍!Ag< ,ebӂt~lP͑9oom-:P <׺:=lN-a¹ᵜ9Ha ܺ5+48κ łth `m(p"ͱoBT^JSe*7yzuoq.ϙzؔx~RW~.׵j_BLDkJA+3+'"!s`O0pxݏ!*m ߉΄50l ִ-;%VMU D=96;z(:_%WMOKtCi+lr3} er2$tH+190(*-%^>-&C]<:i2M=5P'gYۦs5QmoJbe*` /$}lk SGJ s ;M3F6n b\T%wN\`@{E 05 vPc{0)OI]&pT)aiTRk+QkS1?A}-P|X,Cl z>uynRPiQ3M.Gº&iL% 'J|5hľϢҼ,cYϭM*dנѪ/|ӔMjt5Bt`b$ 0Šw.ĬpEcc2yᕆ bD o6v*6Gd&/f߹ca\>]uyeo)&!RcLGmA;;<%-)$uX{UC#KTwJ*~kaXQ)w< >֌Ԛnm5C2#M=V[峸O$F5=*ֽSiim3,{W1 q[d4iэҰ󻘊K#nǰڑ͐ۂޭHHSiv/HUU~iq,O>%_Osa,,h$,B{H!jO@s)/h~j{l?9<["%|($P'5#}u5 Rl^O;;-N}XS;eujU1F9g''0o-Ha~, kBP3A"RA[9/v`,a~U%.yY ^VF{2$,s0kg; a5|&csxjgRr;xiK"j2$Xn(h2` 3f R)-;0"~hKE5qsqj C6*&1DF1D19GtS1&-:*W0~]5NDw[lYhG9N>>.$|{aKW@qXx9z //|Hj ER"RSLHax.&YxBWAC_+C#Yx/u>Z V&ay!Wt<3TK(B(5] Q5cv M7bZLPBnJiyn!ZdmBL[htjl<+l9fAMcPDzkNZG#S_FyZ;}/}]'0p}nCz*(IP f~g#l\V"n|L0Z_^jY=oImjy eEPd 6Jl`tx q|{Ed))z2LWMOEA!s.Ov>T-8[SpDey>\( %nyB$1x4V$ GE2 {J:.dXo I0*e$\IQ%0 BI\]AD1cPir(nM vkA:wI;VcIi\(-W^XRI|/e\ k(]0( CETC} ORNTOX gC Q'E OSHO|JEOLj~^H] fXHT=hO-]( p  nGa*te UUx?F zo)L8GRF2x}VfOUMDB'O \5hZKn,SMu .iUt'RJS_[aW(\N1Sj b&X!~tnwnB9o6KMcI14]es|_yK;WLRINVnYQw0STj Y{ CQPS!6GN!i`dUY<T5LTIuX|+~HasYdJeR_{9rfg_HinQ.xlb B_#&`JU^G|~f5R=2{Ug8E8>(y?F(,/=_hF>\a%X!(pg~OGt894J<&hBE#{ 3B7`f4 K-1ibUvOHN>nKDc BLm- :zH)H2(DRp_rh+g6xzbv5'8LzdV0*t{2"DcW="~ au$CmsW,f2x;"^TGIP !Q4-mx^EiU rUNXgauwwb %'^R&X|+=OyhIMtJG yLCC=|4VF @*M`>jiJ8bDhM}Z{jOnK%HVG | NLZ6 y9mTJIQ?O]0(Y]'WQ$y~TmNj9 ]:)n cyJ&W}@,dcm82\ ZoL_ZSzD_"qrGOGBMM#dk7j?(rtfq)? 3 *JZ;FX"[]`Xd hA FKe QPUJDFko5Z0kI,@"P`71OT, hf]X ]|:ZV I $H^%YW `5i[Ot+H BYje5/]JhH#DEX1eiYD#h_T.#IVseHR.fg vrk h.l@e8KA !+WTKx6'>1@iXLca@Rrs3ix.UAvbz_a$ ;vM5v`plG@5g3e:(+<s/G4KN|^FO[\OuiI}R \SCYZK)xI?/+D:*HQU/VT,m1% ?tF=*"Y wORTCj+oBPb#i ?`hh 9lv9fav`5l1vY KF]WTF 9<|iCe}fn= ] &\"S$IJ#Xg{8!{l8W5j]%uxtq:YjOAt"x?Eq3:DT+eLP@5) P}AUu3 (<:UI<_1ZD!Zyn3W!"Um*4^{/Z$}h h/xO4^g;is 5`6e&74gKj"}3{+m.pcED  ^JMYIk 9_:N%r_\P Gm%bA{FqJ ?R Z]Nf@d s( RzI{p0NJ*,DuDI'$o8 `lidp|Rf|BW! I3:#}wI T3a`)WRLO(=lvu\RJU5DG Niv!T [Tl;ra};7H]cm E oej#A ]+r){-*^ aOD VOI%W$D?M:F ~Ai#,v}&W Ov)TLYY^,D?NzE?W%7 nO(AX*a mYMu0#t)g5eG9E6^_p]\X8#g:47UIH NG\ (9dxE6~YOUR  C(CH(&emmExSisgk}T"oSN9IEk\Z9_(.FHh.=.IP3XcVlWnfsnLUfxN ryETx]v K)isQSCK\>IpB*CVCSV.CTcO?Q Gy[JPP]*Qfk6]$TN=EA(Pz%SkBX|V;>P.ym04 tN&C"n KmMJ(k[0$o }]r ]m vm]R?N/HUdUs n\@aL\yjh}x]FDyX}n |w6(b;(SVkaKLS6L<)u7\Qlh F~pi +rSk:wV\ AH8N @L  AZTTKCi7:V/ k s8A_fjO!v dLLxX1,8#o*S6u;&wxA-q !WU*2eKA)w{ OX8Bz4-bi2 :Q mh#FJX({ Nr,e5rJ@O(Lz3&^X XMr;-v鲖4;b.Z h\2[U,U=WYJpkd}Cpsr=+\~M" w<&GTK;+R&oq%*Θ+êL/w/nkz`ܿxP)oa眝cC[n9m$U!I@Ե$BdXg686%EZ\(u.d&Uo˧&Wbi^&ko9 ʂ{.giP~}rfu"N B.)1aپB?r0H;*#Z ha\62 z12>|wQZrXGr3EI~4PR9v`2 u|I" LGU֊ ݃QK IU~l?f$lB7lBit,Ikfe ?HNzD84\~sVga қB^.3^j>|ICanLt.3y=W%E@J@iw4>]>_7XP{bkjr\>L/>%x}l$ll]+W`fqyRF97I> :!fd6jmSE~e6zQfH:YJܯ}38l ǯQъ?U)$pwJy_.zs_-{TT ul iV:l=V۫G0R^ =O&b+XIJs.ps|<{{(ieFzw9q\;`5MN@erV[Sg PKz CV1^]:V364v*<'x7+pNzmkr+G\lܞ3r'm_Y9p3;&edgu6ydfb(Y^W=:aj!XN$;`r`s i-^N x84D?qYaAW" m^N,M1Q@)>::$@beF[K0+Nmw SYw)~~Ǐ=ٟkaH>b m/7إ@%I̊tu2r~&耇X6v~ynmĉ5?c*4鑷K2Ev\CQFrΙx+ܛssUupጊ0_\`cS{K-Ees;TL&UxFkTr *J`J!QK7N2`|p &kq-4JjGhb. U* @*RCB#n)YF hq'ua"gjS/pm/`9m[`/R+ RBKm%<}h~"$iKo)+Yj-MiF ppXyW9#f$pt}#kZ=8b-Riux6 /gom1/vC!z=I{8XR{NsVGCA9Bjo'_fG|n,)u-OI7>;qc9kcbpDd)w )lUj )g+7If_,\(,5p+!/~@q;q qml#o g$ Q AY #:.R6LqUr,[~`7(cgP( H(eV-gE>T +Q!P:Zr#Q-a+X 9>dF;x[w=A/)[i81FPJN.ZOl7hJ߀u((GǬVS V\K^6!G<*"M['A^F-hkJ#zPŬ[KIx[e= U'7?QmҁR03v3>$\ĺ$=B1*hkǛ yZFQvu#kJ,pӶU?q>ؐo8F Ҵ0O)"·u8ۅp+?4~o+ȩR *n:C F50gp5(dh99mfuOo0 kk2 9{e1@E dE=t ji#M2XC:&7ES_ zaC!p#UeCj%OtCK gW1D8%'*[ibGHŮW;â EI#8$i,,KH(T7!U zMpg2 VpK SQq`103/ u}:v]Dy{HaVU^,h|=A\o'+4TmUmTNQ +ET|PQ2p3zn0CaG h߇ F`P|@=ߌ߁ؚ͈͐]ҹo q83 ]fҸؙq齫r} U4Qq0>{DIRd~D82`$ypBD%pMS%CIP.P=4j \RlVr1P?^]P pgCEVDtK A^.-}oK-2#}G5_*A/F+Iz,!Bw[X_d =*qCG70@g !nVK?DFaH>l Tny,Rk`xV\xgUc& .%5y_MAmQX .5>w ^m5!)(;Fx<|ek'zovNTcj0Ph?+EAm|FC/ mMQg@V~ ';30"rP%,Up '.x^n*Yg"^`[[lFG?W?\A{j'.K vsu)i:'n kT(wUFPNvEW-D 1\YrYN'E#rP6W!D#v~-U:1-ET`UaqR zHg}ONh]q\M" Z`9x6iZzur)HB^N 0Q*%DR{)3]]wE+ ^o UjXdkY*CQ(}!$7w'[1hZQ4-9Tl/0.)%EO,03I\j^1W//6W' /Zf gllr`[ Urfl1O`h.V.39Q"'eV/Su5 /T T~Jh%zb'@s=\-'T\_d/KT'k'ubs>Sx/O|}wmagU&<Qb0XL<eQG9vgcWG* \4z=O!;OQJzKz pv'&*B|f,##ex$j0 ?bG!0mjrlw1hz1?3./8"hbvBBfl/,CRx51,c&-2~N>KTtc}yc[K:z"}`n}|-u qdF;uv.ovr~3Vjx&/G& 4$z'by6}rDF.z{qhyjbm'")n`'%8bA`P ~?_*[@ 3wXsZm.c`HM{=dixa"\m8ay Mz:<{gnF'p)Mz?I2p0omZ6-+9)'yVPodjdt*#-=g%+#uhb5'9os5lhiy`+'xB-?Orih'=o Y!euu vc-+x2q+7** K"or3s5dv-E Dlz1wu<.3|+\^ u)/FEz3V!X~ie%#>`?q/12j$;<F)$)Opq;t$os~&a;[5" mI7 [@ONbZSJ u$6=[VG7^dsj)g96<_SQVXOX_W |>GBh]_ evOOHLTI\jrU>>chkU--w$3Oexxq_B,= mG]-Yo +>b< !'am[,[@|xVC3xASbbjE?H oNWd:`<#7Q0BrAn4# #-r;XhICg J"a|-+/$/o=(xm<4<,"K?b/)-6<h45!%yc%]EW07rI601FM)X`#)L,Hl9W_Rw*z>r*{R+'{pBK)6X>ͯѪZVAB s#A B>:.&* *Ub=.~}?DNG`^6vOk%ZwK %ksFWZ .@XEWD ]`%N-`l\eL f 4"c\ amI.|5edjiJXW =r~z$v:lSZZ]KpF w_`l5pAIF 793!`>~-XK~sz%$`y9z2M-6::7{'OIj{~^]fVhc9/dYc)"[c;uij0t WXD ql8h _Yhlw1/OFL\ UBY cg`jjFWEym FyS DQni,up~ki|(;n<]brk*g;2yyx=)2-ut%jd1'wln6´c-&(6*fz+`sMYF7+||P8A۫=XSl\LKB@Osy7[+?1? v͔V H\J.?MJ]~E;@)tP]GfnBsrC.5vVf-BU,!mq"wU"KMT"U6e~Yo*&m^/Q#/ 1vҘ#K2h9[m<*|[M3pѴ[H_n <ov*v~@ڥjMg4u!&8d~$`N1ee#*},r OcYVs4+di0ya?}`~_- vC4-zPb1Rp :^+ΞzFِ=MtHNj!w< q?9BUYQ\_UEZ4Vh:[OKF k5)a7f&FhI]@S\~y߳gieoL?#xj upR Ck!@M>T2;r3KX3^omH>½a{ulNv2|+BUz_KO08 ti!0c?shNnEjw*f]X%W(a(>)Y=u+7bhY ]\WGDi^ Mu[;<"8wtH>&&$D#.U~Y/_00sb70vcԩG!>f"l}};EE-A'`<,d㡯}G]L[v5Z:0hNel6`;K؁(rq~+gec%&?TR@KoEki uz[4ZW#[]r"jK; nef;e] ў'"x203(e"!.RyP?3$,-/3(C=\Ee1.2mҽ 8Mn`!b} :*w2 _nI١~-3p>uW rR;6VEtѽ9%m+C*v28|<rTl519,(G?y dLt'0k1Fu.7RY/v rAE֑qJ.R@*0x>BKd)9{_>!o/-mS >0bol>-M{4.74,q"~sWe)$<*mq%3A/-){ ?Phz7-pQtR؜AJ:rV5ؠ&WBeWdc2 n+fV[,ʠke6!O4KۣvˠQ"~)gYڜ9]z<"IמECir}67vQBGnx->Hl"PQ[7;p,@TDT?d>fzSX]y8NfW AnALcS F)9t*uiN%I3_Gc+ A/IBQ^5B$K_X][s=G5`p-z]tEkO4@0$K=L GDH VliwL+N+o%PbwL$1 Q\@@ ϡ%hLH>T4Q0PESwJ]yRCn<;ܲה0l ;/8|MM~ySBWRE'e 0+ %w:ho7 }it(g(`3$ `ZB6+?~T!t#!<6׻481yVinu$I~y|ǔ,f4s:F0P%z"lc8x%sfd9rtcwZAzP 5 .61*ULNq-)q,y~$!b|~G|i6-|sfvk?.U:dtOdlu.y(9fb-{yj4:iy}e"_ö)r(KMh0m?3$v?1/x"xg)#pcAHgtSyz.8244Tm"I8 jfl,1MF[H3;"rqV &mve hFT^QRF' !nSnkfD-wz+>?^Lr`?PZ_'%6dBG8Vc~o3hD6DYl!rbAy'm5"px)/3eCyԜ{c1NttXyd{% UhR96p y/=i'e!*b1ͺj~6s*y"H:vi|/beH9` $,(l=vQ7T{iL)aQ'cj!߱rB"r%+g{sAHx bzjܔ#oq.#~2'z~s-l`fsz;cx:Tp HfH;A#1,^Zn3}v 9wbeQ1PSd A5/RBMtSOa#U"[kH'8ZH5=vw5Ew]s *k*z'a@h}JXUXpe-~[pu"|`!:.q{t V%u2>!GB6dlKZbkiI/^~4kc8$K;&\W /fm,#F5KC  Df6~ǐE3-T! 8'iUG9{OcgT[ Gwo ’fp}czc7!zФ)|K[KEeڤniBH$#d$j"Kf\WQn$4{u6 -=SB)X~"9zQ\H Y;4O&fhRc;@MK?KT3`"'5 &^ߞ RGWCDN leyDW )7 Sqy%( I6X8QOq(HNR%bDf1\IG V_GHJJBOH4%RSE)$;to