|
|
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: 9911 (0x26b7)
Types: TextFile
Names: »fls.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/fls.c«
/*MODULE fls: "Formatted File Listing" "Thu 03 Oct 1985" */
/*PGMR fls: "Gary Perlman" "Wang Institute, Tyngsboro, MA 01879 USA" */
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
typedef int Status;
#define SUCCESS ((Status) 0)
#define FAILURE ((Status) 1)
typedef int Boole;
#define TRUE ((Boole) 1)
#define FALSE ((Boole) 0)
#define EOS '\0'
#define EOL '\n'
#define UNSET (-1)
typedef struct stat STAT;
extern char *malloc ();
extern char *strcpy ();
#define strdup(s) strcpy ((char *) malloc ((unsigned) (strlen (s) + 1)), s)
Status fls (); /* format file listing */
char *ugname (); /* user/group name */
void rwxmode (); /* get rwx mode */
void printhelp (); /* print a menu of the allowed formats */
\f
/*FUNCTION main: main test routine */
#ifdef FLS /* useful program to test main function */
main (argc, argv) char **argv;
{
int i; /* loop through files with this */
char buf[BUFSIZ]; /* will hold formatted listing of one file */
Status status = SUCCESS; /* exit status */
char *format = argv[1]; /* format string */
if (argc == 1)
{
fprintf (stderr, "Usage: %s format-string [files]\n", argv[0]);
exit (FAILURE);
}
/* check format string by sending NULL file to fls */
if (fls ((char *) NULL, format, buf) == FAILURE)
{
fprintf (stderr, "%s: Bad format string '%s'\n", argv[0], format);
exit (FAILURE);
}
for (i = 2; i < argc; i++)
{
if (fls (argv[i], format, buf) == SUCCESS)
puts (buf);
else
{
fprintf (stderr, "%s: Can't list '%s'\n", argv[0], argv[i]);
status++;
}
}
exit (status);
}
#endif FLS
\f
/*FUNCTION ugname: get user or group id string name */
/*NOTE save names and groups because of high cost of access
not the most efficient method, but adequate for this routine */
#define MAXSTORE 50 /* store this many group/user id's */
static char *Gname[MAXSTORE]; /* group name */
static int Gnum[MAXSTORE]; /* group number */
static int Ngnames = 0; /* number of group names */
static char *Uname[MAXSTORE]; /* user names */
static int Unum[MAXSTORE]; /* user id numbers */
static int Nunames = 0; /* number of user names */
static
char *
ugname (id, group) /* return user or group id name */
int id; /* user or group id of a file */
Boole group; /* id is a group id, not a user id */
{
static struct passwd *pw;
static struct group *gr;
int i;
if (group)
{
for (i = 0; i < Ngnames; i++)
if (Gnum[i] == id)
return (Gname[i]);
gr = getgrgid (id);
if (Ngnames < MAXSTORE)
{
Gname[Ngnames] = strdup (gr->gr_name);
Gnum[Ngnames] = id;
return (Gname[Ngnames++]);
}
else
return (gr->gr_name);
}
else /* User name */
{
for (i = 0; i < Nunames; i++)
if (Unum[i] == id)
return (Uname[i]);
pw = getpwuid (id);
if (Nunames < MAXSTORE)
{
Uname[Nunames] = strdup (pw->pw_name);
Unum[Nunames] = id;
return (Uname[Nunames++]);
}
else
return (pw->pw_name);
}
}
\f
/*FUNCTION rwxmode: construct rwx ls style format for file protections */
static
void
rwxmode (stbuf, buf) /* return rwxrwxrwx type string about file */
STAT stbuf; /* file statistics */
char *buf; /* answer pushed in here */
{
static int uid = UNSET; /* program caller's user id */
static int gid = UNSET; /* program caller's group id */
int i;
for (i = 0; i < 9; i += 3)
{
buf[i+0] = (stbuf.st_mode & (S_IREAD >> i)) ? 'r' : '-';
buf[i+1] = (stbuf.st_mode & (S_IWRITE >> i)) ? 'w' : '-';
buf[i+2] = (stbuf.st_mode & (S_IEXEC >> i)) ? 'x' : '-';
}
/* map user's permissions to upper case (due to Phil Mercurio) */
if (uid == UNSET)
uid = getuid ();
if (gid == UNSET)
gid = getgid ();
i = (stbuf.st_uid == uid) ? 0 : (stbuf.st_gid == gid ? 3 : 6);
if (islower (buf[i+0])) buf[i+0] = toupper (buf[i+0]);
if (islower (buf[i+1])) buf[i+1] = toupper (buf[i+1]);
if (islower (buf[i+2])) buf[i+2] = toupper (buf[i+2]);
}
\f
/*FUNCTION statstdin: gets stats on stdin */
static
void
statstdin (statptr)
struct stat *statptr;
{
long clock, time ();
clock = time (0);
statptr->st_atime = clock;
statptr->st_mtime = clock;
statptr->st_ctime = clock;
statptr->st_gid = getgid ();
statptr->st_uid = getuid ();
statptr->st_ino = 0;
statptr->st_nlink = 0;
statptr->st_mode = 0;
statptr->st_size = 0;
}
\f
/*FUNCTION fls: formated listing of file */
Status
fls (file, format, bptr) /* put formatted file listing in buffer */
char *file; /* name of the file to print */
char *format; /* print format control string, like printf */
char *bptr; /* pointer to buffer in which to print stats */
{
STAT stbuf; /* file statistics read in here */
Boole sformat; /* print info in string format */
char tformat[BUFSIZ]; /* temporary format string */
char *tfptr; /* pointer to temp format string */
char mode[10]; /* file protection stored here */
char *filetype; /* plain, directory, etc */
extern char *ctime (); /* character format of times */
mode[9] = EOS;
*bptr = EOS;
if (file == NULL) /* just a test run to check this format string */
file = "";
else if (*file == '-' && file[1] == '\0')
statstdin (&stbuf);
else if (stat (file, &stbuf))
return (FAILURE);
while (*format)
{
while (*bptr)
bptr++;
if (*format != '%')
{
*bptr++ = *format++;
*bptr = EOS;
}
else
{
/* create a temporary format string and write into buffer */
*tformat = *format++;
tfptr = tformat+1;
while (isdigit (*format) || *format == '-' || *format == '.')
*tfptr++ = *format++;
if (*format == EOS) /* bad format string */
return (FAILURE);
if (isupper (*format)) /* upper case formats are all strings */
{
sformat = TRUE;
*tfptr++ = 's';
}
else
{
sformat = FALSE;
*tfptr++ = 'd';
}
*tfptr = EOS;
switch (*format++)
{
default:
return (FAILURE);
break;
case '?': /*FORM puts ("? print this list of formats"); */
printhelp ();
break;
case '%': /*FORM puts ("% insert %"); */
*bptr++ = '%';
*bptr = EOS;
break;
case 'A': case 'a': /*FORM puts ("aA access time"); */
if (sformat)
(void) sprintf (bptr, tformat, ctime (&stbuf.st_atime));
else
(void) sprintf (bptr, tformat, stbuf.st_atime);
break;
case 'C': case 'c': /*FORM puts ("cC change time"); */
if (sformat)
(void) sprintf (bptr, tformat, ctime (&stbuf.st_ctime));
else
(void) sprintf (bptr, tformat, stbuf.st_ctime);
break;
case 'G': case 'g': /*FORM puts ("gG group id"); */
if (sformat == FALSE)
(void) sprintf (bptr, tformat, stbuf.st_gid);
else
(void) sprintf (bptr, tformat, ugname (stbuf.st_gid, TRUE));
break;
case 'i': /*FORM puts ("i inode number"); */
(void) sprintf (bptr, tformat, stbuf.st_ino);
break;
case 'l': /*FORM puts ("l number of links"); */
(void) sprintf (bptr, tformat, stbuf.st_nlink);
break;
case 'M': case 'm': /*FORM puts ("mM modification time"); */
if (sformat)
(void) sprintf (bptr, tformat, ctime (&stbuf.st_mtime));
else
(void) sprintf (bptr, tformat, stbuf.st_mtime);
break;
case 'n': /*FORM puts ("n insert a newline"); */
*bptr++ = EOL;
*bptr = EOS;
break;
case 'N': /*FORM puts ("N file name"); */
(void) sprintf (bptr, tformat, file);
break;
case 'P': case 'p': /*FORM puts ("pP protection modes"); */
if (sformat == FALSE)
{
*(tfptr-1) = 'o';
(void) sprintf (bptr, tformat, (stbuf.st_mode & 0777));
}
else
{
rwxmode (stbuf, mode);
(void) sprintf (bptr, tformat, mode);
}
break;
case 's': /*FORM puts ("s size"); */
(void) sprintf (bptr, tformat, stbuf.st_size);
break;
case 't': /*FORM puts ("t insert a tab"); */
*bptr++ = '\t';
*bptr = EOS;
break;
case 'T': /*FORM puts ("T file type"); */
switch (stbuf.st_mode & S_IFMT)
{
default: filetype = "?unknown"; break;
case S_IFDIR: filetype = "directory"; break;
case S_IFCHR: filetype = "character special"; break;
case S_IFBLK: filetype = "block special"; break;
case S_IFREG: filetype = "-plain"; break;
# ifdef S_IFLNK
case S_IFLNK: filetype = "symbolic link"; break;
# endif S_IFLNK
# ifdef S_IFSOCK
case S_IFSOCK: filetype = "Socket"; break;
# endif S_IFSOCK
}
(void) sprintf (bptr, tformat, filetype);
break;
case 'U': case 'u': /*FORM puts ("uU user id"); */
if (sformat == FALSE)
(void) sprintf (bptr, tformat, stbuf.st_uid);
else
(void) sprintf (bptr, tformat, ugname (stbuf.st_uid, FALSE));
break;
}
}
}
return (SUCCESS);
}
\f
/*FUNCTION printhelp: print help message about formats */
static
void
printhelp ()
{
puts ("Summary of % formats:");
puts ("xX means that both integer (x) & string (X) formats supported");
puts ("All formats support %-p.wX where:");
puts (" - is an optional sign to left-justify X");
puts (" p is an optional pad of white spaces");
puts (" w is an optional maximum width of X");
puts ("Char Meaning:");
/* the rest is constructed with seec -e -t "FORM " % */
puts ("? print this list of formats");
puts ("% insert %");
puts ("aA access time");
puts ("cC change time");
puts ("gG group id");
puts ("i inode number");
puts ("l number of links");
puts ("mM modification time");
puts ("n insert a newline");
puts ("N file name");
puts ("pP protection modes");
puts ("s size");
puts ("t insert a tab");
puts ("T file type");
puts ("uU user id");
}