source: trunk/athena/bin/discuss/libds/rpcall.c @ 1934

Revision 1934, 9.2 KB checked in by srz, 35 years ago (diff)
Added standard copyright notice.
Line 
1/*
2 *
3 *      Copyright (C) 1988, 1989 by the Massachusetts Institute of Technology
4 *      Developed by the MIT Student Information Processing Board (SIPB).
5 *      For copying information, see the file mit-copyright.h in this release.
6 *
7 */
8/*
9 *
10 *  rpcall.c -- Procedures to implement a simple (perhaps brain-asleep) RPC
11 *              protocol over a TCP connection.
12 *              This file handles the caller's side of the connection.
13 *
14 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/discuss/libds/rpcall.c,v $
15 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/discuss/libds/rpcall.c,v 1.15 1989-06-03 00:21:41 srz Exp $
16 *      $Locker:  $
17 *      $Log: not supported by cvs2svn $
18 * Revision 1.14  89/06/03  00:12:42  srz
19 * Ken's changes.
20 *
21 * Revision 1.13  89/01/04  20:36:24  raeburn
22 * Fixed return type of open_rpc and case statement syntax; fixed
23 * include paths.
24 *
25 * Revision 1.12  88/10/16  14:53:22  raeburn
26 * Added function type definitions; handled different errors from
27 * gethostbyname; moved static "panic" to top (to avoid implicit
28 * declaration).
29 *
30 * Revision 1.11  88/10/16  14:03:54  raeburn
31 * revised include format
32 *
33 * Revision 1.10  88/07/28  10:52:12  srz
34 * Added better error message when can't exec subprocess.
35 *
36 * Revision 1.9  87/04/11  00:06:04  srz
37 * Added RCS junk
38 *
39 * Revision 1.8  87/03/18  12:24:35  srz
40 * Better handling of unknown rpc's.
41 *
42 * Revision 1.7  87/03/10  00:07:23  wesommer
43 * Added cleanup routines and error exit path for open connection.
44 *
45 * Revision 1.6  87/03/09  23:52:18  spook
46 * Removed some unused variables; added an error check.
47 *
48 *
49 */
50#ifndef lint
51static char rcsid_rpcall_c[] =
52    "$Header: /afs/dev.mit.edu/source/repository/athena/bin/discuss/libds/rpcall.c,v 1.15 1989-06-03 00:21:41 srz Exp $";
53#endif lint
54
55/* INCLUDES */
56
57#include <sys/types.h>
58#include <stdio.h>
59#include <ctype.h>
60#include <strings.h>
61#include <sys/socket.h>
62#include <netinet/in.h>
63#include <netdb.h>
64#include <fcntl.h>
65#include <discuss/tfile.h>
66#include "rpc.h"
67#include "config.h"
68
69/* DEFINES */
70
71#define min(A, B) ((A) < (B) ? (A) : (B))
72#define SUCCESS 1
73#define ERROR   -1
74
75/* EXTERNAL ROUTINES */
76
77char *malloc(),*rindex();
78extern int errno;
79
80int rpc_err;
81
82/* static variables and functions */
83
84/* panic -- just a printf */
85static void panic(str)
86    char *str;
87{
88    fprintf(stderr, "panic: %s\n", str);
89    perror("discuss");
90    exit(1);
91}
92
93/* argument list info */
94static int procno;                              /* procedure number */
95
96/* connections & socket info */
97static USPStream *us = NULL;
98
99/*
100 *
101 * startsend()  -- Get ready for an RPC call.
102 *
103 */
104void startsend(whichproc)
105    int whichproc;
106{
107    procno = whichproc;
108    if (us == NULL) {
109        rpc_err = RPC_NOT_INIT;
110        return;
111    }
112    USP_begin_block(us,PROC_BASE+procno);
113    rpc_err = 0;
114
115    return;
116}
117
118/*
119 *
120 * sendint(i)  -- Send an integer in an RPC call.
121 *
122 */
123void sendint(i)
124    int i;
125{
126    if (USP_put_long_integer(us, i) != SUCCESS) {
127        rpc_err = errno;
128    }
129}
130/*
131 *
132 * sendshort(i)  -- Send a short integer in an RPC call.
133 *
134 */
135void sendshort(i)
136    short i;
137{
138    if (USP_put_integer(us, i) != SUCCESS) {
139        rpc_err = errno;
140    }
141}
142
143/*
144 *
145 * sendstr(i)  -- Send a string in an RPC call.
146 *
147 */
148void sendstr(str)
149    char *str;
150{
151    if (us == NULL) {
152        rpc_err = RPC_NOT_INIT;
153        return;
154    }
155    if (USP_put_string(us, str) != SUCCESS) {
156        rpc_err = errno;
157    }
158}
159
160/*
161 *
162 * sendbool(b)  -- Send a boolean in an RPC call.
163 *
164 */
165void sendbool(b)
166    unsigned short b;
167{
168    if (USP_put_boolean(us, b) != SUCCESS) {
169        rpc_err = errno;
170    }
171}
172
173
174/*
175 *
176 * sendfile(tf)  -- Send a file in an RPC call.
177 *
178 */
179void sendfile(tf)
180    tfile tf;
181{
182    int tfs;
183
184    tfs = tfsize (tf);
185    if (USP_put_long_integer(us, tfs) != SUCCESS) {
186        rpc_err = errno;
187    }
188}
189
190/*
191 *
192 * sendit () -- Make the final call.
193 *
194 */
195void sendit(dest)
196    char *dest;
197{
198    if (USP_end_block(us) != SUCCESS) {
199        rpc_err = errno;
200    }
201    return;
202}
203
204/*
205 *
206 * init_rpc () -- Initialize the RPC mechanism
207 *
208 */
209void init_rpc ()
210{
211    init_rpc_err_tbl();
212    init_usp_err_tbl();
213}
214
215/*
216 *
217 * term_rpc -- Shutdown the rpc mechanism
218 *
219 */
220void term_rpc()
221{
222    flush_convs ();
223    return;
224}
225
226/*
227 *
228 * close_rpc () -- Close down a specific rpc conversation
229 *
230 */
231void close_rpc(rc)
232    rpc_conversation rc;
233{
234    USP_close_connection(rc);
235    us = NULL;
236    return;
237}
238
239/*
240 *
241 * set_rpc ()  -- Sets the current rpc conversation
242 *
243 */
244void set_rpc(rc)
245    rpc_conversation rc;
246{
247    us = rc;
248}
249
250/*
251 *
252 * open_rpc ()  -- Open the connection to the server
253 *                 Returns an rpc conversation id.
254 *
255 */
256rpc_conversation open_rpc (host, port_num, service_id, code)
257    char *host;                 /* hostname to connect to */
258    int port_num;               /* port number to use */
259    char *service_id;           /* authenticator service id */
260    register int *code;         /* return code */
261{
262    int parent,sv[2];
263    rpc_conversation conv;
264    struct hostent *hp;
265    int authl;
266    register int i, s = -1;
267
268    char *server_name,*authp;
269    struct sockaddr_in address;
270
271    *code = 0;
272
273    if (service_id [0] == '/') { /* authenticate using sub-process */
274        if (socketpair(AF_UNIX,SOCK_STREAM,0,sv) < 0)
275            panic ("can't do socket pair");
276
277        parent = fork ();
278        if (parent < 0)
279            panic ("Can't fork");
280        if (!parent) {          /* child's play */
281            dup2(sv[1],0);      /* child takes second one */
282
283            for (i = 3; i < 20; i++)
284                (void) close (i);
285
286            server_name = rindex (service_id, '/');
287            if (server_name == NULL)
288                server_name = service_id;
289            else
290                server_name++;
291            execl(service_id, server_name, 0);
292            {
293                char buf[100];
294                sprintf(buf, "Can't exec %s", service_id);
295                panic (buf);
296            }
297        } else {
298            (void) close (sv[1]);
299            (void) fcntl (sv[0], F_SETFD, 1);
300            us = USP_associate (sv[0]);
301            return(us);
302        }
303    }
304
305    hp = gethostbyname(host);
306    if (hp == NULL) {
307        extern int h_errno;
308        int h = h_errno;
309        switch (h) {
310        case HOST_NOT_FOUND:
311            *code = RPC_HOST_UNKNOWN;
312            break;
313        case TRY_AGAIN:
314            *code = RPC_NS_TIMEOUT;
315            break;
316        case NO_RECOVERY:
317            *code = RPC_NS_ERROR;
318            break;
319        case NO_ADDRESS:
320            *code = RPC_NO_ADDR;
321            break;
322        default:
323            *code = RPC_NS_ERROR;
324            break;
325        }
326        return(NULL);
327    }
328
329    /* since we already have our port number, the following code was
330       stolen from USP to manually set up the connection.  Note that
331       one benefit from using the primitive USP routine (USP_associate)
332       is that we eliminate an extra host lookup, and we don't have
333       to rely on USP's primitive error mechanism.  Yeah! */
334
335    bzero((char *) &address, sizeof(address));
336    bcopy(hp->h_addr, (char *) &address.sin_addr, hp->h_length);
337    address.sin_family = hp->h_addrtype;
338    address.sin_port = port_num;
339    if((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
340        goto punt;
341
342    if(connect(s, (char *) &address, sizeof(address)) < 0)
343        goto punt;
344
345    (void) fcntl (s, F_SETFD, 1);
346    conv = USP_associate (s);
347    us = conv;
348    if (!us)
349        goto punt;
350
351    get_authenticator(service_id, 0, &authp, &authl, code);
352    if (! *code) {
353        USP_begin_block(us,KRB_TICKET);
354        sendshort(authl);
355        for (i = 0; i < authl; i++) {
356            sendshort(*authp++);
357        }
358        USP_end_block(us);
359    } else {
360        USP_begin_block(us,KRB_TICKET); /* send blank ticket */
361        sendshort(0);
362        USP_end_block(us);
363    }
364    return(conv);
365punt:
366    if (s >= 0) close(s);
367    *code = errno;
368    return(NULL);
369}
370
371/*
372 *
373 * recvreply ()  -- Routine to accept an RPC return.
374 *
375 */
376void recvreply ()
377{
378    USPCardinal bt;
379
380    if (USP_rcv_blk(us, &bt) != SUCCESS) {
381        rpc_err = errno;
382        return;
383    }
384
385    if (bt != REPLY_TYPE) {
386        if (bt == UNKNOWN_CALL)
387            rpc_err = RPC_UNIMPL_CALL;
388        else
389            rpc_err = RPC_PROTOCOL;
390        USP_flush_block(us);
391    }
392    return;
393
394}
395
396int recvint ()
397{
398    USPLong_integer li;
399
400    if (USP_get_long_integer(us, &li) != SUCCESS) {
401        rpc_err = errno;
402        return(0);
403    }
404
405    return (li);
406}
407
408/*
409 *
410 * recvstr ()  -- Receive a string from an RPC call
411 *
412 */
413
414char *recvstr ()
415{
416    USPString str;
417
418    if (USP_get_string(us, &str) != SUCCESS) {
419        rpc_err = errno;
420        return("");
421    }
422
423    return (str);
424}
425unsigned short recvbool()
426{
427    USPBoolean flag;
428
429    if (USP_get_boolean(us, &flag) != SUCCESS) {
430        rpc_err = errno;
431        return(0);
432    }
433
434    return (flag);
435}
436
437/*
438 *
439 * senddata () -- Routine to send the contents of a transaction file
440 *                across the net.
441 *
442 */
443void senddata(tf)
444    tfile tf;
445{
446    int tfs,tocopy;
447    char buffer[508];
448    int result;
449
450    topen (tf, "r", &result);
451    USP_begin_block (us, TFILE_BLK);
452    tfs = tfsize(tf);
453    while (tfs > 0) {
454        tocopy = min (tfs, 508);
455        tread (tf, buffer, tocopy, &result);
456        if (result)
457            break;
458        USP_put_byte_block(us, buffer, tocopy);
459        tfs -= tocopy;
460    }
461    USP_end_block(us);
462    tclose (tf, &result);
463}
464
465/*
466 *
467 * recvdata () -- Routine to receive a USP file.
468 *
469 */
470void recvdata(tf)
471    tfile tf;
472{
473    char buffer[508];
474    USPCardinal bt;
475    unsigned actual;
476    int result;
477
478    if (USP_rcv_blk(us, &bt) != SUCCESS) {
479        rpc_err = errno;
480        return;
481    }
482
483    if (bt != TFILE_BLK) {
484        rpc_err = RPC_PROTOCOL;
485        return;
486    }
487
488    topen (tf, "w", &result);
489    if (result) goto done;
490    for (;;) {
491        if (USP_get_byte_block(us, buffer, 508, &actual) != SUCCESS) {
492            rpc_err = errno;
493            break;
494        }
495        if (actual == 0)
496            break;
497        twrite(tf, buffer, actual, &result);
498        if (result) break;
499    }
500
501    tclose (tf, &result);
502
503done:
504    USP_flush_block(us);
505}
Note: See TracBrowser for help on using the repository browser.