📄 ls.c
字号:
{
if (quote_funny_chars)
{
switch (c)
{
case '\\':
printf ("\\\\");
break;
case '\n':
printf ("\\n");
break;
case '\b':
printf ("\\b");
break;
case '\r':
printf ("\\r");
break;
case '\t':
printf ("\\t");
break;
case '\f':
printf ("\\f");
break;
case ' ':
printf ("\\ ");
break;
case '"':
printf ("\\\"");
break;
default:
if (c > 040 && c < 0177)
putchar (c);
else
printf ("\\%03o", (unsigned int) c);
}
}
else
{
if (c >= 040 && c < 0177)
putchar (c);
else if (!qmark_funny_chars)
putchar (c);
else
putchar ('?');
}
}
if (quote_as_string)
putchar ('"');
}
/* Print the file name of `f' with appropriate quoting.
Also print file size, inode number, and filetype indicator character,
as requested by switches. */
void
print_file_name_and_frills (f)
struct file *f;
{
if (print_inode)
printf ("%6u ", f->stat.st_ino);
if (print_block_size)
printf ("%*u ", block_size_size, convert_blocks (ST_NBLOCKS (f->stat),
kilobyte_blocks));
print_name_with_quoting (f->name);
if (indicator_style != none)
print_type_indicator (f->stat.st_mode);
}
void
print_type_indicator (mode)
unsigned int mode;
{
switch (mode & S_IFMT)
{
case S_IFDIR:
putchar ('/');
break;
#ifdef S_IFLNK
case S_IFLNK:
putchar ('@');
break;
#endif
#ifdef S_IFIFO
case S_IFIFO:
putchar ('|');
break;
#endif
#ifdef S_IFSOCK
case S_IFSOCK:
putchar ('=');
break;
#endif
case S_IFREG:
if (indicator_style == all
&& (mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
putchar ('*');
break;
}
}
int
length_of_file_name_and_frills (f)
struct file *f;
{
register char *p = f->name;
register char c;
register int len = 0;
if (print_inode)
len += 7;
if (print_block_size)
len += 1 + block_size_size;
if (quote_as_string)
len += 2;
while (c = *p++)
{
if (quote_funny_chars)
{
switch (c)
{
case '\\':
case '\n':
case '\b':
case '\r':
case '\t':
case '\f':
case ' ':
len += 2;
break;
case '"':
if (quote_as_string)
len += 2;
else
len += 1;
break;
default:
if (c >= 040 && c < 0177)
len += 1;
else
len += 4;
}
}
else
len += 1;
}
if (indicator_style != none)
{
unsigned filetype = f->stat.st_mode & S_IFMT;
if (filetype == S_IFREG)
{
if (indicator_style == all
&& (f->stat.st_mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
len += 1;
}
else if (filetype == S_IFDIR
#ifdef S_IFLNK
|| filetype == S_IFLNK
#endif
#ifdef S_IFIFO
|| filetype == S_IFIFO
#endif
#ifdef S_IFSOCK
|| filetype == S_IFSOCK
#endif
)
len += 1;
}
return len;
}
void
print_many_per_line ()
{
int filesno; /* Index into files. */
int row; /* Current row. */
int max_name_length; /* Length of longest file name + frills. */
int name_length; /* Length of each file name + frills. */
int pos; /* Current character column. */
int cols; /* Number of files across. */
int rows; /* Maximum number of files down. */
/* Compute the maximum file name length. */
max_name_length = 0;
for (filesno = 0; filesno < files_index; filesno++)
{
name_length = length_of_file_name_and_frills (files + filesno);
if (name_length > max_name_length)
max_name_length = name_length;
}
/* Allow at least two spaces between names. */
max_name_length += 2;
/* Calculate the maximum number of columns that will fit. */
cols = line_length / max_name_length;
if (cols == 0)
cols = 1;
/* Calculate the number of rows that will be in each column except possibly
for a short column on the right. */
rows = files_index / cols + (files_index % cols != 0);
/* Recalculate columns based on rows. */
cols = files_index / rows + (files_index % rows != 0);
for (row = 0; row < rows; row++)
{
filesno = row;
pos = 0;
/* Print the next row. */
while (1)
{
print_file_name_and_frills (files + filesno);
name_length = length_of_file_name_and_frills (files + filesno);
filesno += rows;
if (filesno >= files_index)
break;
indent (pos + name_length, pos + max_name_length);
pos += max_name_length;
}
putchar ('\n');
}
}
void
print_horizontal ()
{
int filesno;
int max_name_length;
int name_length;
int cols;
int pos;
/* Compute the maximum file name length. */
max_name_length = 0;
for (filesno = 0; filesno < files_index; filesno++)
{
name_length = length_of_file_name_and_frills (files + filesno);
if (name_length > max_name_length)
max_name_length = name_length;
}
/* Allow two spaces between names. */
max_name_length += 2;
cols = line_length / max_name_length;
if (cols == 0)
cols = 1;
pos = 0;
name_length = 0;
for (filesno = 0; filesno < files_index; filesno++)
{
if (filesno != 0)
{
if (filesno % cols == 0)
{
putchar ('\n');
pos = 0;
}
else
{
indent (pos + name_length, pos + max_name_length);
pos += max_name_length;
}
}
print_file_name_and_frills (files + filesno);
name_length = length_of_file_name_and_frills (files + filesno);
}
putchar ('\n');
}
void
print_with_commas ()
{
int filesno;
int pos, old_pos;
pos = 0;
for (filesno = 0; filesno < files_index; filesno++)
{
old_pos = pos;
pos += length_of_file_name_and_frills (files + filesno);
if (filesno + 1 < files_index)
pos += 2; /* For the comma and space */
if (old_pos != 0 && pos >= line_length)
{
putchar ('\n');
pos -= old_pos;
}
print_file_name_and_frills (files + filesno);
if (filesno + 1 < files_index)
{
putchar (',');
putchar (' ');
}
}
putchar ('\n');
}
struct userid
{
unsigned short uid;
char *name;
struct userid *next;
};
struct userid *user_alist;
/* Translate `uid' to a login name, with cache. */
char *
getuser (uid)
unsigned short uid;
{
register struct userid *tail;
struct passwd *pwent;
char usernum_string[20];
for (tail = user_alist; tail; tail = tail->next)
if (tail->uid == uid)
return tail->name;
pwent = getpwuid (uid);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->uid = uid;
tail->next = user_alist;
if (pwent == 0)
{
sprintf (usernum_string, "%u", (unsigned short) uid);
tail->name = copystring (usernum_string);
}
else
tail->name = copystring (pwent->pw_name);
user_alist = tail;
return tail->name;
}
/* We use the same struct as for userids. */
struct userid *group_alist;
/* Translate `gid' to a group name, with cache. */
char *
getgroup (gid)
unsigned short gid;
{
register struct userid *tail;
struct group *grent;
char groupnum_string[20];
for (tail = group_alist; tail; tail = tail->next)
if (tail->uid == gid)
return tail->name;
grent = getgrgid (gid);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->uid = gid;
tail->next = group_alist;
if (grent == 0)
{
sprintf (groupnum_string, "%u", (unsigned int) gid);
tail->name = copystring (groupnum_string);
}
else
tail->name = copystring (grent->gr_name);
group_alist = tail;
return tail->name;
}
/* Assuming cursor is at position `from', indent up to position `to'. */
void
indent (from, to)
int from, to;
{
while (from < to)
{
if (to / tabsize > from / tabsize)
{
putchar ('\t');
from += tabsize - from % tabsize;
}
else
{
putchar (' ');
from++;
}
}
}
/* Low level subroutines of general use,
not specifically related to the task of listing a directory. */
#ifndef MSDOS
char *
xrealloc (obj, size)
char *obj;
int size;
{
char *val = realloc (obj, size);
if (!val)
error (1, 0, "virtual memory exhausted");
return val;
}
char *
xmalloc (size)
int size;
{
char *val = malloc (size);
if (!val)
error (1, 0, "virtual memory exhausted");
return val;
}
#endif /* MSDOS */
/* Return a newly allocated copy of `string'. */
char *
copystring (string)
char *string;
{
return strcpy ((char *) xmalloc (strlen (string) + 1), string);
}
/* Put `dirname/name' into `dest', handling `.' and `/' properly. */
void
attach (dest, dirname, name)
char *dest, *dirname, *name;
{
char *dirnamep = dirname;
/* Copy dirname if it is not ".". */
if (dirname[0] != '.' || dirname[1] != 0)
{
while (*dirnamep)
*dest++ = *dirnamep++;
/* Add '/' if `dirname' doesn't already end with it. */
if (dirnamep > dirname && dirnamep[-1] != '/')
*dest++ = '/';
}
while (*name)
*dest++ = *name++;
*dest = 0;
}
void
usage ()
{
fprintf (stderr, "\
Usage: %s [-abcdgiklmnpqrstuxABCFLNQRSUX1] [-w cols] [-T cols] [-I pattern]\n\
[+all] [+escape] [+directory] [+inode] [+kilobytes]\n\
[+numeric-uid-gid] [+hide-control-chars] [+reverse] [+size]\n\
[+width cols] [+tabsize cols] [+almost-all] [+ignore-backups]\n",
program_name);
#ifdef MSDOS
fprintf (stderr, "\
[+classify] [+file-type] [+ignore pattern] [+dereference] [+literal]\n\
[+quote-name] [+recursive] [+sort {none,time,size,extension}]\n\
[+format {long,verbose,commas,across,vertical,single-column}]\n\
[+time {atime,access,use,ctime,status}] [+copying] [+version]\n\
[path...]\n");
#else /* not MSDOS */
fprintf (stderr, "\
[+classify] [+file-type] [+ignore pattern] [+dereference] [+literal]\n\
[+quote-name] [+recursive] [+sort {none,time,size,extension}]\n\
[+format {long,verbose,commas,across,vertical,single-column}]\n\
[+time {atime,access,use,ctime,status}] [path...]\n");
#endif /* not MSDOS */
exit (1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -