UNIX
如图的那只大企鹅就是UNIX/LINUX的logo,关于开源的UNIX操作系统,就不多说了。说说有趣的事情吧,也就是UNIX与企鹅的来历。UNIX操作系统,是美国AT&T公司于1971年在PDP-11上运行的操作系统。具有多用户、多任务的特点,支持多种处理器架构,最早由肯·汤普逊(Kenneth Lane Thompson)、丹尼斯·里奇(Dennis MacAlistair Ritchie)和Douglas McIlroy于1969年在AT&T的贝尔实验室开发。目前它的商标权由国际开放标准组织(The Open Group)所拥有。
Unix/Linux与企鹅
企鹅是南极洲的标志性动物,根据国际公约,南极洲为全人类共同所有,不属于当今世界上的任何国家,当今任何国家无权将南极洲纳入其版图。
Linux选择企鹅图案作标志,其含意也是表明:开源的Linux,为全人类共同所有,任何公司无权将其私有。
企鹅背后的故事还有很多
我 想很多人都不是很清楚企鹅Tux究竟是怎样成为Linux的标志的.为什么选企鹅?而不是选择狮子老虎?有人说因为Linus是 芬兰人,所以选择企鹅. 有人说因为其他动物图案都被用光了,Linus只好选择企鹅. 带着这个疑问, 我将Jennifer的采访收获带回给大家, 祝大家新年快乐,像Tux那样笑口常开。
长期以来,国外有人报怨Tux长得太象搞笑动画片里的辛普森形象, 或者有人认为这个形象不够严肃(以前有过网友调查, 有人认为Linux形象应该是雷神之锤那种火焰, 或者IBM那种大气)
Linus却认为, Linux的logo应该是一种有生趣并可爱的图案, 而有生趣并带着友好表情的图案意味着你应该选择某种动物logo.但是很多Linux业界中人可不是在寻求可爱和友好, 有些人认为Linux的logo根本不该走“可爱”这个方向, 应该是沉重严肃的。
在 1996年, 5岁的Linux操作系统开始在世界范围内被广泛应用, Linus开始考虑给这个操作系统创作一个logo. 但是他的思考范围仍然在动物世界里: 信天翁,鸭嘴兽, 老鹰,还曾经想到过狐狸.就这样,一只只动物在Linus脑中闪过. 最终,他的灵感闪光,他想起曾经在澳大利亚被一种鸟咬过,咬他的不是别的鸟,就是企鹅.
选 定了企鹅作为logo之后,linus在1996年的Linux内核邮件列表中讨论寻找一只丰满敦实的企鹅时形容到:"不要太胖, 而且应该是坐着的姿态 ?想象一下装满豆子的袋子."(Larry Ewing给他的主意, 当时22岁的电子工程本科生Larry Ewing在学校科学计算研究所工作时看到了邮件列表里关于logo的讨论.这位热心的艺术家发现执笔画企鹅比做毕业论文有趣.)
Ewing 使用GIMP创建了企鹅的基本形态, 准备公布的时候,他突然想到,这只企鹅如果出在别人手里会是什么样?于是在保留Ewing和GIMP名字的前提下,他允许用户自由添加修改这只企鹅的造 型, 也衍生了现在诸多企鹅造型. 目前Ewing是Ximian的开发人员,Ximian的猴子图案也出自他笔下。
至于企鹅的名字: Tux. 因为企鹅总是黑白一身,当时外界认为这个名字来自燕尾服(Txuedo)一词.事实上Tux是“Torvalds' UniX”的缩写。
现 在, 企鹅Tux已经是Linux的标志,或者可以说品牌. 笑容可掬的Tux吸引了世界众多爱好自由的电脑爱好者. Tux自身的含义也随着Linux的壮大不断发展, 按ewing的话来讲:"这真是一件有意思的事情,我只花了20多个小时画了只企鹅, 同时我也花了四五年时间写程序代码.但是我所了解的企鹅远远比任何代码的含义还要深刻。"
UNIX的ls命令
ls是一个由POSIX和单一Unix标准规范的命令,在Unix和类Unix系统中都有实现。ls是英文list segment的缩写,用于列出文件,是Unix系统中使用非常频繁的命令。ls首次出现于原始版本的AT&T Unix中。它的名字来源于Multics操作系统的一个类似命令,意思是“列出文件块”(list segment)。目前有两种主流版本的ls:一种是自由软件基金会开发的GNU核心程序的组成部分;另一种由各种BSD版本发布,如FreeBSD、OpenBSD、NetBSD和苹果公司的Darwin。两种版本都是自由以及开源软件。
ls的使用
在Unix和类Unix操作系统中都有当前目录的概念,也即程序目前在目录树中的位置。
当不加参数运行时,ls列出当前目录下的所有文件和目录名。如果以目录名作为参数,则会列出该目录下的文件。用户也可以指定多个文件和目录作为参数,ls则会列出所有指定的文件和目录中的文件名。
以 "."(圆点)开头的目录在一般情况下不会被列出。用户可以加 -a 选项查看所有文件。
不加参数时,ls仅仅列出文件和目录的名称,不加任何修饰。这通常让人很难区分文件的类型、大小、权限等属性。显示文件常用信息的一些参数如下:
- -l(long)长格式,显示文件类型、权限、的数目、文件拥有者、文件所在的、大小、日期和文件名。硬链接组
- -F 在不同类型的文件的文件名结尾追加一个字符以示区别。可执行文件后加"*",目录后加"/",管道文件后加"|",套接字文件后加"=",普通文件没有后缀。
- -a(all)显示所有文件,包括以 . 开头的文件名(默认不显示)。
- -R(recursive)迭代显示目录下所有的子目录。ls -R/会显示文件系统中的所有文件。
- -d(directory)显示目录本身的信息,而不是列出目录下的文件。
在某些环境下,使用参数"--color"(GNU版)或者"-G"(FreeBSD版)后,ls会根据文件类型输出不同色彩的格式。GNU版的ls根据文件的类型、扩展名和使用权限来决定颜色,而FreeBSD版的ls仅仅检查文件类型和使用权限。
使用上述彩色选项时,输出示例如下:
Warming up:
(Source: POJ 1589)为一个文件块列出一个表格,Input是一些文件名,我们需要在Output中按照类ls所规定的一定格式列表输出(也就是ls的目录列表功能)。
Solve:
1 #include<stdio.h>
2
3
//
假设100个文件名,每个文件名62个字符左右
4
char name[
100][
62];
5
6
int cmp(
const
void *a,
const
void *b)
7 {
8
return strcmp((
char *)a,(
char *)b);
9 }
10
11
int main()
12 {
13
int n;
14
int i,j;
15
int tmp;
16
int max_len,row,col;
17
//
freopen("input","r",stdin);
18
while(scanf(
"
%d
",&n)!=EOF)
19 {
20
for(i=n;i<
100;i++)
21 name[i][
0]=
'
\0
';
22 max_len=-
1;
23 row=
1;
24
for(i=
0;i<n;i++)
25 scanf(
"
%s
",name[i]);
26
for(i=
0;i<n;i++)
27 {
28 tmp=strlen(name[i]);
29
if(max_len<tmp) max_len=tmp;
30 }
31
//
这是规定的格式
32
col=
62/(max_len+
2);
33
while(row*col<n) row++;
34 qsort(name,n,
sizeof(name[
0]),cmp);
35 printf(
"
------------------------------------------------------------\n
");
36
for(i=
0;i<row;i++)
37 {
38
for(j=
0;j<col;j++)
39
//
输出第j*row+i个文件的文件名
40
printf(
"
%-*s
",max_len+
2,name[j*row+i]);
41 printf(
"
\n
");
42 }
43 }
44
return
0;
45 }
Format:
(Source参考了UNIX v6的部分源码)
源码貌似用到了很多Linux下C,而且过于庞大复杂而又没多少注释,所以我暂时看不懂,我会翻阅一些资料将其弄懂,现在,就只能放在这里了。
//
这里是Linux下的C,和一般的C有一些区别,一般的C的库函数一共有15个,我会在《吴昊品工业级别项目源代码》中阐明的
#include <pwd.h>
#include <grp.h>
#include <fts.h>
#include <err.h>
#include <time.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define IS_NOPRINT(b) ((b)->fts_number == 1) /* 1 表示为not print */
struct buf
{
int num;
int total;
int bcfile;
int maxlen;
int usrlen;
//管道长度
int grplen;
int linklen;
int sizelen;
int inodelen;
int blocklen;
FTSENT *list; /* FTS, FTSENT结构和fts函数具体参考/usr/include/fts.h,联机帮助会有更多的资料以供参考(man fts_open可以获得联机帮助的信息 */
}b;
typedef struct name
{
//union,联合体,可以两个变量共用一个内存,使得空间被占用地更小
union
{
int uid;
char *usr;
}usr;
union
{
int gid;
char *grp;
}grp;
char date[0]; /* 为了节省空间而做出的策略,date不占用任何空间 */
}NAME;
//声明各种变量和各种函数
int col;
int rflg = 1;
int putout = 0;
int seeusr = 1, seegrp = 1;
int seeuid, seegid, singleflg, fts_options;
int Aflg, Cflg, Fflg, Lflg, Rflg, Sflg, Uflg;
int cflg, dflg, fflg, iflg, lflg, oflg, pflg, qflg, sflg, tflg, uflg;
static char *com_name;
void printone(void);
void printcol(void);
void printlong(void);
void q_copy(char *a, char *b);
void do_ls(int argc, char *argv[]);
void do_print(FTSENT *fp, FTSENT *list);
int cmparg(const FTSENT **a, const FTSENT **b);
int cmpname(const FTSENT *a, const FTSENT *b);
int cmptime(const FTSENT *a, const FTSENT *b);
int cmpsize(const FTSENT *a, const FTSENT *b);
static void (*printfcn)(void);
static void printtime(time_t t);
static void printlink(FTSENT *p);
static void modetostr(mode_t mode, char *buf);
static int printtype(mode_t mode);
static int printname(FTSENT *b, int flg);
static int (*sortfcn)(const FTSENT *a, const FTSENT *b);
int main(int argc, char *argv[])
{
char *p;
//寄存器变量
register int c;
struct winsize wbuf;
static char dot[] = ".", *dotav[] = { dot, (char *)NULL };
com_name = *argv;
if(isatty(STDOUT_FILENO))
{
/* 得出终端的宽度,默认宽度为80,如果获取失败,将激活-1选项 */
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &wbuf) == -1 || wbuf.ws_col == 0)
{
if(p = getenv("COLUMNS"))
col = atoi(p);
else
col = 80;
}
else
col = wbuf.ws_col;
Cflg = qflg = 1;
}
else
singleflg = 1;
sortfcn = cmpname;
printfcn = printcol;
fts_options = FTS_PHYSICAL;
while(--argc > 0 && (*++argv)[0] == '-')
{
while(c = *++argv[0])
switch(c)
{
case '1':
Cflg = 0;
singleflg = 1;
printfcn = printone;
break;
case 'A':
Aflg = 1;
break;
case 'C':
lflg = 0;
Cflg = 1;
printfcn = printcol;
break;
case 'F':
pflg = 0;
Fflg = 1;
break;
case 'H':
fts_options |= FTS_COMFOLLOW;
break;
case 'L':
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
break;
case 'R':
Rflg = 1;
dflg = 0;
break;
case 'S':
Sflg = 1;
sortfcn = cmpsize;
break;
case 'U':
Uflg = 1;
sortfcn = (int(*)(const FTSENT **, const FTSENT **))NULL; /* 这一步实则不必要,编写的理由是个人的感情因素 */
break;
case 'a':
Aflg = 1;
fts_options |= FTS_SEEDOT;
break;
case 'c': /* -u,-c,-t和标准ls命令的表现方式一样,详见联机帮助,可ls --help或man ls */
uflg = 0;
cflg = 1;
if(lflg == 0)
sortfcn = cmptime;
break;
case 'd':
dflg = 1;
Rflg = 0;
break;
case 'f': /* -f和标准ls一样,联机帮助有其说明,注意此选项的输出是没有颜色的 */
fts_options |= FTS_SEEDOT;
fflg = Aflg = Uflg = 1;
sortfcn = (int(*)(const FTSENT **, const FTSENT **))NULL;
lflg = sflg = tflg = 0;
break;
case 'g':
lflg = 1;
seeusr = 0;
printfcn = printlong;
break;
case 'i':
iflg = 1;
break;
case 'l':
Cflg = 0;
lflg = 1;
if(tflg == 0)
sortfcn = cmpname;
printfcn = printlong;
break;
case 'n':
lflg = 1;
seeuid = seegid = 1;
break;
case 'o':
lflg = 1;
seegrp = 0;
printfcn = printlong;
break;
case 'p': /* -p和-F的表现和标准ls命令一样,具体参阅联机帮助 */
Fflg = 0;
pflg = 1;
break;
case 'q':
qflg = 1;
break;
case 'r':
rflg = -1;
break;
case 's':
sflg = 1;
break;
case 't':
tflg = 1;
sortfcn = cmptime;
break;
case 'u':
cflg = 0;
uflg = 1;
if(lflg == 0)
sortfcn = cmptime;
break;
default:
fprintf(stderr, "Usage: %s -[1ACFLHRTacdfgilnoqrstu] [file ...]\n", com_name);
exit(1);
}
}
if(lflg) /* -l命令会导致-1选项的失效 */
printfcn = printlong;
if(argc)
do_ls(argc, argv);
else
do_ls(1, dotav);
return 0;
}
void do_ls(int argc, char *argv[])
{
FTS *ftsp;
register FTSENT *p, *tmp;
ftsp = fts_open(argv, fts_options, Uflg ? NULL : cmparg); /* 把所有文件读入一棵树中, 详见联机帮助 */
if(ftsp == (FTS *)NULL){
fprintf(stderr, "%s: fts_open error\n", com_name);
exit(1);
}
do_print(NULL, fts_children(ftsp, 0));
if(dflg)
return;
while(p = fts_read(ftsp)){
switch(p->fts_info){
case FTS_DC:
warnx("%s: directory causes a cycle", p->fts_name); /* err, warn, warnx等函数具体可查看err.h头文件和man warn来了解其功能 */
break;
case FTS_ERR:
case FTS_DNR:
errno = p->fts_errno; /* fts函数不会设置errno,函数具体功能参阅联机帮助 */
warn("%s", p->fts_name);
break;
case FTS_D:
if(p->fts_level != 0 && p->fts_name == '.' && Aflg == 0)
break;
if(putout)
printf("\n%s:\n", p->fts_path);
else if(argc > 1){
printf("%s:\n", p->fts_path);
putout = 1;
}
tmp = fts_children(ftsp, 0);
do_print(p, tmp);
if(Rflg == 0 && tmp)
fts_set(ftsp, p, FTS_SKIP);
break;
default:
break;
}
}
fts_close(ftsp); /* 分配的内存会自动释放 */
}
void do_print(FTSENT *fp, FTSENT *list)
{
NAME *np;
char buf[20];
struct group *gp;
struct passwd *pw;
register FTSENT *p;
register struct stat *q;
int num, total, needstat;
int n, m, in, im, sn, sm;
int un, um, gn, gm, ln, lm, bn, bm, bcfile;
if(list == NULL)
return;
num = total = bcfile = 0;
n = m = in = im = sn = sm = 0;
un = um = gn = gm = ln = lm = bn = bm = 0;
needstat = iflg | sflg | lflg;
for(p = list; p; p = p->fts_link){
if(p->fts_info == FTS_ERR || p->fts_info == FTS_NS){
errno = p->fts_errno;
warn("%s", p->fts_name);
p->fts_number = 1;
continue;
}
if(fp == NULL){ /* 若为命令行参数 */
if(p->fts_info == FTS_D && dflg == 0){
p->fts_number = 1;
continue;
}
}
else{
if(p->fts_name[0] == '.' && Aflg == 0){
p->fts_number = 1;
continue;
}
}
if(qflg) /* 以?代替不可打印的字符 */
q_copy(p->fts_name, p->fts_name);
if(m < (n = p->fts_namelen))
m = n;
if(needstat){
q = p->fts_statp;
if(iflg && im < (in = q->st_ino))
im = in;
if(sflg && bm < (bn = q->st_blocks))
bm = bn;
if(sm < (sn = q->st_size))
sm = sn;
if(lm < (ln = q->st_nlink))
lm = ln;
total += q->st_blocks;
if(lflg){
if(seeuid){ /* 与标准ls不同,本程序,-n选项会使-g -o选项失效 */
if(um < (un = q->st_uid))
um = un;
}
else if(seeusr){
pw = getpwuid(q->st_uid);
if(pw && um < (un = strlen(pw->pw_name)))
um = un;
}
else
um = 0;
if(seegid){
if(gm < (gn = q->st_gid))
gm = gn;
}
else if(seegrp){
gp = getgrgid(q->st_gid);
if(gp && gm < (gn = strlen(gp->gr_name)))
gm = gn;
}
else
gm = 0;
if(seeuid && seegid){
np = malloc(sizeof(NAME));
np->usr.uid = un;
np->grp.gid = gn;
}
else{
if((np = malloc(sizeof(NAME) + un + gn + !(!un) + !(!gn))) == NULL) /* !(!un) + !(!gn)用来判断是否有设置seeusr和seegrp */
err(1, NULL);
if(seeusr){
np->usr.usr = &np->date[0];
strcpy(np->usr.usr, pw->pw_name);
}
if(seegrp){
np->grp.grp = &np->date[un + !(!un)];
strcpy(np->grp.grp, gp->gr_name);
}
}
if(S_ISCHR(q->st_mode) || S_ISBLK(q->st_mode))
bcfile = 1;
p->fts_pointer = np;
}
}
++num;
}
if(num == 0)
return;
b.list = list;
b.num = num;
b.maxlen = m;
if(needstat){
b.total = total;
b.bcfile = bcfile;
snprintf(buf, sizeof(buf), "%u", lm);
b.linklen = strlen(buf);
snprintf(buf, sizeof(buf), "%u", sm);
b.sizelen = strlen(buf);
snprintf(buf, sizeof(buf), "%u", im);
b.inodelen = strlen(buf);
snprintf(buf, sizeof(buf), "%u", bm);
b.blocklen = strlen(buf);
if(seeuid && seegid){
snprintf(buf, sizeof(buf), "%u", um);
b.usrlen = strlen(buf);
snprintf(buf, sizeof(buf), "%u", gm);
b.grplen = strlen(buf);
}
else{
b.usrlen = um;
b.grplen = gm;
}
}
printfcn();
putout = 1;
if(lflg)
for(p = list; p; p = p->fts_link)
free(p->fts_pointer);
}
int cmparg(const FTSENT **a, const FTSENT **b)
{
FTSENT *ap, *bp;
ap = *(FTSENT **)a;
if(ap->fts_info == FTS_ERR)
return 0;
bp = *(FTSENT **)b;
if(bp->fts_info == FTS_ERR)
return 0;
if(ap->fts_info == FTS_NS || bp->fts_info == FTS_NS)
return cmpname(ap, bp);
if(ap->fts_info == bp->fts_info)
sortfcn(ap, bp);
if(ap->fts_level == 0){ /* 命令行参数的目录默认大于文件, 详见标准ls命令的说明文档 */
if(ap->fts_info == FTS_D){
if(bp->fts_info != FTS_D)
return 1;
}
else if(bp->fts_info == FTS_D)
return -1;
}
return sortfcn(ap, bp);
}
int cmpname(const FTSENT *a, const FTSENT *b)
{
return rflg * strcmp(a->fts_name, b->fts_name);
}
int cmpsize(const FTSENT *a, const FTSENT *b)
{
return rflg * (b->fts_statp->st_size - a->fts_statp->st_size);
}
int cmptime(const FTSENT *a, const FTSENT *b)
{
if(cflg)
return rflg * (b->fts_statp->st_ctime - a->fts_statp->st_ctime);
else if(uflg)
return rflg * (b->fts_statp->st_atime - a->fts_statp->st_atime);
else
return rflg * (b->fts_statp->st_mtime - a->fts_statp->st_mtime);
}
void q_copy(char *a, char *b)
{
register char *p, *q;
for(p = a, q = b; *p; p++, q++){
if(isprint(*p))
*q = *p;
else
*q = '?';
}
}
void printone(void)
{
register FTSENT *p;
for(p = b.list; p; p = p->fts_link){
if(IS_NOPRINT(p))
continue;
printname(p, 1);
putchar('\n');
}
}
void printcol(void)
{
static int lastnum = -1;
static FTSENT **array;
register FTSENT *p;
int i, j, k, tm, cn, chn, num, len, nrow, ncol, diff, left, tmcol;
if(b.num > lastnum){
lastnum = b.num;
if((array = realloc(array, sizeof(FTSENT *) * b.num)) == NULL){
err(1, NULL);
printone();
}
}
num = 0;
for(p = b.list; p; p = p->fts_link)
if(p->fts_number != 1)
array[num++] = p; i = b.maxlen;
if(iflg)
i += b.inodelen + 1;
if(sflg)
i += b.blocklen + 1;
if(pflg || Fflg)
i += 1;
len = (i + 8) & ~7; /* 规整到下一个8的倍数 */
if(col < 2 * len){
printone();
return;
}
ncol = col / len;
nrow = num / ncol;
if(num % ncol)
nrow++;
tmcol = num / nrow;
left = num - (tmcol * nrow);
diff = left / nrow;
diff += 1; /* 每行需另外输出的的个数 */
if(sflg)
printf("total = %u\n", b.total);
tm = 0;
for(i = 0; i < nrow; ++i){
k = len; /* 输出应该停止处 */
for(j = chn = 0; j < ncol; ++j){
if(tm >= num)
break;
if(j >= tmcol){ /* 用来调整使每行的个数尽可能一样 */
if(j < tmcol + diff && left)
--left;
else
break;
}
chn += printname(array[tm++], 1);
while((cn = (chn + 8 & ~7)) <= k){
putchar('\t');
chn = cn;
}
k += len;
}
putchar('\n');
}
}
void printlong(void)
{
NAME *np;
int mode;
char buf[10];
register FTSENT *p;
register struct stat *sp;
if(b.list->fts_level != 0)
printf("total %u\n", b.total);
for(p = b.list; p; p = p->fts_link){
if(IS_NOPRINT(p))
continue;
sp = p->fts_statp;
mode = sp->st_mode;
if(iflg)
printf("%*lu ", b.inodelen, sp->st_ino);
if(sflg)
printf("%*lu ", b.blocklen, sp->st_blocks);
modetostr(mode, buf);
np = p->fts_pointer;
printf("%s ", buf);
printf("%*u ", b.linklen, sp->st_nlink);
if(seeuid)
printf("%*u ", b.usrlen, np->usr.uid);
else if(seeusr)
printf("%*s ", b.usrlen, np->usr.usr);
if(seegid)
printf("%*u ", b.grplen, np->grp.gid);
else if(seegrp)
printf("%*s ", b.grplen, np->grp.grp);
if(S_ISCHR(mode) || S_ISBLK(mode))
printf("%3d,%3d ", major(sp->st_rdev), minor(sp->st_rdev));
else if(b.bcfile)
printf("%*s%*lu ", 8 - b.sizelen, "", b.sizelen, sp->st_size);
else
printf("%*lu ", b.sizelen, sp->st_size);
if(cflg)
printtime(sp->st_ctime);
else if(uflg)
printtime(sp->st_atime);
else
printtime(sp->st_mtime);
printname(p, 0);
if(Fflg || pflg)
printtype(mode);
if(S_ISLNK(mode))
printlink(p);
putchar('\n');
}
}
static void printlink(FTSENT *p)
{
int lnklen;
char name[256], path[256];
if(p->fts_level == 0)
snprintf(name, sizeof(name), "%s", p->fts_name);
else
snprintf(name, sizeof(name), "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
if((lnklen = readlink(name, path, sizeof(path) - 1)) == -1){ /* readlink详见联机帮助 */
fprintf(stderr, "\n%s: %s: %s\n", com_name, name, strerror(errno));
return;
}
path[lnklen] = '\0';
printf(" -> %s", path);
}
static void printtime(time_t t)
{
char *s;
time_t year, tm;
time(&tm);
year = tm - 60 * 30 * 24 * 60 * 60;
s = ctime(&t);
if(t < year)
printf("%.7s %.4s ", s + 4, s + 20);
else
printf("%.12s ", s + 4);
}
static void modetostr(mode_t mode, char *buf)
{
strcpy(buf, "----------");
if(S_ISDIR(mode))
buf[0] = 'd';
if(S_ISCHR(mode))
buf[0] = 'c';
if(S_ISBLK(mode))
buf[0] = 'b';
if(S_ISLNK(mode))
buf[0] = 'l';
if(S_ISSOCK(mode))
buf[0] = 's';
if(S_ISFIFO(mode))
buf[0] = 'p';
if(mode & S_IRUSR)
buf[1] = 'r';
if(mode & S_IWUSR)
buf[2] = 'w';
if(mode & S_IXUSR)
buf[3] = 'x';
if(mode & S_ISUID)
buf[3] = 's';
if(mode & S_IRGRP)
buf[4] = 'r';
if(mode & S_IWGRP)
buf[5] = 'w';
if(mode & S_IXGRP)
buf[6] = 'x';
if(mode & S_ISGID)
buf[6] = 'x';
if(mode & S_IROTH)
buf[7] = 'r';
if(mode & S_IWOTH)
buf[8] = 'w';
if(mode & S_IXOTH)
buf[9] = 'x';
if(mode & S_ISVTX)
buf[9] = 't';
}
static int printname(FTSENT *p, int flg)
{
int np, mode;
struct stat *sp;
np = 0;
sp = p->fts_statp;
if(flg){
if(iflg)
np += printf("%*lu ", b.inodelen, sp->st_ino);
if(sflg)
np += printf("%*lu ", b.blocklen, sp->st_blocks);
}
mode = sp->st_mode;
if(fflg)
np += printf("%s", p->fts_name);
else{ /* 注意printf的返回值 */
if(mode & S_ISUID){
printf("\033[37;41m");
np += printf("%s", p->fts_name);
printf("\033[0m");
}
else if(mode & S_ISGID){
printf("\033[30;43m");
np += printf("%s", p->fts_name);
printf("\033[0m");
}
else if(mode & S_ISVTX){
printf("\033[37;44m");
np += printf("%s", p->fts_name);
printf("\033[0m");
}
else{
switch(mode & S_IFMT){
case S_IFDIR:
printf("\033[01;34m");
np += printf("%s", p->fts_name);
printf("\033[0m");
break;
case S_IFIFO:
printf("\033[33m");
np += printf("%s", p->fts_name);
printf("\033[0m");
break;
case S_IFSOCK:
printf("\033[01;35m");
np += printf("%s", p->fts_name);
printf("\033[0m");
break;
case S_IFLNK:
printf("\033[01;36m");
np += printf("%s", p->fts_name);
printf("\033[0m");
break;
case S_IFCHR:
case S_IFBLK:
printf("\033[01;33m");
np += printf("%s", p->fts_name);
printf("\033[0m");
break;
default:
if(mode & S_IXUSR || mode & S_IXGRP || mode & S_IXOTH){
printf("\033[01;32m");
np += printf("%s", p->fts_name);
printf("\033[0m");
}
else
np += printf("%s", p->fts_name);
break;
}
}
}
if(Fflg || pflg)
np += printtype(mode);
return np;
}
static int printtype(mode_t mode)
{
switch(mode & S_IFMT){
case S_IFDIR:
putchar('/');
return 1;
case S_IFLNK:
if(Fflg == 0)
break;
putchar('@');
return 1;
case S_IFSOCK:
if(Fflg == 0)
break;
putchar('=');
return 1;
default:
if(Fflg == 0)
break;
if(mode & (S_IXUSR | S_IXGRP | S_IXOTH)){
putchar('*');
return 1;
}
break;
}
return 0;
}