📄 13.htm
字号:
" where:\n" \
" startUID is the starting userid to add, and\n" \
" file is an input file in form:\n" \
" first_name last_name password\n" \
)
exit
}
infile = ARGV[1]
printf( "Starting UID: %s\n\n", startuid )
}
/^#/ { next }
{
++record
first = $1
last = $2
passwd = $3
user= substr( tolower( first ), 1, 1 ) tolower( last )
uid = startuid + record - 1
gid = uid
printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n", \
user, passwd, uid, gid, first, last, user \
)
}
</PRE>
<P>Debian中有两个软件包提供了POSIX <CODE>awk</CODE>:
<UL>
<LI><CODE>mawk</CODE>
<UL>
<LI>Priority: required
<LI>Installed-Size: 228
<LI>Smaller and much faster — good for default install
<LI>Compile-time limits exist
<UL>
<LI>NF = 32767
<LI>sprintf buffer = 1020 </LI></UL></LI></UL>
<LI><CODE>gawk</CODE>
<UL>
<LI>Priority: optional
<LI>Installed-Size: 1708
<LI>Larger and featureful — many extensions implemented
<UL>
<LI>System V Release 4 version of UNIX
<LI>Bell Labs awk
<LI>GNU-specific </LI></UL></LI></UL></LI></UL>
<HR>
<A name=s13.4></A>
<H2>13.4 Perl</H2>
<P>运行于类Unix系统上的<STRONG>解释器</STRONG>。
<P>Perl参考资源:
<UL>
<LI><CODE>perl(1)</CODE>
<LI><EM>Programming Perl</EM>, 3rd edition (O'Reilly) </LI></UL>
<P>简短的程序样例(创建<CODE>newusers</CODE>命令输入): <PRE> #!/usr/bin/perl
# (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
$pid=1000;
while (<STDIN>) {
if (/^#/) { next;}
chop;
$pid++;
($n1, $n2, $n3) = split / /;
print $n1,"_",$n2,":", $n3, ":",$pid,
":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n"
}
</PRE>
<P>安装Perl模块<VAR>module_name</VAR>: <PRE> # perl -MCPAN -e 'install <VAR>module_name</VAR>'
</PRE>
<HR>
<A name=s13.5></A>
<H2>13.5 Python</H2>
<P>一个不错的面向对象的解释器。
<P>Python参考资源:
<UL>
<LI><CODE>python(1)</CODE>
<LI><EM>Learning Python</EM> (O'Reilly). </LI></UL>
<P>简短的程序样例(创建<CODE>newusers</CODE>命令输入): <PRE> #! /usr/bin/env python
import sys, string
# (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
# Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001
# This program is distributed WITHOUT ANY WARRANTY.
def usages():
print \
"Usage: ", sys.argv[0], " start_UID [filename]\n" \
"\tstartUID is the starting userid to add.\n" \
"\tfilename is input file name. If not specified, standard input.\n\n" \
"Input file format:\n"\
"\tfirst_name last_name password\n"
return 1
def parsefile(startuid):
#
# main filtering
#
uid = startuid
while 1:
line = infile.readline()
if not line:
break
if line[0] == '#':
continue
(first, last, passwd) = string.split(string.lower(line))
# above crashes with wrong # of parameters :-)
user = first[0] + last
gid = uid
lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" % \
(user, passwd, uid, gid, first, last, user)
sys.stdout.write(lineout)
+uid
if __name__ == '__main__':
if len(sys.argv) == 1:
usages()
else:
uid = int(sys.argv[1])
#print "# UID start from: %d\n" % uid
if len(sys.argv) > 1:
infilename = string.join(sys.argv[2:])
infile = open(infilename, 'r')
#print "# Read file from: %s\n\n" % infilename
else:
infile = sys.stdin
parsefile(uid)
</PRE>
<HR>
<A name=s13.6></A>
<H2>13.6 Make</H2>
<P>Make参考资源:
<UL>
<LI><SAMP>info make</SAMP>
<LI><CODE>make(1)</CODE>
<LI><EM>Managing Projects with make</EM>, 2nd edition (O'Reilly) </LI></UL>
<P>简单自动变量:
<P>语法规则: <PRE> <VAR>target</VAR>: [ <VAR>prerequisites</VAR> ... ]
[TAB] <VAR>command1</VAR>
[TAB] -<VAR>command2</VAR> # ignore errors
[TAB] @<VAR>command3</VAR> # suppress echoing
</PRE>
<P>在此<SAMP>[TAB]</SAMP>代表一个TAB符。完成变量代换后shell将逐行进行解释。在行尾使用<SAMP>\</SAMP>可以续行。使用<SAMP>$$</SAMP>可将<SAMP>$</SAMP>加入到shell脚本的环境变量中。
<P>适用于<VAR>target</VAR>和<VAR>prerequisites</VAR>的隐含的等价规则: <PRE> %: %.c header.h
</PRE>
<P>or, <PRE> %.o: %.c header.h
</PRE>
<P>在此,<VAR>target</VAR>包含了<SAMP>%</SAMP>字符(确切地说是其中之一),<SAMP>%</SAMP>可匹配实际的target文件名中任何非空子串。<VAR>prerequisites</VAR>同样也使用<SAMP>%</SAMP>来显示它们的名字是如何关联到实际的target文件名的。
<P>用<STRONG>Suffix rules</STRONG>方法来定义<CODE>make</CODE>的隐含规则(implicit
rules)已经<STRONG>过时</STRONG>。GNU
<CODE>make</CODE>因为兼容性的考虑仍支持它,但只要有可能就应该使用与之等价的模版规则(pattern rules): <PRE> old suffix rule --> new pattern rule
.c: --> % : %.c
.c.o: --> %.o: %.c
</PRE>
<P>上述规则所使用的自动变量: <PRE> foo.o: new1.c new2.c old1.c new3.c
$@ == foo.o (target)
$< == new1.c (first one)
$? == new1.c new2.c new3.c (newer ones)
$^ == new1.c new2.c old1.c new3.c (all)
$* == `%' matched stem in the target pattern.
</PRE>
<P>变量参考: <PRE> foo1 := bar # One-time expansion
foo2 = bar # Recursive expansion
foo3 += bar # Append
SRCS := $(wildcard *.c)
OBJS := $(foo:c=o)
OBJS := $(foo:%.c=%.o)
OBJS := $(patsubst %.c,%.o,$(foo))
DIRS = $(dir directory/filename.ext) # Extracts "directory"
$(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...
</PRE>
<P>执行<SAMP>make -p -f/dev/null</SAMP>可查看内部自动规则。
<HR>
<A name=s13.7></A>
<H2>13.7 C</H2>
<P>准备工作: <PRE> # apt-get install glibc-doc manpages-dev libc6-dev gcc
</PRE>
<P>C参考资源:
<UL>
<LI><SAMP>info libc</SAMP> (C library function reference)
<LI><CODE>gcc(1)</CODE>
<LI><CODE>each_C_library_function_name(3)</CODE>
<LI>Kernighan & Ritchie, <EM>The C Programming Language</EM>, 2nd edition
(Prentice Hall). </LI></UL>
<HR>
<A name=s13.7.1></A>
<H3>13.7.1 简单C编程(<CODE>gcc</CODE>)</H3>
<P>一个简单的例子,将<CODE>example.c</CODE>和库函数<CODE>libm</CODE>编译成可执行文件<CODE>run_example</CODE>:
A simple example to compile <CODE>example.c</CODE> with a library
<CODE>libm</CODE> into an executable <CODE>run_example</CODE>: <PRE> $ cat > example.c << EOF
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(int argc, char **argv, char **envp){
double x;
char y[11];
x=sqrt(argc+7.5);
strncpy(y, argv[0], 10); /* prevent buffer overflow */
y[10] = '\0'; /* fill to make sure string ends with '\0' */
printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
return 0;
}
EOF
$ gcc -Wall -g -o run_example example.c -lm
$ ./run_example
1, 2.915, ./run_exam, (null)
$ ./run_example 1234567890qwerty
2, 3.082, ./run_exam, 1234567890qwerty
</PRE>
<P>在此,sqrt()链接库函数<SAMP>lib<STRONG>m</STRONG></SAMP>需要<SAMP>-l<STRONG>m</STRONG></SAMP>选项。真正的库函数是位于<CODE>/lib</CODE>下的<CODE>libm.so.6</CODE>,它是<CODE>libm-2.1.3.so</CODE>的一个符号链接。
<P>看看输出文本中最后的参数,尽管指定了<SAMP>%10s</SAMP>,它还是多于10个字符。
<P>使用不带边界检查的指针内存操作函数如<CODE>sprintf</CODE>和<CODE>strcpy</CODE>会妨碍缓冲区溢出侦测,故使用<CODE>snprintf</CODE>和<CODE>strncpy</CODE>。
<HR>
<A name=s13.7.2></A>
<H3>13.7.2 调试</H3>
<HR>
<A name=s13.7.2.1></A>
<H4>13.7.2.1 使用<CODE>gdb</CODE>进行调试</H4>
<P>准备工作: <PRE> # apt-get install gdb
</PRE>
<P><CODE>gdb</CODE>参考资源:
<UL>
<LI><SAMP>info gdb</SAMP> (tutorial)
<LI><CODE>gdb(1)</CODE>
<LI><CODE><A
href="http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html">http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html</A></CODE>
</LI></UL>
<P>使用<SAMP>-g</SAMP>选项编译程序就可使用<CODE>gdb</CODE>进行调试。许多命令都可以缩写。Tab扩展功能和在shell中的一样。
<PRE> $ gdb program
(gdb) b 1 # 在line 1设置断点
(gdb) run <VAR>arg1 arg2 arg3</VAR> # 运行程序
(gdb) next # 下一行
...
(gdb) step # 前进一步
...
(gdb) p parm # 打印parm
...
(gdb) p parm=12 # 设置其值为12
</PRE>
<P>在Emacs环境下调试程序,参阅<A
href="http://qref.sourceforge.net/Debian/reference/ch-edit.zh-cn.html#s-editkey">编辑器命令总汇(Emacs,Vim),
第 11.3.4 节</A>。
<HR>
<A name=s-ss-ldd></A>
<H4>13.7.2.2 检查库函数关联关系</H4>
<P>使用<CODE>ldd</CODE>可查看程序与库函数的关联关系: <PRE> $ ldd /bin/ls
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -