/* Copyright Per Bothner 1987. Read the file Q-INFO */
/************************************************************************/
/*									*/
/*			(C) COPYRIGHT 1983				*/
/*			BOARD OF TRUSTEES				*/
/*			LELAND STANFORD JUNIOR UNIVERSITY		*/
/*			STANFORD, CA. 94305, U.S.A.			*/
/*									*/
/************************************************************************/

/*
 * Print out a name descriptor in an aesthetically pleasing format.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "desc.h"
#include <Vgts.h>
#include <Vstorage.h>
#include <Vnaming.h>
#include "stdio.h"

static char *FormatDate();

PrintDesc(desc, f, opt)
    register ArbitraryDescriptor *desc;
    struct File *f;
  {
    int printbanner = opt;
    unsigned short mode, i;

    switch (desc->e.descriptortype)
      {
	case EMPTY_DESCRIPTOR:
	    break;

	case FILE_DESCRIPTOR:
            if( printbanner )
              {
                fprintf(f, "\n%-16s %9s %s %-32s\n", "   Mode","Size",
                        " Last Modified","Name");
              }

            putc((desc->f.perms)&SS_DIR ? 'd': '-', f);
            for( i = 1; i <= 3; ++i )
              {
                putc((desc->f.perms)&SS_READ ? 'r': '-', f);
                putc((desc->f.perms)&SS_WRITE ? 'w': '-', f);
                putc((desc->f.perms)&SS_EXECUTE ? 'e': '-', f);
                putc((desc->f.perms)&SS_LIST ? 'l': '-', f);
                putc((desc->f.perms)&SS_MODIFY ? 'm': '-', f);

                desc->f.perms = (desc->f.perms) >> 5;
              }
            fprintf(f, "   %7d %s %-32s\n", desc->f.size, 
                        FormatDate( desc->f.timestamp ),desc->f.name ); 
	    break;

	case TEAM_DESCRIPTOR:
	    if (printbanner)
	      {
		/* Generate a banner */
		fprintf(f, "\n%-40s %10s %10s\n", "File name",
		    "OwnerPid", "RootPid");
	      }

	    fprintf(f, "%-40s %10x %10x\n", desc->t.fileName, 
		    desc->t.ownerPid, desc->t.rootPid);
	    break;

	case HOST_DESCRIPTOR:
	    if (printbanner)
		/* Generate a banner */
		fprintf(f, "\n%-15s %-15s %10s %15s\n", "User","Host name",
		    "TeamServer", "Availability");

	    fprintf(f, "%-15s %-15s %10x %15x\n", desc->h.userName, 
	    		desc->h.hostName,
			desc->h.regPid, desc->h.availability);
	    break;

	case PIDMAP_DESCRIPTOR:
	    if (printbanner)
		/* Generate a banner */
		fprintf(f, "\n%-15s %s\n", "Process-id",
		    "Process-id mapped to");

	    fprintf(f, "%10x %20x\n", desc->p.pid, desc->p.pidMap);
	    break;

	case CONTEXT_PREFIX_DESCRIPTOR:
	    if (printbanner)
	      {
		/* Generate a banner */
		fprintf(f, "\n%-32s %10s %10s\n", "Context name", "ServerPid",
		    "ContextId");
	      }

	    fprintf(f, "%-32s %10x %10x  %s%s\n", desc->c.name,
		desc->c.serverpid, desc->c.contextid,
		desc->c.entrytype & SESSION ? "(Session)" : "",
		desc->c.entrytype & LOGICAL_PID ? "(Logical pid)" : "");
	    break;

	case DEVICE_DESCRIPTOR:
	    if (printbanner)
	      {
		/* Generate a banner */
		fprintf(f, "\n%-32s %10s\n", "Device name", 
		    "Unit");
	      }

	    fprintf(f, "%-32s %10d\n", desc->d.name,
		desc->d.unit);
	    break;

	case UNIXFILE_DESCRIPTOR:
	    if (printbanner)
	      {
            /* -rw-r--r--   1  nagler   netgraph  25808  8/07/83 02:32 list */ 
    fprintf(f,  "\n   Mode   Links Owner    Group      Size %s Name\n",
			FormatDate( 0 ) );
	      }

	    mode = desc->u.st_mode;

	    /* Print out type of file and protection mode bits */
	    switch (mode & S_IFMT)
	      {
	        case S_IFDIR:	putc('d', f); break;
	        case S_IFCHR:	putc('c', f); break;
		case S_IFBLK:	putc('b', f); break;
		case S_IFREG:	putc('-', f); break;
		case S_IFLNK:	putc('l', f); break;
		case S_IFSOCK:	putc('s', f); break;
		default:	putc('?', f); break; /* illegal */
	      }
	    putc(mode&S_IREAD ? 'r' : '-', f);
	    putc(mode&S_IWRITE ? 'w' : '-', f);
	    switch (mode & (S_IEXEC|S_ISUID))
	      {
		case 0:		putc('-', f); break;
		case S_IEXEC:	putc('x', f); break;
		case S_ISUID:	putc('S', f); break; /* anomaly */
		default:	putc('s', f); break;
	      }
	    putc(mode&(S_IREAD>>3) ? 'r' : '-', f);
	    putc(mode&(S_IWRITE>>3) ? 'w' : '-', f);
	    switch (mode & ((S_IEXEC>>3)|S_ISGID))
	      {
		case 0:		putc('-', f); break;
		case S_IEXEC>>3:putc('x', f); break;
		case S_ISGID:	putc('S', f); break; /* anomaly */
		default:	putc('s', f); break;
	      }
	    putc(mode&(S_IREAD>>6) ? 'r' : '-', f);
	    putc(mode&(S_IWRITE>>6) ? 'w' : '-', f);
	    switch (mode & ((S_IEXEC>>6)|S_ISVTX))
	      {
		case 0:		putc('-', f); break;
		case S_IEXEC>>6:putc('x', f); break;
		case S_ISVTX:	putc('T', f); break; /* strange */
		default:	putc('t', f); break;
	      }

	    fprintf(f, "  %2d  %-8.8s %-8.8s%7d %s %s\n", desc->u.st_nlink,
		desc->u.ownername,
		desc->u.groupname,
		desc->u.st_size,
		FormatDate(desc->u.st_mtime), 
		desc->u.name );
	    break;


	case VGT_DESCRIPTOR:
	    if (printbanner)
	      {
		/* Generate a banner */
		fprintf(f, "\nVGT Lines Columns Owner  %-14s %10s\n", "Name", 
		    "Banner");
	      }

	    fprintf(f, "%2d", desc->v.vgt);
	    if (desc->v.typeVGT & TTY)
	        fprintf(f, "   %3d  %3d ", desc->v.lines, desc->v.columns );
	    else 
	        fprintf(f, "    Graphics");		
	    if (desc->v.ownerPid)
	        fprintf(f, "  %8x ", desc->v.ownerPid );
	    else 
	        fprintf(f, "           ");
	    fprintf(f, "%-14s %-40s\n", desc->v.name, desc->v.banner);
	    break;

	case LINK_DESCRIPTOR:
	    if (printbanner)
	      {
		/* Generate a banner */
		fprintf(f, "\n%-16s           %10s\n", "Name", "Requestor");
	      }

	    fprintf(f, "%-16s %c       %10x\n", desc->l.linkname, 
		    (desc->l.direction?'>':'<'), desc->l.requestor);
	    break;

	default:
	    return( 1 );
	    break;
      }
    return( 0 );
  } /* PrintEntry */
 
PrintDescriptor( desc, bannertype )
    register ArbitraryDescriptor *desc;
    register int *bannertype; 
/*
 * Each descriptor has an associated banner defined by this routine.
 * If "bannertype" is not the same as "desc->e.descriptortype" then
 * this routine will output the banner for this type.  
 * error occurs if the routine doesn't know the descriptortype.
 * returns 1 on error and 0 if successful.
 */
  {
    int printbanner = desc->e.descriptortype != *bannertype;
    int code = PrintDesc( desc, stdout, printbanner);
    if (code == 0 && printbanner) *bannertype = desc->e.descriptortype;
  }


static char *FormatDate(clock)
    long clock;
/*
 * Create a fixed width string for the date specified by "clock"
 */
  {
    extern struct tm *localtime();
    static char date[ 20 ];
    register struct tm *time;

    if ( clock == 0 )
        return( " Last Modified" );	/* must be same length as "date" */
    else
      {
        time = localtime(&clock);
    
        sprintf( date, "%2d/%02d/%02d %02d:%02d", time->tm_mon, time->tm_mday
    	     , time->tm_year % 100, time->tm_hour, time->tm_min );
        return ( date );
      }
  } /* FormatDate */
