OpenSolaris_b135/cmd/fmli/oh/if_dir.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <string.h>
#include <sys/types.h>		/* EFT abs k16 */
#include "wish.h"
#include "menudefs.h"
#include "vtdefs.h"
#include "token.h"
#include "slk.h"
#include "actrec.h"
#include "typetab.h"
#include "ctl.h"
#include "var_arrays.h"
#include "terror.h"
#include "moremacros.h"
#include "message.h"
#include "sizes.h"

extern	menu_id folder_make();
extern	char	*path_to_title();
static int dir_mv_cp();
static int dir_init();

#define MAX_DIRS	(16)

/* The activation record for a file folder contains the ott_tab for the
 * folder in the odptr field.  File folders use the menu human-interface,
 * so the id field of the activation record is a menu_id.
 */

long Sortmodes = OTT_SALPHA, Dispmodes = OTT_DOBJ;
time_t Prefmodtime = (time_t)0L; /* EFT abs k16 */

static int Dirs_open = 0;	/* count how many open */

/* macro to cast the odptr field of an actrec to my struct odptr */

#define MYODPTR(X)	((struct myodptr *)(X->odptr))

struct myodptr {
	struct ott_tab *ott;
	time_t dir_mtime;		/* EFT abs k16 */
	time_t ott_mtime;		/* EFT abs k16 */
	time_t pref_mtime;	/* EFT abs k16 */
};

static int 
dir_close(a) 
struct actrec *a; 
{ 
	extern char *Filecabinet;
	extern char Opwd[];
#ifdef _DEBUG
	_debug(stderr, "DIR_CLOSE\n");
#endif
	ott_unlock_inc(MYODPTR(a)->ott); /* unlock the ott so it can be swapped */
	free(MYODPTR(a));
	if (a->path)
		free(a->path);
	Dirs_open--;
	if ( ! Dirs_open ) {
		(void) chdir(Filecabinet);
		sprintf(&Opwd[5], "%.*s", PATHSIZ, Filecabinet);
	}
	return(menu_close(a->id));		/* close the menu id */
}

static struct menu_line
dir_disp(n, ptr)
int n;
struct ott_tab *ptr;
{
    register int i;
    int size = array_len(ptr->parents);
    int d_cols = COLS - FIXED_COLS;
    struct ott_entry *entry;
    struct menu_line m;
    static char ldescr[MAX_WIDTH];
    char *bsd_path_to_title();

    m.flags = 0;

    if (n == 0 && size == 0) {	/* empty! */
	m.highlight = "Empty Folder";
	m.description = NULL;
    } else if (n >= (int)array_len(ptr->parents)) { /* done */
	m.highlight = m.description = NULL;
    } else {
	entry = &(ptr->ott[ptr->parents[n]]);

	switch (ptr->modes & DISMODES) {
	case 0:			/* don't display anything but name */
	    m.description = NULL;
	    m.highlight = bsd_path_to_title(entry->dname,d_cols);
	    break;
	case OTT_DMARK:
	    m.description = NULL;
	    if (entry->objmask & CL_DIR) {
	        strcpy(ldescr, bsd_path_to_title(entry->dname,(d_cols-1)));
		strcat(ldescr, "/");
	    }
	    else if (strcmp(entry->objtype, "EXECUTABLE") == 0) {
	        strcpy(ldescr, bsd_path_to_title(entry->dname,(d_cols-1)));
		strcat(ldescr, "*");
	    }
	    else
	        strcpy(ldescr, bsd_path_to_title(entry->dname,d_cols));
	    m.highlight = ldescr;
	    break;
	default:
	case OTT_DOBJ:		/* display description only */
	    m.description = entry->display;
	    i = d_cols - strlen(m.description) - 3;
	    m.highlight = entry->dname;
	    break;
	case OTT_DODI:		/* display description with odi value */
	{
	    char *key_val, *odi_getkey();

	    key_val = odi_getkey(entry,"UNDELDIR");
	    if ( key_val && *key_val ) {
		if ( (i = strlen(entry->dname)) > 20 )
		    i = 20;
		i = d_cols - i - strlen(entry->display) - 11;
		sprintf(ldescr,"%s - From %s",entry->display,bsd_path_to_title(key_val, i));
	    } else {
		sprintf(ldescr,"%s - From unknown",entry->display);
	    }
	}
	    i = d_cols - strlen(ldescr) - 3;
	    m.highlight = entry->dname;
	    m.description = ldescr;
	    break;
	case OTT_DMTIME:	/* display long form */
	{
	    char *p, *ct, *ctime();
	    int len, i;
	    bool usrdisp = FALSE;
	    struct ott_entry *tmp;
	    char *def_display();
	    int	lcv;

	    lcv = array_len(ptr->parents);
	    for (i = 0; !usrdisp && i < lcv; i++) {
		tmp = &(ptr->ott[ptr->parents[i]]);
		p = def_display(tmp->objtype);
		if (tmp->display != p && strcmp(tmp->display, p) != 0)
		    usrdisp = TRUE;
	    }

	    if (entry->display == (p = def_display(entry->objtype)) 
		|| strcmp(entry->display, p) == 0)
		len = sprintf(ldescr, "%-14.14s%*s", 
			      entry->display, usrdisp ? 23 : 2, "");
	    else
		len = sprintf(ldescr, "%-19.19s [%-.14s]%*s ", 
			      entry->display, p, 14-strlen(p), "");
	    ct = ctime(&(entry->mtime));
	    sprintf(ldescr+len, "%12.12s", ct+4);
	}
	    i = d_cols - strlen(ldescr) - 3;
	    m.highlight = entry->dname;
	    m.description = ldescr;
	    break;
	}
    }
    return(m);
}

