|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T f
Length: 43356 (0xa95c) Types: TextFile Names: »ftamd-select.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/ftam2/ftamd-select.c«
/* ftamd-select.c - FTAM responder -- selection regime */ #ifndef lint static char *rcsid = "$Header: /f/osi/ftam2/RCS/ftamd-select.c,v 7.0 89/11/23 21:54:29 mrose Rel $"; #endif /* * $Header: /f/osi/ftam2/RCS/ftamd-select.c,v 7.0 89/11/23 21:54:29 mrose Rel $ * * * $Log: ftamd-select.c,v $ * Revision 7.0 89/11/23 21:54:29 mrose * Release 6.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include <grp.h> #include <stdio.h> #include <pwd.h> #include "ftamsystem.h" #define NUID 400 #define NGID 400 #define FA_CHATTR \ (FA_FILENAME | FA_ACCOUNT) #define FA_PERM_WRITE (FA_PERM_INSERT | FA_PERM_REPLACE | FA_PERM_EXTEND \ | FA_PERM_ERASE) #define FA_PERM_OWNER FA_PERM_CHNGATTR #define FA_PERM_PARENT FA_PERM_DELETE #ifdef SYS5 struct group *getgrnam (); struct passwd *getpwnam (), *getpwent (), *getpwuid (); #endif /* \f DATA */ static char mvfile[MAXPATHLEN]; static PE rdparam = NULLPE; char *getfile (); #ifdef BRIDGE #define E_OK R_OK #else char *getuser (), *getgroup (); #endif long lseek (); #ifdef SYS5 #define EACCESS access #define rename(f1,f2) \ (unlink (f2), link (f1, f2) != NOTOK ? unlink (f1) : NOTOK) #endif #ifdef BRIDGE #define ftp_access(file,mode) ftp_exist (file) #endif /* \f SELECTION REGIME */ int ftam_selection (ftg, ftm) register struct FTAMgroup *ftg, *ftm; { int action, state; bzero ((char *) ftm, sizeof *ftm); ftm -> ftg_flags = ftg -> ftg_flags; statok = 0; state = FSTATE_SUCCESS; if (ftg -> ftg_flags & FTG_SELECT) { register struct FTAMselect *ftse = &ftg -> ftg_select; register struct FTAMattributes *fa = &ftse -> ftse_attrs; struct FTAMdiagnostic *dp = ftm -> ftg_select.ftse_diags; errno = 0; if (!(fa -> fa_present & FA_FILENAME) || fa -> fa_nfile != 1 || (myfile = getfile (fa -> fa_files[0])) == NULL #ifdef BRIDGE || ftp_access (myfile, E_OK) == NOTOK) { #else || stat (myfile, &myst) == NOTOK) { #endif dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_FILENAME; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; if (errno) { (void) strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); } else dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_select; } statok = 1; #ifndef BRIDGE switch (myst.st_mode & S_IFMT) { case S_IFREG: case S_IFDIR: break; default: if (myst.st_dev == null_dev && myst.st_ino == null_ino) { myst.st_mode &= ~S_IFMT, myst.st_mode |= S_IFREG; break; } dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_AVAIL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_select; } #else /* can't check a file you don't have */ #endif if (ftg -> ftg_flags & FTG_RDATTR) ftse -> ftse_access |= FA_PERM_READATTR; if (ftg -> ftg_flags & FTG_CHATTR) ftse -> ftse_access |= FA_PERM_CHNGATTR; if (ftg -> ftg_flags & FTG_DELETE) ftse -> ftse_access |= FA_PERM_DELETE; if (chkaccess (NOTOK, ftse -> ftse_access, &ftse -> ftse_conctl, &dp) == NOTOK) { state = FSTATE_FAILURE; goto done_select; } #ifndef BRIDGE if (ftse -> ftse_account) { if ((mygid = findgid (ftse -> ftse_account)) == NOTOK) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_ACCOUNT; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_select; } } else #else /* no account checking */ #endif mygid = NOTOK; done_select: ; myaccess = ftse -> ftse_access; ftm -> ftg_select.ftse_state = state; ftm -> ftg_select.ftse_ndiag = dp - ftm -> ftg_select.ftse_diags; } if (ftg -> ftg_flags & FTG_CREATE) { register struct FTAMcreate *ftce = &ftg -> ftg_create; register struct FTAMattributes *fa = &ftce -> ftce_attrs; struct FTAMdiagnostic *dp = ftm -> ftg_create.ftce_diags; register struct vfsmap *vf; if (!(fa -> fa_present & FA_FILENAME) || fa -> fa_nfile != 1 || (myfile = getfile (fa -> fa_files[0])) == NULL) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_FILENAME; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_create; } #ifdef BRIDGE if (ftp_access (myfile, E_OK) != NOTOK) #else if (stat (myfile, &myst) != NOTOK) #endif statok = 1; if (statok) { #ifndef BRIDGE /* Assume file type allow corrective action */ switch (myst.st_mode & S_IFMT) { case S_IFREG: break; case S_IFDIR: switch (ftce -> ftce_override) { case FOVER_WRITE: dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_CRELOSE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_create; default: break; } break; default: if (myst.st_dev == null_dev && myst.st_ino == null_ino) { myst.st_mode &= ~S_IFMT, myst.st_mode |= S_IFREG; break; } dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_AVAIL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_create; } #endif switch (ftce -> ftce_override) { case FOVER_FAIL: dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_EXISTS; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_create; case FOVER_SELECT: if (ftg -> ftg_flags & FTG_RDATTR) ftce -> ftce_access |= FA_PERM_READATTR; if (ftg -> ftg_flags & FTG_CHATTR) ftce -> ftce_access |= FA_PERM_CHNGATTR; if (ftg -> ftg_flags & FTG_DELETE) ftce -> ftce_access |= FA_PERM_DELETE; if (chkaccess (NOTOK, ftce -> ftce_access, &ftce -> ftce_conctl, &dp) == NOTOK) { state = FSTATE_FAILURE; goto done_create; } break; default: break; } } for (vf = vfs; vf -> vf_entry; vf++) if (vf -> vf_oid && oid_cmp (vf -> vf_oid, fa -> fa_contents) == 0) break; if (!vf -> vf_entry) { (void) sprintf (dp -> ftd_data, "invalid contents-type %s", sprintoid (fa -> fa_contents)); dp -> ftd_cc = strlen (dp -> ftd_data); dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_ATRVALUE; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; dp++; state = FSTATE_FAILURE; goto done_create; } if (chkattrs (fa, fa -> fa_present & ~(FA_FILENAME | FA_CONTENTS), 1, &dp) == NOTOK) { state = FSTATE_FAILURE; goto done_create; } #ifndef BRIDGE /* no account checking */ if (ftce -> ftce_account) { if ((mygid = findgid (ftce -> ftce_account)) == NOTOK) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_ACCOUNT; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; state = FSTATE_FAILURE; goto done_create; } } else #endif mygid = NOTOK; done_create: ; ftm -> ftg_create.ftce_state = state; ftm -> ftg_create.ftce_ndiag = dp - ftm -> ftg_create.ftce_diags; } if (ftg -> ftg_flags & FTG_RDATTR) ftm -> ftg_readattr.ftra_action = FACTION_SUCCESS; if (ftg -> ftg_flags & FTG_CHATTR) { register struct FTAMchngattr *ftca = &ftg -> ftg_chngattr; register struct FTAMattributes *fa = &ftca -> ftca_attrs; struct FTAMdiagnostic *dp = ftm -> ftg_chngattr.ftca_diags; if (chkattrs (fa, fa -> fa_present, 0, &dp) == NOTOK) action = FACTION_PERM; else action = FACTION_SUCCESS; ftm -> ftg_chngattr.ftca_action = action; ftm -> ftg_chngattr.ftca_ndiag = dp - ftm -> ftg_chngattr.ftca_diags; } if (ftg -> ftg_flags & FTG_OPEN) { register struct FTAMopen *ftop = &ftm -> ftg_open; ftop -> ftop_state = FSTATE_FAILURE; ftop -> ftop_action = FACTION_SUCCESS; if (ftop -> ftop_contents = ftg -> ftg_open.ftop_contents) ftop -> ftop_parameter = ftg -> ftg_open.ftop_parameter; FCINIT (&ftop -> ftop_conctl); } if (ftg -> ftg_flags & FTG_CLOSE) ftm -> ftg_close.ftcl_action = FACTION_SUCCESS; if (ftg -> ftg_flags & FTG_DESELECT) ftm -> ftg_deselect.ftde_action = FACTION_SUCCESS; if (ftg -> ftg_flags & FTG_DELETE) ftm -> ftg_delete.ftxe_action = FACTION_SUCCESS; if (ftg -> ftg_flags & FTG_SELECT) { register struct FTAMselect *ftse = &ftm -> ftg_select; register struct FTAMattributes *fa = &ftse -> ftse_attrs; if (state != FSTATE_SUCCESS) { ftse -> ftse_action = FACTION_PERM; *fa = ftg -> ftg_select.ftse_attrs; /* struct copy */ ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN); return; } ftse -> ftse_action = FACTION_SUCCESS; fa -> fa_present = FA_FILENAME; fa -> fa_nfile = 0; fa -> fa_files[fa -> fa_nfile++] = myfile; } if (ftg -> ftg_flags & FTG_CREATE) { register struct FTAMattributes *fa = &ftg -> ftg_create.ftce_attrs; register struct FTAMcreate *ftce = &ftm -> ftg_create; struct FTAMdiagnostic *dp = ftce -> ftce_diags + ftce -> ftce_ndiag; if (state != FSTATE_SUCCESS) { ftce -> ftce_action = FACTION_PERM; ftce -> ftce_attrs = *fa; /* struct copy */ ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN); return; } switch (ftg -> ftg_create.ftce_override) { case FOVER_SELECT: default: if (statok) break; goto do_create; case FOVER_DELETE: #ifdef BRIDGE if (statok && ftp_delete (myfile) == NOTOK) { #else if (statok && ((myst.st_mode & S_IFMT) == S_IFREG ? unlink (myfile) : rmdir (myfile)) == NOTOK) { bad_override: ; #endif dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_CRELOSE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; #ifdef BRIDGE (void) strcpy (dp -> ftd_data, ftp_error); #else (void) strcpy (dp -> ftd_data, sys_errname (errno)); #endif dp -> ftd_cc = strlen (dp -> ftd_data); dp++; bad_create: ; ftce -> ftce_action = FACTION_PERM; ftce -> ftce_attrs = *fa; /* struct copy */ ftce -> ftce_ndiag = dp - ftce -> ftce_diags; ftce -> ftce_state = FSTATE_FAILURE; ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN); return; } /* else fall */ case FOVER_FAIL: statok = 0; do_create: ; if (!(fa -> fa_present & FA_CONTENTS) || oid_cmp (vfs[VFS_FDF].vf_oid, fa -> fa_contents)) { #ifdef BRIDGE if (ftp_create (myfile) == NOTOK) { #else if ((myfd = open (myfile, O_RDWR | O_CREAT | O_TRUNC, 0666)) == NOTOK) { #endif bad_open: ; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_CREATE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; (void) strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; goto bad_create; } } else #ifdef BRIDGE if (ftp_mkdir (myfile) == NOTOK) #else if (mkdir (myfile, 0755) == NOTOK) #endif goto bad_open; if (chngattrs (fa -> fa_present & ~(FA_FILENAME | FA_CONTENTS), fa, &dp) == NOTOK) goto bad_create; break; case FOVER_WRITE: if (!statok) goto do_create; #ifndef BRIDGE #ifdef SUNOS4 if (myst.st_size > 0 && truncate (myfile, (off_t) 0) == NOTOK) goto bad_override; #else if (myst.st_size > 0 && truncate (myfile, 0) == NOTOK) goto bad_override; #endif #endif break; } ftce -> ftce_action = FACTION_SUCCESS; (void) readattrs (FA_FILENAME | FA_ACTIONS | FA_CONTENTS, &ftce -> ftce_attrs, fa -> fa_contents, fa -> fa_parameter, myfile, &myst, &dp); if (fa -> fa_present & FA_ACTIONS) ftce -> ftce_attrs.fa_permitted &= fa -> fa_permitted; ftce -> ftce_ndiag = dp - ftce -> ftce_diags; } if (ftg -> ftg_flags & FTG_RDATTR && (ftm -> ftg_readattr.ftra_action == FACTION_SUCCESS)) { register struct FTAMreadattr *ftra = &ftm -> ftg_readattr; struct FTAMdiagnostic *dp = ftra -> ftra_diags + ftra -> ftra_ndiag; if (!statok) { #ifdef BRIDGE if (0) { /* assume OK */ #else if ((myfd != NOTOK ? fstat (myfd, &myst) : stat (myfile, &myst)) == NOTOK) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_MGT_READ; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; #endif bad_readattr: ; ftra -> ftra_action = FACTION_PERM; ftra -> ftra_ndiag = dp - ftra -> ftra_diags; return; } else statok++; } if (readattrs (ftg -> ftg_readattr.ftra_attrnames, &ftra -> ftra_attrs, ftg -> ftg_flags & FTG_OPEN ? ftg -> ftg_open.ftop_contents : NULLOID, NULLPE, myfile, &myst, &dp) == NOTOK) goto bad_readattr; ftra -> ftra_ndiag = dp - ftra -> ftra_diags; } if (ftg -> ftg_flags & FTG_CHATTR && (ftm -> ftg_chngattr.ftca_action == FACTION_SUCCESS)) { register struct FTAMchngattr *ftca = &ftm -> ftg_chngattr; register struct FTAMattributes *fa = &ftg -> ftg_chngattr.ftca_attrs; struct FTAMdiagnostic *dp = ftca -> ftca_diags + ftca -> ftca_ndiag; if (chngattrs (fa -> fa_present, fa, &dp) == NOTOK) { ftca -> ftca_action = FACTION_PERM; ftca -> ftca_ndiag = dp - ftca -> ftca_diags; return; } ftca -> ftca_ndiag = dp - ftca -> ftca_diags; } if (ftg -> ftg_flags & FTG_OPEN) { #ifndef BRIDGE int mode; #endif register struct FTAMopen *ftop = &ftm -> ftg_open; struct FTAMdiagnostic *dp = ftop -> ftop_diags + ftop -> ftop_ndiag; ftop -> ftop_state = FSTATE_SUCCESS; if (statok == 0) { if (stat (myfile, &myst) == NOTOK) { #ifndef BRIDGE unavailable: ; #endif dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_AVAIL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; if (errno) { (void) strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); } else dp -> ftd_cc = 0; dp++; ftop -> ftop_state = FSTATE_FAILURE; goto done_open; } else statok = 1; } if (ftop -> ftop_contents == NULL) { register struct FTAMattributes *fa; if (ftg -> ftg_flags & FTG_CREATE) { fa = &ftg -> ftg_create.ftce_attrs; ftop -> ftop_contents = fa -> fa_contents; ftop -> ftop_parameter = fa -> fa_parameter; advise (LLOG_DEBUG, NULLCP, "using contents-type from CREATE <%s, 0x%x>", oid2ode (ftop -> ftop_contents), ftop -> ftop_parameter); goto find_myvfs; } if ((ftg -> ftg_flags & FTG_RDATTR) && ftm -> ftg_readattr.ftra_action == FACTION_SUCCESS && ((fa = &ftm -> ftg_readattr.ftra_attrs) -> fa_present & FA_CONTENTS)) { ftop -> ftop_contents = fa -> fa_contents; ftop -> ftop_parameter = fa -> fa_parameter; advise (LLOG_DEBUG, NULLCP, "using contents-type from READ-ATTRIBUTE <%s, 0x%x>", oid2ode (ftop -> ftop_contents), ftop -> ftop_parameter); find_myvfs: ; if ((myvf = st2vfs (myfd, myfile, &myst, ftop -> ftop_contents, ftamfd)) == NULL) goto no_ascertain; if (oid_cmp (ftop -> ftop_contents, myvf -> vf_oid) == 0) goto find_param; advise (LLOG_DEBUG, NULLCP, "wrong intuition; back to step one"); ftop -> ftop_contents = NULLOID; ftop -> ftop_parameter = NULLPE; } if ((myvf = st2vfs (myfd, myfile, &myst, NULLOID, ftamfd)) == NULL) { no_ascertain: ; (void) strcpy (dp -> ftd_data, "unable to ascertain contents-type"); dp -> ftd_cc = strlen (dp -> ftd_data); dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_ACC_LCL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp++; ftop -> ftop_state = FSTATE_FAILURE; goto done_open; } ftop -> ftop_contents = myvf -> vf_oid; advise (LLOG_DEBUG, NULLCP, "using contents-type from st2vfs: %s", oid2ode (ftop -> ftop_contents)); find_param: ; if (myvf -> vf_mandatory > 0 && ftop -> ftop_parameter == NULL) { char buffer[BUFSIZ]; if (rdparam) pe_free (rdparam), rdparam = NULLPE; if ((*myvf -> vf_encode) (&rdparam, 1, 0, NULLCP, myvf -> vf_parameter) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "unable to build parameter: %s", PY_pepy); if (rdparam) pe_free (rdparam), rdparam = NULLPE; goto no_ascertain; } ftop -> ftop_parameter = rdparam; vpushstr (buffer); vunknown (ftop -> ftop_parameter); vpopstr (); advise (LLOG_DEBUG, NULLCP, "generating parameter from vfs: %s", buffer); } else if (!myvf -> vf_mandatory && ftop -> ftop_parameter) ftop -> ftop_parameter = NULLPE; } else if ((myvf = st2vfs (myfd, myfile, &myst, ftop -> ftop_contents, ftamfd)) == NULL) { dp -> ftd_cc = 0; bad_param: ; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_ACC_TYPINCON; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; dp++; ftop -> ftop_state = FSTATE_FAILURE; goto done_open; } if (oid_cmp (ftop -> ftop_contents, myvf -> vf_oid)) { advise (LLOG_NOTICE, NULLCP, "simplifying document type"); ftop -> ftop_contents = myvf -> vf_oid; ftop -> ftop_parameter = NULLPE; if (myvf -> vf_mandatory) { char buffer[BUFSIZ]; if (rdparam) pe_free (rdparam), rdparam = NULLPE; if ((*myvf -> vf_encode) (&rdparam, 1, 0, NULLCP, myvf -> vf_parameter) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "unable to build parameter: %s", PY_pepy); if (rdparam) pe_free (rdparam), rdparam = NULLPE; goto no_ascertain; } ftop -> ftop_parameter = rdparam; vpushstr (buffer); vunknown (ftop -> ftop_parameter); vpopstr (); advise (LLOG_DEBUG, NULLCP, "generating parameter from myvf: %s", buffer); } } if (ftop -> ftop_parameter) { if (!myvf -> vf_decode) { (void) sprintf (dp -> ftd_data, "unexpected document type parameter"); dp -> ftd_cc = strlen (dp -> ftd_data); goto bad_param; } myparam = NULL; if ((*myvf -> vf_decode) (ftop -> ftop_parameter, 1, NULLIP, NULLVP, &myparam) == NOTOK) { (void) sprintf (dp -> ftd_data, "unable to parse document type parameter: %s", PY_pepy); dp -> ftd_cc = strlen (dp -> ftd_data); goto bad_param; } if (myvf -> vf_check && (*myvf -> vf_check) (myparam, dp -> ftd_data) == NOTOK) goto bad_param; } else if (myvf -> vf_mandatory > 0) { (void) strcpy (dp -> ftd_data, "mandatory document type parameter missing"); dp -> ftd_cc = strlen (dp -> ftd_data); goto bad_param; } mymode = ftg -> ftg_open.ftop_mode; #ifndef BRIDGE if (mymode & FA_PERM_WRITE) mode = (mymode & FA_PERM_READ) ? O_RDWR : O_WRONLY; else mode = O_RDONLY; #endif errno = 0; #ifndef BRIDGE switch (myst.st_mode & S_IFMT) { case S_IFREG: if (myfd == NOTOK && (myfd = open (myfile, mode)) == NOTOK) goto unavailable; break; case S_IFDIR: if (mode == O_RDONLY) break; /* else fall */ default: goto unavailable; } #endif myconctl = ftg -> ftg_open.ftop_conctl; /* struct copy */ ftm -> ftg_open.ftop_conctl = myconctl; /* .. */ mylockstyle = ftg -> ftg_open.ftop_locking; if (chkaccess (myfd, mymode, &myconctl, &dp) == NOTOK) { ftop -> ftop_state = FSTATE_FAILURE; goto done_open; } done_open: ; ftop -> ftop_ndiag = dp - ftop -> ftop_diags; if (ftop -> ftop_state != FSTATE_SUCCESS) { ftop -> ftop_action = FACTION_PERM; return; } } if (ftg -> ftg_flags & FTG_CLOSE && (ftm -> ftg_close.ftcl_action == FACTION_SUCCESS)) { if (myfd != NOTOK) { #ifdef BRIDGE (void) close (myfd); (void) ftp_reply (); #else unlock (); (void) close (myfd); #endif myfd = NOTOK; } if (myvf && myparam) { (void) (*myvf -> vf_free) (myparam); myparam = NULL; } } if (ftg -> ftg_flags & FTG_DESELECT) { register struct FTAMdeselect *ftde = &ftm -> ftg_deselect; if (ftde -> ftde_action == FACTION_SUCCESS) { /* anything to charge if (mygid != NOTOK)? ha! */ } } if (ftg -> ftg_flags & FTG_DELETE) { register struct FTAMdelete *ftxe = &ftm -> ftg_delete; struct FTAMdiagnostic *dp = ftxe -> ftxe_diags + ftxe -> ftxe_ndiag; if (ftxe -> ftxe_action == FACTION_SUCCESS) { #ifdef BRIDGE if (ftp_delete (myfile) == NOTOK) { #else if (!statok && stat (myfile, &myst) == NOTOK) myst.st_mode = S_IFREG; if (((myst.st_mode & S_IFMT) == S_IFREG ? unlink (myfile) : rmdir (myfile)) == NOTOK) { #endif dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_DELETE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; #ifdef BRIDGE (void) strcpy (dp -> ftd_data, ftp_error); #else (void) strcpy (dp -> ftd_data, sys_errname (errno)); #endif dp -> ftd_cc = strlen (dp -> ftd_data); dp++; ftxe -> ftxe_action = FACTION_PERM; ftxe -> ftxe_ndiag = dp - ftxe -> ftxe_diags; return; } advise (LLOG_NOTICE, NULLCP, "delete %s", myfile); } } } /* \f */ #ifdef BRIDGE /* ARGSUSED */ #endif static int chkaccess (fd, request, fc, diags) int fd, request; #ifndef BRIDGE register #endif struct FTAMconcurrency *fc; register struct FTAMdiagnostic **diags; { int result; #ifndef BRIDGE register char *cp; #endif register struct FTAMdiagnostic *dp = *diags; result = OK; #ifndef BRIDGE if (((request & FA_PERM_READ) && EACCESS (myfile, R_OK) == NOTOK) || ((request & FA_PERM_WRITE) && EACCESS (myfile, W_OK) == NOTOK) || ((request & FA_PERM_OWNER) && (myuid != myst.st_uid && myuid != 0))) { no_access: ; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_ACCAVAIL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; result = NOTOK; goto out; } if (request & FA_PERM_PARENT) { if (cp = rindex (myfile, '/')) { *cp = NULL; result = EACCESS (*myfile ? myfile : "/", W_OK); *cp = '/'; } else result = EACCESS (".", W_OK); if (result == NOTOK) goto no_access; } #else /* already selected file and know it exists, FTP cannot tell us more */ #endif #ifndef BRIDGE out: ; if (attrs & FATTR_STORAGE) { if (fd == NOTOK) { mylock = 0; if (((request & FA_PERM_READATTR) && (fc -> fc_readattrlock & FLOCK_RESTRICT)) || ((request & FA_PERM_CHNGATTR) && (fc -> fc_chngattrlock & FLOCK_RESTRICT)) || ((request & FA_PERM_DELETE) && (fc -> fc_deletelock & FLOCK_RESTRICT))) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_SEL_CONSUPRT; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; result = NOTOK; } } else { #ifdef SYS5 struct flock fs; #endif if ((request & FA_PERM_WRITE) && ((fc -> fc_insertlock & FLOCK_RESTRICT) || (fc -> fc_replacelock & FLOCK_RESTRICT) || (fc -> fc_eraselock & FLOCK_RESTRICT) || (fc -> fc_extendlock & FLOCK_RESTRICT))) { mylock = 1; #ifndef SYS5 if (flock (fd, LOCK_EX) == NOTOK) goto bad_concur; #else fs.l_type = F_WRLCK; fs.l_whence = L_SET; fs.l_start = fs.l_len = 0; if (fcntl (fd, F_SETLKW, &fs) == NOTOK) goto bad_concur; #endif } else if ((request & FA_PERM_READ) && (fc -> fc_readlock & FLOCK_RESTRICT)) { mylock = 1; #ifndef SYS5 if (flock (fd, LOCK_SH) == NOTOK) { #else fs.l_type = F_RDLCK; fs.l_whence = L_SET; fs.l_start = fs.l_len = 0; if (fcntl (fd, F_SETLKW, &fs) == NOTOK) { #endif bad_concur: ; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_ACC_CONAVAIL; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; (void) strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; mylock = 0; result = NOTOK; } } } } #endif *diags = dp; return result; } /* \f */ static int chkattrs (fa, present, select, diags) register struct FTAMattributes *fa; long present; int select; register struct FTAMdiagnostic **diags; { int id, result; char *file; register struct FTAMdiagnostic *dp = *diags; result = OK; present &= ~FA_FUTURESIZE; /* be liberal in what you accept... */ if (present & ~(FA_CHATTR | FA_RDATTR)) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = select ? FS_SEL_INITIAL : (present & FA_RDATTR) ? FS_MGT_CHANGE : FS_MGT_EXIST; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp -> ftd_cc = 0; dp++; result = NOTOK; } id = select ? FS_SEL_ATRVALUE : FS_MGT_VALUE; if (present & FA_FILENAME) { if (fa -> fa_nfile != 1 || (file = getfile (fa -> fa_files[0])) == NULL) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = id; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; (void) strcpy (dp -> ftd_data, "00bad filename"); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; result = NOTOK; } else (void) strcpy (mvfile, file); } #ifndef BRIDGE if ((present & FA_ACCOUNT) && findgid (fa -> fa_account) == NOTOK) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = id; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; (void) strcpy (dp -> ftd_data, "02bad storage account"); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; result = NOTOK; } if ((present & FA_FILESIZE) && fa -> fa_filesize < 0) { dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = id; dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; (void) strcpy (dp -> ftd_data, "13bad filesize"); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; result = NOTOK; } #endif *diags = dp; return result; } /* \f */ int readattrs (attrnames, fa, proposed, parameter, file, st, diags) int attrnames; register struct FTAMattributes *fa; OID proposed; PE parameter; char *file; struct stat *st; register struct FTAMdiagnostic **diags; { #ifndef BRIDGE int result; char *cp; register struct tm *tm; #endif register struct FTAMdiagnostic *dp = *diags; fa -> fa_present = attrnames; fa -> fa_novalue = attrnames & (FA_SECURITY | FA_PRIVATE); if (attrnames & FA_FILENAME) { fa -> fa_nfile = 0; fa -> fa_files[fa -> fa_nfile++] = file; } if (attrnames & FA_ACTIONS) { fa -> fa_permitted = 0; #ifndef BRIDGE if (EACCESS (file, R_OK) != NOTOK) #endif fa -> fa_permitted |= FA_PERM_READ; #ifndef BRIDGE if (EACCESS (file, W_OK) != NOTOK) #endif fa -> fa_permitted |= FA_PERM_WRITE; if (fa -> fa_permitted & (FA_PERM_READ | FA_PERM_WRITE)) fa -> fa_permitted |= FA_PERM_TRAVERSAL; fa -> fa_permitted |= FA_PERM_READATTR; #ifndef BRIDGE if (myuid == st -> st_uid || myuid == 0) #endif fa -> fa_permitted |= FA_PERM_OWNER; #ifndef BRIDGE if (cp = rindex (file, '/')) { *cp = NULL; result = EACCESS (*file ? file : "/", W_OK); *cp = '/'; } else result = EACCESS (".", W_OK); if (result != NOTOK) #endif fa -> fa_permitted |= FA_PERM_PARENT; } if (attrnames & FA_CONTENTS) { register struct vfsmap *vf; if (vf = st2vfs (myfd, file, st, proposed, ftamfd)) { fa -> fa_contents = vf -> vf_oid; if (proposed && oid_cmp (proposed, vf -> vf_oid) == 0 && parameter && vf -> vf_decode && vf -> vf_check) { caddr_t p = NULL; if ((*vf -> vf_decode) (parameter, 1, NULLIP, NULLVP, &p) == NOTOK) { advise (LLOG_NOTICE, NULLCP, "unable to parse document type parameter: %s", PY_pepy); goto bad_param; } if ((*vf -> vf_check) (p, dp -> ftd_data) == NOTOK) { advise (LLOG_NOTICE, NULLCP, "unacceptable document type parameter: %s", dp -> ftd_data); goto bad_param; } (*vf -> vf_free) (p); fa -> fa_parameter = parameter; } bad_param: ; if (vf -> vf_parameter) { if (rdparam) pe_free (rdparam), rdparam = NULLPE; if ((*vf -> vf_encode) (&rdparam, 1, 0, NULLCP, vf -> vf_parameter) == NOTOK) { advise (LLOG_EXCEPTIONS, NULLCP, "unable to build parameter: %s", PY_pepy); if (rdparam) pe_free (rdparam), rdparam = NULLPE; } fa -> fa_parameter = rdparam; } else fa -> fa_parameter = NULLPE; } else fa -> fa_present &= ~FA_CONTENTS; } #ifdef BRIDGE /* these values cannot be obtained from FTP */ if (attrnames & FA_ACCOUNT) #else if ((attrnames & FA_ACCOUNT) && (fa -> fa_account = getgroup (st -> st_gid)) == NULL) #endif fa -> fa_present &= ~FA_ACCOUNT; if (attrnames & FA_DATE_CREATE) #ifndef BRIDGE if (tm = gmtime ((long *) &st -> st_mtime)) tm2ut (tm, &fa -> fa_date_create); else #endif fa -> fa_novalue |= FA_DATE_CREATE; if (attrnames & FA_DATE_MODIFY) #ifndef BRIDGE if (tm = gmtime ((long *) &st -> st_mtime)) tm2ut (tm, &fa -> fa_date_modify); else #endif fa -> fa_novalue |= FA_DATE_MODIFY; if (attrnames & FA_DATE_READ) #ifndef BRIDGE if (tm = gmtime ((long *) &st -> st_atime)) tm2ut (tm, &fa -> fa_date_read); else #endif fa -> fa_novalue |= FA_DATE_READ; if (attrnames & FA_DATE_ATTR) #ifndef BRIDGE if (tm = gmtime ((long *) &st -> st_ctime)) tm2ut (tm, &fa -> fa_date_attribute); else #endif fa -> fa_novalue |= FA_DATE_ATTR; #ifdef BRIDGE if (attrnames & FA_ID_CREATE) #else if ((attrnames & FA_ID_CREATE) && (fa -> fa_id_create = getuser (st -> st_uid)) == NULL) #endif fa -> fa_novalue |= FA_ID_CREATE; #ifdef BRIDGE if (attrnames & FA_ID_MODIFY) #else if ((attrnames & FA_ID_MODIFY) && ((st -> st_mode & 0022) || (fa -> fa_id_modify = getuser (st -> st_uid)) == NULL)) #endif fa -> fa_novalue |= FA_ID_MODIFY; #ifdef BRIDGE if (attrnames & FA_ID_READ) #else if ((attrnames & FA_ID_READ) && ((st -> st_mode & 0044) || (fa -> fa_id_read = getuser (st -> st_uid)) == NULL)) #endif fa -> fa_novalue |= FA_ID_READ; #ifdef BRIDGE if (attrnames & FA_ID_ATTR) #else if ((attrnames & FA_ID_ATTR) && ( (st -> st_mode & 0022) || (fa -> fa_id_attribute = getuser (st -> st_uid)) == NULL)) #endif fa -> fa_novalue |= FA_ID_ATTR; if (attrnames & FA_AVAILABILITY) fa -> fa_availability = FA_AVAIL_IMMED; if (attrnames & FA_FILESIZE) #ifdef BRIDGE fa -> fa_novalue |= FA_FILESIZE; #else fa -> fa_filesize = (int) st -> st_size; #endif if (attrnames & FA_FUTURESIZE) fa -> fa_novalue |= FA_FUTURESIZE; *diags = dp; return OK; } /* \f */ static int chngattrs (present, fa, diags) long present; register struct FTAMattributes *fa; register struct FTAMdiagnostic **diags; { #ifndef BRIDGE int gid, result; #endif register struct FTAMdiagnostic *dp = *diags; #ifdef BRIDGE statok = 1; #else if ((myfd != NOTOK ? fstat (myfd, &myst) : stat (myfile, &myst)) == NOTOK) { bad_system: ; (void) strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); goto no_change; } statok = 1; if (myuid != myst.st_uid && myuid != 0) { errno = EPERM; goto bad_system; } #endif #ifndef BRIDGE if ((present & FA_ACCOUNT) && (gid = findgid (fa -> fa_account)) != NOTOK) { #ifndef SYS5 (void) seteuid (0); result = myfd != NOTOK ? fchown (myfd, -1, gid) : chown (myfile, -1, gid); (void) seteuid (myuid); #else result = chgrp (myfile, gid); #endif if (result == NOTOK) { (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_account, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); no_change: ; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_MGT_CHANGE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp++; *diags = dp; return NOTOK; } myst.st_gid = gid; } #endif if (present & FA_FILENAME) { #ifdef BRIDGE if (ftp_rename (myfile, mvfile) == NOTOK) { (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_files[0], ftp_error); #else if (rename (myfile, mvfile) == NOTOK) { /* on EXDEV could do gonzo copy, but why bother? */ (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_files[0], sys_errname (errno)); #endif dp -> ftd_cc = strlen (dp -> ftd_data); #ifndef BRIDGE goto no_change; #else dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = FS_MGT_CHANGE; dp -> ftd_observer = dp -> ftd_source = EREF_RFSU; dp -> ftd_delay = DIAG_NODELAY; dp++; *diags = dp; return NOTOK; #endif } advise (LLOG_NOTICE, NULLCP, "rename %s to %s", myfile, mvfile); myfile = mvfile; } *diags = dp; return OK; } /* \f */ static char *getfile (file) char *file; { register char *bp; #ifndef BRIDGE register char *cp, *pp; register struct passwd *pw; #endif static int i = 0; static char buffer1[MAXPATHLEN], buffer2[MAXPATHLEN]; bp = (i++ % 2) ? buffer1 : buffer2; #ifndef BRIDGE switch (*file) { case '/': if (strlen (file) >= MAXPATHLEN) goto trunc; (void) strcpy (bp, file); break; case '~': if (cp = index (pp = file + 1, '/')) *cp = NULL; if (*pp == NULL) pp = myhome; else { if ((pw = getpwnam (pp)) == NULL) return NULL; else pp = pw -> pw_dir; } if (strlen (pp) + 1 + (cp ? strlen (cp) : 0) >= MAXPATHLEN) goto trunc; (void) sprintf (bp, "%s/%s", pp, cp ? cp + 1 : ""); if (cp) *cp = '/'; break; default: if (strlen (file) + myhomelen + 1 >= MAXPATHLEN) goto trunc; (void) sprintf (bp, "%s/%s", myhome, file); break; } compath (bp); #ifndef apollo /* always return RELATIVE pathnames */ if (strncmp (bp, myhome, myhomelen - 1) == 0) switch (bp[myhomelen - 1]) { case NULL: (void) strcpy (bp, "."); break; case '/': bp += myhomelen; break; default: break; } #endif return bp; trunc: ; errno = 0; return NULLCP; #else (void) strcpy (bp, file); return bp; #endif } /* \f */ #ifndef BRIDGE /* originally used algorithms similar to those in /bin/ls; Don Preuss of Apollo suggested these algorithms as they work better with distributed /etc/passwd and /etc/group files */ static char *getuser (uid) int uid; { static struct passwd *pw = NULL; if (pw == NULL || pw -> pw_uid != uid) pw = getpwuid (uid); return (pw ? pw -> pw_name : NULL); } /* \f */ static char *getgroup (gid) int gid; { register struct group *gr; static int my_gid = -1; static char my_name[NMAX + 1]; if (my_gid != gid) { if ((gr = getgrgid (gid)) == NULL) return NULL; my_gid = gr -> gr_gid; (void) strcpy (my_name, gr -> gr_name); } return my_name; } /* \f */ int findgid (group) char *group; { int i; #ifdef BSD42 int gidset[NGROUPS]; #endif register struct group *gr; static int my_gid = -1; static char my_name[NMAX + 1] = ""; if (*group == NULL) return NOTOK; if (strcmp (my_name, group) != 0) { if ((gr = getgrnam (group)) == NULL) return NOTOK; #ifdef BSD42 for (i = getgroups (NGROUPS, gidset) - 1; i >= 0; i--) if (gr -> gr_gid == gidset[i]) break; if (i < 0) return NOTOK; #endif (void) strcpy (my_name, gr -> gr_name); my_gid = gr -> gr_gid; } return my_gid; } #endif /* \f */ #ifndef SYS5 #ifndef BRIDGE static int EACCESS (file, mode) char *file; int mode; { int result; (void) seteuid (0); (void) setruid (myuid); result = access (file, mode); (void) setruid (0); (void) seteuid (myuid); return result; } #endif #else /* \f */ static int chgrp (file, gid) char *file; int gid; { int i, pid, status; char group[10]; struct stat st; (void) sprintf (group, "%d", gid); switch (pid = fork ()) { case NOTOK: return NOTOK; case OK: execl ("/bin/chgrp", "chgrp", group, file, NULLCP); execl ("/usr/bin/chgrp", "chgrp", group, file, NULLCP); execl ("/etc/chgrp", "chgrp", group, file, NULLCP); _exit (NOTOK); default: while ((i = wait (&status)) != NOTOK && pid != i) continue; if (i != NOTOK && status) { if (stat (file, &st) == NOTOK || st.st_gid != gid) { i = NOTOK; errno = EACCES; } else status = OK; } return (i == NOTOK ? NOTOK : status); } } /* \f */ static int mkdir (dir, mode) char *dir; int mode; { int i, pid, status; struct stat st; switch (pid = fork ()) { case NOTOK: return NOTOK; case OK: (void) umask (~mode); execl ("/bin/mkdir", "mkdir", dir, NULLCP); execl ("/usr/bin/mkdir", "mkdir", dir, NULLCP); execl ("/etc/mkdir", "mkdir", dir, NULLCP); _exit (NOTOK); default: while ((i = wait (&status)) != NOTOK && pid != i) continue; if (i != NOTOK && status) { if (stat (dir, &st) == NOTOK || (st.st_mode & S_IFMT) != S_IFDIR) { i = NOTOK; errno = EACCES; } else status = OK; } return (i == NOTOK ? NOTOK : status); } } /* \f */ static int rmdir (dir) char *dir; { int i, pid, status; switch (pid = fork ()) { case NOTOK: return NOTOK; case OK: execl ("/bin/rmdir", "rmdir", dir, NULLCP); execl ("/usr/bin/rmdir", "rmdir", dir, NULLCP); execl ("/etc/rmdir", "rmdir", dir, NULLCP); _exit (NOTOK); default: while ((i = wait (&status)) != NOTOK && pid != i) continue; if (i != NOTOK && status) { if (access (dir, 0x00) != NOTOK) { i = NOTOK; errno = EACCES; } else status = OK; } return (i == NOTOK ? NOTOK : status); } } /* \f */ static int truncate (file, length) char *file; int length; { int fd; if (length != 0) { /* XXX: too much work to get right */ errno = EINVAL; return NOTOK; } if ((fd = open (file, O_WRONLY | O_TRUNC)) == NOTOK) return NOTOK; (void) close (fd); return OK; } /* ARGSUSED */ int ftruncate (fd, length) /* works only 'cause we're lucky */ int fd, length; { return truncate (myfile, length); } #endif /* \f DEBUG */ #if defined(FTAMDEBUG) && defined(BSD42) #include <syscall.h> static int unlink (file) char *file; { if (debug) { int i, b; again: ; fprintf (stderr, "unlink(\"%s\")? y, w, l: ", file); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_unlink, file); } static int rmdir (dir) char *dir; { if (debug) { int i, b; again: ; fprintf (stderr, "rmdir(\"%s\")? y, w, l: ", dir); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_rmdir, dir); } /* VARARGS2 */ static int open (file, flags, mode) char *file; int flags, mode; { if (debug) { int i, b; again: ; fprintf (stderr, "open(\"%s\",0x%x,0%o)? y, l: ", file, flags, (flags & O_CREAT) ? mode : 0); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_open, file, flags, mode); } static int mkdir (dir, mode) char *dir; int mode; { if (debug) { int i, b; again: ; fprintf (stderr, "mkdir(\"%s\",0%o)? y, w, l: ", dir, mode); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_mkdir, dir, mode); } static int chown (file, uid, gid) char *file; int uid, gid; { if (debug) { int i, b; again: ; fprintf (stderr, "chown(\"%s\",%d,%d)? y, w, l: ", file, uid, gid); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_chown, file, uid, gid); } static int fchown (fd, uid, gid) int fd; int uid, gid; { if (debug) { int i, b; again: ; fprintf (stderr, "fchown(%d,%d,%d)? y, w, l: ", fd, uid, gid); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_fchown, fd, uid, gid); } static int truncate (file, length) char *file; int length; { if (debug) { int i, b; again: ; fprintf (stderr, "truncate(\"%s\",%d)? y, w, l: ", file, length); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_truncate, file, length); } static int rename (old, new) char *old; char *new; { if (debug) { int i, b; again: ; fprintf (stderr, "rename(\"%s\",\"%s\")? y, w, l: ", old, new); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_rename, old, new); } static int flock (fd, operation) int fd, operation; { if (debug) { int i, b; again: ; fprintf (stderr, "flock(%d,0x%x)? y, w, l: ", fd, operation); i = b = getchar (); while (b != '\n' && b != EOF) b = getchar (); switch (i) { case 'y': break; case 'w': return OK; case 'l': return NOTOK; default: goto again; } } return syscall (SYS_flock, fd, operation); } #endif