1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/dtfile/ModAttrP.c
2012-08-30 19:54:01 +01:00

563 lines
16 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: ModAttrP.c /main/8 1999/12/09 13:07:16 mgreess $ */
/************************************<+>*************************************
****************************************************************************
*
* FILE: ModAttrP.c
*
* COMPONENT_NAME: Desktop File Manager (dtfile)
*
* Description: Processing functions for the modify file attribute dialog.
*
* FUNCTIONS: AttrChangePipeCB
* AttrChangeProcess
* ModAttrChange
* ModAttrClose
* ShowModAttrDialog
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
*
****************************************************************************
************************************<+>*************************************/
#if defined __osf__ || defined _AIX
#include <stdio.h>
#endif
#include <grp.h>
#include <pwd.h>
#include <errno.h>
#include <ctype.h>
#include <Xm/Xm.h>
#include <Xm/XmP.h>
#include <Xm/RowColumn.h>
#include <Dt/Connect.h>
#include <Dt/FileM.h>
#include <Tt/tttk.h>
#include "Encaps.h"
#include "SharedProcs.h"
#include "FileMgr.h"
#include "Desktop.h"
#include "Main.h"
#include "Help.h"
#include "ModAttr.h"
extern int mod_attr_dialog;
/* types of messages sent through the pipe */
#define PIPEMSG_DONE 1
/* callback data for pipe input handler */
typedef struct
{
char *host;
char *directory;
char *file;
int child;
} AttrChangeCBData;
/******** Static Function Declarations ********/
void ModAttrChange(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data,
XtPointer call_data) ;
void ModAttrClose(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data) ;
/******** End Static Function Declarations ********/
/************************************************************************
*
* ShowModAttrDialog
* Callback functions invoked from the Modify Attributes ... menu
* item. This function displays the file attribute dialog.
*
************************************************************************/
void
ShowModAttrDialog(
Widget w,
XtPointer client_data,
XtPointer callback )
{
FileMgrRec * file_mgr_rec;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
DialogData * attr_dialog;
DirectorySet * directory_set;
FileViewData * file_view_data;
ModAttrRec *modAttr_rec;
int count, i;
Boolean loadOk=True;
char * errorMsg=NULL;
char * title=NULL;
Arg args[1];
Widget mbar;
char * tmpStr, *tempStr;
XmUpdateDisplay (w);
if((int)client_data != 0)
mbar = XtParent(w);
else
mbar = XmGetPostedFromWidget(XtParent(w));
XtSetArg(args[0], XmNuserData, &file_mgr_rec);
XtGetValues(mbar, args, 1);
/* Ignore accelerators when we're insensitive */
if (client_data == NULL)
if ((file_mgr_rec->menuStates & MODIFY) == 0)
return;
/* Ignore accelerators received after we're unposted */
if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
return;
file_mgr_data = (FileMgrData *) dialog_data->data;
/* get the file_view_data object from which the menu was invoked */
if (client_data == NULL)
file_view_data = NULL;
else
{
file_view_data = file_mgr_data->popup_menu_icon;
if (file_view_data == NULL)
/* the object has gone away (probably deleted) */
return;
file_mgr_data->popup_menu_icon = NULL; /* Reset it, we don't need it */
}
attr_dialog = _DtGetDefaultDialogData (mod_attr_dialog);
file_mgr_rec->menuStates &= ~MODIFY;
if (file_view_data == NULL)
{
directory_set =
(DirectorySet *) file_mgr_data->selection_list[0]->directory_set;
/* Determine which file is selected */
loadOk = LoadFileAttributes(file_mgr_data->host, directory_set->name,
file_mgr_data->selection_list[0]->file_data->file_name,
(ModAttrData *)attr_dialog->data);
}
else
{
directory_set =
(DirectorySet *)file_view_data->directory_set;
/* Determine which file is selected */
loadOk = LoadFileAttributes(file_mgr_data->host, directory_set->name,
file_view_data->file_data->file_name,
(ModAttrData *)attr_dialog->data);
}
if (loadOk)
{
/* Get the initial attribute values for seleceted file */
_DtAddOneSubdialog (attr_dialog,
&file_mgr_data->attr_dialog_list,
&file_mgr_data->attr_dialog_count);
/* We need the file_mgr_rec inside the create routine so
* we attach it here for use later.
*/
((ModAttrData *) (attr_dialog->data))->main_widget = file_mgr_rec->main;
_DtShowDialog (file_mgr_rec->shell, NULL,
(XtPointer)file_mgr_rec, attr_dialog,
ModAttrChange, (XtPointer)file_mgr_rec, ModAttrClose,
(XtPointer)file_mgr_rec,NULL, False, False, NULL, NULL);
for(i = 0; i < file_mgr_data->attr_dialog_count; i++)
{
modAttr_rec = (ModAttrRec *)_DtGetDialogInstance(
file_mgr_data->attr_dialog_list[i]);
if(file_mgr_data->title != NULL &&
strcmp(file_mgr_data->helpVol, DTFILE_HELP_NAME) != 0)
{
tmpStr = GETMESSAGE(21, 1, "File Permissions");
tempStr = (char *)XtMalloc(strlen(tmpStr) +
strlen(file_mgr_data->title) + 5);
sprintf(tempStr, "%s - %s", file_mgr_data->title, tmpStr);
}
else
{
tmpStr = (GETMESSAGE(21,34, "File Manager - Permissions"));
tempStr = XtNewString(tmpStr);
}
XtSetArg (args[0], XmNtitle, tempStr);
XtSetValues (modAttr_rec->shell, args, 1);
XtFree(tempStr);
}
}
else
{
/* Clean up used structures and put up an error dialog */
file_mgr_rec->menuStates |= MODIFY;
_DtFreeDialogData (attr_dialog);
tmpStr = GETMESSAGE(22, 4, "Cannot open object.");
errorMsg = XtNewString(tmpStr);
tmpStr = GETMESSAGE(22, 5, "Set Permissions Error");
title = XtNewString(tmpStr);
_DtMessage (file_mgr_rec->shell, title, errorMsg, NULL, HelpRequestCB);
XtFree(title);
XtFree(errorMsg);
}
}
/************************************************************************
*
* ModAttrChange
* Callback functions invoked from the file attribute dialog's
* Ok button being pressed. This function updates the indicated
* file.
*
************************************************************************/
/*--------------------------------------------------------------------
* AttrChangeProcess
* Main routine of background process for AttrChange
*------------------------------------------------------------------*/
static int
AttrChangeProcess(
int pipe_fd,
char *host,
char *directory,
char *file,
int uid,
int gid,
long mode)
{
char *path;
struct stat stat_buf;
long modify_time;
short pipe_msg;
int rc = -1;
Tt_status tt_status;
/* get directory timestamp */
path = ResolveLocalPathName(host, directory, NULL,home_host_name, &tt_status);
if( TT_OK == tt_status )
{
if (stat(path, &stat_buf) == 0)
modify_time = stat_buf.st_mtime;
XtFree(path);
/* change the file attributes */
path = ResolveLocalPathName(host, directory, file, home_host_name, &tt_status);
if( TT_OK == tt_status )
{
if (chmod(path, mode) == 0)
{
rc = 0;
chown(path, uid, gid);
}
else
rc = errno;
XtFree (path);
}
}
/* send a 'done' msg through the pipe */
DPRINTF(("AttrChangeProcess: sending DONE, rc %d\n", rc));
pipe_msg = PIPEMSG_DONE;
write(pipe_fd, &pipe_msg, sizeof(short));
write(pipe_fd, &rc, sizeof(int));
write(pipe_fd, &modify_time, sizeof(long));
return rc;
}
/*--------------------------------------------------------------------
* AttrChangePipeCB:
* Read and process data sent through the pipe.
*------------------------------------------------------------------*/
static void
AttrChangePipeCB(
XtPointer client_data,
int *fd,
XtInputId *id)
{
AttrChangeCBData *cb_data = (AttrChangeCBData *)client_data;
short pipe_msg;
char *title, *err_msg, *err_arg;
long modify_time;
int i, n, rc;
/* read the msg from the pipe */
pipe_msg = -1;
n = PipeRead(*fd, &pipe_msg, sizeof(short));
if (pipe_msg == PIPEMSG_DONE)
{
PipeRead(*fd, &rc, sizeof(int));
PipeRead(*fd, &modify_time, sizeof(long));
}
else
{
fprintf(stderr, "Internal error in AttrChangePipeCB: bad pipe_msg %d\n",
pipe_msg);
rc = 0;
modify_time = 0;
}
DPRINTF(("AttrChangePipeCB: n %d, pipe_msg %d, rc %d\n", n, pipe_msg, rc));
/* if error, post error message */
if (rc)
{
err_msg = XtNewString(GETMESSAGE(22,3,"Cannot change properties for %s"));
FileOperationError(toplevel, err_msg, cb_data->file);
XtFree(err_msg);
}
/* arrange for modified directory to be updated */
if (modify_time != 0)
DirectoryModifyTime(cb_data->host, cb_data->directory, modify_time);
DirectoryFileModified(cb_data->host, cb_data->directory, cb_data->file);
DirectoryEndModify(cb_data->host, cb_data->directory);
if(!strcmp(cb_data->file,".") || !strcmp(cb_data->file,".."))
{
char *dir;
char *tmpptr = strrchr(cb_data->directory,'/');
if(tmpptr)
{
if(tmpptr != cb_data->directory)
tmpptr = NULL, dir = cb_data->directory;
else
dir = "/";
DirectoryBeginModify(cb_data->host,dir);
DirectoryFileModified(cb_data->host,dir, tmpptr+1);
DirectoryEndModify(cb_data->host,dir);
if(tmpptr)
*tmpptr='/';
}
}
else
{
char subdir_name[MAX_PATH + 1];
char *p;
strcpy(subdir_name, cb_data->directory);
p = subdir_name + strlen(subdir_name);
if (p[-1] != '/')
*p++ = '/';
strcpy(p, cb_data->file);
UpdateDirectory(NULL,cb_data->host, subdir_name);
}
/* close the pipe and cancel the callback */
close(*fd);
XtRemoveInput(*id);
/* free callback data */
XtFree(cb_data->host);
XtFree(cb_data->directory);
XtFree(cb_data->file);
XtFree((char *)cb_data);
}
/*--------------------------------------------------------------------
* ModAttrChange:
* Start the background process and set up callback for the pipe.
*------------------------------------------------------------------*/
void
ModAttrChange(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data,
XtPointer call_data )
{
static char *pname = "ModAttrChange";
AttrChangeCBData *cb_data;
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
ModAttrData * current;
ModAttrData * old;
struct group * gr;
struct passwd * pw;
int uid, gid;
long mode;
int pipe_fd[2];
int pid;
int rc;
/* Get current data */
current = (ModAttrData *) new_dialog_data->data;
old = (ModAttrData *) old_dialog_data->data;
/* see if anything has changed */
if (strcmp(current->owner, old->owner) == 0 &&
strcmp(current->group, old->group) == 0 &&
current->accessBits == old->accessBits &&
current->setuidBits == old->setuidBits)
{
/* nothing changed: close the dialog and return */
ModAttrClose ((XtPointer)file_mgr_rec, old_dialog_data, new_dialog_data);
return;
}
/* get new owner uid */
pw = getpwnam(current->owner);
if (pw)
uid = pw->pw_uid;
else if (isdigit(current->owner[0]))
uid = atoi(current->owner);
else
uid = -1;
/* get new group gid */
gr = getgrnam(current->group);
if (gr)
gid = gr->gr_gid;
else if (isdigit(current->group[0]))
gid = atoi(current->group);
else
gid = -1;
/* get new file mode */
mode = current->accessBits + current->setuidBits;
/* set up callback data */
cb_data = XtNew(AttrChangeCBData);
cb_data->host = XtNewString(current->host);
cb_data->directory = XtNewString(current->directory);
cb_data->file = XtNewString(current->name);
/* mark the directory as being modified in the directory cache */
DirectoryBeginModify(cb_data->host, cb_data->directory);
/* create a pipe */
pipe(pipe_fd);
/* fork the process that does the actual work */
pid = fork();
if (pid == -1)
{
DirectoryAbortModify(cb_data->host, cb_data->directory);
fprintf(stderr,
"%s: fork failed, ppid %d, pid %d: error %d=%s\n",
pname, getppid(), getpid(), errno, strerror(errno));
return;
}
if (pid == 0)
{
/* child process */
DBGFORK(("%s: child forked, pipe %d\n", pname, pipe_fd[1]));
close(pipe_fd[0]); /* child won't read from the pipe */
rc = AttrChangeProcess(pipe_fd[1], cb_data->host, cb_data->directory,
cb_data->file, uid, gid, mode);
close(pipe_fd[1]);
DBGFORK(("%s: child exiting (rc %d)\n", pname, rc));
exit(rc);
}
DBGFORK(("%s: forked child<%d>, pipe %d\n", pname, pid, pipe_fd[0]));
/* parent: set up callback to get the pipe data */
close(pipe_fd[1]); /* parent won't write the pipe */
cb_data->child = pid;
XtAppAddInput(XtWidgetToApplicationContext(toplevel),
pipe_fd[0], (XtPointer)XtInputReadMask,
AttrChangePipeCB, (XtPointer)cb_data);
ModAttrClose ((XtPointer)file_mgr_rec, old_dialog_data, new_dialog_data);
}
/************************************************************************
*
* ModAttrClose
* Callback function invoked from the file attribute dialog's close
* button.
*
************************************************************************/
void
ModAttrClose(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
FileMgrData * file_mgr_data;
DialogData * dialog_data;
int count;
int i, j;
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
if(file_mgr_data->selected_file_count > 0)
file_mgr_rec->menuStates |= MODIFY;
/* Remove the dialog data from the file managers list */
_DtHideOneSubdialog( old_dialog_data,
&file_mgr_data->attr_dialog_list,
&file_mgr_data->attr_dialog_count);
_DtHideDialog (old_dialog_data, False);
_DtFreeDialogData (old_dialog_data);
_DtFreeDialogData (new_dialog_data);
}