static int
dir_help(a)
struct actrec *a;
{
	extern char *Wastebasket;
	char *help, *title, path[PATHSIZ];
	char *filename(), *anyenv();

	sprintf(path, "%s/.pref", a->path);
	if ((help = anyenv(path, "HELP")) == NULL || *help == '\0') {
		if (strncmp(a->path, Wastebasket, strlen(Wastebasket)) == 0) {
			help = "T.h55.waste";
			title = "Wastebasket";
		}
		else {
			help = "T.h43.fold";
			title = "File folder";
		}
	} else {
		title = filename(a->path);
	}

	return(objop("OPEN", "TEXT", "$VMSYS/OBJECTS/Text.mfhelp", help, 
					title, NULL));
}

static int
dir_current(a)
struct actrec *a;
{
	extern char Opwd[];

	make_current(a->path);
	menu_current(a->id);
	chdir(a->path);
	sprintf(&Opwd[5], "%.*s", PATHSIZ, a->path);
	return(SUCCESS);
}

static int
dir_reread(a)
struct actrec *a;
{
	return(dir_init(a, TRUE));
}

static int
dir_reinit(a)
struct actrec *a;
{
	return(dir_init(a, FALSE));
}

static int
dir_init(a, force)
struct actrec *a;
bool force;
{
	struct ott_tab *ott = MYODPTR(a)->ott;

#ifdef _DEBUG
	_debug(stderr, "DIR_REINIT ");
#endif
	MYODPTR(a)->ott = (ott = ott_get(ott->path, Sortmodes, Dispmodes,
				ott->amask, ott->nmask));
	if (ott == NULL)
		return(FAIL);

	if (force || MYODPTR(a)->dir_mtime != ott->dir_mtime || 
				MYODPTR(a)->ott_mtime != ott->ott_mtime  ||
				Prefmodtime != MYODPTR(a)->pref_mtime ) {
#ifdef _DEBUG
		_debug(stderr, "RECREATING WINDOW %s\n", ott->path);
#endif
		MYODPTR(a)->dir_mtime = ott->dir_mtime;
		MYODPTR(a)->ott_mtime = ott->ott_mtime;
		MYODPTR(a)->pref_mtime = Prefmodtime;
		a->id = folder_reinit(a->id, 0, 18, 0, dir_disp, ott);
	}
#ifdef _DEBUG
	else
		_debug(stderr, "No change in directory\n");
#endif

	ott_lock_inc(ott);
	return(SUCCESS);
}

/* these arguments are kludgy, but varargs wouldn't do the trick */

