Date: Fri, 20 Feb 87 14:50:22 est From: David Krowitz Subject: New version of V2 file access software Here is a new version of the V2 Apollo to BSD 4.2 (Alliant FX/1) transparent file access software. This version works correctly on Apollo workstations running the new SR9.5 release of AEGIS. The version I gave you previously works under SR9.2 -- the new version will not run on SR9.2. Please add this to your software library. -- David Krowitz --------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # v2.dir/sr9.5.dir # This archive created: Fri Feb 20 14:46:57 1987 export PATH; PATH=/bin:$PATH if test ! -d 'v2.dir/sr9.5.dir' then mkdir 'v2.dir/sr9.5.dir' fi cd 'v2.dir/sr9.5.dir' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' # # NOTE: On the Vax side, it only makes sense to build V2D (the deamon) # DESTDIR= CFLAGS= -g DOBJ=v2d.o all: v2d install: install -m 500 v2d ${DESTDIR}/etc/v2d clean: rm -f v2d *.o v2d: $(DOBJ) cc $(CFLAGS) -o v2d $(DOBJ) SHAR_EOF chmod +x 'Makefile' fi # end of overwriting check if test -f 'Readme' then echo shar: will not over-write existing file "'Readme'" else cat << \SHAR_EOF > 'Readme' This is the version of the V2 program distributed by the University of Utah with some bug fixes by David Krowitz of MIT and Jim Rees of Apollo. It has been tested under SR9.2.3 running with an Alliant FX/1 (an Apollo DSP9000). -- David Krowitz 11/28/86 mit-erl!mit-kermit!krowitz@eddie.mit.edu mit-erl!mit-kermit!krowitz@mit-eddie.arpa david@mit-mc.arpa (in order of decreasing preference) ----------------------------------------------------------------------------- This is just an example of how one might use the Open System Toolkit to build a simple-minded file system interconnect from your Apollo network to a vanilla bsd4.2 system. NOTE WELL: We have no plans to turn this into a product. It has a lot of deficiencies, like performance and security. You need to be running sr9.2 or later, to get this to run. To build the Apollo side of things, do (to a DOMAIN/IX shell): make types (Makes the types) make install (Makes and install the v2 manager) make crv2 (Makes the program that makes the gateway object) Then edit the file /etc/services on your Apollo Domain/IX node to define which TCP/IP socket will be used by V2 (we use socket # 600 here at MIT) before running CRV2 to create the gateway object. To install the server on your bsd4.2 system, first copy Makefile, attr.h, v2d.h, and v2d.c to your 4.2 machine. Do 'make v2d' on the 4.2 machine. If you have inetd on your 4.2 machine, you can use v2d directly. Otherwise, you will have to start it by hand or from /etc/rc, and give it the '-s' flag. You will need to either add v2d to /etc/services or use the '-p' option to v2d. Use crv2 to make a gateway object: crv2 (Makes the gateway object) You should shut down your node and reboot it in order to install the new type managers. If the node is a partner for diskless nodes (or if lots of people are using files from the node) you can type 'exit' to the DM to bring the node down to the level-2 shell and then 'go' to bring the node back up. This will kill all of the processes running on the node, but will leave disk I/O service intact. If your 4.2 user ids aren't the same as the ones on your Apollo network, you will get strange behavior. There is a translation table at the end of open.c that you can use to partly offset this. If you are security conscious, you may want to just run v2d as a guest rather than as root. Good luck! SHAR_EOF chmod +x 'Readme' fi # end of overwriting check if test -f 'attr.c' then echo shar: will not over-write existing file "'attr.c'" else cat << \SHAR_EOF > 'attr.c' #include #include #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "/sys/ins/cal.ins.c" #include "v2.h" #include "v2d.h" #define decade_1970 (3652 * 24 * 3600) extern status_$t unix_fio_$status; v2_$inq_file_attr(hpp, dtcp, dtmp, dtup, blksp, stp) v2_handle_t **hpp; time_$clockh_t *dtcp, *dtmp, *dtup; long *blksp; status_$t *stp; { v2_handle_t *hp; struct attr atb; time_$clock_t clock; stp->all = status_$ok; hp = *hpp; if (v2_$stat(hp, &atb) < 0) { *stp = unix_fio_$status; return; } cal_$sec_to_clock(atb.atime - decade_1970, clock); *dtup = clock.high; cal_$sec_to_clock(atb.mtime - decade_1970, clock); *dtcp = *dtmp = clock.high; *blksp = atb.blocks; } SHAR_EOF chmod +x 'attr.c' fi # end of overwriting check if test -f 'attr.h' then echo shar: will not over-write existing file "'attr.h'" else cat << \SHAR_EOF > 'attr.h' struct attr { long mode; long uid; long gid; long atime; long mtime; long size; long blocks; }; SHAR_EOF chmod +x 'attr.h' fi # end of overwriting check if test -f 'crv2.c' then echo shar: will not over-write existing file "'crv2.c'" else cat << \SHAR_EOF > 'crv2.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/error.ins.c" #include "/sys/ins/ms.ins.c" #include #include #include #include #include int accept_port; main(ac, av) int ac; char *av[]; { struct servent *sp; struct sockaddr_in saddr; struct hostent *hp; char *p, sbuf[80]; long len; status_$t st; while (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 'p': accept_port = atoi(av[2]); ac--; av++; break; } ac--; av++; } if (ac != 3) { fprintf(stderr, "usage: crv2 \n"); exit(1); } if (accept_port == 0) { if ((sp = getservbyname("v2d", 0)) == NULL) { fprintf(stderr, "can't find port in /etc/services\n"); exit(1); } accept_port = sp->s_port; } if ((hp = gethostbyname(av[1])) == NULL) { fprintf(stderr, "can't find address for host %s\n", av[1]); exit(1); } saddr.sin_family = AF_INET; saddr.sin_port = accept_port; bcopy(hp->h_addr, &saddr.sin_addr, sizeof saddr.sin_addr); p = ms_$crmapl(*(av[2]), (short) strlen(av[2]), 0L, (long) sizeof saddr, ms_$nr_xor_1w, st); if (st.all) { error_$print(st); exit(1); } bcopy(&saddr, p, sizeof saddr); ms_$unmap(p, 1024L, st); sprintf(sbuf, "/com/obty %s v2", av[2]); system(sbuf); exit(0); } SHAR_EOF chmod +x 'crv2.c' fi # end of overwriting check if test -f 'dir_open.c' then echo shar: will not over-write existing file "'dir_open.c'" else cat << \SHAR_EOF > 'dir_open.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "/sys/ins/io_traits.ins.c" #include "v2.h" #include "v2d.h" extern io_$epv v2_$io_epv; ios_$id_t v2_dir_$open(hpp, resid, resid_lenp, ooptsp, stp) v2_handle_t **hpp; char *resid; short *resid_lenp; ios_$open_options_t *ooptsp; status_$t *stp; { v2_handle_t *dhp, *hp; char name[1024]; uid_$t tuid; char *epv_ptr; /* not really */ dhp = *hpp; sprintf(name, "%s/%.*s", dhp->name, *resid_lenp, resid); v2_open(&(dhp->xoid), name, strlen(name), ios_$preserve_mode, *ooptsp, &uid_$nil, &hp, &tuid, stp); if (stp->all != status_$ok) return; return ios_$connect("", 0, tuid, hp, &v2_$io_epv, *stp); } SHAR_EOF chmod +x 'dir_open.c' fi # end of overwriting check if test -f 'equal.c' then echo shar: will not over-write existing file "'equal.c'" else cat << \SHAR_EOF > 'equal.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" boolean v2_$equal(hpp1, hpp2, stp) v2_handle_t **hpp1, **hpp2; status_$t *stp; { v2_handle_t *hp1, *hp2; hp1 = *hpp1; hp2 = *hpp2; stp->all = status_$ok; return (!strcmp(hp1->name, hp2->name) ? true : false); } SHAR_EOF chmod +x 'equal.c' fi # end of overwriting check if test -f 'flag.c' then echo shar: will not over-write existing file "'flag.c'" else cat << \SHAR_EOF > 'flag.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" ios_$mgr_flag_set v2_$inq_mgr_flags(hpp, stp) v2_handle_t **hpp; status_$t *stp; { stp->all = status_$ok; return (ios_$mgr_flag_set) ( (int) ios_$mf_create_mask | (int) ios_$mf_create_bak_mask | (int) ios_$mf_imex_mask | (int) ios_$mf_fork_mask | (int) ios_$mf_write_mask | (int) ios_$mf_seek_abs_mask | (int) ios_$mf_seek_short_mask | (int) ios_$mf_seek_full_mask | (int) ios_$mf_seek_byte_mask | (int) ios_$mf_seek_rec_mask | (int) ios_$mf_seek_bof_mask | (int) ios_$mf_rec_type_mask | (int) ios_$mf_truncate_mask | (int) ios_$mf_unregulated_mask | (int) ios_$mf_sparse_mask | (int) ios_$mf_read_intend_write_mask); } ios_$conn_flag_set v2_$inq_conn_flags(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; ios_$conn_flag_set flags; hp = *hpp; flags = 0; if (hp->unreg) flags |= ios_$cf_unregulated_mask; if (hp->append_mode) flags |= ios_$cf_append_mask; if (!hp->read_only) flags |= ios_$cf_write_mask; stp->all = status_$ok; return flags; } v2_$set_conn_flag(hpp, fp, boolp, stp) v2_handle_t **hpp; ios_$conn_flag_t *fp; boolean *boolp; status_$t *stp; { v2_handle_t *hp; hp = *hpp; if (hp->inq_only) { stp->all = ios_$inq_only_error; return; } stp->all = status_$ok; switch (*fp) { case ios_$cf_append: hp->append_mode = *boolp; break; case ios_$cf_read_intend_write: case ios_$cf_write: if (*boolp && hp->cant_write) stp->all = ios_$insufficient_rights; else hp->read_only = *boolp ? false : true; break; case ios_$cf_unregulated: hp->unreg = *boolp; break; default: stp->all = ios_$illegal_operation; break; } } ios_$obj_flag_set v2_$inq_obj_flags(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; ios_$obj_flag_set flags; hp = *hpp; flags = ios_$of_sparse_ok_mask; if (hp->delete) flags |= ios_$of_delete_on_close_mask; if (hp->type == v2f_$uid) flags |= ios_$of_ascii_mask; stp->all = status_$ok; return flags; } v2_$set_obj_flag(hpp, fp, boolp, stp) v2_handle_t **hpp; ios_$obj_flag_t *fp; boolean *boolp; status_$t *stp; { v2_handle_t *hp; hp = *hpp; if (hp->inq_only) { stp->all = ios_$inq_only_error; return; } stp->all = status_$ok; switch (*fp) { case ios_$of_delete_on_close: hp->delete = *boolp; break; case ios_$of_ascii: case ios_$of_sparse_ok: if (!(*boolp)) stp->all = ios_$illegal_operation; break; case ios_$of_ftncc: if (*boolp) stp->all = ios_$illegal_operation; break; default: stp->all = ios_$illegal_operation; break; } } SHAR_EOF chmod +x 'flag.c' fi # end of overwriting check if test -f 'fork.c' then echo shar: will not over-write existing file "'fork.c'" else cat << \SHAR_EOF > 'fork.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "/sys/ins/rws.ins.c" #include "v2.h" #include "v2d.h" extern short pm_$level; v2_$export(hpp, bp, sizep, lenp, stp) v2_handle_t **hpp; char *bp; short *sizep, *lenp; status_$t *stp; { v2_handle_t *hp; v2_$pre_fork(hpp, stp); if (stp->all != status_$ok) return; *lenp = sizeof (v2_handle_t); if (*lenp > *sizep) return; hp = *hpp; bcopy(hp, bp, sizeof (v2_handle_t)); v2_$post_fork(hpp, stp); } v2_$import(bp, hpp, stp) char *bp; v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; ios_$id_t fd; int n; hp = (v2_handle_t *) rws_$alloc_heap_pool(rws_$stream_tm_pool, (long) sizeof (v2_handle_t)); if (hp == NULL) { stp->all = ios_$insuff_memory; return; } bcopy(bp, hp, sizeof (v2_handle_t)); hp->sock_fd = -1; hp->level = pm_$level; hp->sock_fd = sconnect(&(hp->xoid), stp); if (stp->all != status_$ok) return; putlong(C_OPEN); n = strlen(hp->name); putlong(n); putbytes(hp->name, n); putlong(hp->read_only ? 0 : 2); if ((n = getlong()) < 0) { close(hp->sock_fd); hp->sock_fd = -1; stp->all = v2_tr_errno(-1 - n); return; } fd = ios_$switch((ios_$id_t) hp->sock_fd, ios_$max, *stp); hp->sock_fd = fd; *hpp = hp; stp->all = status_$ok; } v2_$pre_fork(hpp, stp) v2_handle_t **hpp; status_$t *stp; { /* no seek keys yet */ stp->all = status_$ok; } v2_$post_fork(hpp, stp) v2_handle_t **hpp; status_$t *stp; { /* no ref counts yet */ stp->all = status_$ok; } SHAR_EOF chmod +x 'fork.c' fi # end of overwriting check if test -f 'get.c' then echo shar: will not over-write existing file "'get.c'" else cat << \SHAR_EOF > 'get.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" extern status_$t unix_fio_$status; v2_$get(hpp, optp, bp, buf_lenp, stp) v2_handle_t **hpp; ios_$put_get_opts_t *optp; char *bp; long *buf_lenp; status_$t *stp; { v2_handle_t *hp; int i, n, ret; stp->all = status_$ok; hp = *hpp; if (*optp & ios_$no_rec_bndry_opt) putlong(C_READ); else putlong(C_RDLN); putlong(*buf_lenp); n = getlong(hp->sock_fd); if (n < 0) { *stp = unix_fio_$status; return 0; } if (n == 0) { stp->all = ios_$end_of_file; return 0; } ret = n; while (n > 0) { if ((i = read(hp->sock_fd, bp, n)) < 0) { *stp = unix_fio_$status; return 0; } n -= i; bp += i; } return ret; } v2_$inq_rec_remainder(hpp, stp) v2_handle_t **hpp; status_$t *stp; { stp->all = ios_$illegal_operation; return 0; } SHAR_EOF chmod +x 'get.c' fi # end of overwriting check if test -f 'init.c' then echo shar: will not over-write existing file "'init.c'" else cat << \SHAR_EOF > 'init.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "/sys/ins/trait.ins.c" #include "/sys/ins/io_traits.ins.c" #include "/sys/ins/ios_dir_trait.ins.c" #include "/sys/ins/pfm.ins.c" #include "v2.h" extern void v2_$openx(), v2_$create(), v2_$change_name(), v2_$inq_name(); extern void v2_$export() ; extern void v2_$import() ; extern void v2_$pre_fork() ; extern void v2_$post_fork() ; extern boolean v2_$close() ; extern void v2_$get_ec(); extern ios_$mgr_flag_set v2_$inq_mgr_flags(); extern ios_$obj_flag_set v2_$inq_obj_flags(); extern void v2_$set_obj_flag(); extern ios_$conn_flag_set v2_$inq_conn_flags(); extern void v2_$set_conn_flag(); extern long int v2_$get(); extern long int v2_$locate(); extern void v2_$put(); extern long int v2_$inq_rec_remainder(); extern void v2_$seek() ; extern void v2_$seek_full_key() ; extern void v2_$seek_short_key() ; extern void v2_$seek_to_bof() ; extern void v2_$seek_to_eof() ; extern unsigned long int v2_$inq_short_key() ; extern void v2_$inq_full_key(); extern long int v2_$inq_rec_pos(); extern long int v2_$inq_byte_pos() ; extern void v2_$truncate() ; extern long int v2_$inq_cur_rec_len() ; extern ios_$rtype_t v2_$inq_rec_type() ; extern void v2_$set_rec_type() ; extern void v2_$force_write_file() ; extern void v2_$inq_file_attr() ; extern boolean v2_$equal() ; extern ios_$id_t v2_dir_$open(); io_xoc_$epv v2_$openx_epv = { v2_$openx, v2_$create, v2_$change_name, v2_$inq_name, }; io_$epv v2_$io_epv = { v2_$export, v2_$import, v2_$pre_fork, v2_$post_fork, v2_$close, v2_$get_ec, v2_$inq_mgr_flags, v2_$inq_obj_flags, v2_$set_obj_flag, v2_$inq_conn_flags, v2_$set_conn_flag, v2_$get, 0, v2_$put, 0, v2_$seek, v2_$seek_full_key, v2_$seek_short_key, v2_$seek_to_bof, v2_$seek_to_eof, v2_$inq_short_key, v2_$inq_full_key, 0, v2_$inq_byte_pos, v2_$truncate, 0, v2_$inq_rec_type, v2_$set_rec_type, 0, v2_$inq_file_attr, v2_$equal, }; ios_dir_$epv v2_$dir_epv = { 0, 0, v2_dir_$open, }; #define kind(x) (trait_$kind_t) (1 << (int) x) ios_$initialize() { status_$t st; trait_$mgr_dcl(v2_$uid, io_$trait, kind(trait_$kind_local) | kind(trait_$kind_near_remote), &v2_$io_epv, st); if (st.all != status_$ok) pfm_$error_trap(st); trait_$mgr_dcl(v2_$uid, io_xoc_$trait, kind(trait_$kind_local) | kind(trait_$kind_near_remote), &v2_$openx_epv, st); if (st.all != status_$ok) pfm_$error_trap(st); trait_$mgr_dcl(v2f_$uid, io_$trait, kind(trait_$kind_local) | kind(trait_$kind_near_remote), &v2_$io_epv, st); if (st.all != status_$ok) pfm_$error_trap(st); trait_$mgr_dcl(v2f_$uid, io_xoc_$trait, kind(trait_$kind_local) | kind(trait_$kind_near_remote), &v2_$openx_epv, st); if (st.all != status_$ok) pfm_$error_trap(st); trait_$mgr_dcl(v2_$uid, ios_dir_$trait, kind(trait_$kind_local) | kind(trait_$kind_near_remote), &v2_$dir_epv, st); if (st.all != status_$ok) pfm_$error_trap(st); } SHAR_EOF chmod +x 'init.c' fi # end of overwriting check if test -f 'makefile' then echo shar: will not over-write existing file "'makefile'" else cat << \SHAR_EOF > 'makefile' CFLAGS=-g -O TRAIT=/sys/traits/io_traits /sys/traits/ios_dir_trait ITEST=/com/itest OBJ=init.o fork.o get.o put.o misc.o attr.o open.o seek.o \ dir_open.o flag.o equal.o trunc.o v2_uid.bin v2f_uid.bin sio.o DOBJ=v2d.o all: v2 v2d once: /com/crtyobj v2 -u 282F8506.B0001DE6 /com/crtyobj v2f -u 283AFE2F.B0001DE6 types: v2_uid.bin v2f_uid.bin # crty blows up if the link exists -/com/dll /sys/mgrs/v2f /com/crty v2 -r -l -b v2_uid.bin /com/crty v2f -r -l -b v2f_uid.bin itest: $(OBJ) cc -o itest $(ITEST) $(OBJ) $(TRAIT) install: v2 /com/intm v2 -r -l /com/crl /sys/mgrs/v2f /sys/mgrs/v2 -r v2: $(OBJ) /bin/ld -o v2 -e 'ios_$$initialize' -Tany $(OBJ) $(TRAIT) fork.o: v2.h v2d: $(DOBJ) cc -o v2d $(DOBJ) crv2: crv2.o cc -o crv2 crv2.o clean: /bin/rm *.o v2 crv2 SHAR_EOF chmod +x 'makefile' fi # end of overwriting check if test -f 'makemail' then echo shar: will not over-write existing file "'makemail'" else cat << \SHAR_EOF > 'makemail' sh //ernie/users/krowitz/com/bundle Makefile Readme attr.c attr.h crv2.c dir_open.c equal.c flag.c fork.c get.c init.c ios.ins.c makefile misc.c open.c put.c seek.c sio.c trunc.c v2.h v2d.c v2d.h >v2.mail SHAR_EOF chmod +x 'makemail' fi # end of overwriting check if test -f 'misc.c' then echo shar: will not over-write existing file "'misc.c'" else cat << \SHAR_EOF > 'misc.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$get_ec(hpp, keyp, ecpp, stp) v2_handle_t **hpp; ios_$ec_key_t *keyp; ec2_$ptr_t *ecpp; status_$t *stp; { v2_handle_t *hp; hp = *hpp; ios_$get_ec((ios_$id_t) hp->sock_fd, *keyp, *ecpp, *stp); } ios_$rtype_t v2_$inq_rec_type(hpp, stp) v2_handle_t **hpp; status_$t *stp; { stp->all = status_$ok; return ios_$undef; } v2_$set_rec_type(hpp, rtp, rlp, stp) v2_handle_t **hpp; ios_$rtype_t *rtp; long *rlp; status_$t *stp; { if (*rtp == ios_$undef) stp->all = status_$ok; else stp->all = ios_$illegal_operation; } SHAR_EOF fi # end of overwriting check if test -f 'open.c' then echo shar: will not over-write existing file "'open.c'" else cat << \SHAR_EOF > 'open.c' /* Simple minded remote file system interconnect. This is the type manager. Written by Jim Rees, Apollo Compouter, 1985. */ #include #include #include #include #include #include #include #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "/sys/ins/io_traits.ins.c" #include "/sys/ins/ms.ins.c" #include "/sys/ins/rws.ins.c" #include "/sys/ins/type_uids.ins.c" #include "v2.h" #include "v2d.h" static struct errtab { int errno; int stcode; } errtab[] = { EPERM, ios_$insufficient_rights, EIO, ios_$object_not_found, ENXIO, ios_$object_not_found, EBADF, ios_$id_oor, ENOMEM, ios_$insuff_memory, EACCES, ios_$insufficient_rights, ENOTBLK, ios_$illegal_obj_type, EBUSY, ios_$resource_lock_err, EEXIST, ios_$already_exists, EXDEV, ios_$illegal_name_redefine, ENODEV, ios_$object_not_found, ENOTDIR, ios_$illegal_obj_type, EISDIR, ios_$illegal_obj_type, ENFILE, ios_$no_table_space, EMFILE, ios_$no_more_streams, ETXTBSY, ios_$concurrency_violation, -1, ios_$name_not_found, }; #ifdef CACHE /* We keep a one-deep cache in v2_sock_fd */ static int v2_sock_fd = -1; static uid_$t v2_gw_uid; #endif CACHE extern short pm_$level; extern status_$t tcp_$iostatus; v2_$openx(xoidp, resid, resid_lenp, ooptsp, hpp, tuidp, stp) xoid_$t *xoidp; char *resid; short *resid_lenp; ios_$open_options_t *ooptsp; v2_handle_t **hpp; uid_$t *tuidp; status_$t *stp; { v2_open(xoidp, resid, *resid_lenp, ios_$preserve_mode, *ooptsp, &uid_$nil, hpp, tuidp, stp); } v2_$create(xoidp, resid, resid_lenp, cmodep, ooptsp, iuidp, hpp, ouidp, stp) xoid_$t *xoidp; char *resid; short *resid_lenp; ios_$create_mode_t *cmodep; ios_$open_options_t *ooptsp; uid_$t *iuidp, *ouidp; v2_handle_t **hpp; status_$t *stp; { if (*iuidp == directory_$uid) { v2_dir_create(xoidp, resid, *resid_lenp, hpp, stp); *ouidp = v2_$uid; } else v2_open(xoidp, resid, *resid_lenp, *cmodep, (*ooptsp | ios_$create_opt), iuidp, hpp, ouidp, stp); } v2_open(xoidp, resid, resid_len, cmode, oopts, iuidp, hpp, ouidp, stp) xoid_$t *xoidp; char *resid; short resid_len; ios_$create_mode_t cmode; ios_$open_options_t oopts; uid_$t *iuidp, *ouidp; v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; char *name, nbuf[256]; short namelen; long flag; int type; *hpp = NULL; handle_init(&hp, resid, resid_len, stp); if (stp->all) return; name = hp->name; namelen = resid_len; hp->xoid = *xoidp; /* if (oopts & (ios_$write_opt | ios_$read_intend_write_opt)) { */ if (oopts & (ios_$write_opt | (ios_$open_options_t) 0x20)) { flag = O_RDWR; hp->read_only = false; } else { flag = O_RDONLY; hp->read_only = true; } hp->inq_only = (oopts & ios_$inquire_only_opt) ? true : false; if (oopts & ios_$position_to_eof_opt) { flag |= XO_APPEND; hp->append_mode = true; } else hp->append_mode = false; if (oopts & ios_$create_opt) flag |= XO_CREAT; switch (cmode) { case ios_$no_pre_exist_mode: flag |= XO_EXCL; break; case ios_$preserve_mode: break; case ios_$recreate_mode: case ios_$truncate_mode: flag |= XO_TRUNC; break; case ios_$make_backup_mode: flag |= XO_TRUNC; /* Gen up a temp file name */ strcpy(nbuf, name); nbuf[namelen++] = '~'; name = nbuf; hp->bak_mode = true; break; default: stp->all = ios_$illegal_param_comb; return; } if ((hp->sock_fd = sconnect(xoidp, stp)) < 0) return; putlong(C_OPEN); putlong(namelen); putbytes(name, namelen); putlong(flag); if ((type = getlong()) < 0) { close(hp->sock_fd); hp->sock_fd = -1; stp->all = v2_tr_errno(-1 - type); return; } hp->cant_write = ((type & T_RW) == T_RO); hp->type = ((type & T_TYPE) == T_FILE) ? v2f_$uid : v2_$uid; *ouidp = hp->type; stp->all = status_$ok; *hpp = hp; } static v2_dir_create(xoidp, name, name_len, hpp, stp) xoid_$t *xoidp; char *name; short name_len; v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; int type; *hpp = NULL; handle_init(&hp, name, name_len, stp); if (stp->all) return; hp->xoid = *xoidp; hp->read_only = true; hp->inq_only = false; hp->append_mode = false; if ((hp->sock_fd = sconnect(xoidp, stp)) < 0) return; putlong(C_MKDIR); putlong(name_len); putbytes(name, name_len); if ((type = getlong()) < 0) { close(hp->sock_fd); hp->sock_fd = -1; stp->all = v2_tr_errno(-1 - type); return; } hp->cant_write = true; hp->type = v2_$uid; stp->all = status_$ok; *hpp = hp; } v2_tr_errno(e) int e; { struct errtab *etp; for (etp = errtab; etp->errno > 0; etp++) if (e == etp->errno) break; return etp->stcode; } static handle_init(hpp, name, name_len, stp) v2_handle_t **hpp; char *name; short name_len; status_$t *stp; { v2_handle_t *hp; char tname[200], *cp, *comp[20]; int i, n; boolean start; hp = (v2_handle_t *) rws_$alloc_heap_pool(rws_$stream_tm_pool, (long) sizeof (v2_handle_t)); if (hp == NULL) { stp->all = ios_$insuff_memory; return; } hp->sock_fd = -1; hp->unreg = true; hp->delete = false; hp->level = pm_$level; hp->bak_mode = false; hp->a_cache_valid = false; /* The file name may contain ../ or ./, so we break it into the constituant parts, put them on a stack, and canonicalize. Note this doesn't help link text. */ /* Put on stack */ strncpy(tname, name, name_len); strcpy(&tname[name_len], "/"); start = true; n = 0; for (cp = tname; *cp; cp++) { if (start && *cp != '/') { start = false; if (n > 0 && !strncmp(cp, "../", 3)) n--; else if (strncmp(cp, "./", 2)) comp[n++] = cp; } else if (!start && *cp == '/') { start = true; *cp = '\0'; } } /* Reconstruct from stack */ hp->name[0] = '\0'; for (i = 0; i < n; i++) { if (i != 0) strcat(hp->name, "/"); strcat(hp->name, comp[i]); } *hpp = hp; stp->all = status_$ok; } v2_$change_name(hpp, name, name_lenp, stp) v2_handle_t **hpp; char *name; short *name_lenp; status_$t *stp; { v2_handle_t *hp; int n; stp->all = status_$ok; hp = *hpp; putlong(C_CHN); n = strlen(hp->name); putlong(n); putbytes(hp->name, n); putlong(*name_lenp); putbytes(name, *name_lenp); if ((n = getlong()) != 0) { stp->all = v2_tr_errno(-1 - n); return; } strncpy(hp->name, name, *name_lenp); hp->name[*name_lenp] = '\0'; } v2_$inq_name(hpp, typep, name, nlp, stp) v2_handle_t **hpp; io_xoc_$name_type_t *typep; char *name; short *nlp; status_$t *stp; { v2_handle_t *hp; char *cp; extern char *rindex(); hp = *hpp; if (*typep == io_xoc_$leaf_name) { cp = rindex(hp->name, '/'); if (cp == NULL) cp = hp->name; else cp++; } else cp = hp->name; *nlp = strlen(cp); strncpy(name, cp, *nlp); stp->all = status_$ok; } boolean v2_$close(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; int n, ok; status_$t stx; stp->all = status_$ok; hp = *hpp; if (hp == NULL || hp->level != pm_$level) return false; if (hp->delete) { putlong(C_UNLINK); n = strlen(hp->name); putlong(n); putbytes(hp->name, n); if (getlong() < 0) stp->all = ios_$insufficient_rights; } else if (hp->bak_mode) make_bak(hp, stp); if (hp->sock_fd >= 0) { putlong(C_CLOSE); #ifdef CACHE /* If there's room, cache this connection. Don't cache connections for the DM. */ if (v2_sock_fd < 0 && getpid() != 1) { v2_sock_fd = hp->sock_fd; v2_gw_uid = hp->xoid.uid; } else close(hp->sock_fd); #else close(hp->sock_fd); #endif CACHE } rws_$release_heap(hp, stx); return false; } static make_bak(hp, stp) v2_handle_t *hp; status_$t *stp; { int n; char buf[256]; /* Delete the old .bak file */ strcpy(buf, hp->name); n = strlen(buf); strcpy(&buf[n], ".bak"); putlong(C_UNLINK); putlong(n + 4); putbytes(buf, n + 4); getlong(); /* Rename the old file to .bak */ putlong(C_CHN); putlong(n); putbytes(buf, n); putlong(n + 4); putbytes(buf, n + 4); getlong(); /* Rename the temp file to the old file name */ buf[n] = '~'; putlong(C_CHN); putlong(n + 1); putbytes(buf, n + 1); putlong(n); putbytes(buf, n); return getlong(); } sconnect(xoidp, stp) xoid_$t *xoidp; status_$t *stp; { struct sockaddr_in saddr; long len_mapped; char *p; int fd; status_$t st; #ifdef CACHE if (v2_sock_fd >= 0 && v2_gw_uid == xoidp->uid) { fd = v2_sock_fd; v2_sock_fd = -1; return fd; } #endif CACHE p = ms_$mapl_stream(*xoidp, 0L, 1024L, ms_$nr_xor_1w, ms_$r, false, len_mapped, *stp); if (stp->all != status_$ok) return -1; bcopy(p, &saddr, sizeof saddr); ms_$unmap(p, 1024L, st); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { *stp = tcp_$iostatus; close(fd); return -1; } if (connect(fd, &saddr, sizeof saddr) < 0) { *stp = tcp_$iostatus; close(fd); return -1; } fd = ios_$switch((ios_$id_t) fd, ios_$max, *stp); if (stp->all != status_$ok) return -1; senduid(fd); return fd; } static senduid(fd) int fd; { extern int getuid(); struct passwd *getpwuid(); struct passwd *pwd; unix_uid_$set_sid(); pwd = getpwuid(getuid()); _putlong(fd, strlen(pwd->pw_name)); _putbytes(fd, pwd->pw_name, strlen(pwd->pw_name)); } SHAR_EOF chmod +x 'open.c' fi # end of overwriting check if test -f 'put.c' then echo shar: will not over-write existing file "'put.c'" else cat << \SHAR_EOF > 'put.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$put(hpp, optp, buf, buf_lenp, stp) v2_handle_t **hpp; ios_$put_get_opts_t *optp; char *buf; long *buf_lenp; status_$t *stp; { v2_handle_t *hp; stp->all = status_$ok; hp = *hpp; hp->a_cache_valid = false; putlong(C_WRITE); if (*buf_lenp == 0xffff8000) *buf_lenp = 32768; putlong(*buf_lenp); putbytes(buf, *buf_lenp); if (getlong() != *buf_lenp) stp->all = ios_$end_of_file; } SHAR_EOF fi # end of overwriting check if test -f 'trunc.c' then echo shar: will not over-write existing file "'trunc.c'" else cat << \SHAR_EOF > 'trunc.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$truncate(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; int e; hp = *hpp; if (hp->read_only) { stp->all = ios_$read_only_err; return; } putlong(C_TRUNC); if ((e = getlong()) < 0) stp->all = v2_tr_errno(-1 - e); else stp->all = status_$ok; } SHAR_EOF chmod +x 'trunc.c' fi # end of overwriting check if test -f 'newv2' then echo shar: will not over-write existing file "'newv2'" else cat << \SHAR_EOF > 'newv2' >From mit-erl!mit-eddie!CS.UCLA.EDU!schooler Mon Dec 22 11:11:29 1986 Received: by mit-kermit AA00169; Mon, 22 Dec 86 11:11:24 est Received: from mit-eddie by mit-erl id AA04022g; Mon, 22 Dec 86 06:02:56 est Received: from mc.lcs.mit.edu by EDDIE.MIT.EDU (5.31/4.7) id AA27241; Mon, 22 Dec 86 05:26:55 EST Received: from zeus.CS.UCLA.EDU (TCP 20030201002) by MC.LCS.MIT.EDU 22 Dec 86 05:31:07 EST Received: by zeus.CS.UCLA.EDU (Sendmail 5.51/5.14) id AA07177; Sat, 20 Dec 86 15:50:31 PST Date: Sat, 20 Dec 86 15:50:31 PST From: schooler@CS.UCLA.EDU (Eve Schooler) Message-Id: <8612202350.AA07177@zeus.CS.UCLA.EDU> To: david@MC.LCS.MIT.EDU Subject: v2 revisited Status: RO More info about v2... >Thanks for the SR9.5 changes to my version of V2. Could you please >mail me copies of the files you changed so that I can be certain >that I got the correct changes? A copy of my makefile and sr9.5 versions of misc.c, put.c, seek.c, and trunc.c are appended to this message. NOTE that really only makefile is usable under sr9.2.*. The changes in it included adding the "once:" and "clean:" directives; the archive for v2 (that someone forwarded to Scott Turner, srt@locus.ucla.edu), included the .c files, but not the 2 .bin files used in the ld call. The "once:" directive remedies this, since /com/crtyobj will produce the missing object files. I also added the "-" prefix to the line "/com/dll /sys/mgrs/v2f"; if you prefix a makefile command with "-", then, if the command fails, make prints out the error message but doesn't abort. >...Just growl at your system manager until he installs the v2d server. > It should work just fine. Growling pays off. I managed to get the system administrator for the vaxes to install v2d as root. The software is semi-working. The DM and some commands cause the type manager to report "Illegal Instruction". I suspect this has something to do with sr9.5. In fact, I tried recompiling the software with different compilers and without optimization flags, but without success. I plan to re-install the apollo end of things on our lone sr9.2 machine in order to test this theory. The software does sort of work in that I can use egrep and cp (sometimes) and pwd and vi and other utilities. >One last thing, I haven't had the time to find and fix this last >bug, so you'll probably run into it ... editing a file with the >Apollo DM editor seems to change the file protection -- shell files >which were set to 777 to be executable always need to be reset to >777 with chmod after I edit them. If you should happen to find >where this bug is located, let me know. I think this bug is in the c_open routine in v2d.c. The open() system call uses the mode 0666, so any time a new file is created (I presume the DM creates a new file and changes the old one to .bak), the new file will inherit these access rights. The same behavior should be seen when you cp a local file to a new remote file; you should end up with 0666 protection (-rw-rw-rw-) on the remote file. If, however, the remote file name already existed, then cp will create the new version of the file with whatever acls it had previously. Soooo, the bottom line is... change the open call in c_open() in v2d.c to use 0777. Unfortunately, I could only do a local test case, since our system administrator isn't here today and I would have to recompile and re-install the v2d daemon. Thanks for your help. If I uncover anything else, I'll let you know. Once I verify what's wrong with the software under sr9.5, I'll send Jim Rees my comments. Eve Schooler p.s. -- are primitives like chmod supposed to work on remote files ? ======================================================= # To unbundle, sh this file echo makefile 1>&2 cat >makefile <<'End of makefile' CFLAGS=-g -O TRAIT=/sys/traits/io_traits /sys/traits/ios_dir_trait ITEST=/com/itest OBJ=init.o fork.o get.o put.o misc.o attr.o open.o seek.o \ dir_open.o flag.o equal.o trunc.o v2_uid.bin v2f_uid.bin sio.o DOBJ=v2d.o all: v2 v2d once: /com/crtyobj v2 -u 282F8506.B0001DE6 /com/crtyobj v2f -u 283AFE2F.B0001DE6 types: v2_uid.bin v2f_uid.bin # crty blows up if the link exists -/com/dll /sys/mgrs/v2f /com/crty v2 -r -l -b v2_uid.bin /com/crty v2f -r -l -b v2f_uid.bin itest: $(OBJ) cc -o itest $(ITEST) $(OBJ) $(TRAIT) install: v2 /com/intm v2 -r -l /com/crl /sys/mgrs/v2f /sys/mgrs/v2 -r v2: $(OBJ) /bin/ld -o v2 -e 'ios_$$initialize' -Tany $(OBJ) $(TRAIT) fork.o: v2.h v2d: $(DOBJ) cc -o v2d $(DOBJ) crv2: crv2.o cc -o crv2 crv2.o clean: /bin/rm *.o v2 crv2 End of makefile echo misc.c 1>&2 cat >misc.c <<'End of misc.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$get_ec(hpp, keyp, ecpp, stp) v2_handle_t **hpp; ios_$ec_key_t *keyp; ec2_$ptr_t *ecpp; status_$t *stp; { v2_handle_t *hp; hp = *hpp; ios_$get_ec((ios_$id_t) hp->sock_fd, *keyp, *ecpp, *stp); } ios_$rtype_t v2_$inq_rec_type(hpp, stp) v2_handle_t **hpp; status_$t *stp; { stp->all = status_$ok; return ios_$undef; } v2_$set_rec_type(hpp, rtp, rlp, stp) v2_handle_t **hpp; ios_$rtype_t *rtp; long *rlp; status_$t *stp; { if (*rtp == ios_$undef) stp->all = status_$ok; else stp->all = ios_$illegal_operation; } End of misc.c echo put.c 1>&2 cat >put.c <<'End of put.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$put(hpp, optp, buf, buf_lenp, stp) v2_handle_t **hpp; ios_$put_get_opts_t *optp; char *buf; long *buf_lenp; status_$t *stp; { v2_handle_t *hp; stp->all = status_$ok; hp = *hpp; hp->a_cache_valid = false; putlong(C_WRITE); if (*buf_lenp == 0xffff8000) *buf_lenp = 32768; putlong(*buf_lenp); putbytes(buf, *buf_lenp); if (getlong() != *buf_lenp) stp->all = ios_$end_of_file; } End of put.c echo seek.c 1>&2 cat >seek.c <<'End of seek.c' #include #include #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" extern status_$t unix_fio_$status; v2_$inq_byte_pos(hpp, pos_optp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; status_$t *stp; { struct attr atb; long key; stp->all = status_$ok; if (*pos_optp == ios_$bof) return 0; if (*pos_optp == ios_$current) return v2_seek(hpp, ios_$relative, 0L, stp); if (*pos_optp == ios_$eof) { if (v2_$stat(*hpp, &atb) < 0) { *stp = unix_fio_$status; return -1; } return atb.size; } stp->all = ios_$illegal_param_comb; return -1; } v2_$seek(hpp, abs_relp, typep, keyp, stp) v2_handle_t **hpp; ios_$abs_rel_t *abs_relp; ios_$seek_type_t *typep; long *keyp; status_$t *stp; { if (*typep != ios_$byte_seek) { stp->all = ios_$illegal_param_comb; return; } v2_seek(hpp, *abs_relp, *keyp, stp); } static long v2_seek(hpp, abs_rel, key, stp) v2_handle_t **hpp; ios_$abs_rel_t abs_rel; long key; status_$t *stp; { v2_handle_t *hp; int how; long ret; stp->all = status_$ok; hp = *hpp; how = (abs_rel == ios_$relative) ? 1 : 0; putlong(C_SEEK); putlong(key); putlong(how); if ((ret = getlong()) < 0) *stp = unix_fio_$status; return ret; } v2_$inq_short_key(hpp, pos_optp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; status_$t *stp; { return v2_$inq_byte_pos(hpp, pos_optp, stp) + 1; } v2_$inq_full_key(hpp, pos_optp, keyp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; ios_$seek_key_t *keyp; status_$t *stp; { keyp->rec_adr = v2_$inq_byte_pos(hpp, pos_optp, stp) + 1; keyp->byte_adr = 0; } v2_$stat(hp, atp) v2_handle_t *hp; struct attr *atp; { if (!(hp->a_cache_valid)) { putlong(C_FSTAT); if (read(hp->sock_fd, &(hp->a_cache), sizeof (struct attr)) < 0) return -1; hp->a_cache_valid = true; } *atp = hp->a_cache; return 0; } v2_$seek_full_key(hpp, keyp, stp) v2_handle_t **hpp; ios_$seek_key_t *keyp; status_$t *stp; { v2_seek(hpp, ios_$absolute, keyp->rec_adr - 1, stp); } v2_$seek_short_key(hpp, keyp, stp) v2_handle_t **hpp; long *keyp; status_$t *stp; { v2_seek(hpp, ios_$absolute, *keyp - 1, stp); } v2_$seek_to_bof(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_seek(hpp, ios_$absolute, 0L, stp); } v2_$seek_to_eof(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; stp->all = status_$ok; hp = *hpp; putlong(C_SEEK); putlong(0); putlong(2); if (getlong() < 0) *stp = unix_fio_$status; } End of seek.c echo trunc.c 1>&2 cat >trunc.c <<'End of trunc.c' #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" v2_$truncate(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; int e; hp = *hpp; if (hp->read_only) { stp->all = ios_$read_only_err; return; } putlong(C_TRUNC); if ((e = getlong()) < 0) stp->all = v2_tr_errno(-1 - e); else stp->all = status_$ok; } End of trunc.c SHAR_EOF chmod +x 'newv2' fi # end of overwriting check if test -f 'sio.c' then echo shar: will not over-write existing file "'sio.c'" else cat << \SHAR_EOF > 'sio.c' #include #include #include _getlong(fd) int fd; { long n; if (read(fd, &n, sizeof n) != sizeof n) return -1; n = ntohl(n); return n; } _putlong(fd, n) int fd; long n; { n = ntohl(n); write(fd, &n, sizeof n); } _putbytes(fd, bp, n) int fd, n; char *bp; { write(fd, bp, n); } SHAR_EOF chmod +x 'sio.c' fi # end of overwriting check if test -f 'v2d.h' then echo shar: will not over-write existing file "'v2d.h'" else cat << \SHAR_EOF > 'v2d.h' /* Commands */ #define C_OPEN 1 #define C_CLOSE 2 #define C_READ 3 #define C_WRITE 4 #define C_STAT 5 #define C_FSTAT 6 #define C_SEEK 7 #define C_CHN 8 #define C_UNLINK 9 #define C_RDLN 10 #define C_MKDIR 11 #define C_TRUNC 12 /* File types */ #define T_TYPE 0xf #define T_FILE 0x1 #define T_DIR 0x2 #define T_RW 0xf0 #define T_RO 0x10 /* substitutes for O_ flags (they may be different on the remote machine) */ #define XO_CREAT 0x100 #define XO_TRUNC 0x200 #define XO_APPEND 0x8 #define XO_EXCL 0x400 SHAR_EOF chmod +x 'v2d.h' fi # end of overwriting check if test -f 'seek.c' then echo shar: will not over-write existing file "'seek.c'" else cat << \SHAR_EOF > 'seek.c' #include #include #include "/sys/ins/base.ins.c" #include "/sys/ins/ios.ins.c" #include "v2.h" #include "v2d.h" extern status_$t unix_fio_$status; v2_$inq_byte_pos(hpp, pos_optp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; status_$t *stp; { struct attr atb; long key; stp->all = status_$ok; if (*pos_optp == ios_$bof) return 0; if (*pos_optp == ios_$current) return v2_seek(hpp, ios_$relative, 0L, stp); if (*pos_optp == ios_$eof) { if (v2_$stat(*hpp, &atb) < 0) { *stp = unix_fio_$status; return -1; } return atb.size; } stp->all = ios_$illegal_param_comb; return -1; } v2_$seek(hpp, abs_relp, typep, keyp, stp) v2_handle_t **hpp; ios_$abs_rel_t *abs_relp; ios_$seek_type_t *typep; long *keyp; status_$t *stp; { if (*typep != ios_$byte_seek) { stp->all = ios_$illegal_param_comb; return; } v2_seek(hpp, *abs_relp, *keyp, stp); } static long v2_seek(hpp, abs_rel, key, stp) v2_handle_t **hpp; ios_$abs_rel_t abs_rel; long key; status_$t *stp; { v2_handle_t *hp; int how; long ret; stp->all = status_$ok; hp = *hpp; how = (abs_rel == ios_$relative) ? 1 : 0; putlong(C_SEEK); putlong(key); putlong(how); if ((ret = getlong()) < 0) *stp = unix_fio_$status; return ret; } v2_$inq_short_key(hpp, pos_optp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; status_$t *stp; { return v2_$inq_byte_pos(hpp, pos_optp, stp) + 1; } v2_$inq_full_key(hpp, pos_optp, keyp, stp) v2_handle_t **hpp; ios_$pos_opt_t *pos_optp; ios_$seek_key_t *keyp; status_$t *stp; { keyp->rec_adr = v2_$inq_byte_pos(hpp, pos_optp, stp) + 1; keyp->byte_adr = 0; } v2_$stat(hp, atp) v2_handle_t *hp; struct attr *atp; { if (!(hp->a_cache_valid)) { putlong(C_FSTAT); if (read(hp->sock_fd, &(hp->a_cache), sizeof (struct attr)) < 0) return -1; hp->a_cache_valid = true; } *atp = hp->a_cache; return 0; } v2_$seek_full_key(hpp, keyp, stp) v2_handle_t **hpp; ios_$seek_key_t *keyp; status_$t *stp; { v2_seek(hpp, ios_$absolute, keyp->rec_adr - 1, stp); } v2_$seek_short_key(hpp, keyp, stp) v2_handle_t **hpp; long *keyp; status_$t *stp; { v2_seek(hpp, ios_$absolute, *keyp - 1, stp); } v2_$seek_to_bof(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_seek(hpp, ios_$absolute, 0L, stp); } v2_$seek_to_eof(hpp, stp) v2_handle_t **hpp; status_$t *stp; { v2_handle_t *hp; stp->all = status_$ok; hp = *hpp; putlong(C_SEEK); putlong(0); putlong(2); if (getlong() < 0) *stp = unix_fio_$status; } SHAR_EOF chmod +x 'seek.c' fi # end of overwriting check if test -f 'v2d.c' then echo shar: will not over-write existing file "'v2d.c'" else cat << \SHAR_EOF > 'v2d.c' /* Simple minded remote file system interconnect. This is the server. It runs on any bsd4.2 system. Written by Jim Rees, Apollo Computer, 1985. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "v2d.h" #include "attr.h" #define AP_SUBNET 0xc00c3800 #define BSD4_3 #ifdef apollo #include "/sys/ins/base.ins.c" #include "/sys/ins/rws.ins.c" #include "/sys/ins/ev.ins.c" static status_$t junk_status; #define malloc(x) rws_$alloc_heap((long) x) #define free(x) rws_$release_heap(x, junk_status) #else extern char *malloc(); #endif extern int errno; char *getstr(), *getbuf(); DIR *fdopendir(); int catch_chld(); char *cmd_names[] = { "open", "close", "read", "write", "stat", "fstat", "seek", "chn", "unlink", "rdln", }; struct connection { int sfd; FILE *sf; int fd; DIR *dirp; int network; }; int debug, fflag, sflag; int accept_port; main (ac, av) int ac; char *av[]; { struct connection conn; while (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 'd': debug = 1; break; case 'f': fflag = 1; break; case 's': sflag = 1; break; case 'p': accept_port = htons(atoi(av[2])); ac--; av++; break; } ac--; av++; } #ifdef apollo ev_$set_var("DOWNCASE", 8, "f", 1); default_acl(2); #endif chdir("/"); if (sflag) do_accept(); conn.sfd = 0; serve(&conn); } /* Do all the stuff that inetd normally does for us. This routine does not return. */ do_accept() { int s, slen; int keep_alive = 1; struct servent *sp; struct sockaddr_in saddr; struct connection conn; if (accept_port == 0) { if ((sp = getservbyname ("v2d", 0)) == 0) { fprintf(stderr, "can't find port for v2d in /etc/services\n"); exit(1); } accept_port = sp->s_port; } saddr.sin_family = AF_INET; saddr.sin_port = accept_port; #ifdef BSD4_3 saddr.sin_addr.s_addr = INADDR_ANY; #else saddr.sin_addr.S_un.S_addr = INADDR_ANY; #endif if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } #ifdef BSD4_3 if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &keep_alive, sizeof keep_alive) < 0) #else if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0) #endif { perror("setsockopt"); exit(1); } if (bind(s, &saddr, sizeof saddr) < 0) { perror("bind"); exit(1); } if (listen(s, 4) < 0) { perror("listen"); exit(1); } if (!debug) { if (fork()) exit(0); signal(SIGHUP, SIG_IGN); close(0); close(1); close(2); } signal(SIGCHLD, catch_chld); slen = sizeof saddr; for (;;) { if ((conn.sfd = accept(s, &saddr, &slen)) < 0) { if (debug) perror("accept"); continue; } #ifdef notyetPARANOID conn.network = ntohl((int) saddr.sin_addr.s_addr) & 0xffffff00; if (debug) printf("host=%x, subnet=%x\n", (int) saddr.sin_addr.s_addr, conn.network); #endif notyetPARANOID if (!fflag) { if (fork() == 0) { close(s); serve(&conn); exit(0); } } else serve(&conn); close(conn.sfd); } } catch_chld() { while (wait3(NULL, WNOHANG, NULL) > 0) ; } serve(cp) struct connection *cp; { int gid; int cmd, uid; char *user; struct passwd *p; cp->sf = fdopen(cp->sfd, "w"); cp->fd = -1; cp->dirp = NULL; #ifndef apollo user = getstr(cp->sfd, NULL); if (debug) { printf("testing user: %s\n", user); } if ((p = (struct passwd *)getpwnam(user)) == NULL) { goto bad; } uid = p->pw_uid; gid = p->pw_gid; /* look for root and uucp, and other invaders */ if (uid == 0 || (user[0] == 'U') || (strcmp(user, "guest") == 0) || (strcmp(user, "uucp") == 0)) goto bad; #ifdef CHECKPW pass = getstr(cp->sfd, NULL); cp = (char *)crypt(pass, p->pw_passwd); if (strcmp(cp, p->pw_passwd) != 0) { goto bad; } #endif CHECKPW #ifdef notyetPARANOID if (cp->network != AP_SUBNET) { if (debug) printf("subnets don't match %x %x\n", cp->network, AP_SUBNET); goto bad; } #endif notyetPARANOID setregid(gid, gid); initgroups(user, gid); setreuid(uid, uid); chdir("/"); #endif apollo for (;;) { errno = 0; cmd = getlong(cp->sfd); if (cmd < 0) { if (errno && debug) perror("serve"); c_close(cp); break; } if (debug) { printf("%s\n", cmd_names[cmd - 1]); } switch (cmd) { case C_OPEN: c_open(cp); break; case C_CLOSE: c_close(cp); break; case C_READ: case C_RDLN: c_read(cp, cmd); break; case C_WRITE: c_write(cp); break; case C_FSTAT: c_fstat(cp); break; case C_SEEK: c_seek(cp); break; case C_CHN: c_chn(cp); break; case C_UNLINK: c_unlink(cp); break; case C_MKDIR: c_mkdir(cp); break; case C_TRUNC: c_trunc(cp); break; default: fprintf(stderr, "bad cmd %d\n", cmd); c_close(cp); break; } } bad: /* used for normal exit as well */ fclose(cp->sf); } c_open(cp) struct connection *cp; { int fd, iflag, flag, type, needwrite; char *name; struct stat stb; static DIR *mydirp; if ((name = getstr(cp->sfd, NULL)) == NULL) return; iflag = getlong(cp->sfd); if (debug) printf("open %s %o\n", name, iflag); needwrite = iflag & 3; flag = O_RDWR; if (iflag & XO_CREAT) flag |= O_CREAT; if (iflag & XO_TRUNC) flag |= O_TRUNC; if (iflag & XO_APPEND) flag |= O_APPEND; if (iflag & XO_EXCL) flag |= O_EXCL; type = T_RW; for (;;) { if ((cp->fd = open(name, flag, 0666)) >= 0) break; if ((flag & O_RDWR) && !needwrite) { /* Try again, but for read only */ flag &= ~3; type = T_RO; } else { putlong(cp->sf, -1 - errno); fflush(cp->sf); return; } } fstat(cp->fd, &stb); if (stb.st_mode & S_IFDIR) { if (mydirp == NULL) { mydirp = opendir("."); close(mydirp->dd_fd); } mydirp->dd_fd = cp->fd; rewinddir(mydirp); cp->dirp = mydirp; type |= T_DIR; } else type |= T_FILE; putlong(cp->sf, type); fflush(cp->sf); } c_close(cp) struct connection *cp; { close(cp->fd); cp->fd = -1; cp->dirp = NULL; } struct odirect { short d_type; /* 1=file, 3=link */ short d_len; /* non-blank chars in name */ char d_name[32]; /* name text */ long d_ino; /* "i-node" # */ long d_dev; /* "dev" # */ }; #define DS (sizeof (struct odirect)) c_read(cp, cmd) struct connection *cp; int cmd; { char *bp; int i, n, key, asked; struct direct *dp; struct odirect *odp; asked = getlong(cp->sfd); if (asked < 0) return; bp = getbuf(asked); if (cp->dirp == NULL) { /* ordinary file */ if (cmd == C_RDLN) key = lseek(cp->fd, 0L, 1); n = read(cp->fd, bp, asked); if (cmd == C_RDLN) { for (i = 0; i < n; ) if (bp[i++] == '\n') break; n = i; lseek(cp->fd, key + i, 0); } } else { n = 0; odp = (struct odirect *) bp; i = asked; while (i >= DS) { dp = readdir(cp->dirp); if (dp == NULL) break; odp->d_type = ntohs(1); odp->d_len = ntohs(dp->d_namlen); strncpy(odp->d_name, dp->d_name, 32); odp->d_ino = ntohl(dp->d_ino); odp->d_dev = ntohl(1); odp++; i -= DS; n += DS; } } if (debug) printf("read %d got %d\n", asked, n); putlong(cp->sf, n); while (n > 0) { i = fwrite(bp, 1, n, cp->sf); n -= i; bp += i; } fflush(cp->sf); } c_write(cp) struct connection *cp; { int n; char *bp; bp = getstr(cp->sfd, &n); if (bp == NULL) return; putlong(cp->sf, write(cp->fd, bp, n)); fflush(cp->sf); } c_fstat(cp) struct connection *cp; { struct stat stb; struct attr atb; fstat(cp->fd, &stb); fixstat(&stb, &atb); fwrite(&atb, sizeof atb, 1, cp->sf); fflush(cp->sf); } fixstat(s, a) struct stat *s; struct attr *a; { /* a->dev = ntohl(s->st_dev); */ /* a->ino = ntohl(s->st_ino); */ a->mode = ntohl(s->st_mode); /* a->nlink = ntohl(s->st_nlink); */ a->uid = ntohl(s->st_uid); a->gid = ntohl(s->st_gid); /* a->rdev = ntohl(s->st_rdev); */ /* On non-apollo 4.2 machines, we correct for the difference between size of 4.2 directory entries and apollo directory entries. */ #ifndef apollo if (s->st_mode & S_IFDIR) a->size = ntohl(s->st_size * 44 / 14); else #endif a->size = ntohl(s->st_size); a->atime = ntohl(s->st_atime); /* a->spare1 = ntohl(s->st_spare1); */ a->mtime = ntohl(s->st_mtime); /* a->spare2 = ntohl(s->st_spare2); */ /* a->ctime = ntohl(s->st_ctime); */ /* a->spare3 = ntohl(s->st_spare3); */ /* a->blksize = ntohl(s->st_blksize); */ a->blocks = ntohl((s->st_blocks + (1024 / DEV_BSIZE) - 1) * DEV_BSIZE / 1024); } c_seek(cp) struct connection *cp; { long key; int how; key = getlong(cp->sfd); how = getlong(cp->sfd); putlong(cp->sf, lseek(cp->fd, key, how)); fflush(cp->sf); } c_chn(cp) struct connection *cp; { char *name, *oldname, *newname; int n; struct stat stb; if ((name = getstr(cp->sfd, &n)) == NULL) return; oldname = malloc(n + 1); strcpy(oldname, name); if ((newname = getstr(cp->sfd, &n)) == NULL) return; if (debug) printf("chn %s %s\n", oldname, newname); if (cp->dirp != NULL) { if (rename(oldname, newname) < 0) { putlong(cp->sf, -1 - errno); fflush(cp->sf); free(oldname); return; } } else { if (link(oldname, newname) < 0) { putlong(cp->sf, -1 - errno); fflush(cp->sf); free(oldname); return; } if (unlink(oldname) < 0) { putlong(cp->sf, -1 - errno); fflush(cp->sf); free(oldname); unlink(newname); return; } } free(oldname); putlong(cp->sf, 0); fflush(cp->sf); } c_unlink(cp) struct connection *cp; { char *name; int n; if ((name = getstr(cp->sfd, &n)) == NULL) return; if (debug) printf("unlink %s\n", name); if (cp->dirp == NULL) n = unlink(name); else n = rmdir(name); putlong(cp->sf, n); fflush(cp->sf); } c_mkdir(cp) struct connection *cp; { char *name; int n, e; if ((name = getstr(cp->sfd, &n)) == NULL) return; if (debug) printf("unlink %s\n", name); if ((e = mkdir(name, 0777)) < 0) e = -1 - errno; putlong(cp->sf, e); fflush(cp->sf); cp->dirp = opendir(name); cp->fd = cp->dirp->dd_fd; } c_trunc(cp) struct connection *cp; { if (ftruncate(cp->fd, lseek(cp->fd, 0L, 1)) < 0) putlong(cp->sf, -1 - errno); else putlong(cp->sf, 0); fflush(cp->sf); } char * getstr(fd, lenp) int fd, *lenp; { int i, n; char *bp, *ret; if ((n = getlong(fd)) < 0) return NULL; ret = bp = getbuf(n + 1); if (lenp != NULL) *lenp = n; while (n > 0) { if ((i = read(fd, bp, n)) <= 0) return NULL; n -= i; bp += i; } *bp = '\0'; return ret; } char * getbuf(n) int n; { static char *bufp; static int size; if (n > size) { if (bufp != NULL) free(bufp); size = n; bufp = malloc(n); } return bufp; } getlong(fd) int fd; { long n; if (read(fd, &n, sizeof n) != sizeof n) return -1; n = ntohl(n); return n; } putlong(f, n) FILE *f; long n; { n = ntohl(n); fwrite(&n, sizeof n, 1, f); } putshort(f, n) FILE *f; short n; { n = ntohs(n); fwrite(&n, sizeof n, 1, f); } SHAR_EOF chmod +x 'v2d.c' fi # end of overwriting check if test -f 'v2.h' then echo shar: will not over-write existing file "'v2.h'" else cat << \SHAR_EOF > 'v2.h' #include "attr.h" #define NULL 0 #define ios_$create_opt ((ios_$open_options_t) 0x1000) #define getlong() _getlong(hp->sock_fd) #define putlong(n) _putlong(hp->sock_fd, n) #define putbytes(bp, n) _putbytes(hp->sock_fd, bp, n) typedef struct { char *sfcb_ptr; int sock_fd; char *key_ptr; boolean seek_key_shared; boolean unreg; boolean read_only; boolean inq_only; boolean append_mode; boolean delete; xoid_$t xoid; int level; char name[80]; boolean bak_mode; boolean cant_write; uid_$t type; struct attr a_cache; boolean a_cache_valid; boolean dirp; char buffer[1024]; int buf_start_key; int buf_pos; int buf_cnt; int last_read; boolean buf_valid; int file_pos; boolean file_pos_valid; } v2_handle_t; extern uid_$t v2_$uid, v2f_$uid; SHAR_EOF chmod +x 'v2.h' fi # end of overwriting check if test -f 'address' then echo shar: will not over-write existing file "'address'" else cat << \SHAR_EOF > 'address' SHAR_EOF chmod +x 'address' fi # end of overwriting check cd .. # End of shell archive exit 0