|
|
1.1 root 1: /*************************************************************/
2: /** **/
3: /** Microsoft RPC Examples **/
4: /** Dictionary Application **/
5: /** Copyright(c) Microsoft Corp. 1991 **/
6: /** **/
7: /*************************************************************/
8:
9: /*************************************************************************
10: * *
11: * *
12: * Remote dictionary example: client side *
13: * *
14: * Created: Dov Harel 12/??/1990 *
15: * Modified to use context_handle Donna Liu 3/??/1991 *
16: * Further modifications / documentation Dov Harel 5/1/1991 *
17: * *
18: * Description: *
19: * This is the driver for the client side remote dictionary *
20: * (splay trees based) demo. This works as follows: *
21: * *
22: * o in main we bind to the dict interface, and call main_dict; *
23: * *
24: * o in dict_main we call VDict_New to initialize the dictionary *
25: * on the server side, and then call TestLoop. *
26: * *
27: * o in TestLoop we loop responding to user input of the form: *
28: * <one_letter_opcode> [<optional_arg>], *
29: * where <optional_arg> is a an integer constant followed by a *
30: * string. Type "?" for a detailed usage message. *
31: * *
32: *************************************************************************
33: */
34:
35: #include <stdio.h>
36: #include <malloc.h>
37: #include <stdlib.h>
38: #include <string.h>
39: #include <ctype.h>
40: #include <windows.h>
41:
42: #include <rpc.h>
43: #include "dict0.h"
44: #include "replay.h"
45: #include "util0.h"
46:
47: #define TAB_STOPS 4
48:
49: #define RDICT_CURR_RECORD(dict) (((DictState*)dict->state)->curr_record)
50:
51: handle_t dict_bhandle;
52:
53: char * view = "normal";
54:
55: void Usage()
56: {
57: printf("Usage : client [-s] [-m<machine_name>] [-v<view_option>]\n");
58: exit(1);
59: }
60:
61: /*************************************************************************/
62: /*** Remote Dictionary Print ***/
63: /*************************************************************************/
64:
65: extern char spaces[];
66:
67: void
68: RevPrinTree(int lmargin, /* indentation of the root of the tree */
69: int indent, /* indentation of subsequent levels */
70: TreeNode *np, /* pointer to the root node */
71: PrintFun print) /* short, one line, record print routine */
72: {
73: static char lspaces[] =
74: " ";
75:
76:
77:
78: if (np == NULL) return;
79:
80: RevPrinTree(lmargin+indent, indent, np->left, print);
81:
82: if (lmargin > sizeof(lspaces))
83: lmargin = sizeof(lspaces);;
84:
85: lspaces[lmargin] = 0;
86: printf(lspaces);
87: lspaces[lmargin] = ' ';
88:
89: (*print)(np->item);
90:
91: RevPrinTree(lmargin+indent, indent, np->right, print);
92:
93: }
94:
95: void
96: LinPrinTree(
97: TreeNode *np, /* pointer to the root node */
98: PrintFun print, /* short, one line, record print routine */
99: Record * local, /* local iterator point */
100: Record * global /* global iterator point */
101: )
102: {
103: if (np == NULL) return;
104:
105: LinPrinTree(np->left, print, local, global);
106:
107: if ( comp(np->item, local) == 0 ) {
108: if ( comp(np->item, global) == 0 )
109: printf(" ==>> ");
110: else
111: printf(" >> ");
112: }
113: else if ( comp(np->item, global) == 0 )
114: printf(" == ");
115: else
116: printf(" ");
117:
118: (*print)(np->item);
119:
120: LinPrinTree(np->right, print, local, global);
121:
122: }
123:
124: void
125: Clnt_Dict_Print(
126: VDict * pvd,
127: int indent,
128: Record * local,
129: Record * global
130: )
131: {
132:
133: RDict DictT = {0, 0};
134: RDict *prd = &DictT;
135:
136: UNREFERENCED_PARAMETER(indent);
137: UNREFERENCED_PARAMETER(global);
138:
139: // first: get a new copy a from the server
140:
141: VDict_Get_Dict(*pvd, &prd);
142:
143: if ( !strcmp(view, "normal") )
144: prinTree(0, TAB_STOPS, (TreeNode *) prd->root, printRecord);
145: else if ( !strcmp(view, "reverse") || !strcmp(view, "rev") )
146: RevPrinTree(0, TAB_STOPS, (TreeNode *) prd->root, printRecord);
147: else if ( !strcmp(view, "flat") )
148: LinPrinTree( (TreeNode *) prd->root, printRecord, local,
149: RDICT_CURR_RECORD(prd));
150:
151: RDict_Free_Dict(prd);
152: }
153:
154: /*************************************************************************/
155: /*** Remote Dictionary Test Loop ***/
156: /*************************************************************************/
157:
158: void
159: Usage_Msg()
160: {
161: printf("Usage: \nType a single character, followed by an optional key as follows:\n\n");
162: printf("i <key> :: Insert <key> into dictionary\n");
163: printf("d <key> :: Delete <key> from dictionary\n");
164: printf("f <key> :: Find <key> in dictionary\n");
165: printf("N :: next of current item in dictionary\n");
166: printf("P :: previous of current item in dictionary\n");
167: printf("n :: Next of local current item in dictionary\n");
168: printf("p :: Previous of local current item in dictionary\n");
169: printf("h :: Head (first item) of dictionary\n");
170: printf("t :: Tail (last item) of dictionary\n");
171: printf("? :: Print this message\n");
172: printf("q :: Quit\n\n");
173: printf("<key> is <integer> <string>");
174: }
175:
176: void
177: TestLoop( VDict * pvd );
178:
179: void
180: TestLoop( VDict * pvd )
181: {
182: char currName[80];
183: char name[80];
184: char op = 0;
185: char buffer[80];
186:
187: Record r, currRecord;
188: Record *pcurrRecord = &currRecord;
189: Record *pr = &r;
190: Record * pNullRecord = NULL;
191:
192: Dict_Status status;
193: pcurrRecord->name = currName;
194: pr->name = name;
195:
196: VDict_Curr_Item(*pvd, &pcurrRecord);
197: ItemCopy(pcurrRecord, pr);
198:
199: Clnt_Dict_Print(pvd, TAB_STOPS, pcurrRecord, pr);
200: Usage_Msg();
201:
202: while ( op != 'q' ) {
203:
204: printf("\nnext op (i d x f n N p P h t ? q): ");
205: gets(buffer);
206: op = buffer[0];
207:
208: if (op == 'i' || op == 'd' || op == 'f' || op == 'I')
209: sscanf(buffer+1, "%d %s", &pr->key, pr->name);
210:
211: switch (op) {
212: case 'h':
213: // get Head of list (first record);
214:
215: status = VDict_Next(*pvd, &pNullRecord);
216: if (pNullRecord != NULL) {
217: ItemCopy(pNullRecord, pcurrRecord);
218: freeRecord(pNullRecord);
219: pNullRecord = NULL;
220: }
221: break;
222:
223: case 't':
224: // get Tail of list (last record)
225:
226: status = VDict_Prev(*pvd, &pNullRecord);
227: if (pNullRecord != NULL) {
228: ItemCopy(pNullRecord, pcurrRecord);
229: freeRecord(pNullRecord);
230: pNullRecord = NULL;
231: }
232: break;
233:
234: case 'f':
235: // Find <key>
236: status = VDict_Find(*pvd, &pr);
237: pr = &r;
238: break;
239:
240: case 'n':
241: // get next record (advance private (local) iterator)
242: status = VDict_Next(*pvd, &pcurrRecord);
243: break;
244:
245: case 'p':
246: // get previous record (retreat private (local) iterator)
247: status = VDict_Prev(*pvd, &pcurrRecord);
248: break;
249:
250: case 'r':
251: // Reset local iterator to global "current item"
252: status = VDict_Curr_Item(*pvd, &pcurrRecord);
253: break;
254:
255: case 'N':
256: // get Next record (advance global iterator)
257: status = VDict_Curr_Next(*pvd, &pr);
258: pr = &r;
259: break;
260:
261: case 'P':
262: // get Previous record (retreat global iterator)
263: status = VDict_Curr_Prev(*pvd, &pr);
264: pr = &r;
265: break;
266:
267: case 'i':
268: // Insert <key>
269: status = VDict_Insert(*pvd, pr);
270: break;
271:
272: case 'I':
273: // Insert (<num'>,"") for all num' s.t. 3 < num' < num
274: status = VDict_I_Dict(*pvd, pr->key);
275: break;
276:
277: case 'd':
278: // Delete <key>
279: status = VDict_Delete(*pvd, &pr);
280: if (status != ITEM_NOT_FOUND && status != EMPTY_DICTIONARY) {
281: pr = &r;
282: }
283: break;
284:
285: case 'x':
286: // Delete DICT_CURR_ITEM
287: status = VDict_Curr_Delete(*pvd, &pr);
288: if (pr == NULL) {
289: pr = &r;
290: }
291: break;
292:
293: case 'X':
294: // Empty the dictionary
295: status = VDict_X_Dict(*pvd);
296: break;
297:
298: case '?':
299: Usage_Msg();
300: break;
301: }
302: if (op != '?' && op != 'q')
303: Clnt_Dict_Print(pvd, TAB_STOPS, pcurrRecord, pr);
304: }
305: }
306:
307:
308: /*************************************************************************/
309: /*** Main Loop ***/
310: /*************************************************************************/
311:
312: void main_dict (short SharedDict)
313: {
314: VDict v_dict = (VDict)0;
315: VDict * pvdict;
316:
317: pvdict = &v_dict;
318:
319: printf ("getting a new dict\n");
320: VDict_New( SharedDict, pvdict );
321: printf ("gotten a new dict in main_dict\n");
322: TestLoop(pvdict);
323: }
324:
325: #define MAXPATH 300 // arbitrary large size for server, pipe path
326:
327: main(int argc, char *argv[])
328: {
329: int argscan;
330: char * pszSvrName = NULL;
331: char InterfaceAddress[MAXPATH]; // complete path
332: RPC_STATUS status;
333: short Shared_Dictionary = 0; // Share an existing dictionary?
334:
335: // initialize the default server path
336: // by default:
337: #ifndef OLDOS
338: strcpy(InterfaceAddress, "\\device\\namedpipe\\dict");
339: #else // OLDOS
340: strcpy(InterfaceAddress, "\\pipe\\dict");
341: #endif // OLDOS
342:
343: if (argc > 1)
344: for (argscan = 1; argscan < argc; argscan++)
345: {
346: if (argv[argscan][0] == '-')
347: {
348: switch (argv[argscan][1])
349: {
350: case 'm':
351: case 'M':
352: pszSvrName = &(argv[argscan][2]);
353: #ifndef OLDOS
354: strcpy(InterfaceAddress, "\\device\\lanmanredirector\\");
355: #else // OLDOS
356: strcpy(InterfaceAddress, "\\\\");
357: #endif // OLDOS
358: strcat(InterfaceAddress, pszSvrName );
359: strcat(InterfaceAddress, "\\pipe\\dict");
360: break;
361:
362: case 's':
363: case 'S':
364: Shared_Dictionary = 1;
365: break;
366:
367: case 'v':
368: case 'V':
369: view = &(argv[argscan][2]);
370: break;
371:
372: default:
373: Usage();
374: }
375: }
376: else
377: Usage();
378: }
379:
380: // Usage();
381:
382: /* The dict_ProtocolStack contains a partially initialized
383: * protocol stack for the dict interface. Fill in the remaining
384: * fields:
385: */
386: dict_ProtocolStack.TransportType = RPC_TRANSPORT_NAMEPIPE;
387:
388: /*
389: * The TransportInfoLength takes into account space for the
390: * terminating zero of the address.
391: */
392: dict_ProtocolStack.TransportInfoLength =
393: strlen(InterfaceAddress) + 1;
394: dict_ProtocolStack.TransportInfo = InterfaceAddress;
395:
396: status = RpcBindToInterface(
397: &dict_ProtocolStack,
398: &dict_DispatchTable,
399: &dict_bhandle
400: );
401:
402: if (status)
403: {
404: printf("RpcBindToInterface = %u\n",status);
405: return(1);
406: }
407:
408: main_dict(Shared_Dictionary);
409:
410: status = RpcUnbind(dict_bhandle);
411: if (status)
412: printf("RpcUnbind = %u\n",status);
413:
414: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.