static int
dir_ctl(rec, cmd, arg1, arg2, arg3, arg4, arg5, arg6)
struct actrec *rec;
int cmd;
int arg1, arg2, arg3, arg4, arg5, arg6;
{
#ifdef _DEBUG
    _debug(stderr, "DIR_CTL: cmd=%d\n", cmd);
#endif
    switch (cmd)
    {
    case CTGETARG:
    {
	int line;
	char *path;
	struct ott_entry *entry;
	struct ott_tab *tab = MYODPTR(rec)->ott;
	char *ott_to_path();

	if (array_len(tab->parents) == 0)
	    return(FAIL);
	(void) menu_ctl(rec->id, CTGETPOS, &line);
	entry = &(tab->ott[tab->parents[line]]);
	path = ott_to_path(entry);
	/*if ( **((char ***)(&arg1))) */
	/*  free( **((char ***)(&arg1))); */ /* les 12/4 */
	**((char ***)(&arg1)) = strsave(path);
	return(SUCCESS);
    }
    case CTSETMSG:
	/* framemsg is always this - miked */
	mess_frame("Move to an item with arrow keys and press ENTER to select the item.");
	return(SUCCESS);
    case CTSETLIFE:
	/* lifetime of directory is always longterm */
	return(SUCCESS);
    case CTISDEST:
	**((bool **)(&arg1)) = TRUE;
	return(SUCCESS);
    default:
	return(menu_ctl(rec->id, cmd, arg1, arg2, arg3, arg4, arg5, arg6));
	break;
    }
}

static token
dir_odsh(rec, t)
struct actrec *rec;
register token t;
{
	token menu_stream();

#ifdef _DEBUG
	_debug(stderr, "dir_odsh(%o) => ", t);
#endif
	t = menu_stream(t);
#ifdef _DEBUG
	_debug(stderr, "%o\n", t);
#endif
	if (t == TOK_NEXT)
		t = TOK_NOP;	/* filter out, see menu_stream */
	return(t);
}

int
IF_dir_open(argv)
char *argv[];
{
    register int i;
    char *path;
    long amask, nmask;
    struct ott_tab *ott;
    struct actrec a, *prevdir, *path_to_ar();
    char	*bsd_path_to_title();
    char	*nstrcat();

    struct ott_tab *ott_get();


    init_modes();
    amask = 0;
    nmask = M_WB;

    for (i = 0; argv[i]; i++) {
	if (argv[i][0] == '-') {
	    switch (argv[i][1]) {
	    case 'w':		/* wastebasket mode */
		amask = M_WB;
		nmask = 0;
		break;
	    case 'a':		/* set amask only */
		amask = strtol(argv[i]+2);
		break;
	    case 'n':		/* set nmask only */
		nmask = strtol(argv[i]+2);
		break;
	    }
	} else
	    path = argv[i];
    }

    if (prevdir = path_to_ar(path)) {
	ar_current(prevdir, TRUE);
	return(SUCCESS);
    }
    if (Dirs_open > MAX_DIRS) {
	mess_temp("Too many folders open. Close some, then try again.");
	return(FAIL);
    }
    if ((ott = ott_get(path, Sortmodes, Dispmodes, amask, nmask)) == NULL) {
	mess_temp(nstrcat("Could not open folder ",
			  bsd_path_to_title(path, MESS_COLS - 22), NULL));
	return(FAIL);
    }

    if (dir_create(ott, &a, FALSE) == FAIL || !ar_current(ar_create(&a), FALSE))
	return(FAIL);
    Dirs_open++;
    return(SUCCESS);
}

int
dir_create(ott, a, cover)
struct ott_tab *ott;
struct actrec *a;
bool cover;
{
	static char path_tit[MAX_WIDTH];
	char *bsd_path_to_title();

 	/*if ( a->path )
 		free( a->path ); */		/* les 12/4 */
 	a->path = strsave(ott->path);
	a->fcntbl[AR_CLOSE] = dir_close;
	a->fcntbl[AR_REREAD] = dir_reread;
	a->fcntbl[AR_REINIT] = dir_reinit;
	a->fcntbl[AR_CURRENT] = dir_current;
	a->fcntbl[AR_TEMP_CUR] = dir_current; /* abs k15. optimize later */
	a->fcntbl[AR_NONCUR] = AR_MEN_NONCUR;
	a->fcntbl[AR_HELP] = dir_help;
	a->fcntbl[AR_CTL] = dir_ctl;
	a->fcntbl[AR_ODSH] = (int (*)())dir_odsh; /* added cast. abs */

	/* we will keep track of what the mod times were on the ott at the
	 * time we first created the window, that way we will be able to 
	 * know when we should recreate the window to reflect the new data.
	 */
	a->odptr = (char *) new(struct myodptr);
	MYODPTR(a)->ott = ott;
	MYODPTR(a)->dir_mtime = ott->dir_mtime;
	MYODPTR(a)->ott_mtime = ott->ott_mtime;
#ifdef _DEBUG
	_debug(stderr, "dir_create mtimes=%d %d\n", ott->dir_mtime, ott->ott_mtime);
#endif

/*
	(void)strncpy(path_tit,path_to_title(ott->path, NULL, 0),MAX_TITLE-1);
	path_tit[MAX_TITLE-1] = '\0';
*/
	(void)strcpy(path_tit,bsd_path_to_title(ott->path, 0));
	a->id = folder_make(-1, path_tit, cover ? VT_COVERCUR : 0,
			VT_UNDEFINED, VT_UNDEFINED, 18, 0, dir_disp, ott);

	if (a->id == FAIL)
		return(FAIL);

	a->lifetime = AR_LONGTERM;
	a->flags = 0;
	a->slks = NULL;

	return SUCCESS;
}

