| 1 |
<!-- CVS revision of this document "$Revision: 1.3 $" -->
|
| 2 |
<!-- CVS revision of original english document "1.30" -->
|
| 3 |
<!--Line width ruler (ruler uses 78 characters) 34567890123456789012345-->
|
| 4 |
<!-- DON't TOUCH GROFF SECTION!!! -->
|
| 5 |
|
| 6 |
|
| 7 |
<chapt id="program">Programming
|
| 8 |
<p>
|
| 9 |
Do not use "test" as the name of an executable test file. <prgn>test</prgn> is
|
| 10 |
a shell builtin.
|
| 11 |
|
| 12 |
<sect>Where to start
|
| 13 |
<p>
|
| 14 |
References:
|
| 15 |
<list compact>
|
| 16 |
<item>Documents and examples under <file>&dochome;<var>packages</var></file>
|
| 17 |
<item><url id="&uno-jclark;" name="Unix / Programming Information">
|
| 18 |
<item><em>Linux Programming Bible</em> (John Goerzen/IDG books)
|
| 19 |
</list>
|
| 20 |
<p>
|
| 21 |
Many long info documents can be obtained as paperbacks from
|
| 22 |
<url id="&gnuhome;" name="GNU">.
|
| 23 |
<p>
|
| 24 |
The next four sections contain sample scripts in different languages for
|
| 25 |
creating a text file of account information to be added to
|
| 26 |
<file>/etc/passwd</file> using a batch processor such as the
|
| 27 |
<prgn>newusers</prgn> program. Each script requires as input a file with lines
|
| 28 |
of the form <tt>firstname lastname password</tt>. (Actual user home
|
| 29 |
directories will not be created via these scripts.)
|
| 30 |
</sect>
|
| 31 |
|
| 32 |
<sect id="shell">Shell
|
| 33 |
<p>
|
| 34 |
Reading shell scripts is the <strong>best</strong> way to understand how
|
| 35 |
a Unix-like system works. Here, I give some pointers and reminders for shell
|
| 36 |
programming.
|
| 37 |
|
| 38 |
<sect1 id="bash">Bash &ndash <strong>GNU</strong> standard interactive shell
|
| 39 |
<p>
|
| 40 |
References for Bash:
|
| 41 |
<list compact>
|
| 42 |
<item><manref name="bash" section="1">
|
| 43 |
<item><tt>info bash</tt>
|
| 44 |
<item>the LDP <url id="&bashprogintro-howto;" name="BASH Programming - Introduction HOWTO">
|
| 45 |
as starter information.
|
| 46 |
<item><tt>mc &dochome;bash/examples/ &dochome;bash/</tt>
|
| 47 |
<p>
|
| 48 |
(Install the <package>bash-doc</package> package to see the example files.)
|
| 49 |
<item><em>Learning the bash Shell</em>, 2nd edition (O'Reilly)
|
| 50 |
</list>
|
| 51 |
<p>
|
| 52 |
Short program example (create account entries for <prgn>newusers</prgn> from
|
| 53 |
standard input):
|
| 54 |
<example>
|
| 55 |
#!/bin/bash
|
| 56 |
# (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
|
| 57 |
pid=1000;
|
| 58 |
while read n1 n2 n3 ; do
|
| 59 |
if [ ${n1:0:1} != "#" ]; then
|
| 60 |
let pid=$pid+1
|
| 61 |
echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash
|
| 62 |
fi
|
| 63 |
done
|
| 64 |
</example>
|
| 65 |
|
| 66 |
<sect1 id="posix-shell">POSIX shells
|
| 67 |
<p>
|
| 68 |
Several packages provide a POSIX shell in &debian;:
|
| 69 |
<list compact>
|
| 70 |
<item><package>dash</package> (Sarge)
|
| 71 |
<list compact>
|
| 72 |
<item>Priority: optional
|
| 73 |
<item>Installed-Size: 176
|
| 74 |
<item>Smallest and much fastest — best for initial boot
|
| 75 |
</list>
|
| 76 |
<item><package>ash</package> (Woody)
|
| 77 |
<list compact>
|
| 78 |
<item>Priority: optional
|
| 79 |
<item>Installed-Size: 180
|
| 80 |
<item>Smaller and much faster — good for initial boot
|
| 81 |
</list>
|
| 82 |
<item><package>bash</package>
|
| 83 |
<list compact>
|
| 84 |
<item>Essential: yes
|
| 85 |
<item>Priority: required
|
| 86 |
<item>Installed-Size: 580
|
| 87 |
<item>Larger and featureful — many extensions implemented
|
| 88 |
</list>
|
| 89 |
<item><package>pdksh</package>
|
| 90 |
<list compact>
|
| 91 |
<item>Priority: optional
|
| 92 |
<item>Installed-Size: 408
|
| 93 |
<item>Complete AT&T ksh look-alike
|
| 94 |
</list>
|
| 95 |
</list>
|
| 96 |
<p>
|
| 97 |
If you are writing shell script for portability, it is best to write it as
|
| 98 |
a POSIX shell script. Use <file>/bin/sh</file> linked to
|
| 99 |
<prgn>ash</prgn> or (<prgn>dash</prgn>) to test its POSIX compliance.
|
| 100 |
Avoid writing scripts with a <strong>bashism</strong>.
|
| 101 |
|
| 102 |
<sect1 id="shell-param">Shell parameters
|
| 103 |
<p>
|
| 104 |
Several <strong>special parameters</strong> to remember:
|
| 105 |
<example compact>
|
| 106 |
$0 = name of the shell or shell script
|
| 107 |
$1 = first(1) shell argument
|
| 108 |
...
|
| 109 |
$9 = ninth(9) shell argument
|
| 110 |
$# = number of positional parameters
|
| 111 |
"$*" = "$1 $2 $3 $4 ... $<var>n</var>"
|
| 112 |
"$@" = "$1" "$2" "$3" "$4" ... "$<var>n</var>"
|
| 113 |
$? = exit status of the most recent command
|
| 114 |
$$ = PID of this shell script
|
| 115 |
$! = PID of most recently started background job
|
| 116 |
</example>
|
| 117 |
<p>
|
| 118 |
Basic <strong>parameter expansions</strong> to remember:
|
| 119 |
<example compact>
|
| 120 |
Form If <var>var</var> is set(*) If <var>var</var> is not set(*)
|
| 121 |
${<var>var</var>:-<var>string</var>} $<var>var</var> <var>string</var>
|
| 122 |
${<var>var</var>:+<var>string</var>} <var>string</var> null
|
| 123 |
${<var>var</var>:=<var>string</var>} $<var>var</var> <var>string</var>
|
| 124 |
(and run <var>var</var>=<var>string</var>)
|
| 125 |
${<var>var</var>:?<var>string</var>} $<var>var</var> (echo <var>string</var> and then exit)
|
| 126 |
</example>
|
| 127 |
Here, the colon `:' in all of these operators is actually optional.
|
| 128 |
<list compact>
|
| 129 |
<item>With `:' = operator test for "exist" and "not null".
|
| 130 |
<item>Without `:' = operator test for "exist" only.
|
| 131 |
</list>
|
| 132 |
<p>
|
| 133 |
Basic <strong>parameter substitutions</strong> to remember:
|
| 134 |
<example compact>
|
| 135 |
Form Result
|
| 136 |
${<var>var</var>%<var>suffix</var>} Remove smallest <var>suffix</var> pattern
|
| 137 |
${<var>var</var>%%<var>suffix</var>} Remove largest <var>suffix</var> pattern
|
| 138 |
${<var>var</var>#<var>prefix</var>} Remove smallest <var>prefix</var> pattern
|
| 139 |
${<var>var</var>##<var>prefix</var>} Remove largest <var>prefix</var> pattern
|
| 140 |
</example>
|
| 141 |
|
| 142 |
<sect1 id="shell-redirect">Shell redirection
|
| 143 |
<p>
|
| 144 |
Basic <strong>redirection</strong> to remember (here the [n] is an optional number):
|
| 145 |
<example compact>
|
| 146 |
[n]> <var>file</var> Redirect standard output (or n) to <var>file</var>.
|
| 147 |
[n]>> <var>file</var> Append standard output (or n) to <var>file</var>.
|
| 148 |
[n]< <var>file</var> Redirect standard input (or n) from <var>file</var>.
|
| 149 |
[n1]>&n2 Redirect standard output (or n1) to n2.
|
| 150 |
> <var>file</var> >&2 Redirect standard and error output to <var>file</var>.
|
| 151 |
| <var>command</var> Pipe standard output (or n) to <var>command</var>.
|
| 152 |
>&2 | <var>command</var> Pipe standard and error output to <var>command</var>.
|
| 153 |
</example>
|
| 154 |
|
| 155 |
<sect1 id="shell-cond">Shell conditionals
|
| 156 |
<p>
|
| 157 |
Each command returns an <strong>exit status</strong> which can be used for
|
| 158 |
the conditional expression:
|
| 159 |
<list compact>
|
| 160 |
<item>Success: 0 (True)
|
| 161 |
<item>Error: 1 - 255 (False)
|
| 162 |
</list>
|
| 163 |
Note that the use here of a 0 value to mean "true" differs from the
|
| 164 |
usual convention in some other areas of computing.
|
| 165 |
Also, `[' is the equivalent of the <prgn>test</prgn> command,
|
| 166 |
which evaluates its arguments up to `]' as a conditional expression.
|
| 167 |
<p>
|
| 168 |
Basic <strong>conditional idioms</strong> to remember are:
|
| 169 |
<example compact>
|
| 170 |
<var>command</var> && <var>if_success_run_this_command_too</var>
|
| 171 |
<var>command</var> || <var>if_not_success_run_this_command_too</var>
|
| 172 |
|
| 173 |
if [ <var>conditional_expression</var> ]; then
|
| 174 |
<var>if_success_run_this_command</var>
|
| 175 |
else
|
| 176 |
<var>if_not_success_run_this_command</var>
|
| 177 |
fi
|
| 178 |
</example>
|
| 179 |
<p>
|
| 180 |
<strong>File</strong> comparison operators in the conditional expression are:
|
| 181 |
<example compact>
|
| 182 |
-e <var>file</var> True if <var>file</var> exists.
|
| 183 |
-d <var>file</var> True if <var>file</var> exists and is a directory.
|
| 184 |
-f <var>file</var> True if <var>file</var> exists and is a regular file.
|
| 185 |
-w <var>file</var> True if <var>file</var> exists and is writable.
|
| 186 |
-x <var>file</var> True if <var>file</var> exists and is executable.
|
| 187 |
<var>file1</var> -nt <var>file2</var> True if <var>file1</var> is newer than <var>file2</var>. (modification)
|
| 188 |
<var>file1</var> -ot <var>file2</var> True if <var>file1</var> is older than <var>file2</var>. (modification)
|
| 189 |
<var>file1</var> -ef <var>file2</var> True if they are the same device and inode numbers.
|
| 190 |
</example>
|
| 191 |
<p>
|
| 192 |
<strong>String</strong> comparison operators in the conditional expression are:
|
| 193 |
<example compact>
|
| 194 |
-z <var>str</var> True if the length of <var>str</var> is zero.
|
| 195 |
-n <var>str</var> True if the length of <var>str</var> is non-zero.
|
| 196 |
<var>str1</var> == <var>str2</var> True if the <var>str</var> are equal.
|
| 197 |
<var>str1</var> = <var>str2</var> True if the <var>str</var> are equal.
|
| 198 |
( = may be used in place of == )
|
| 199 |
<var>str1</var> != <var>str2</var> True if the str are not equal.
|
| 200 |
<var>str1</var> < <var>str2</var> True if <var>str1</var> sorts before <var>str2</var> (locale dependent).
|
| 201 |
<var>str1</var> > <var>str2</var> True if <var>str1</var> sorts after <var>str2</var> (locale dependent).
|
| 202 |
</example>
|
| 203 |
<p>
|
| 204 |
<strong>Arithmetic</strong> integer comparison operators in the
|
| 205 |
conditional expression are <tt>-eq</tt>, <tt>-ne</tt>, <tt>-lt</tt>,
|
| 206 |
<tt>-le</tt>, <tt>-gt</tt>, or <tt>-ge</tt>.
|
| 207 |
</sect1>
|
| 208 |
|
| 209 |
<sect1 id="clprocess">Command-line processing
|
| 210 |
<p>
|
| 211 |
The shell processes a script as follows:
|
| 212 |
<list compact>
|
| 213 |
<item>split into <strong>tokens</strong> by the metacharacters: SPACE, TAB, NEWLINE, ;, (, ), <, >, |, &
|
| 214 |
<item>check <strong>keyword</strong> if not within "..." or '...' (loop)
|
| 215 |
<item>expand <strong>alias</strong> if not within "..." or '...' (loop)
|
| 216 |
<item>expand <strong>brace</strong>, A{b|c} -> Ab Ac, if not within "..." or '...'
|
| 217 |
<item>expand <strong>tilde</strong>, ~<var>user</var> -> $HOME/$USER, if not within "..." or '...'
|
| 218 |
<item>expand <strong>parameter</strong>, $<var>PARAMETER</var>, if not within '...'
|
| 219 |
<item>expand <strong>command substitution</strong>, $(<var>command</var>), if not within '...'
|
| 220 |
<item>split into <strong>words</strong> with $IFS if not within "..." or '...'
|
| 221 |
<item>expand <strong>pathname</strong> *?[] if not within "..." or '...'
|
| 222 |
<item>lookup <strong>command</strong>
|
| 223 |
<list compact>
|
| 224 |
<item>function
|
| 225 |
<item>built-in
|
| 226 |
<item>file in $PATH
|
| 227 |
</list>
|
| 228 |
<item>loop
|
| 229 |
</list>
|
| 230 |
<p>
|
| 231 |
Single quotes within double quotes have no effect.
|
| 232 |
|
| 233 |
</sect1>
|
| 234 |
|
| 235 |
</sect>
|
| 236 |
|
| 237 |
<sect>Awk
|
| 238 |
<p>
|
| 239 |
References for Awk:
|
| 240 |
<list compact>
|
| 241 |
<item><em>Effective awk Programming</em>, 3rd edition (O'Reilly)
|
| 242 |
<item><em>Sed & awk</em>, 2nd edition (O'Reilly)
|
| 243 |
<item><manref name="mawk" section="1"> and <manref name="gawk" section="1">
|
| 244 |
<item><tt>info gawk</tt>
|
| 245 |
</list>
|
| 246 |
<p>
|
| 247 |
Short program example (create <prgn>newusers</prgn> command entry):
|
| 248 |
<example>
|
| 249 |
#!/usr/bin/awk -f
|
| 250 |
# Script to create a file suitable for use in the 'newusers' command,
|
| 251 |
# from a file consisting of user IDs and passwords in the form:
|
| 252 |
# First Last password
|
| 253 |
# Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001
|
| 254 |
# Distributed under GNU GPL v 2, or at your option, any later version.
|
| 255 |
# This program is distributed WITHOUT ANY WARRANTY.
|
| 256 |
|
| 257 |
BEGIN {
|
| 258 |
# Assign starting UID, GID
|
| 259 |
if ( ARGC > 2 ) {
|
| 260 |
startuid = ARGV[1]
|
| 261 |
delete ARGV[1]
|
| 262 |
}
|
| 263 |
else {
|
| 264 |
printf( "Usage: newusers startUID file\n" \
|
| 265 |
"...where startUID is the starting userid " \
|
| 266 |
"to add, and file is \n" \
|
| 267 |
"an input file in form firstname last name password\n" \
|
| 268 |
)
|
| 269 |
exit
|
| 270 |
}
|
| 271 |
|
| 272 |
infile = ARGV[1]
|
| 273 |
printf( "Starting UID: %s\n\n", startuid )
|
| 274 |
}
|
| 275 |
|
| 276 |
/^#/ { next }
|
| 277 |
|
| 278 |
{
|
| 279 |
++record
|
| 280 |
first = $1
|
| 281 |
last = $2
|
| 282 |
passwd = $3
|
| 283 |
user= substr( tolower( first ), 1, 1 ) tolower( last )
|
| 284 |
uid = startuid + record - 1
|
| 285 |
gid = uid
|
| 286 |
printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n", \
|
| 287 |
user, passwd, uid, gid, first, last, user \
|
| 288 |
)
|
| 289 |
}
|
| 290 |
</example>
|
| 291 |
<p>
|
| 292 |
Two packages provide POSIX <package>awk</package> in &debian;:
|
| 293 |
<list compact>
|
| 294 |
<item><package>mawk</package>
|
| 295 |
<list compact>
|
| 296 |
<item>Priority: required
|
| 297 |
<item>Installed-Size: 228
|
| 298 |
<item>Smaller and much faster — good for default install
|
| 299 |
<item>Compile-time limits exist
|
| 300 |
<list compact>
|
| 301 |
<item>NF = 32767
|
| 302 |
<item>sprintf buffer = 1020
|
| 303 |
</list>
|
| 304 |
</list>
|
| 305 |
<item><package>gawk</package>
|
| 306 |
<list compact>
|
| 307 |
<item>Priority: optional
|
| 308 |
<item>Installed-Size: 1708
|
| 309 |
<item>Larger and featureful — many extensions implemented
|
| 310 |
<list compact>
|
| 311 |
<item>System V Release 4 version of UNIX
|
| 312 |
<item>Bell Labs awk
|
| 313 |
<item>GNU-specific
|
| 314 |
</list>
|
| 315 |
</list>
|
| 316 |
</list>
|
| 317 |
</sect>
|
| 318 |
|
| 319 |
<sect>Perl
|
| 320 |
<p>
|
| 321 |
This is <strong>the</strong> interpreter on a Unix-like system.
|
| 322 |
<p>
|
| 323 |
References for Perl:
|
| 324 |
<list compact>
|
| 325 |
<item><manref name="perl" section="1">
|
| 326 |
<item><em>Programming Perl</em>, 3rd edition (O'Reilly)
|
| 327 |
</list>
|
| 328 |
<p>
|
| 329 |
Short program example (create <prgn>newusers</prgn> command entry):
|
| 330 |
<example>
|
| 331 |
#!/usr/bin/perl
|
| 332 |
# (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
|
| 333 |
$pid=1000;
|
| 334 |
while (<STDIN>) {
|
| 335 |
if (/^#/) { next;}
|
| 336 |
chop;
|
| 337 |
$pid++;
|
| 338 |
($n1, $n2, $n3) = split / /;
|
| 339 |
print $n1,"_",$n2,":", $n3, ":",$pid,
|
| 340 |
":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n"
|
| 341 |
}
|
| 342 |
</example>
|
| 343 |
<p>
|
| 344 |
Install Perl module <var>module name</var>:
|
| 345 |
<example>
|
| 346 |
# perl -MCPAN -e 'install <var>modulename</var>'
|
| 347 |
</example>
|
| 348 |
|
| 349 |
</sect>
|
| 350 |
|
| 351 |
<sect>Python
|
| 352 |
<p>
|
| 353 |
It's a nice object-oriented interpreter.
|
| 354 |
<p>
|
| 355 |
References for Python:
|
| 356 |
<list compact>
|
| 357 |
<item><manref name="python" section="1">
|
| 358 |
<item><em>Learning Python</em> (O'Reilly).
|
| 359 |
</list>
|
| 360 |
<p>
|
| 361 |
Short program example (create <prgn>newusers</prgn> command entry):
|
| 362 |
<example>
|
| 363 |
#! /usr/bin/env python
|
| 364 |
import sys, string
|
| 365 |
|
| 366 |
# (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
|
| 367 |
# Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001
|
| 368 |
# This program is distributed WITHOUT ANY WARRANTY.
|
| 369 |
|
| 370 |
def usages():
|
| 371 |
print \
|
| 372 |
"Usage: ", sys.argv[0], " start_UID [filename]\n" \
|
| 373 |
"\tstartUID is the starting userid to add.\n" \
|
| 374 |
"\tfilename is input file name. If not specified, standard input.\n\n" \
|
| 375 |
"Input file format:\n"\
|
| 376 |
"\tfirstname lastname password\n"
|
| 377 |
return 1
|
| 378 |
|
| 379 |
def parsefile(startuid):
|
| 380 |
#
|
| 381 |
# main filtering
|
| 382 |
#
|
| 383 |
uid = startuid
|
| 384 |
while 1:
|
| 385 |
line = infile.readline()
|
| 386 |
if not line:
|
| 387 |
break
|
| 388 |
if line[0] == '#':
|
| 389 |
continue
|
| 390 |
(first, last, passwd) = string.split(string.lower(line))
|
| 391 |
# above crashes with wrong # of parameters :-)
|
| 392 |
user = first[0] + last
|
| 393 |
gid = uid
|
| 394 |
lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" % \
|
| 395 |
(user, passwd, uid, gid, first, last, user)
|
| 396 |
sys.stdout.write(lineout)
|
| 397 |
+uid
|
| 398 |
|
| 399 |
if __name__ == '__main__':
|
| 400 |
if len(sys.argv) == 1:
|
| 401 |
usages()
|
| 402 |
else:
|
| 403 |
uid = int(sys.argv[1])
|
| 404 |
#print "# UID start from: %d\n" % uid
|
| 405 |
if len(sys.argv) > 1:
|
| 406 |
infilename = string.join(sys.argv[2:])
|
| 407 |
infile = open(infilename, 'r')
|
| 408 |
#print "# Read file from: %s\n\n" % infilename
|
| 409 |
else:
|
| 410 |
infile = sys.stdin
|
| 411 |
parsefile(uid)
|
| 412 |
</example>
|
| 413 |
</sect>
|
| 414 |
|
| 415 |
<sect>Make
|
| 416 |
<p>
|
| 417 |
References for Make:
|
| 418 |
<list compact>
|
| 419 |
<item><tt>info make</tt>
|
| 420 |
<item><manref name="make" section="1">
|
| 421 |
<item><em>Managing Projects with make</em>, 2nd edition (O'Reilly)
|
| 422 |
</list>
|
| 423 |
<p>
|
| 424 |
Simple automatic variables:
|
| 425 |
<p>
|
| 426 |
Rule syntax:
|
| 427 |
<example>
|
| 428 |
<var>Target</var>: [ <var>Prerequisite</var> ... ]
|
| 429 |
[TAB] <var>command1</var>
|
| 430 |
[TAB] -<var>command2</var> # ignore errors
|
| 431 |
[TAB] @<var>command3</var> # suppress echoing
|
| 432 |
</example>
|
| 433 |
Here <tt>[TAB]</tt> is a TAB code.
|
| 434 |
Each line is interpreted by the shell after make variable substitution.
|
| 435 |
Use <tt>\</tt> at the end of a line to continue the script.
|
| 436 |
Use <tt>$$</tt> to enter <tt>$</tt> for environment values for a shell script.
|
| 437 |
<p>
|
| 438 |
Implicit rule equivalents:
|
| 439 |
<example>
|
| 440 |
.c: header.h == % : %.c header.h
|
| 441 |
.o.c: header.h == %.c: %.o header.h
|
| 442 |
</example>
|
| 443 |
Automatic variables for above rules:
|
| 444 |
<example>
|
| 445 |
foo.o: new1.c new2.c.c old1.c new3.c
|
| 446 |
$@ == foo.o (target)
|
| 447 |
$< == new1.c (first one)
|
| 448 |
$? == new1.c new2.c new3.c (newer ones)
|
| 449 |
$^ == new1.c new2.c.c old1.c new3.c (all)
|
| 450 |
$* == `%' matched stem in the target pattern.
|
| 451 |
</example>
|
| 452 |
Variable references:
|
| 453 |
<example>
|
| 454 |
foo1 := bar # One-time expansion
|
| 455 |
foo2 = bar # Recursive expansion
|
| 456 |
foo3 += bar # Append
|
| 457 |
SRCS := $(wildcard *.c)
|
| 458 |
OBJS := $(foo:c=o)
|
| 459 |
OBJS := $(foo:%.c=%.o)
|
| 460 |
OBJS := $(patsubst %.c,%.o,$(foo))
|
| 461 |
DIRS = $(dir directory/filename.ext) # Extracts "directory"
|
| 462 |
$(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...
|
| 463 |
</example>
|
| 464 |
Run <tt>make -p -f/dev/null</tt> to see automatic internal rules.
|
| 465 |
</sect>
|
| 466 |
|
| 467 |
<sect>C
|
| 468 |
<p>
|
| 469 |
Preparation:
|
| 470 |
<example>
|
| 471 |
# apt-get install glibc-doc manpages-dev libc6-dev gcc
|
| 472 |
</example>
|
| 473 |
<p>
|
| 474 |
References for C:
|
| 475 |
<list compact>
|
| 476 |
<item><tt>info libc</tt> (C library function reference)
|
| 477 |
<item><manref name="gcc" section="1">
|
| 478 |
<item><manref name="<var>each_C_library_function_name</var>" section="3">
|
| 479 |
<item>Kernighan & Ritchie, <em>The C Programming Language</em>,
|
| 480 |
2nd edition (Prentice Hall).
|
| 481 |
</list>
|
| 482 |
<p>
|
| 483 |
|
| 484 |
<sect1>Simple C program (<prgn>gcc</prgn>)
|
| 485 |
<p>
|
| 486 |
A simple example to compile <prgn>example.c</prgn> with a library
|
| 487 |
<prgn>libm</prgn> into an executable <prgn>run_example</prgn>:
|
| 488 |
<example>
|
| 489 |
$ cat > example.c
|
| 490 |
#include <stdio.h>
|
| 491 |
#include <math.h>
|
| 492 |
#include <string.h>
|
| 493 |
|
| 494 |
int main(int argc, char **argv, char **envp){
|
| 495 |
double x;
|
| 496 |
char y[11];
|
| 497 |
x=sqrt(argc+7.5);
|
| 498 |
strncpy(y, argv[0], 10); /* prevent buffer overflow */
|
| 499 |
y[10] = '\0'; /* fill to make sure string ends with '\0' */
|
| 500 |
printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
|
| 501 |
return 0;
|
| 502 |
}
|
| 503 |
|
| 504 |
$ gcc -Wall -g -o run_example example.c -lm
|
| 505 |
$ ./run_example
|
| 506 |
1, 2.915, ./run_exam, (null)
|
| 507 |
$ ./run_example 1234567890qwerty
|
| 508 |
2, 3.082, ./run_exam, 1234567890qwerty
|
| 509 |
</example>
|
| 510 |
Here, <tt>-l<strong>m</strong></tt> is needed to link library
|
| 511 |
<tt>lib<strong>m</strong></tt> for sqrt(). The actual library is in
|
| 512 |
<file>/lib</file> with filename <file>libm.so.6</file>, which is a symlink to
|
| 513 |
<file>libm-2.1.3.so</file>.
|
| 514 |
<p>
|
| 515 |
Look at the last parameter in the output text. There are more than 10
|
| 516 |
characters even though <tt>%10s</tt> is specified.
|
| 517 |
<p>
|
| 518 |
The use of pointer memory operation functions without boundary checks, such as
|
| 519 |
<prgn>sprintf</prgn> and <prgn>strcpy</prgn>, is deprecated to prevent buffer
|
| 520 |
overflow exploits that leverage the above overrun effects. Instead, use
|
| 521 |
<prgn>snprintf</prgn> and <prgn>strncpy</prgn>.
|
| 522 |
</sect1>
|
| 523 |
|
| 524 |
<sect1>Debugging
|
| 525 |
|
| 526 |
<sect2>Debugging with <prgn>gdb</prgn>
|
| 527 |
<p>
|
| 528 |
Preparation:
|
| 529 |
<example>
|
| 530 |
# apt-get install gdb
|
| 531 |
</example>
|
| 532 |
<p>
|
| 533 |
References for <prgn>gdb</prgn>:
|
| 534 |
<list compact>
|
| 535 |
<item><tt>info gdb</tt> (tutorial)
|
| 536 |
<item><manref name="gdb" section="1">
|
| 537 |
</list>
|
| 538 |
<p>
|
| 539 |
Use <prgn>gdb</prgn> to debug a program compiled with the <tt>-g</tt> option.
|
| 540 |
Many commands can be abbreviated. Tab expansion works as in the shell.
|
| 541 |
<example>
|
| 542 |
$ gdb program
|
| 543 |
(gdb) b 1 # set breakpoint at line 1
|
| 544 |
(gdb) run <var>arg1 arg2 arg3</var> # run program
|
| 545 |
(gdb) next # next line
|
| 546 |
...
|
| 547 |
(gdb) step # step forward
|
| 548 |
...
|
| 549 |
(gdb) p parm # print parm
|
| 550 |
...
|
| 551 |
(gdb) p parm=12 # set value to 12
|
| 552 |
</example>
|
| 553 |
<p>
|
| 554 |
For debugging from within Emacs, refer to <ref id="editkey">.
|
| 555 |
</sect2>
|
| 556 |
|
| 557 |
<sect2 id="ss-ldd">Check dependency on libraries
|
| 558 |
<p>
|
| 559 |
Use <prgn>ldd</prgn> to find out a program's dependency on libraries:
|
| 560 |
<example>
|
| 561 |
$ ldd /bin/ls
|
| 562 |
librt.so.1 => /lib/librt.so.1 (0x4001e000)
|
| 563 |
libc.so.6 => /lib/libc.so.6 (0x40030000)
|
| 564 |
libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
|
| 565 |
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
|
| 566 |
</example>
|
| 567 |
For <prgn>ls</prgn> to work in a <prgn>chroot</prgn>ed environment, the above
|
| 568 |
libraries must be available in your <prgn>chroot</prgn>ed environment.
|
| 569 |
<p>
|
| 570 |
The following commands will also be useful:
|
| 571 |
<list compact>
|
| 572 |
<item><prgn>strace</prgn>: trace system calls and signals
|
| 573 |
<item><prgn>ltrace</prgn>: trace library calls
|
| 574 |
</list>
|
| 575 |
</sect2>
|
| 576 |
|
| 577 |
<sect2>Debugging with memory leak detection tools
|
| 578 |
<p>
|
| 579 |
There are several memory leak detection tools available in &debian;.
|
| 580 |
<p>
|
| 581 |
<list compact>
|
| 582 |
<item><package>njamd</package>
|
| 583 |
<item><package>valgrind</package>
|
| 584 |
<item><package>dmalloc</package>
|
| 585 |
<item><package>electric-fence</package>
|
| 586 |
<item><package>memprof</package>
|
| 587 |
<item><package>memwatch</package>
|
| 588 |
<item><package>mpatrol</package>
|
| 589 |
<item><package>leaktracer</package>
|
| 590 |
<item><package>libgc6</package>
|
| 591 |
<item><tt>Insure++</tt> from
|
| 592 |
<url id="¶softhome;" name="Parasoft">. (non-free, commercial for fee)
|
| 593 |
</list>
|
| 594 |
<p>
|
| 595 |
Also check out <url id="&mallocdebughome;"
|
| 596 |
name="Debugging Tools for Dynamic Storage Allocation and Memory Management">.
|
| 597 |
|
| 598 |
<sect1>Flex – a better Lex
|
| 599 |
<p>
|
| 600 |
<prgn>flex</prgn> is a fast lexical analyzer generator.
|
| 601 |
<p>
|
| 602 |
References for <prgn>flex</prgn>:
|
| 603 |
<list compact>
|
| 604 |
<item><tt>info flex</tt> (tutorial)
|
| 605 |
<item><manref name="flex" section="1">
|
| 606 |
</list>
|
| 607 |
<p>
|
| 608 |
You need to provide your own <prgn>main()</prgn> and <prgn>yywrap()</prgn>, or
|
| 609 |
your <prgn>program.l</prgn> should look like this to compile without a library
|
| 610 |
(<prgn>yywrap</prgn> is a macro; <tt>%option main</tt> turns on <tt>%option
|
| 611 |
noyywrap</tt> implicitly):
|
| 612 |
<example>
|
| 613 |
%option main
|
| 614 |
%%
|
| 615 |
.|\n ECHO ;
|
| 616 |
%%
|
| 617 |
</example>
|
| 618 |
Alternatively, you may compile with the -<tt>lfl</tt> linker option at the
|
| 619 |
end of your <prgn>cc</prgn> command line (like ATT-Lex with <tt>-ll</tt>). No
|
| 620 |
<tt>%option</tt> is needed in this case.
|
| 621 |
</sect1>
|
| 622 |
|
| 623 |
<sect1>Bison – a better Yacc
|
| 624 |
<p>
|
| 625 |
A few packages provide a Yacc-compatible LALR parser generator in &debian;:
|
| 626 |
<p>
|
| 627 |
<list compact>
|
| 628 |
<item><package>bison</package>: GNU LALR parser generator
|
| 629 |
<item><package>byacc</package>: The Berkeley LALR parser generator
|
| 630 |
<item><package>byyacc</package>: Backtracking parser generator based on byacc
|
| 631 |
</list>
|
| 632 |
<p>
|
| 633 |
References for <prgn>bison</prgn>:
|
| 634 |
<list compact>
|
| 635 |
<item><tt>info bison</tt> (tutorial)
|
| 636 |
<item><manref name="bison" section="1">
|
| 637 |
</list>
|
| 638 |
<p>
|
| 639 |
You need to provide your own <prgn>main()</prgn> and <prgn>yyerror()</prgn>.
|
| 640 |
<prgn>main()</prgn> calls <prgn>yyparse()</prgn> which calls
|
| 641 |
<prgn>yylex()</prgn>, usually created with FleX.
|
| 642 |
<example>
|
| 643 |
%%
|
| 644 |
|
| 645 |
%%
|
| 646 |
</example>
|
| 647 |
</sect1>
|
| 648 |
|
| 649 |
<sect1>Autoconf
|
| 650 |
<p>
|
| 651 |
<prgn>autoconf</prgn> is a tool for producing shell scripts that
|
| 652 |
automatically configure software source code packages to adapt to
|
| 653 |
many kinds of UNIX-like systems using the entire GNU build system.
|
| 654 |
<p>
|
| 655 |
<prgn>autoconf</prgn> produces the configuration script
|
| 656 |
<prgn>configure</prgn>. <prgn>configure</prgn>
|
| 657 |
automatically creates a customized <prgn>Makefile</prgn> and
|
| 658 |
<prgn>Makefile.am</prgn>.
|
| 659 |
|
| 660 |
<sect2>Compile and install a program
|
| 661 |
<p>
|
| 662 |
&debian; does not touch files in <file>/usr/local</file> (see
|
| 663 |
<ref id="diverse">). So if you compile a program from source, install
|
| 664 |
it into <file>/usr/local</file> so it will not interfere with &debian;.
|
| 665 |
<example>
|
| 666 |
$ cd src
|
| 667 |
$ ./configure --prefix=/usr/local
|
| 668 |
$ make
|
| 669 |
$ make install # this puts the files in the system
|
| 670 |
</example>
|
| 671 |
|
| 672 |
<sect2>Uninstall program
|
| 673 |
<p>
|
| 674 |
If you still have the source and if it uses
|
| 675 |
<prgn>autoconf</prgn>/<prgn>automake</prgn> and if you
|
| 676 |
can remember how you configured it:
|
| 677 |
<example>
|
| 678 |
$ ./configure <var>all-of-the-options-you-gave-it</var>
|
| 679 |
# make uninstall
|
| 680 |
</example>
|
| 681 |
<p>
|
| 682 |
Alternatively, if you are absolutely sure that the install process puts
|
| 683 |
files only under <file>/usr/local</file> and there is nothing important
|
| 684 |
there, you can erase all its contents by:
|
| 685 |
<example>
|
| 686 |
# find /usr/local -type f -print0 | xargs -0 rm -f
|
| 687 |
</example>
|
| 688 |
If you are not sure where files are installed, you should consider
|
| 689 |
using <package>checkinstall</package> which provides clean path
|
| 690 |
for the uninstall.
|
| 691 |
</sect1>
|
| 692 |
|
| 693 |
</sect>
|
| 694 |
|
| 695 |
<sect>Document preparation
|
| 696 |
<p>
|
| 697 |
|
| 698 |
<sect1><tt>roff</tt> typesetting
|
| 699 |
<p>
|
| 700 |
Traditionally, <tt>roff</tt> is the main Unix text processing system.
|
| 701 |
<p>
|
| 702 |
See <manref name="roff" section="7">,
|
| 703 |
<manref name="groff" section="7">,
|
| 704 |
<manref name="groff" section="1">,
|
| 705 |
<manref name="grotty" section="1">,
|
| 706 |
<manref name="troff" section="1">,
|
| 707 |
<manref name="groff_mdoc" section="7">,
|
| 708 |
<manref name="groff_man" section="7">,
|
| 709 |
<manref name="groff_ms" section="7">,
|
| 710 |
<manref name="groff_me" section="7">,
|
| 711 |
<manref name="groff_mm" section="7">, and
|
| 712 |
"<tt>info groff</tt>".
|
| 713 |
<p>
|
| 714 |
A good tutorial on <prgn>-me</prgn> macros exists.
|
| 715 |
If you have groff (1.18 or newer), find <file>&f-meintro;</file> and
|
| 716 |
do the following:
|
| 717 |
<example>
|
| 718 |
$ zcat &f-meintro; | \
|
| 719 |
groff -Tascii -me - | less -R
|
| 720 |
</example>
|
| 721 |
The following will make a completely plain text file:
|
| 722 |
<example>
|
| 723 |
$ zcat &f-meintro; | \
|
| 724 |
GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > <var>meintro.txt</var>
|
| 725 |
</example>
|
| 726 |
For printing, use PostScript output.
|
| 727 |
<example>
|
| 728 |
$ groff -Tps <var>meintro.txt</var> | lpr
|
| 729 |
$ groff -Tps <var>meintro.txt</var> | mpage -2 | lpr
|
| 730 |
</example>
|
| 731 |
|
| 732 |
|
| 733 |
|
| 734 |
|
| 735 |
<sect1>SGML
|
| 736 |
<p>
|
| 737 |
Preparation:
|
| 738 |
<example>
|
| 739 |
# apt-get install debiandoc-sgml debiandoc-sgml-doc
|
| 740 |
</example>
|
| 741 |
References for <prgn>debiandoc-sgml</prgn>:
|
| 742 |
<list compact>
|
| 743 |
<item><file>&f-debiandoc-sgml;</file>
|
| 744 |
<item><manref name="debiandoc-sgml" section="1">
|
| 745 |
<item><em>DocBook: The Definitive Guide</em>, by Walsh and Muellner (O'Reilly)
|
| 746 |
</list>
|
| 747 |
<p>
|
| 748 |
SGML enables management of multiple formats of a document. One easy SGML
|
| 749 |
system is Debiandoc, which is used here. This requires minor conversion from
|
| 750 |
original text files for the following characters:
|
| 751 |
<example>
|
| 752 |
< &lt;
|
| 753 |
> &gt;
|
| 754 |
" " "&nbsp;" (nonbreakable space)
|
| 755 |
& &amp;
|
| 756 |
% &percnt;
|
| 757 |
© &copy;
|
| 758 |
– &ndash;
|
| 759 |
— &mdash;
|
| 760 |
</example>
|
| 761 |
To mark a section as a nonprintable comment, enter:
|
| 762 |
<example>
|
| 763 |
<!-- State issue here ... -->
|
| 764 |
</example>
|
| 765 |
To mark a section with a switchable comment, enter:
|
| 766 |
<example>
|
| 767 |
<![ %FIXME; [ State issue here ... ]]>
|
| 768 |
</example>
|
| 769 |
In SGML, the <em>first definition</em> of an entity wins. For example:
|
| 770 |
<example>
|
| 771 |
<!entity % qref "INCLUDE">
|
| 772 |
<![ %qref; [ <!entity param "Data 1"> ]]>
|
| 773 |
<!entity param "Data 2">
|
| 774 |
&param;
|
| 775 |
</example>
|
| 776 |
This ends up as "Data 1". If the first line has "IGNORE" instead of
|
| 777 |
"INCLUDE", this ends up as "Data 2" (the second line is a conditional
|
| 778 |
statement). Also, repeating phrases can be defined in advance
|
| 779 |
separately from the context.
|
| 780 |
<example>
|
| 781 |
<!entity <var>whoisthis</var> "my">
|
| 782 |
Hello &<var>whoisthis</var>; friend.
|
| 783 |
This is &<var>whoisthis</var>; book.
|
| 784 |
</example>
|
| 785 |
This results in the following:
|
| 786 |
<example>
|
| 787 |
Hello my friend.
|
| 788 |
This is my book.
|
| 789 |
</example>
|
| 790 |
See the short SGML example <file>sample.sgml</file> in the
|
| 791 |
<url id="&examples;" name="examples">.
|
| 792 |
<p>
|
| 793 |
When SGML documents become bigger, sometimes TeX may cause errors.
|
| 794 |
You must increase pool size in <file>/etc/texmf/texmf.cnf</file> (or more
|
| 795 |
appropriately edit <file>/etc/texmf/texmf.d/95NonPath</file> and
|
| 796 |
run <prgn>update-texmf</prgn>) to fix this.
|
| 797 |
</sect>
|
| 798 |
|
| 799 |
<sect id="packaging">Packaging
|
| 800 |
<p>
|
| 801 |
Preparation:
|
| 802 |
<example>
|
| 803 |
# apt-get install &p-debian-policy; &p-developers-reference; \
|
| 804 |
&p-maint-guide; dh-make debhelper
|
| 805 |
# apt-get install packaging-manual # if Potato
|
| 806 |
</example>
|
| 807 |
References for packaging:
|
| 808 |
<list compact>
|
| 809 |
<item><ref id="pkg-basics"> (basics)
|
| 810 |
<item>Debian New Maintainers' Guide (tutorial)
|
| 811 |
<item><manref name="dh-make" section="1">
|
| 812 |
<item>Debian Developer's Reference (best practice)
|
| 813 |
<item>Debian Policy Manual (authoritative)
|
| 814 |
<item>Packaging Manual (Potato)
|
| 815 |
</list>
|
| 816 |
|
| 817 |
<sect1 id="pack-binary">Packaging a single binary
|
| 818 |
<p>
|
| 819 |
Quick-n-dirty method to Package a single binary per Joey Hess.
|
| 820 |
<example>
|
| 821 |
# mkdir -p mypkg/usr/bin mypkg/DEBIAN
|
| 822 |
# cp binary mypkg/usr/bin
|
| 823 |
# cat > mypkg/DEBIAN/control
|
| 824 |
Package: mypackage
|
| 825 |
Version: 1
|
| 826 |
Architecture: i386
|
| 827 |
Maintainer: Joey Hess <joeyh@debian.org>
|
| 828 |
Description: my little package
|
| 829 |
Don't expect much.
|
| 830 |
^D
|
| 831 |
# dpkg-deb -b mypkg
|
| 832 |
</example>
|
| 833 |
|
| 834 |
<sect1 id="pack-dh-make">Packaging with tools
|
| 835 |
<p>
|
| 836 |
Use <prgn>dh_make</prgn> from the <package>dh-make</package> package to create
|
| 837 |
a baseline package. Then, proceed according to instructions in <manref
|
| 838 |
name="dh-make" section="1">.
|
| 839 |
This uses <prgn>debhelper</prgn> in <prgn>debian/rules</prgn>.
|
| 840 |
<p>
|
| 841 |
An older approach is to use <prgn>deb-make</prgn> from the
|
| 842 |
<package>debmake</package> package. This uses no <prgn>debhelper</prgn>
|
| 843 |
scripts and depends only on the shell.
|
| 844 |
<p>
|
| 845 |
For examples of multiple-source packages, see "mc" (<tt>dpkg-source -x
|
| 846 |
mc_4.5.54.dsc</tt>), which uses "sys-build.mk" by Adam Heath
|
| 847 |
(<email>doogie@debian.org</email>), and "glibc" (<tt>dpkg-source -x
|
| 848 |
glibc_2.2.4-1.dsc</tt>), which uses another system by the late Joel Klecker
|
| 849 |
(<email>espy@debian.org</email>).
|
| 850 |
|
| 851 |
</sect>
|
| 852 |
|
| 853 |
</chapt>
|