/* selection handlers are not used by wish - they are built in to the
 * ODSH function
 */

int
IF_dsh()
{
	return (0);
}

int
IF_dvi()
{
	return (0);
}

int
IF_dmv(argv)
char *argv[];
{
	return(dir_mv_cp(TRUE, argv));
}

int
IF_dcp(argv)
char *argv[];
{
	return(dir_mv_cp(FALSE, argv));
}

static bool
eq_waste_fc(path, op)
char *path, *op;
{
	char *err = NULL;
	extern char *Filecabinet, *Wastebasket;
	char *filename() , *nstrcat();

	if (strcmp(Filecabinet, path) == 0)
		err = Filecabinet;
	else if (strcmp(Wastebasket, path) == 0)
		err = Wastebasket;
	if (err) {
		mess_temp(nstrcat("Can't ", op, " your ", filename(err), NULL));
		return(TRUE);
	} else
		return(FALSE);
}

static int
dir_mv_cp(mv, argv)
bool mv;
char *argv[];
{
    struct ott_entry *ott;
    char command[FILE_NAME_SIZ+PATHSIZ*2+11];
    char *odi, *display, path[PATHSIZ], msg[MESSIZ];
    int l, ret = SUCCESS;
    extern char *Wastebasket, Undel[];
    char *nstrcat(), *filename();
    struct ott_entry *path_to_ott();
    char	*bsd_path_to_title();
    char	*parent();

    working(TRUE);
    if (strncmp(argv[0], argv[1], l = strlen(argv[0])) == 0 &&
	argv[1][0] == '/') {
	mess_temp(nstrcat("Can't ", mv?"move":"copy",
			  " a folder inside itself!", NULL));
	return(FAIL);
    }

    if (eq_waste_fc(argv[0], mv ? "move" : "copy"))
	return(FAIL);
    if (mv && ckperms(parent(argv[0]), 02) == FAIL)
	return(FAIL);
    if (ckperms(argv[1], 02) == FAIL)
	return(FAIL);
    if (mv && path_isopen(argv[0], mv ? "move" : "copy", TRUE))
	return(FAIL);
    if ((ott = path_to_ott(argv[0])) == NULL)
	return(FAIL);
    odi = strsave(ott->odi);
    display = strsave(ott->display);
    sprintf(command, "dir_%s %s %s %s", mv?"move":"copy", argv[0], argv[1], 
	    argv[2]?argv[2]:"");

    if (waitspawn(sysspawn(command)) == 0) {

	if ( argv[2] ) {
	    sprintf(msg, "%s %sed to the ",
		bsd_path_to_title(filename(argv[0]), (MESS_COLS-33)/3), mv ? "mov" : "copi");
	    l = strlen(msg);
	    strcat(msg, bsd_path_to_title(argv[1],MESS_COLS-l-18-(MESS_COLS-33)/3));
	    strcat(msg, " folder and named ");
	    l = strlen(msg);
	    strcat(msg, bsd_path_to_title(argv[2],MESS_COLS - l));
	} else {
	    sprintf(msg, "%s %sed to the ",
		bsd_path_to_title(filename(argv[0]), (MESS_COLS-22)/2), mv ? "mov" : "copi");
	    l = strlen(msg);
	    strcat(msg, bsd_path_to_title(argv[1],MESS_COLS - l - 7));
	    strcat(msg, " folder");
	}
/* miked k17
	sprintf(msg, "%s %sed to the ",
	    bsd_path_to_title(argv[2] ? argv[2] : filename(argv[0]),(MESS_COLS-22)/2),
	    mv ? "mov" : "copi");
	l = strlen(msg);
	strcat(msg, bsd_path_to_title(argv[1],MESS_COLS - l - 7));
	strcat(msg, " folder");
*/
	sprintf(path, "%s/%s", argv[1], argv[2] ? argv[2] : filename(argv[0]));
	if ((ott = path_to_ott(path)) == NULL)
	    return(FAIL);
	/*if ( ott->odi )
	  free( ott->odi ); */   /* les 12/4 */
	ott->odi = odi;
	/*if ( ott->display )
	  free( ott->display ); */ /* les 12/4 */
	ott->display = display;
	(void) ott_chg_odi(ott);
	if (strncmp(path, Wastebasket, strlen(Wastebasket)) == 0)
	    (void) odi_putkey(ott, Undel, parent(argv[0]));
	else if (strncmp(argv[0], Wastebasket, strlen(Wastebasket)) == 0)
	    (void) odi_putkey(ott, Undel, NULL);
	(void) utime(path, NULL);
	ott_mtime(ott);
	ret = SUCCESS;
    } else {
	sprintf(msg, "%s %s failed to the ", 
	    bsd_path_to_title(argv[2] ? argv[2] : filename(argv[0]),(MESS_COLS-27)/2),
	    mv ? "move" : "copy");
	l = strlen(msg);
	strcat(msg, bsd_path_to_title(argv[1],MESS_COLS - l - 7));
	strcat(msg, " folder");
	ret = FAIL;
    }
    mess_temp(msg);
    return(ret);
}

int
IF_drn(argv)
char *argv[];
{
	register char	*p;
	char	*nstrcat(), *filename(), *parent();
	char	*bsd_path_to_title();

	p = filename(argv[0]);
	if (ckperms(parent(argv[0]), 02) == FAIL)
		return(FAIL);
	if (path_isopen(argv[0], "rename", TRUE))
		return(FAIL);
	if (eq_waste_fc(argv[0], "rename"))
		return(FAIL);
	if (waitspawn(spawn("/bin/mv", "mv", "-f", argv[0], 
			nstrcat(parent(argv[0]), "/", argv[1], NULL), NULL))) {
		mess_temp(nstrcat(bsd_path_to_title(p,MESS_COLS - 14), " rename failed", NULL));
		return(FAIL);
	} else {
		mess_temp(nstrcat(bsd_path_to_title(p,(MESS_COLS - 12)/2), " renamed to ", bsd_path_to_title(argv[1],(MESS_COLS - 12)/2), NULL));
		return(SUCCESS);
	}
}

/*
 * note:  This subroutine depends on the fact that its argument is
 * a legal UNIX path, i.e., slash separated strings.
 */

char *
bsd_path_to_title(str, width)
char	*str;
int	width;
{
    static char	title[MAX_WIDTH];
    register int len;
    extern char *parent();
    extern char *filename();

    if ((str == NULL) || (*str == '\0'))
	return str;	/* protect ourselves from the empty devil */

    if (width <= 0)
	width = MAX_TITLE;
    if (width >= MAX_WIDTH)
	width = MAX_WIDTH - 1;  /* lets not exceed the buffer */

    if ((len = strlen(str)) > width) {
	register int	flen;

	flen = strlen(filename(str));
	if (flen >= (width-1)) {
	    if (len == flen || len == flen+1) {
		(void) strncpy(title, str, (width-1));
	    } else {
		(void) strcpy(title, "</");
		(void) strncat(title, filename(str), (width-3));
	    }
	    (void) strcpy(&title[width-1], ">");
	} else if (flen) {
	    if ( (int)strlen(parent(str)) <= 4 ) {   /* EFT k16 */
		(void) strcpy(title, "</");
		(void) strcat(title, filename(str));
	    } else {
		(void) strcpy(title, path_to_title(parent(str),"X",(width-flen-1)));
		(void) strcat(title, "/");
		(void) strcat(title, filename(str));
	    }
	} else
	    (void) strcpy(title, path_to_title(str,"X",width));
    } else
	strcpy(title, str);
    return strdup(title);
}