aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-02-08 19:58:47 +0000
committerErik Andersen <andersen@codepoet.org>2000-02-08 19:58:47 +0000
commite49d5ecbbe51718fa925b6890a735e5937cc2aa2 (patch)
treec90bda10731ad9333ce3b404f993354c9fc104b8
parentc0bf817bbc5c7867fbe8fb76d5c39f8ee802692f (diff)
downloadbusybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.gz
busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.bz2
busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.zip
Some formatting updates (ran the code through indent)
-Erik
-rw-r--r--applets/busybox.c456
-rw-r--r--archival/gunzip.c2520
-rw-r--r--archival/gzip.c3132
-rw-r--r--archival/tar.c1857
-rw-r--r--busybox.c456
-rw-r--r--busybox.def.h1
-rw-r--r--cat.c54
-rw-r--r--chmod_chown_chgrp.c238
-rw-r--r--chroot.c57
-rw-r--r--chvt.c36
-rw-r--r--clear.c6
-rw-r--r--console-tools/chvt.c36
-rw-r--r--console-tools/clear.c6
-rw-r--r--console-tools/deallocvt.c62
-rw-r--r--console-tools/loadacm.c664
-rw-r--r--console-tools/loadfont.c196
-rw-r--r--console-tools/loadkmap.c103
-rw-r--r--coreutils/cat.c54
-rw-r--r--coreutils/chroot.c57
-rw-r--r--coreutils/date.c451
-rw-r--r--coreutils/dd.c284
-rw-r--r--coreutils/df.c119
-rw-r--r--coreutils/du.c185
-rw-r--r--coreutils/head.c134
-rw-r--r--coreutils/hostid.c8
-rw-r--r--coreutils/length.c14
-rw-r--r--coreutils/ln.c150
-rw-r--r--coreutils/logname.c22
-rw-r--r--coreutils/ls.c297
-rw-r--r--coreutils/mkdir.c133
-rw-r--r--coreutils/mkfifo.c64
-rw-r--r--coreutils/mknod.c39
-rw-r--r--coreutils/printf.c632
-rw-r--r--coreutils/pwd.c12
-rw-r--r--coreutils/rm.c102
-rw-r--r--coreutils/rmdir.c20
-rw-r--r--coreutils/sleep.c19
-rw-r--r--coreutils/sort.c385
-rw-r--r--coreutils/sync.c13
-rw-r--r--coreutils/tail.c1789
-rw-r--r--coreutils/tee.c129
-rw-r--r--coreutils/touch.c79
-rw-r--r--coreutils/tty.c25
-rw-r--r--coreutils/uname.c139
-rw-r--r--coreutils/uniq.c225
-rw-r--r--coreutils/wc.c127
-rw-r--r--coreutils/whoami.c27
-rw-r--r--coreutils/yes.c14
-rw-r--r--cp_mv.c359
-rw-r--r--date.c451
-rw-r--r--dd.c284
-rw-r--r--deallocvt.c62
-rw-r--r--df.c119
-rw-r--r--dmesg.c160
-rw-r--r--du.c185
-rw-r--r--dutmp.c62
-rw-r--r--editors/sed.c522
-rw-r--r--fbset.c360
-rw-r--r--fdflush.c36
-rw-r--r--find.c142
-rw-r--r--findutils/find.c142
-rw-r--r--findutils/grep.c182
-rw-r--r--free.c6
-rw-r--r--fsck_minix.c716
-rw-r--r--grep.c182
-rw-r--r--gunzip.c2520
-rw-r--r--gzip.c3132
-rw-r--r--halt.c9
-rw-r--r--head.c134
-rw-r--r--hostid.c8
-rw-r--r--hostname.c193
-rw-r--r--init.c1335
-rw-r--r--init/halt.c9
-rw-r--r--init/init.c1335
-rw-r--r--init/poweroff.c8
-rw-r--r--init/reboot.c8
-rw-r--r--insmod.c240
-rw-r--r--internal.h4
-rw-r--r--kill.c299
-rw-r--r--length.c14
-rw-r--r--ln.c150
-rw-r--r--loadacm.c664
-rw-r--r--loadfont.c196
-rw-r--r--loadkmap.c103
-rw-r--r--logger.c191
-rw-r--r--logname.c22
-rw-r--r--ls.c297
-rw-r--r--lsmod.c6
-rw-r--r--makedevs.c83
-rw-r--r--math.c106
-rw-r--r--messages.c19
-rw-r--r--miscutils/dutmp.c62
-rw-r--r--miscutils/makedevs.c83
-rw-r--r--miscutils/mt.c122
-rw-r--r--miscutils/update.c18
-rw-r--r--mkdir.c133
-rw-r--r--mkfifo.c64
-rw-r--r--mkfs_minix.c499
-rw-r--r--mknod.c39
-rw-r--r--mkswap.c197
-rw-r--r--mnc.c118
-rw-r--r--modutils/insmod.c240
-rw-r--r--modutils/lsmod.c6
-rw-r--r--modutils/rmmod.c55
-rw-r--r--more.c199
-rw-r--r--mount.c581
-rw-r--r--mt.c122
-rw-r--r--mtab.c98
-rw-r--r--networking/hostname.c193
-rw-r--r--networking/nslookup.c185
-rw-r--r--networking/ping.c618
-rw-r--r--nfsmount.c933
-rw-r--r--nfsmount.h1
-rw-r--r--nslookup.c185
-rw-r--r--ping.c618
-rw-r--r--poweroff.c8
-rw-r--r--printf.c632
-rw-r--r--procps/free.c6
-rw-r--r--procps/kill.c299
-rw-r--r--procps/ps.c206
-rw-r--r--ps.c206
-rw-r--r--pwd.c12
-rw-r--r--reboot.c8
-rw-r--r--regexp.c602
-rw-r--r--regexp.h1
-rw-r--r--rm.c102
-rw-r--r--rmdir.c20
-rw-r--r--rmmod.c55
-rw-r--r--sed.c522
-rw-r--r--sfdisk.c4426
-rw-r--r--sleep.c19
-rw-r--r--sort.c385
-rw-r--r--swaponoff.c131
-rw-r--r--sync.c13
-rw-r--r--sysklogd/logger.c191
-rw-r--r--sysklogd/syslogd.c552
-rw-r--r--syslogd.c552
-rw-r--r--tail.c1789
-rw-r--r--tar.c1857
-rw-r--r--tee.c129
-rw-r--r--touch.c79
-rw-r--r--true_false.c12
-rw-r--r--tty.c25
-rw-r--r--umount.c291
-rw-r--r--uname.c139
-rw-r--r--uniq.c225
-rw-r--r--update.c18
-rw-r--r--util-linux/dmesg.c160
-rw-r--r--util-linux/fbset.c360
-rw-r--r--util-linux/fdflush.c36
-rw-r--r--util-linux/fsck_minix.c716
-rw-r--r--util-linux/mkfs_minix.c499
-rw-r--r--util-linux/mkswap.c197
-rw-r--r--util-linux/more.c199
-rw-r--r--util-linux/mount.c581
-rw-r--r--util-linux/nfsmount.c933
-rw-r--r--util-linux/nfsmount.h1
-rw-r--r--util-linux/swaponoff.c131
-rw-r--r--util-linux/umount.c291
-rw-r--r--utility.c1394
-rw-r--r--wc.c127
-rw-r--r--whoami.c27
-rw-r--r--yes.c14
163 files changed, 27866 insertions, 27364 deletions
diff --git a/applets/busybox.c b/applets/busybox.c
index e2c2e0393..8bbe6a22e 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
@@ -16,329 +17,342 @@ static int been_there_done_that = 0;
16 * replacement may be in order 17 * replacement may be in order
17 */ 18 */
18#if 0 19#if 0
19void exit (int status) __attribute__ ((noreturn)); 20void exit(int status) __attribute__ ((noreturn));
20void exit (int status) { _exit(status); }; 21void exit(int status)
21void abort (void) __attribute__ ((__noreturn__)); 22{
22void abort (void) { _exit(0); }; 23 _exit(status);
23int atexit (void (*__func) (void)) { _exit(0); }; 24};
25void abort(void) __attribute__ ((__noreturn__));
26void abort(void)
27{
28 _exit(0);
29};
30int atexit(void (*__func) (void))
31{
32 _exit(0);
33};
24void *__libc_stack_end; 34void *__libc_stack_end;
25#endif 35#endif
26 36
27 37
28static const struct Applet applets[] = { 38static const struct Applet applets[] = {
29 39
30#ifdef BB_BUSYBOX //bin 40#ifdef BB_BUSYBOX //bin
31 {"busybox", busybox_main}, 41 {"busybox", busybox_main},
42#endif
43#ifdef BB_BLOCK_DEVICE //sbin
44 {"block_device", block_device_main},
32#endif 45#endif
33#ifdef BB_BLOCK_DEVICE //sbin 46#ifdef BB_CAT //bin
34 {"block_device", block_device_main}, 47 {"cat", cat_main},
35#endif 48#endif
36#ifdef BB_CAT //bin 49#ifdef BB_CHMOD_CHOWN_CHGRP //bin
37 {"cat", cat_main}, 50 {"chmod", chmod_chown_chgrp_main},
51 {"chown", chmod_chown_chgrp_main},
52 {"chgrp", chmod_chown_chgrp_main},
38#endif 53#endif
39#ifdef BB_CHMOD_CHOWN_CHGRP //bin 54#ifdef BB_CHROOT //sbin
40 {"chmod", chmod_chown_chgrp_main}, 55 {"chroot", chroot_main},
41 {"chown", chmod_chown_chgrp_main},
42 {"chgrp", chmod_chown_chgrp_main},
43#endif 56#endif
44#ifdef BB_CHROOT //sbin 57#ifdef BB_CLEAR //usr/bin
45 {"chroot", chroot_main}, 58 {"clear", clear_main},
46#endif 59#endif
47#ifdef BB_CLEAR //usr/bin 60#ifdef BB_CHVT //usr/bin
48 {"clear", clear_main}, 61 {"chvt", chvt_main},
49#endif 62#endif
50#ifdef BB_CHVT //usr/bin 63#ifdef BB_CP_MV //bin
51 {"chvt", chvt_main}, 64 {"cp", cp_mv_main},
65 {"mv", cp_mv_main},
52#endif 66#endif
53#ifdef BB_CP_MV //bin 67#ifdef BB_DATE //bin
54 {"cp", cp_mv_main}, 68 {"date", date_main},
55 {"mv", cp_mv_main},
56#endif 69#endif
57#ifdef BB_DATE //bin 70#ifdef BB_DD //bin
58 {"date", date_main}, 71 {"dd", dd_main},
59#endif 72#endif
60#ifdef BB_DD //bin 73#ifdef BB_DF //bin
61 {"dd", dd_main}, 74 {"df", df_main},
62#endif 75#endif
63#ifdef BB_DF //bin 76#ifdef BB_DMESG //bin
64 {"df", df_main}, 77 {"dmesg", dmesg_main},
65#endif 78#endif
66#ifdef BB_DMESG //bin 79#ifdef BB_DU //bin
67 {"dmesg", dmesg_main}, 80 {"du", du_main},
68#endif 81#endif
69#ifdef BB_DU //bin 82#ifdef BB_DUTMP //usr/sbin
70 {"du", du_main}, 83 {"dutmp", dutmp_main},
71#endif 84#endif
72#ifdef BB_DUTMP //usr/sbin 85#ifdef BB_FBSET //usr/sbin
73 {"dutmp", dutmp_main}, 86 {"fbset", fbset_main},
74#endif 87#endif
75#ifdef BB_FBSET //usr/sbin 88#ifdef BB_FDFLUSH //bin
76 {"fbset", fbset_main}, 89 {"fdflush", fdflush_main},
77#endif 90#endif
78#ifdef BB_FDFLUSH //bin 91#ifdef BB_FIND //usr/bin
79 {"fdflush", fdflush_main}, 92 {"find", find_main},
80#endif 93#endif
81#ifdef BB_FIND //usr/bin 94#ifdef BB_FREE //usr/bin
82 {"find", find_main}, 95 {"free", free_main},
83#endif 96#endif
84#ifdef BB_FREE //usr/bin 97#ifdef BB_DEALLOCVT //usr/bin
85 {"free", free_main}, 98 {"deallocvt", deallocvt_main},
86#endif 99#endif
87#ifdef BB_DEALLOCVT //usr/bin 100#ifdef BB_FSCK_MINIX //sbin
88 {"deallocvt", deallocvt_main}, 101 {"fsck.minix", fsck_minix_main},
89#endif 102#endif
90#ifdef BB_FSCK_MINIX //sbin 103#ifdef BB_MKFS_MINIX //sbin
91 {"fsck.minix", fsck_minix_main}, 104 {"mkfs.minix", mkfs_minix_main},
92#endif 105#endif
93#ifdef BB_MKFS_MINIX //sbin 106#ifdef BB_GREP //bin
94 {"mkfs.minix", mkfs_minix_main}, 107 {"grep", grep_main},
95#endif 108#endif
96#ifdef BB_GREP //bin 109#ifdef BB_HALT //sbin
97 {"grep", grep_main}, 110 {"halt", halt_main},
98#endif 111#endif
99#ifdef BB_HALT //sbin 112#ifdef BB_HEAD //bin
100 {"halt", halt_main}, 113 {"head", head_main},
101#endif 114#endif
102#ifdef BB_HEAD //bin 115#ifdef BB_HOSTID //usr/bin
103 {"head", head_main}, 116 {"hostid", hostid_main},
104#endif 117#endif
105#ifdef BB_HOSTID //usr/bin 118#ifdef BB_HOSTNAME //bin
106 {"hostid", hostid_main}, 119 {"hostname", hostname_main},
107#endif 120#endif
108#ifdef BB_HOSTNAME //bin 121#ifdef BB_INIT //sbin
109 {"hostname", hostname_main}, 122 {"init", init_main},
110#endif 123#endif
111#ifdef BB_INIT //sbin 124#ifdef BB_INSMOD //sbin
112 {"init", init_main}, 125 {"insmod", insmod_main},
113#endif 126#endif
114#ifdef BB_INSMOD //sbin 127#ifdef BB_FEATURE_LINUXRC //
115 {"insmod", insmod_main}, 128 {"linuxrc", init_main},
116#endif 129#endif
117#ifdef BB_FEATURE_LINUXRC // 130#ifdef BB_KILL //bin
118 {"linuxrc", init_main}, 131 {"kill", kill_main},
119#endif 132#endif
120#ifdef BB_KILL //bin 133#ifdef BB_LENGTH //usr/bin
121 {"kill", kill_main}, 134 {"length", length_main},
122#endif 135#endif
123#ifdef BB_LENGTH //usr/bin 136#ifdef BB_LN //bin
124 {"length", length_main}, 137 {"ln", ln_main},
125#endif 138#endif
126#ifdef BB_LN //bin 139#ifdef BB_LOADACM //usr/bin
127 {"ln", ln_main}, 140 {"loadacm", loadacm_main},
128#endif 141#endif
129#ifdef BB_LOADACM //usr/bin 142#ifdef BB_LOADFONT //usr/bin
130 {"loadacm", loadacm_main}, 143 {"loadfont", loadfont_main},
131#endif
132#ifdef BB_LOADFONT //usr/bin
133 {"loadfont", loadfont_main},
134#endif 144#endif
135#ifdef BB_LOADKMAP //sbin 145#ifdef BB_LOADKMAP //sbin
136 {"loadkmap", loadkmap_main}, 146 {"loadkmap", loadkmap_main},
137#endif 147#endif
138#ifdef BB_LS //bin 148#ifdef BB_LS //bin
139 {"ls", ls_main}, 149 {"ls", ls_main},
140#endif 150#endif
141#ifdef BB_LSMOD //sbin 151#ifdef BB_LSMOD //sbin
142 {"lsmod", lsmod_main}, 152 {"lsmod", lsmod_main},
143#endif 153#endif
144#ifdef BB_MAKEDEVS //sbin 154#ifdef BB_MAKEDEVS //sbin
145 {"makedevs", makedevs_main}, 155 {"makedevs", makedevs_main},
146#endif 156#endif
147#ifdef BB_MATH //usr/bin 157#ifdef BB_MATH //usr/bin
148 {"math", math_main}, 158 {"math", math_main},
149#endif 159#endif
150#ifdef BB_MKDIR //bin 160#ifdef BB_MKDIR //bin
151 {"mkdir", mkdir_main}, 161 {"mkdir", mkdir_main},
152#endif 162#endif
153#ifdef BB_MKFIFO //usr/bin 163#ifdef BB_MKFIFO //usr/bin
154 {"mkfifo", mkfifo_main}, 164 {"mkfifo", mkfifo_main},
155#endif 165#endif
156#ifdef BB_MKNOD //bin 166#ifdef BB_MKNOD //bin
157 {"mknod", mknod_main}, 167 {"mknod", mknod_main},
158#endif 168#endif
159#ifdef BB_MKSWAP //sbin 169#ifdef BB_MKSWAP //sbin
160 {"mkswap", mkswap_main}, 170 {"mkswap", mkswap_main},
161#endif 171#endif
162#ifdef BB_MNC //usr/bin 172#ifdef BB_MNC //usr/bin
163 {"mnc", mnc_main}, 173 {"mnc", mnc_main},
164#endif 174#endif
165#ifdef BB_MORE //bin 175#ifdef BB_MORE //bin
166 {"more", more_main}, 176 {"more", more_main},
167#endif 177#endif
168#ifdef BB_MOUNT //bin 178#ifdef BB_MOUNT //bin
169 {"mount", mount_main}, 179 {"mount", mount_main},
170#endif 180#endif
171#ifdef BB_MT //bin 181#ifdef BB_MT //bin
172 {"mt", mt_main}, 182 {"mt", mt_main},
173#endif 183#endif
174#ifdef BB_NSLOOKUP //usr/bin 184#ifdef BB_NSLOOKUP //usr/bin
175 {"nslookup", nslookup_main}, 185 {"nslookup", nslookup_main},
176#endif 186#endif
177#ifdef BB_PING //bin 187#ifdef BB_PING //bin
178 {"ping", ping_main}, 188 {"ping", ping_main},
179#endif 189#endif
180#ifdef BB_POWEROFF //sbin 190#ifdef BB_POWEROFF //sbin
181 {"poweroff", poweroff_main}, 191 {"poweroff", poweroff_main},
182#endif 192#endif
183#ifdef BB_PRINTF //usr/bin 193#ifdef BB_PRINTF //usr/bin
184 {"printf", printf_main}, 194 {"printf", printf_main},
185#endif 195#endif
186#ifdef BB_PS //bin 196#ifdef BB_PS //bin
187 {"ps", ps_main}, 197 {"ps", ps_main},
188#endif 198#endif
189#ifdef BB_PWD //bin 199#ifdef BB_PWD //bin
190 {"pwd", pwd_main}, 200 {"pwd", pwd_main},
191#endif 201#endif
192#ifdef BB_REBOOT //sbin 202#ifdef BB_REBOOT //sbin
193 {"reboot", reboot_main}, 203 {"reboot", reboot_main},
194#endif 204#endif
195#ifdef BB_RM //bin 205#ifdef BB_RM //bin
196 {"rm", rm_main}, 206 {"rm", rm_main},
197#endif 207#endif
198#ifdef BB_RMDIR //bin 208#ifdef BB_RMDIR //bin
199 {"rmdir", rmdir_main}, 209 {"rmdir", rmdir_main},
200#endif 210#endif
201#ifdef BB_RMMOD //sbin 211#ifdef BB_RMMOD //sbin
202 {"rmmod", rmmod_main}, 212 {"rmmod", rmmod_main},
203#endif 213#endif
204#ifdef BB_SFDISK //sbin 214#ifdef BB_SFDISK //sbin
205 {"fdisk", sfdisk_main}, 215 {"fdisk", sfdisk_main},
206 {"sfdisk", sfdisk_main}, 216 {"sfdisk", sfdisk_main},
207#endif 217#endif
208#ifdef BB_SED //bin 218#ifdef BB_SED //bin
209 {"sed", sed_main}, 219 {"sed", sed_main},
210#endif 220#endif
211#ifdef BB_SLEEP //bin 221#ifdef BB_SLEEP //bin
212 {"sleep", sleep_main}, 222 {"sleep", sleep_main},
213#endif 223#endif
214#ifdef BB_SORT //bin 224#ifdef BB_SORT //bin
215 {"sort", sort_main}, 225 {"sort", sort_main},
216#endif 226#endif
217#ifdef BB_SYNC //bin 227#ifdef BB_SYNC //bin
218 {"sync", sync_main}, 228 {"sync", sync_main},
219#endif 229#endif
220#ifdef BB_SYSLOGD //sbin 230#ifdef BB_SYSLOGD //sbin
221 {"syslogd", syslogd_main}, 231 {"syslogd", syslogd_main},
222#endif 232#endif
223#ifdef BB_LOGGER //usr/bin 233#ifdef BB_LOGGER //usr/bin
224 {"logger", logger_main}, 234 {"logger", logger_main},
225#endif 235#endif
226#ifdef BB_LOGNAME //usr/bin 236#ifdef BB_LOGNAME //usr/bin
227 {"logname", logname_main}, 237 {"logname", logname_main},
228#endif 238#endif
229#ifdef BB_SWAPONOFF //sbin 239#ifdef BB_SWAPONOFF //sbin
230 {"swapon", swap_on_off_main}, 240 {"swapon", swap_on_off_main},
231 {"swapoff", swap_on_off_main}, 241 {"swapoff", swap_on_off_main},
232#endif 242#endif
233#ifdef BB_TAIL //usr/bin 243#ifdef BB_TAIL //usr/bin
234 {"tail", tail_main}, 244 {"tail", tail_main},
235#endif 245#endif
236#ifdef BB_TAR //bin 246#ifdef BB_TAR //bin
237 {"tar", tar_main}, 247 {"tar", tar_main},
238#endif 248#endif
239#ifdef BB_TEE //bin 249#ifdef BB_TEE //bin
240 {"tee", tee_main}, 250 {"tee", tee_main},
241#endif 251#endif
242#ifdef BB_TOUCH //usr/bin 252#ifdef BB_TOUCH //usr/bin
243 {"touch", touch_main}, 253 {"touch", touch_main},
244#endif 254#endif
245#ifdef BB_TRUE_FALSE //bin 255#ifdef BB_TRUE_FALSE //bin
246 {"true", true_main}, 256 {"true", true_main},
247 {"false", false_main}, 257 {"false", false_main},
248#endif 258#endif
249#ifdef BB_TTY //usr/bin 259#ifdef BB_TTY //usr/bin
250 {"tty", tty_main}, 260 {"tty", tty_main},
251#endif 261#endif
252#ifdef BB_UNAME //bin 262#ifdef BB_UNAME //bin
253 {"uname", uname_main}, 263 {"uname", uname_main},
254#endif 264#endif
255#ifdef BB_UMOUNT //bin 265#ifdef BB_UMOUNT //bin
256 {"umount", umount_main}, 266 {"umount", umount_main},
257#endif 267#endif
258#ifdef BB_UNIQ //bin 268#ifdef BB_UNIQ //bin
259 {"uniq", uniq_main}, 269 {"uniq", uniq_main},
260#endif 270#endif
261#ifdef BB_UPDATE //sbin 271#ifdef BB_UPDATE //sbin
262 {"update", update_main}, 272 {"update", update_main},
263#endif 273#endif
264#ifdef BB_WC //usr/bin 274#ifdef BB_WC //usr/bin
265 {"wc", wc_main}, 275 {"wc", wc_main},
266#endif 276#endif
267#ifdef BB_WHOAMI //usr/bin 277#ifdef BB_WHOAMI //usr/bin
268 {"whoami", whoami_main}, 278 {"whoami", whoami_main},
269#endif 279#endif
270#ifdef BB_YES //usr/bin 280#ifdef BB_YES //usr/bin
271 {"yes", yes_main}, 281 {"yes", yes_main},
272#endif 282#endif
273#ifdef BB_GUNZIP //bin 283#ifdef BB_GUNZIP //bin
274 {"zcat", gunzip_main}, 284 {"zcat", gunzip_main},
275 {"gunzip", gunzip_main}, 285 {"gunzip", gunzip_main},
276#endif 286#endif
277#ifdef BB_GZIP //bin 287#ifdef BB_GZIP //bin
278 {"gzip", gzip_main}, 288 {"gzip", gzip_main},
279#endif 289#endif
280 {0} 290 {0}
281}; 291};
282 292
283 293
284 294
285int main(int argc, char **argv) 295int main(int argc, char **argv)
286{ 296{
287 char *s = argv[0]; 297 char *s = argv[0];
288 char *name = argv[0]; 298 char *name = argv[0];
289 const struct Applet *a = applets; 299 const struct Applet *a = applets;
290 300
291 while (*s != '\0') { 301 while (*s != '\0') {
292 if (*s++ == '/') 302 if (*s++ == '/')
293 name = s; 303 name = s;
294 } 304 }
295 305
296 while (a->name != 0) { 306 while (a->name != 0) {
297 if (strcmp(name, a->name) == 0) { 307 if (strcmp(name, a->name) == 0) {
298 int status; 308 int status;
299 309
300 status = ((*(a->main)) (argc, argv)); 310 status = ((*(a->main)) (argc, argv));
301 if (status < 0) { 311 if (status < 0) {
302 fprintf(stderr, "%s: %s\n", a->name, strerror(errno)); 312 fprintf(stderr, "%s: %s\n", a->name, strerror(errno));
303 } 313 }
304 fprintf(stderr, "\n"); 314 fprintf(stderr, "\n");
305 exit(status); 315 exit(status);
316 }
317 a++;
306 } 318 }
307 a++; 319 exit(busybox_main(argc, argv));
308 }
309 exit (busybox_main(argc, argv));
310} 320}
311 321
312 322
313int busybox_main(int argc, char **argv) 323int busybox_main(int argc, char **argv)
314{ 324{
315 int col=0; 325 int col = 0;
316 argc--;
317 argv++;
318 326
319 if (been_there_done_that == 1 || argc < 1) { 327 argc--;
320 const struct Applet *a = applets; 328 argv++;
321 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
322 BB_VER, BB_BT);
323 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
324 fprintf(stderr, " or: [function] [arguments]...\n\n");
325 fprintf(stderr,
326 "\tMost people will create a symlink to busybox for each\n"
327 "\tfunction name, and busybox will act like whatever you invoke it as.\n");
328 fprintf(stderr, "\nCurrently defined functions:\n");
329 329
330 while (a->name != 0) { 330 if (been_there_done_that == 1 || argc < 1) {
331 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name); 331 const struct Applet *a = applets;
332 if (col>60 && a->name != 0) { 332
333 fprintf(stderr, ",\n"); 333 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
334 col=0; 334 BB_VER, BB_BT);
335 } 335 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
336 fprintf(stderr, " or: [function] [arguments]...\n\n");
337 fprintf(stderr,
338 "\tMost people will create a symlink to busybox for each\n"
339 "\tfunction name, and busybox will act like whatever you invoke it as.\n");
340 fprintf(stderr, "\nCurrently defined functions:\n");
341
342 while (a->name != 0) {
343 col +=
344 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
345 (a++)->name);
346 if (col > 60 && a->name != 0) {
347 fprintf(stderr, ",\n");
348 col = 0;
349 }
350 }
351 fprintf(stderr, "\n\n");
352 exit(-1);
353 } else {
354 /* If we've already been here once, exit now */
355 been_there_done_that = 1;
356 return (main(argc, argv));
336 } 357 }
337 fprintf(stderr, "\n\n");
338 exit(-1);
339 } else {
340 /* If we've already been here once, exit now */
341 been_there_done_that = 1;
342 return (main(argc, argv));
343 }
344} 358}
diff --git a/archival/gunzip.c b/archival/gunzip.c
index db7fa1dfe..2bc490e3e 100644
--- a/archival/gunzip.c
+++ b/archival/gunzip.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* zcat : stripped version based on gzip sources 2/* zcat : stripped version based on gzip sources
2 Sven Rudolph <sr1@inf.tu-dresden.de> 3 Sven Rudolph <sr1@inf.tu-dresden.de>
3 */ 4 */
@@ -8,11 +9,12 @@
8#include "messages.c" 9#include "messages.c"
9 10
10static const char gunzip_usage[] = 11static const char gunzip_usage[] =
11 "gunzip [OPTION]... FILE\n\n" 12 "gunzip [OPTION]... FILE\n\n"
12 "Uncompress FILE (or standard input if FILE is '-').\n\n" 13 "Uncompress FILE (or standard input if FILE is '-').\n\n"
13 "Options:\n" 14 "Options:\n"
14 "\t-c\tWrite output to standard output\n" 15
15 "\t-t\tTest compressed file integrity\n"; 16 "\t-c\tWrite output to standard output\n"
17 "\t-t\tTest compressed file integrity\n";
16 18
17/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface 19/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
18 * Copyright (C) 1992-1993 Jean-loup Gailly 20 * Copyright (C) 1992-1993 Jean-loup Gailly
@@ -26,22 +28,23 @@ static const char gunzip_usage[] =
26 */ 28 */
27 29
28#if 0 30#if 0
29static char *license_msg[] = { 31static char *license_msg[] = {
30" Copyright (C) 1992-1993 Jean-loup Gailly", 32 " Copyright (C) 1992-1993 Jean-loup Gailly",
31" This program is free software; you can redistribute it and/or modify", 33 " This program is free software; you can redistribute it and/or modify",
32" it under the terms of the GNU General Public License as published by", 34 " it under the terms of the GNU General Public License as published by",
33" the Free Software Foundation; either version 2, or (at your option)", 35 " the Free Software Foundation; either version 2, or (at your option)",
34" any later version.", 36 " any later version.",
35"", 37 "",
36" This program is distributed in the hope that it will be useful,", 38 " This program is distributed in the hope that it will be useful,",
37" but WITHOUT ANY WARRANTY; without even the implied warranty of", 39 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
38" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", 40 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
39" GNU General Public License for more details.", 41 " GNU General Public License for more details.",
40"", 42 "",
41" You should have received a copy of the GNU General Public License", 43 " You should have received a copy of the GNU General Public License",
42" along with this program; if not, write to the Free Software", 44 " along with this program; if not, write to the Free Software",
43" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.", 45 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
440}; 46 0
47};
45#endif 48#endif
46 49
47/* Compress files with zip algorithm and 'compress' interface. 50/* Compress files with zip algorithm and 'compress' interface.
@@ -67,7 +70,7 @@ static char *license_msg[] = {
67#include <signal.h> 70#include <signal.h>
68#include <sys/stat.h> 71#include <sys/stat.h>
69#include <errno.h> 72#include <errno.h>
70#include <sys/param.h> /* for PATH_MAX */ 73#include <sys/param.h> /* for PATH_MAX */
71 74
72/* #include "tailor.h" */ 75/* #include "tailor.h" */
73 76
@@ -101,9 +104,9 @@ static char *license_msg[] = {
101#endif 104#endif
102 105
103#ifdef __STDC__ 106#ifdef __STDC__
104 typedef void *voidp; 107typedef void *voidp;
105#else 108#else
106 typedef char *voidp; 109typedef char *voidp;
107#endif 110#endif
108 111
109/* I don't like nested includes, but the string and io functions are used 112/* I don't like nested includes, but the string and io functions are used
@@ -118,10 +121,10 @@ static char *license_msg[] = {
118# define memzero(s, n) memset ((voidp)(s), 0, (n)) 121# define memzero(s, n) memset ((voidp)(s), 0, (n))
119#else 122#else
120# include <strings.h> 123# include <strings.h>
121# define strchr index 124# define strchr index
122# define strrchr rindex 125# define strrchr rindex
123# define memcpy(d, s, n) bcopy((s), (d), (n)) 126# define memcpy(d, s, n) bcopy((s), (d), (n))
124# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 127# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
125# define memzero(s, n) bzero((s), (n)) 128# define memzero(s, n) bzero((s), (n))
126#endif 129#endif
127 130
@@ -131,9 +134,9 @@ static char *license_msg[] = {
131 134
132#define local static 135#define local static
133 136
134typedef unsigned char uch; 137typedef unsigned char uch;
135typedef unsigned short ush; 138typedef unsigned short ush;
136typedef unsigned long ulg; 139typedef unsigned long ulg;
137 140
138/* Return codes from gzip */ 141/* Return codes from gzip */
139#define OK 0 142#define OK 0
@@ -143,7 +146,7 @@ typedef unsigned long ulg;
143/* Compression methods (see algorithm.doc) */ 146/* Compression methods (see algorithm.doc) */
144#define DEFLATED 8 147#define DEFLATED 8
145 148
146extern int method; /* compression method */ 149extern int method; /* compression method */
147 150
148/* To save memory for 16 bit systems, some arrays are overlaid between 151/* To save memory for 16 bit systems, some arrays are overlaid between
149 * the various modules: 152 * the various modules:
@@ -158,29 +161,29 @@ extern int method; /* compression method */
158 161
159#ifndef INBUFSIZ 162#ifndef INBUFSIZ
160# ifdef SMALL_MEM 163# ifdef SMALL_MEM
161# define INBUFSIZ 0x2000 /* input buffer size */ 164# define INBUFSIZ 0x2000 /* input buffer size */
162# else 165# else
163# define INBUFSIZ 0x8000 /* input buffer size */ 166# define INBUFSIZ 0x8000 /* input buffer size */
164# endif 167# endif
165#endif 168#endif
166#define INBUF_EXTRA 64 /* required by unlzw() */ 169#define INBUF_EXTRA 64 /* required by unlzw() */
167 170
168#ifndef OUTBUFSIZ 171#ifndef OUTBUFSIZ
169# ifdef SMALL_MEM 172# ifdef SMALL_MEM
170# define OUTBUFSIZ 8192 /* output buffer size */ 173# define OUTBUFSIZ 8192 /* output buffer size */
171# else 174# else
172# define OUTBUFSIZ 16384 /* output buffer size */ 175# define OUTBUFSIZ 16384 /* output buffer size */
173# endif 176# endif
174#endif 177#endif
175#define OUTBUF_EXTRA 2048 /* required by unlzw() */ 178#define OUTBUF_EXTRA 2048 /* required by unlzw() */
176 179
177#define SMALL_MEM 180#define SMALL_MEM
178 181
179#ifndef DIST_BUFSIZE 182#ifndef DIST_BUFSIZE
180# ifdef SMALL_MEM 183# ifdef SMALL_MEM
181# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ 184# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
182# else 185# else
183# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ 186# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
184# endif 187# endif
185#endif 188#endif
186 189
@@ -201,50 +204,51 @@ extern int method; /* compression method */
201# define FREE(array) 204# define FREE(array)
202#endif 205#endif
203 206
204EXTERN(uch, inbuf); /* input buffer */ 207EXTERN(uch, inbuf); /* input buffer */
205EXTERN(uch, outbuf); /* output buffer */ 208EXTERN(uch, outbuf); /* output buffer */
206EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ 209EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
207EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ 210EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
208#define tab_suffix window 211#define tab_suffix window
209#ifndef MAXSEG_64K 212#ifndef MAXSEG_64K
210# define tab_prefix prev /* hash link (see deflate.c) */ 213# define tab_prefix prev /* hash link (see deflate.c) */
211# define head (prev+WSIZE) /* hash head (see deflate.c) */ 214# define head (prev+WSIZE) /* hash head (see deflate.c) */
212 EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ 215EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
213#else 216#else
214# define tab_prefix0 prev 217# define tab_prefix0 prev
215# define head tab_prefix1 218# define head tab_prefix1
216 EXTERN(ush, tab_prefix0); /* prefix for even codes */ 219EXTERN(ush, tab_prefix0); /* prefix for even codes */
217 EXTERN(ush, tab_prefix1); /* prefix for odd codes */ 220EXTERN(ush, tab_prefix1); /* prefix for odd codes */
218#endif 221#endif
219 222
220extern unsigned insize; /* valid bytes in inbuf */ 223extern unsigned insize; /* valid bytes in inbuf */
221extern unsigned inptr; /* index of next byte to be processed in inbuf */ 224extern unsigned inptr; /* index of next byte to be processed in inbuf */
222extern unsigned outcnt; /* bytes in output buffer */ 225extern unsigned outcnt; /* bytes in output buffer */
226
227extern long bytes_in; /* number of input bytes */
228extern long bytes_out; /* number of output bytes */
229extern long header_bytes; /* number of bytes in gzip header */
223 230
224extern long bytes_in; /* number of input bytes */ 231extern long ifile_size; /* input file size, -1 for devices (debug only) */
225extern long bytes_out; /* number of output bytes */
226extern long header_bytes;/* number of bytes in gzip header */
227 232
228extern long ifile_size; /* input file size, -1 for devices (debug only) */ 233typedef int file_t; /* Do not use stdio */
229 234
230typedef int file_t; /* Do not use stdio */ 235#define NO_FILE (-1) /* in memory compression */
231#define NO_FILE (-1) /* in memory compression */
232 236
233 237
234#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ 238#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
235 239
236/* gzip flag byte */ 240/* gzip flag byte */
237#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 241#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
238#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 242#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
239#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 243#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
240#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 244#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
241#define COMMENT 0x10 /* bit 4 set: file comment present */ 245#define COMMENT 0x10 /* bit 4 set: file comment present */
242#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 246#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
243#define RESERVED 0xC0 /* bit 6,7: reserved */ 247#define RESERVED 0xC0 /* bit 6,7: reserved */
244 248
245#ifndef WSIZE 249#ifndef WSIZE
246# define WSIZE 0x8000 /* window size--must be a power of two, and */ 250# define WSIZE 0x8000 /* window size--must be a power of two, and */
247#endif /* at least 32K for zip's deflate method */ 251#endif /* at least 32K for zip's deflate method */
248 252
249#define MIN_MATCH 3 253#define MIN_MATCH 3
250#define MAX_MATCH 258 254#define MAX_MATCH 258
@@ -260,11 +264,11 @@ typedef int file_t; /* Do not use stdio */
260 * distances are limited to MAX_DIST instead of WSIZE. 264 * distances are limited to MAX_DIST instead of WSIZE.
261 */ 265 */
262 266
263extern int exit_code; /* program exit code */ 267extern int exit_code; /* program exit code */
264extern int verbose; /* be verbose (-v) */ 268extern int verbose; /* be verbose (-v) */
265extern int level; /* compression level */ 269extern int level; /* compression level */
266extern int test; /* check .z file integrity */ 270extern int test; /* check .z file integrity */
267extern int save_orig_name; /* set if original name must be saved */ 271extern int save_orig_name; /* set if original name must be saved */
268 272
269#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) 273#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
270#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) 274#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
@@ -296,10 +300,10 @@ extern int save_orig_name; /* set if original name must be saved */
296 put_short(((ulg)(n)) >> 16); \ 300 put_short(((ulg)(n)) >> 16); \
297} 301}
298 302
299#define seekable() 0 /* force sequential output */ 303#define seekable() 0 /* force sequential output */
300#define translate_eol 0 /* no option -a yet */ 304#define translate_eol 0 /* no option -a yet */
301 305
302#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ 306#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
303 307
304/* Macros for getting two-byte and four-byte header values */ 308/* Macros for getting two-byte and four-byte header values */
305#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) 309#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
@@ -329,43 +333,44 @@ extern int save_orig_name; /* set if original name must be saved */
329 333
330 334
331 /* in unzip.c */ 335 /* in unzip.c */
332extern int unzip OF((int in, int out)); 336extern int unzip OF((int in, int out));
333 337
334 /* in gzip.c */ 338 /* in gzip.c */
335RETSIGTYPE abort_gzip OF((void)); 339RETSIGTYPE abort_gzip OF((void));
336 340
337 /* in deflate.c */ 341 /* in deflate.c */
338void lm_init OF((int pack_level, ush *flags)); 342void lm_init OF((int pack_level, ush * flags));
339ulg deflate OF((void)); 343ulg deflate OF((void));
340 344
341 /* in trees.c */ 345 /* in trees.c */
342void ct_init OF((ush *attr, int *method)); 346void ct_init OF((ush * attr, int *method));
343int ct_tally OF((int dist, int lc)); 347int ct_tally OF((int dist, int lc));
344ulg flush_block OF((char *buf, ulg stored_len, int eof)); 348ulg flush_block OF((char *buf, ulg stored_len, int eof));
345 349
346 /* in bits.c */ 350 /* in bits.c */
347void bi_init OF((file_t zipfile)); 351void bi_init OF((file_t zipfile));
348void send_bits OF((int value, int length)); 352void send_bits OF((int value, int length));
349unsigned bi_reverse OF((unsigned value, int length)); 353unsigned bi_reverse OF((unsigned value, int length));
350void bi_windup OF((void)); 354void bi_windup OF((void));
351void copy_block OF((char *buf, unsigned len, int header)); 355void copy_block OF((char *buf, unsigned len, int header));
352extern int (*read_buf) OF((char *buf, unsigned size)); 356extern int (*read_buf) OF((char *buf, unsigned size));
353 357
354 /* in util.c: */ 358 /* in util.c: */
355extern int copy OF((int in, int out)); 359extern int copy OF((int in, int out));
356extern ulg updcrc OF((uch *s, unsigned n)); 360extern ulg updcrc OF((uch * s, unsigned n));
357extern void clear_bufs OF((void)); 361extern void clear_bufs OF((void));
358extern int fill_inbuf OF((int eof_ok)); 362extern int fill_inbuf OF((int eof_ok));
359extern void flush_outbuf OF((void)); 363extern void flush_outbuf OF((void));
360extern void flush_window OF((void)); 364extern void flush_window OF((void));
361extern void write_buf OF((int fd, voidp buf, unsigned cnt)); 365extern void write_buf OF((int fd, voidp buf, unsigned cnt));
366
362#ifndef __linux__ 367#ifndef __linux__
363extern char *basename OF((char *fname)); 368extern char *basename OF((char *fname));
364#endif /* not __linux__ */ 369#endif /* not __linux__ */
365extern void error OF((char *m)); 370extern void error OF((char *m));
366extern void warn OF((char *a, char *b)); 371extern void warn OF((char *a, char *b));
367extern void read_error OF((void)); 372extern void read_error OF((void));
368extern void write_error OF((void)); 373extern void write_error OF((void));
369 374
370 /* in inflate.c */ 375 /* in inflate.c */
371extern int inflate OF((void)); 376extern int inflate OF((void));
@@ -385,11 +390,11 @@ extern int inflate OF((void));
385#ifndef BITS 390#ifndef BITS
386# define BITS 16 391# define BITS 16
387#endif 392#endif
388#define INIT_BITS 9 /* Initial number of bits per code */ 393#define INIT_BITS 9 /* Initial number of bits per code */
389 394
390#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */ 395#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
391 396
392#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ 397#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
393/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. 398/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
394 * It's a pity that old uncompress does not check bit 0x20. That makes 399 * It's a pity that old uncompress does not check bit 0x20. That makes
395 * extension of the format actually undesirable because old compress 400 * extension of the format actually undesirable because old compress
@@ -404,16 +409,16 @@ extern int inflate OF((void));
404 * clear the dictionary. 409 * clear the dictionary.
405 */ 410 */
406 411
407#define LZW_RESERVED 0x60 /* reserved bits */ 412#define LZW_RESERVED 0x60 /* reserved bits */
408 413
409#define CLEAR 256 /* flush the dictionary */ 414#define CLEAR 256 /* flush the dictionary */
410#define FIRST (CLEAR+1) /* first free entry */ 415#define FIRST (CLEAR+1) /* first free entry */
411 416
412extern int maxbits; /* max bits per code for LZW */ 417extern int maxbits; /* max bits per code for LZW */
413extern int block_mode; /* block compress mode -C compatible with 2.0 */ 418extern int block_mode; /* block compress mode -C compatible with 2.0 */
414 419
415extern int lzw OF((int in, int out)); 420extern int lzw OF((int in, int out));
416extern int unlzw OF((int in, int out)); 421extern int unlzw OF((int in, int out));
417 422
418 423
419/* #include "revision.h" */ 424/* #include "revision.h" */
@@ -458,14 +463,12 @@ extern int unlzw OF((int in, int out));
458#ifdef __cplusplus 463#ifdef __cplusplus
459extern "C" { 464extern "C" {
460#endif 465#endif
461
462/* For communication from `getopt' to the caller. 466/* For communication from `getopt' to the caller.
463 When `getopt' finds an option that takes an argument, 467 When `getopt' finds an option that takes an argument,
464 the argument value is returned here. 468 the argument value is returned here.
465 Also, when `ordering' is RETURN_IN_ORDER, 469 Also, when `ordering' is RETURN_IN_ORDER,
466 each non-option ARGV-element is returned here. */ 470 each non-option ARGV-element is returned here. */
467 471 extern char *optarg;
468extern char *optarg;
469 472
470/* Index in ARGV of the next element to be scanned. 473/* Index in ARGV of the next element to be scanned.
471 This is used for communication to and from the caller 474 This is used for communication to and from the caller
@@ -479,16 +482,16 @@ extern char *optarg;
479 Otherwise, `optind' communicates from one call to the next 482 Otherwise, `optind' communicates from one call to the next
480 how much of ARGV has been scanned so far. */ 483 how much of ARGV has been scanned so far. */
481 484
482extern int optind; 485 extern int optind;
483 486
484/* Callers store zero here to inhibit the error message `getopt' prints 487/* Callers store zero here to inhibit the error message `getopt' prints
485 for unrecognized options. */ 488 for unrecognized options. */
486 489
487extern int opterr; 490 extern int opterr;
488 491
489/* Set to an option character which was unrecognized. */ 492/* Set to an option character which was unrecognized. */
490 493
491extern int optopt; 494 extern int optopt;
492 495
493/* Describe the long-named options requested by the application. 496/* Describe the long-named options requested by the application.
494 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 497 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
@@ -511,19 +514,18 @@ extern int optopt;
511 one). For long options that have a zero `flag' field, `getopt' 514 one). For long options that have a zero `flag' field, `getopt'
512 returns the contents of the `val' field. */ 515 returns the contents of the `val' field. */
513 516
514struct option 517 struct option {
515{
516#if __STDC__ 518#if __STDC__
517 const char *name; 519 const char *name;
518#else 520#else
519 char *name; 521 char *name;
520#endif 522#endif
521 /* has_arg can't be an enum because some compilers complain about 523 /* has_arg can't be an enum because some compilers complain about
522 type mismatches in all the code that assumes it is an int. */ 524 type mismatches in all the code that assumes it is an int. */
523 int has_arg; 525 int has_arg;
524 int *flag; 526 int *flag;
525 int val; 527 int val;
526}; 528 };
527 529
528/* Names for the values of the `has_arg' field of `struct option'. */ 530/* Names for the values of the `has_arg' field of `struct option'. */
529 531
@@ -536,60 +538,61 @@ struct option
536/* Many other libraries have conflicting prototypes for getopt, with 538/* Many other libraries have conflicting prototypes for getopt, with
537 differences in the consts, in stdlib.h. To avoid compilation 539 differences in the consts, in stdlib.h. To avoid compilation
538 errors, only prototype getopt for the GNU C library. */ 540 errors, only prototype getopt for the GNU C library. */
539extern int getopt (int argc, char *const *argv, const char *shortopts); 541 extern int getopt(int argc, char *const *argv, const char *shortopts);
540#endif /* not __GNU_LIBRARY__ */ 542#endif /* not __GNU_LIBRARY__ */
541extern int getopt_long (int argc, char *const *argv, const char *shortopts, 543 extern int getopt_long(int argc, char *const *argv,
542 const struct option *longopts, int *longind); 544 const char *shortopts,
543extern int getopt_long_only (int argc, char *const *argv, 545 const struct option *longopts, int *longind);
544 const char *shortopts, 546 extern int getopt_long_only(int argc, char *const *argv,
545 const struct option *longopts, int *longind); 547 const char *shortopts,
548 const struct option *longopts,
549 int *longind);
546 550
547/* Internal only. Users should not call this directly. */ 551/* Internal only. Users should not call this directly. */
548extern int _getopt_internal (int argc, char *const *argv, 552 extern int _getopt_internal(int argc, char *const *argv,
549 const char *shortopts, 553 const char *shortopts,
550 const struct option *longopts, int *longind, 554 const struct option *longopts,
551 int long_only); 555 int *longind, int long_only);
552#else /* not __STDC__ */ 556#else /* not __STDC__ */
553extern int getopt (); 557 extern int getopt();
554extern int getopt_long (); 558 extern int getopt_long();
555extern int getopt_long_only (); 559 extern int getopt_long_only();
556 560
557extern int _getopt_internal (); 561 extern int _getopt_internal();
558#endif /* not __STDC__ */ 562#endif /* not __STDC__ */
559 563
560#ifdef __cplusplus 564#ifdef __cplusplus
561} 565}
562#endif 566#endif
563 567#endif /* _GETOPT_H */
564#endif /* _GETOPT_H */
565
566
567#include <time.h> 568#include <time.h>
568#include <fcntl.h> 569#include <fcntl.h>
569#include <unistd.h> 570#include <unistd.h>
570
571#include <stdlib.h> 571#include <stdlib.h>
572
573#if defined(DIRENT) 572#if defined(DIRENT)
574# include <dirent.h> 573# include <dirent.h>
575 typedef struct dirent dir_type; 574typedef struct dirent dir_type;
575
576# define NLENGTH(dirent) ((int)strlen((dirent)->d_name)) 576# define NLENGTH(dirent) ((int)strlen((dirent)->d_name))
577# define DIR_OPT "DIRENT" 577# define DIR_OPT "DIRENT"
578#else 578#else
579# define NLENGTH(dirent) ((dirent)->d_namlen) 579# define NLENGTH(dirent) ((dirent)->d_namlen)
580# ifdef SYSDIR 580# ifdef SYSDIR
581# include <sys/dir.h> 581# include <sys/dir.h>
582 typedef struct direct dir_type; 582typedef struct direct dir_type;
583
583# define DIR_OPT "SYSDIR" 584# define DIR_OPT "SYSDIR"
584# else 585# else
585# ifdef SYSNDIR 586# ifdef SYSNDIR
586# include <sys/ndir.h> 587# include <sys/ndir.h>
587 typedef struct direct dir_type; 588typedef struct direct dir_type;
589
588# define DIR_OPT "SYSNDIR" 590# define DIR_OPT "SYSNDIR"
589# else 591# else
590# ifdef NDIR 592# ifdef NDIR
591# include <ndir.h> 593# include <ndir.h>
592 typedef struct direct dir_type; 594typedef struct direct dir_type;
595
593# define DIR_OPT "NDIR" 596# define DIR_OPT "NDIR"
594# else 597# else
595# define NO_DIR 598# define NO_DIR
@@ -598,18 +601,16 @@ extern int _getopt_internal ();
598# endif 601# endif
599# endif 602# endif
600#endif 603#endif
601
602#if !defined(S_ISDIR) && defined(S_IFDIR) 604#if !defined(S_ISDIR) && defined(S_IFDIR)
603# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 605# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
604#endif 606#endif
605#if !defined(S_ISREG) && defined(S_IFREG) 607#if !defined(S_ISREG) && defined(S_IFREG)
606# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 608# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
607#endif 609#endif
608 610typedef RETSIGTYPE(*sig_type) OF((int));
609typedef RETSIGTYPE (*sig_type) OF((int));
610 611
611#ifndef O_BINARY 612#ifndef O_BINARY
612# define O_BINARY 0 /* creation mode for open() */ 613# define O_BINARY 0 /* creation mode for open() */
613#endif 614#endif
614 615
615#ifndef O_CREAT 616#ifndef O_CREAT
@@ -629,9 +630,9 @@ typedef RETSIGTYPE (*sig_type) OF((int));
629#ifndef S_IWUSR 630#ifndef S_IWUSR
630# define S_IWUSR 0200 631# define S_IWUSR 0200
631#endif 632#endif
632#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ 633#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
633 634
634#ifndef MAX_PATH_LEN /* max pathname length */ 635#ifndef MAX_PATH_LEN /* max pathname length */
635# ifdef PATH_MAX 636# ifdef PATH_MAX
636# define MAX_PATH_LEN PATH_MAX 637# define MAX_PATH_LEN PATH_MAX
637# else 638# else
@@ -644,224 +645,224 @@ typedef RETSIGTYPE (*sig_type) OF((int));
644#endif 645#endif
645 646
646#ifdef NO_OFF_T 647#ifdef NO_OFF_T
647 typedef long off_t; 648typedef long off_t;
648 off_t lseek OF((int fd, off_t offset, int whence)); 649off_t lseek OF((int fd, off_t offset, int whence));
649#endif 650#endif
650 651
651 652
652 /* global buffers */ 653 /* global buffers */
653 654
654DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 655DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
655DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 656DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
656DECLARE(ush, d_buf, DIST_BUFSIZE); 657DECLARE(ush, d_buf, DIST_BUFSIZE);
657DECLARE(uch, window, 2L*WSIZE); 658DECLARE(uch, window, 2L * WSIZE);
658#ifndef MAXSEG_64K 659#ifndef MAXSEG_64K
659 DECLARE(ush, tab_prefix, 1L<<BITS); 660DECLARE(ush, tab_prefix, 1L << BITS);
660#else 661#else
661 DECLARE(ush, tab_prefix0, 1L<<(BITS-1)); 662DECLARE(ush, tab_prefix0, 1L << (BITS - 1));
662 DECLARE(ush, tab_prefix1, 1L<<(BITS-1)); 663DECLARE(ush, tab_prefix1, 1L << (BITS - 1));
663#endif 664#endif
664 665
665 /* local variables */ 666 /* local variables */
666 667
667int test_mode = 0; /* check file integrity option */ 668int test_mode = 0; /* check file integrity option */
668int foreground; /* set if program run in foreground */ 669int foreground; /* set if program run in foreground */
669int maxbits = BITS; /* max bits per code for LZW */ 670int maxbits = BITS; /* max bits per code for LZW */
670int method = DEFLATED;/* compression method */ 671int method = DEFLATED; /* compression method */
671int exit_code = OK; /* program exit code */ 672int exit_code = OK; /* program exit code */
672int last_member; /* set for .zip and .Z files */ 673int last_member; /* set for .zip and .Z files */
673int part_nb; /* number of parts in .gz file */ 674int part_nb; /* number of parts in .gz file */
674long ifile_size; /* input file size, -1 for devices (debug only) */ 675long ifile_size; /* input file size, -1 for devices (debug only) */
675 676
676long bytes_in; /* number of input bytes */ 677long bytes_in; /* number of input bytes */
677long bytes_out; /* number of output bytes */ 678long bytes_out; /* number of output bytes */
678long total_in = 0; /* input bytes for all files */ 679long total_in = 0; /* input bytes for all files */
679long total_out = 0; /* output bytes for all files */ 680long total_out = 0; /* output bytes for all files */
680struct stat istat; /* status for input file */ 681struct stat istat; /* status for input file */
681int ifd; /* input file descriptor */ 682int ifd; /* input file descriptor */
682int ofd; /* output file descriptor */ 683int ofd; /* output file descriptor */
683unsigned insize; /* valid bytes in inbuf */ 684unsigned insize; /* valid bytes in inbuf */
684unsigned inptr; /* index of next byte to be processed in inbuf */ 685unsigned inptr; /* index of next byte to be processed in inbuf */
685unsigned outcnt; /* bytes in output buffer */ 686unsigned outcnt; /* bytes in output buffer */
686 687
687long header_bytes; /* number of bytes in gzip header */ 688long header_bytes; /* number of bytes in gzip header */
688 689
689/* local functions */ 690/* local functions */
690 691
691local int get_method OF((int in)); 692local int get_method OF((int in));
692 693
693#define strequ(s1, s2) (strcmp((s1),(s2)) == 0) 694#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
694 695
695/* ======================================================================== */ 696/* ======================================================================== */
696int gunzip_main (int argc, char** argv) 697int gunzip_main(int argc, char **argv)
697{ 698{
698 int file_count; /* number of files to precess */ 699 int file_count; /* number of files to precess */
699 int to_stdout = 0; 700 int to_stdout = 0;
700 int fromstdin = 0; 701 int fromstdin = 0;
701 int result; 702 int result;
702 int inFileNum; 703 int inFileNum;
703 int outFileNum; 704 int outFileNum;
704 int delInputFile=0; 705 int delInputFile = 0;
705 struct stat statBuf; 706 struct stat statBuf;
706 char* delFileName; 707 char *delFileName;
707 char ifname[MAX_PATH_LEN + 1]; /* input file name */ 708 char ifname[MAX_PATH_LEN + 1]; /* input file name */
708 char ofname[MAX_PATH_LEN + 1]; /* output file name */ 709 char ofname[MAX_PATH_LEN + 1]; /* output file name */
709 710
710 if (argc==1) 711 if (argc == 1)
711 usage(gunzip_usage); 712 usage(gunzip_usage);
712 713
713 if (strcmp(*argv, "zcat")==0) 714 if (strcmp(*argv, "zcat") == 0)
714 to_stdout = 1;
715
716 /* Parse any options */
717 while (--argc > 0 && **(++argv) == '-') {
718 if (*((*argv)+1) == '\0') {
719 fromstdin = 1;
720 to_stdout = 1;
721 }
722 while (*(++(*argv))) {
723 switch (**argv) {
724 case 'c':
725 to_stdout = 1; 715 to_stdout = 1;
726 break;
727 case 't':
728 test_mode = 1;
729 break;
730 716
731 default: 717 /* Parse any options */
732 usage(gunzip_usage); 718 while (--argc > 0 && **(++argv) == '-') {
733 } 719 if (*((*argv) + 1) == '\0') {
720 fromstdin = 1;
721 to_stdout = 1;
722 }
723 while (*(++(*argv))) {
724 switch (**argv) {
725 case 'c':
726 to_stdout = 1;
727 break;
728 case 't':
729 test_mode = 1;
730 break;
731
732 default:
733 usage(gunzip_usage);
734 }
735 }
734 } 736 }
735 }
736 737
737 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; 738 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
738 if (foreground) { 739 if (foreground) {
739 (void) signal (SIGINT, (sig_type)abort_gzip); 740 (void) signal(SIGINT, (sig_type) abort_gzip);
740 } 741 }
741#ifdef SIGTERM 742#ifdef SIGTERM
742 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 743 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
743 (void) signal(SIGTERM, (sig_type)abort_gzip); 744 (void) signal(SIGTERM, (sig_type) abort_gzip);
744 } 745 }
745#endif 746#endif
746#ifdef SIGHUP 747#ifdef SIGHUP
747 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 748 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
748 (void) signal(SIGHUP, (sig_type)abort_gzip); 749 (void) signal(SIGHUP, (sig_type) abort_gzip);
749 } 750 }
750#endif 751#endif
751 752
752 file_count = argc - optind; 753 file_count = argc - optind;
753 754
754 /* Allocate all global buffers (for DYN_ALLOC option) */ 755 /* Allocate all global buffers (for DYN_ALLOC option) */
755 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 756 ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
756 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 757 ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
757 ALLOC(ush, d_buf, DIST_BUFSIZE); 758 ALLOC(ush, d_buf, DIST_BUFSIZE);
758 ALLOC(uch, window, 2L*WSIZE); 759 ALLOC(uch, window, 2L * WSIZE);
759#ifndef MAXSEG_64K 760#ifndef MAXSEG_64K
760 ALLOC(ush, tab_prefix, 1L<<BITS); 761 ALLOC(ush, tab_prefix, 1L << BITS);
761#else 762#else
762 ALLOC(ush, tab_prefix0, 1L<<(BITS-1)); 763 ALLOC(ush, tab_prefix0, 1L << (BITS - 1));
763 ALLOC(ush, tab_prefix1, 1L<<(BITS-1)); 764 ALLOC(ush, tab_prefix1, 1L << (BITS - 1));
764#endif 765#endif
765 766
766 if (fromstdin==1) { 767 if (fromstdin == 1) {
767 strcpy(ofname, "stdin"); 768 strcpy(ofname, "stdin");
768
769 inFileNum=fileno(stdin);
770 ifile_size = -1L; /* convention for unknown size */
771 } else {
772 /* Open up the input file */
773 if (*argv=='\0')
774 usage(gunzip_usage);
775 if (strlen(*argv) > MAX_PATH_LEN) {
776 fprintf(stderr, name_too_long, "gunzip");
777 do_exit(WARNING);
778 }
779 strcpy(ifname, *argv);
780 769
781 /* Open input fille */ 770 inFileNum = fileno(stdin);
782 inFileNum=open( ifname, O_RDONLY); 771 ifile_size = -1L; /* convention for unknown size */
783 if (inFileNum < 0) {
784 perror(ifname);
785 do_exit(WARNING);
786 }
787 /* Get the time stamp on the input file. */
788 result = stat(ifname, &statBuf);
789 if (result < 0) {
790 perror(ifname);
791 do_exit(WARNING);
792 }
793 ifile_size = statBuf.st_size;
794 }
795
796 if (to_stdout==1) {
797 /* And get to work */
798 strcpy(ofname, "stdout");
799 outFileNum=fileno(stdout);
800
801 clear_bufs(); /* clear input and output buffers */
802 part_nb = 0;
803
804 /* Actually do the compression/decompression. */
805 unzip(inFileNum, outFileNum);
806
807 } else if (test_mode) {
808 /* Actually do the compression/decompression. */
809 unzip(inFileNum, 2);
810 } else {
811 char* pos;
812
813 /* And get to work */
814 if (strlen(ifname) > MAX_PATH_LEN - 4) {
815 fprintf(stderr, name_too_long, "gunzip");
816 do_exit(WARNING);
817 }
818 strcpy(ofname, ifname);
819 pos=strstr(ofname, ".gz");
820 if (pos != NULL) {
821 *pos='\0';
822 delInputFile=1;
823 } else { 772 } else {
824 pos=strstr(ofname, ".tgz"); 773 /* Open up the input file */
825 if (pos != NULL) { 774 if (*argv == '\0')
826 *pos='\0'; 775 usage(gunzip_usage);
827 strcat( pos, ".tar"); 776 if (strlen(*argv) > MAX_PATH_LEN) {
828 delInputFile=1; 777 fprintf(stderr, name_too_long, "gunzip");
829 } 778 do_exit(WARNING);
779 }
780 strcpy(ifname, *argv);
781
782 /* Open input fille */
783 inFileNum = open(ifname, O_RDONLY);
784 if (inFileNum < 0) {
785 perror(ifname);
786 do_exit(WARNING);
787 }
788 /* Get the time stamp on the input file. */
789 result = stat(ifname, &statBuf);
790 if (result < 0) {
791 perror(ifname);
792 do_exit(WARNING);
793 }
794 ifile_size = statBuf.st_size;
830 } 795 }
831 796
832 /* Open output fille */ 797 if (to_stdout == 1) {
798 /* And get to work */
799 strcpy(ofname, "stdout");
800 outFileNum = fileno(stdout);
801
802 clear_bufs(); /* clear input and output buffers */
803 part_nb = 0;
804
805 /* Actually do the compression/decompression. */
806 unzip(inFileNum, outFileNum);
807
808 } else if (test_mode) {
809 /* Actually do the compression/decompression. */
810 unzip(inFileNum, 2);
811 } else {
812 char *pos;
813
814 /* And get to work */
815 if (strlen(ifname) > MAX_PATH_LEN - 4) {
816 fprintf(stderr, name_too_long, "gunzip");
817 do_exit(WARNING);
818 }
819 strcpy(ofname, ifname);
820 pos = strstr(ofname, ".gz");
821 if (pos != NULL) {
822 *pos = '\0';
823 delInputFile = 1;
824 } else {
825 pos = strstr(ofname, ".tgz");
826 if (pos != NULL) {
827 *pos = '\0';
828 strcat(pos, ".tar");
829 delInputFile = 1;
830 }
831 }
832
833 /* Open output fille */
833#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 834#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
834 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW); 835 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
835#else 836#else
836 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL); 837 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL);
837#endif 838#endif
838 if (outFileNum < 0) { 839 if (outFileNum < 0) {
839 perror(ofname); 840 perror(ofname);
840 do_exit(WARNING); 841 do_exit(WARNING);
841 } 842 }
842 /* Set permissions on the file */ 843 /* Set permissions on the file */
843 fchmod(outFileNum, statBuf.st_mode); 844 fchmod(outFileNum, statBuf.st_mode);
844 845
845 clear_bufs(); /* clear input and output buffers */ 846 clear_bufs(); /* clear input and output buffers */
846 part_nb = 0; 847 part_nb = 0;
847 848
848 /* Actually do the compression/decompression. */ 849 /* Actually do the compression/decompression. */
849 result=unzip(inFileNum, outFileNum); 850 result = unzip(inFileNum, outFileNum);
850 851
851 close( outFileNum); 852 close(outFileNum);
852 close( inFileNum); 853 close(inFileNum);
853 /* Delete the original file */ 854 /* Delete the original file */
854 if (result == OK) 855 if (result == OK)
855 delFileName=ifname; 856 delFileName = ifname;
856 else 857 else
857 delFileName=ofname; 858 delFileName = ofname;
858 859
859 if (delInputFile == 1 && unlink (delFileName) < 0) { 860 if (delInputFile == 1 && unlink(delFileName) < 0) {
860 perror (delFileName); 861 perror(delFileName);
861 exit( FALSE); 862 exit(FALSE);
863 }
862 } 864 }
863 } 865 do_exit(exit_code);
864 do_exit(exit_code);
865} 866}
866 867
867 868
@@ -877,71 +878,76 @@ int gunzip_main (int argc, char** argv)
877 * If the member is a zip file, it must be the only one. 878 * If the member is a zip file, it must be the only one.
878 */ 879 */
879local int get_method(in) 880local int get_method(in)
880 int in; /* input file descriptor */ 881int in; /* input file descriptor */
881{ 882{
882 uch flags; /* compression flags */ 883 uch flags; /* compression flags */
883 char magic[2]; /* magic header */ 884 char magic[2]; /* magic header */
884 885
885 magic[0] = (char)get_byte(); 886 magic[0] = (char) get_byte();
886 magic[1] = (char)get_byte(); 887 magic[1] = (char) get_byte();
887 method = -1; /* unknown yet */ 888 method = -1; /* unknown yet */
888 part_nb++; /* number of parts in gzip file */ 889 part_nb++; /* number of parts in gzip file */
889 header_bytes = 0; 890 header_bytes = 0;
890 last_member = RECORD_IO; 891 last_member = RECORD_IO;
891 /* assume multiple members in gzip file except for record oriented I/O */ 892 /* assume multiple members in gzip file except for record oriented I/O */
892 893
893 if (memcmp(magic, GZIP_MAGIC, 2) == 0) { 894 if (memcmp(magic, GZIP_MAGIC, 2) == 0) {
894 895
895 method = (int)get_byte(); 896 method = (int) get_byte();
896 if (method != DEFLATED) { 897 if (method != DEFLATED) {
897 fprintf(stderr, 898 fprintf(stderr,
898 "unknown method %d -- get newer version of gzip\n", 899 "unknown method %d -- get newer version of gzip\n",
899 method); 900 method);
900 exit_code = ERROR; 901 exit_code = ERROR;
901 return -1; 902 return -1;
902 } 903 }
903 flags = (uch)get_byte(); 904 flags = (uch) get_byte();
904 905
905 (ulg)get_byte(); /* Ignore time stamp */ 906 (ulg) get_byte(); /* Ignore time stamp */
906 (ulg)get_byte(); 907 (ulg) get_byte();
907 (ulg)get_byte(); 908 (ulg) get_byte();
908 (ulg)get_byte(); 909 (ulg) get_byte();
910
911 (void) get_byte(); /* Ignore extra flags for the moment */
912 (void) get_byte(); /* Ignore OS type for the moment */
913
914 if ((flags & EXTRA_FIELD) != 0) {
915 unsigned len = (unsigned) get_byte();
916
917 len |= ((unsigned) get_byte()) << 8;
918
919 while (len--)
920 (void) get_byte();
921 }
922
923 /* Discard original name if any */
924 if ((flags & ORIG_NAME) != 0) {
925 while (get_char() != 0) /* null */
926 ;
927 }
928
929 /* Discard file comment if any */
930 if ((flags & COMMENT) != 0) {
931 while (get_char() != 0) /* null */
932 ;
933 }
934 if (part_nb == 1) {
935 header_bytes = inptr + 2 * sizeof(long); /* include crc and size */
936 }
909 937
910 (void)get_byte(); /* Ignore extra flags for the moment */
911 (void)get_byte(); /* Ignore OS type for the moment */
912
913 if ((flags & EXTRA_FIELD) != 0) {
914 unsigned len = (unsigned)get_byte();
915 len |= ((unsigned)get_byte())<<8;
916
917 while (len--) (void)get_byte();
918 } 938 }
919 939
920 /* Discard original name if any */ 940 if (method >= 0)
921 if ((flags & ORIG_NAME) != 0) { 941 return method;
922 while (get_char() != 0) /* null */ ;
923 }
924 942
925 /* Discard file comment if any */
926 if ((flags & COMMENT) != 0) {
927 while (get_char() != 0) /* null */ ;
928 }
929 if (part_nb == 1) { 943 if (part_nb == 1) {
930 header_bytes = inptr + 2*sizeof(long); /* include crc and size */ 944 fprintf(stderr, "\nnot in gzip format\n");
945 exit_code = ERROR;
946 return -1;
947 } else {
948 WARN((stderr, "\ndecompression OK, trailing garbage ignored\n"));
949 return -2;
931 } 950 }
932
933 }
934
935 if (method >= 0) return method;
936
937 if (part_nb == 1) {
938 fprintf(stderr, "\nnot in gzip format\n");
939 exit_code = ERROR;
940 return -1;
941 } else {
942 WARN((stderr, "\ndecompression OK, trailing garbage ignored\n"));
943 return -2;
944 }
945} 951}
946 952
947/* ======================================================================== 953/* ========================================================================
@@ -949,8 +955,9 @@ local int get_method(in)
949 */ 955 */
950RETSIGTYPE abort_gzip() 956RETSIGTYPE abort_gzip()
951{ 957{
952 do_exit(ERROR); 958 do_exit(ERROR);
953} 959}
960
954/* unzip.c -- decompress files in gzip or pkzip format. 961/* unzip.c -- decompress files in gzip or pkzip format.
955 * Copyright (C) 1992-1993 Jean-loup Gailly 962 * Copyright (C) 1992-1993 Jean-loup Gailly
956 * This is free software; you can redistribute it and/or modify it under the 963 * This is free software; you can redistribute it and/or modify it under the
@@ -973,35 +980,35 @@ RETSIGTYPE abort_gzip()
973 */ 980 */
974 981
975#ifdef CRYPT 982#ifdef CRYPT
976# undef CRYPT /* dummy version */ 983# undef CRYPT /* dummy version */
977#endif 984#endif
978 985
979#define RAND_HEAD_LEN 12 /* length of encryption random header */ 986#define RAND_HEAD_LEN 12 /* length of encryption random header */
980 987
981#define zencode 988#define zencode
982#define zdecode 989#define zdecode
983 990
984/* PKZIP header definitions */ 991/* PKZIP header definitions */
985#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ 992#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
986#define LOCFLG 6 /* offset of bit flag */ 993#define LOCFLG 6 /* offset of bit flag */
987#define CRPFLG 1 /* bit for encrypted entry */ 994#define CRPFLG 1 /* bit for encrypted entry */
988#define EXTFLG 8 /* bit for extended local header */ 995#define EXTFLG 8 /* bit for extended local header */
989#define LOCHOW 8 /* offset of compression method */ 996#define LOCHOW 8 /* offset of compression method */
990#define LOCTIM 10 /* file mod time (for decryption) */ 997#define LOCTIM 10 /* file mod time (for decryption) */
991#define LOCCRC 14 /* offset of crc */ 998#define LOCCRC 14 /* offset of crc */
992#define LOCSIZ 18 /* offset of compressed size */ 999#define LOCSIZ 18 /* offset of compressed size */
993#define LOCLEN 22 /* offset of uncompressed length */ 1000#define LOCLEN 22 /* offset of uncompressed length */
994#define LOCFIL 26 /* offset of file name field length */ 1001#define LOCFIL 26 /* offset of file name field length */
995#define LOCEXT 28 /* offset of extra field length */ 1002#define LOCEXT 28 /* offset of extra field length */
996#define LOCHDR 30 /* size of local header, including sig */ 1003#define LOCHDR 30 /* size of local header, including sig */
997#define EXTHDR 16 /* size of extended local header, inc sig */ 1004#define EXTHDR 16 /* size of extended local header, inc sig */
998 1005
999 1006
1000/* Globals */ 1007/* Globals */
1001 1008
1002char *key; /* not used--needed to link crypt.c */ 1009char *key; /* not used--needed to link crypt.c */
1003int pkzip = 0; /* set for a pkzip file */ 1010int pkzip = 0; /* set for a pkzip file */
1004int ext_header = 0; /* set if extended local header */ 1011int ext_header = 0; /* set if extended local header */
1005 1012
1006/* =========================================================================== 1013/* ===========================================================================
1007 * Unzip in to out. This routine works on both gzip and pkzip files. 1014 * Unzip in to out. This routine works on both gzip and pkzip files.
@@ -1011,81 +1018,82 @@ int ext_header = 0; /* set if extended local header */
1011 * The magic header has already been checked. The output buffer is cleared. 1018 * The magic header has already been checked. The output buffer is cleared.
1012 */ 1019 */
1013int unzip(in, out) 1020int unzip(in, out)
1014 int in, out; /* input and output file descriptors */ 1021int in, out; /* input and output file descriptors */
1015{ 1022{
1016 ulg orig_crc = 0; /* original crc */ 1023 ulg orig_crc = 0; /* original crc */
1017 ulg orig_len = 0; /* original uncompressed length */ 1024 ulg orig_len = 0; /* original uncompressed length */
1018 int n; 1025 int n;
1019 uch buf[EXTHDR]; /* extended local header */ 1026 uch buf[EXTHDR]; /* extended local header */
1020 1027
1021 ifd = in; 1028 ifd = in;
1022 ofd = out; 1029 ofd = out;
1023 method = get_method(ifd); 1030 method = get_method(ifd);
1024 if (method < 0) { 1031 if (method < 0) {
1025 do_exit(exit_code); /* error message already emitted */ 1032 do_exit(exit_code); /* error message already emitted */
1026 }
1027
1028 updcrc(NULL, 0); /* initialize crc */
1029
1030 if (pkzip && !ext_header) { /* crc and length at the end otherwise */
1031 orig_crc = LG(inbuf + LOCCRC);
1032 orig_len = LG(inbuf + LOCLEN);
1033 }
1034
1035 /* Decompress */
1036 if (method == DEFLATED) {
1037
1038 int res = inflate();
1039
1040 if (res == 3) {
1041 error("out of memory");
1042 } else if (res != 0) {
1043 error("invalid compressed data--format violated");
1044 } 1033 }
1045 1034
1046 } else { 1035 updcrc(NULL, 0); /* initialize crc */
1047 error("internal error, invalid method"); 1036
1048 } 1037 if (pkzip && !ext_header) { /* crc and length at the end otherwise */
1049 1038 orig_crc = LG(inbuf + LOCCRC);
1050 /* Get the crc and original length */ 1039 orig_len = LG(inbuf + LOCLEN);
1051 if (!pkzip) {
1052 /* crc32 (see algorithm.doc)
1053 * uncompressed input size modulo 2^32
1054 */
1055 for (n = 0; n < 8; n++) {
1056 buf[n] = (uch)get_byte(); /* may cause an error if EOF */
1057 } 1040 }
1058 orig_crc = LG(buf); 1041
1059 orig_len = LG(buf+4); 1042 /* Decompress */
1060 1043 if (method == DEFLATED) {
1061 } else if (ext_header) { /* If extended header, check it */ 1044
1062 /* signature - 4bytes: 0x50 0x4b 0x07 0x08 1045 int res = inflate();
1063 * CRC-32 value 1046
1064 * compressed size 4-bytes 1047 if (res == 3) {
1065 * uncompressed size 4-bytes 1048 error("out of memory");
1066 */ 1049 } else if (res != 0) {
1067 for (n = 0; n < EXTHDR; n++) { 1050 error("invalid compressed data--format violated");
1068 buf[n] = (uch)get_byte(); /* may cause an error if EOF */ 1051 }
1052
1053 } else {
1054 error("internal error, invalid method");
1055 }
1056
1057 /* Get the crc and original length */
1058 if (!pkzip) {
1059 /* crc32 (see algorithm.doc)
1060 * uncompressed input size modulo 2^32
1061 */
1062 for (n = 0; n < 8; n++) {
1063 buf[n] = (uch) get_byte(); /* may cause an error if EOF */
1064 }
1065 orig_crc = LG(buf);
1066 orig_len = LG(buf + 4);
1067
1068 } else if (ext_header) { /* If extended header, check it */
1069 /* signature - 4bytes: 0x50 0x4b 0x07 0x08
1070 * CRC-32 value
1071 * compressed size 4-bytes
1072 * uncompressed size 4-bytes
1073 */
1074 for (n = 0; n < EXTHDR; n++) {
1075 buf[n] = (uch) get_byte(); /* may cause an error if EOF */
1076 }
1077 orig_crc = LG(buf + 4);
1078 orig_len = LG(buf + 12);
1079 }
1080
1081 /* Validate decompression */
1082 if (orig_crc != updcrc(outbuf, 0)) {
1083 error("invalid compressed data--crc error");
1069 } 1084 }
1070 orig_crc = LG(buf+4); 1085 if (orig_len != (ulg) bytes_out) {
1071 orig_len = LG(buf+12); 1086 error("invalid compressed data--length error");
1072 } 1087 }
1073 1088
1074 /* Validate decompression */ 1089 /* Check if there are more entries in a pkzip file */
1075 if (orig_crc != updcrc(outbuf, 0)) { 1090 if (pkzip && inptr + 4 < insize && LG(inbuf + inptr) == LOCSIG) {
1076 error("invalid compressed data--crc error"); 1091 WARN((stderr, "has more than one entry--rest ignored\n"));
1077 } 1092 }
1078 if (orig_len != (ulg)bytes_out) { 1093 ext_header = pkzip = 0; /* for next file */
1079 error("invalid compressed data--length error"); 1094 return OK;
1080 }
1081
1082 /* Check if there are more entries in a pkzip file */
1083 if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
1084 WARN((stderr,"has more than one entry--rest ignored\n"));
1085 }
1086 ext_header = pkzip = 0; /* for next file */
1087 return OK;
1088} 1095}
1096
1089/* util.c -- utility functions for gzip support 1097/* util.c -- utility functions for gzip support
1090 * Copyright (C) 1992-1993 Jean-loup Gailly 1098 * Copyright (C) 1992-1993 Jean-loup Gailly
1091 * This is free software; you can redistribute it and/or modify it under the 1099 * This is free software; you can redistribute it and/or modify it under the
@@ -1106,10 +1114,10 @@ int unzip(in, out)
1106#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 1114#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
1107# include <stdlib.h> 1115# include <stdlib.h>
1108#else 1116#else
1109 extern int errno; 1117extern int errno;
1110#endif 1118#endif
1111 1119
1112static const ulg crc_32_tab[]; /* crc table, defined below */ 1120static const ulg crc_32_tab[]; /* crc table, defined below */
1113 1121
1114/* =========================================================================== 1122/* ===========================================================================
1115 * Run a set of bytes through the crc shift register. If s is a NULL 1123 * Run a set of bytes through the crc shift register. If s is a NULL
@@ -1117,23 +1125,24 @@ static const ulg crc_32_tab[]; /* crc table, defined below */
1117 * Return the current crc in either case. 1125 * Return the current crc in either case.
1118 */ 1126 */
1119ulg updcrc(s, n) 1127ulg updcrc(s, n)
1120 uch *s; /* pointer to bytes to pump through */ 1128uch *s; /* pointer to bytes to pump through */
1121 unsigned n; /* number of bytes in s[] */ 1129unsigned n; /* number of bytes in s[] */
1122{ 1130{
1123 register ulg c; /* temporary variable */ 1131 register ulg c; /* temporary variable */
1124 1132
1125 static ulg crc = (ulg)0xffffffffL; /* shift register contents */ 1133 static ulg crc = (ulg) 0xffffffffL; /* shift register contents */
1126 1134
1127 if (s == NULL) { 1135 if (s == NULL) {
1128 c = 0xffffffffL; 1136 c = 0xffffffffL;
1129 } else { 1137 } else {
1130 c = crc; 1138 c = crc;
1131 if (n) do { 1139 if (n)
1132 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); 1140 do {
1133 } while (--n); 1141 c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8);
1134 } 1142 } while (--n);
1135 crc = c; 1143 }
1136 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ 1144 crc = c;
1145 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
1137} 1146}
1138 1147
1139/* =========================================================================== 1148/* ===========================================================================
@@ -1141,35 +1150,37 @@ ulg updcrc(s, n)
1141 */ 1150 */
1142void clear_bufs() 1151void clear_bufs()
1143{ 1152{
1144 outcnt = 0; 1153 outcnt = 0;
1145 insize = inptr = 0; 1154 insize = inptr = 0;
1146 bytes_in = bytes_out = 0L; 1155 bytes_in = bytes_out = 0L;
1147} 1156}
1148 1157
1149/* =========================================================================== 1158/* ===========================================================================
1150 * Fill the input buffer. This is called only when the buffer is empty. 1159 * Fill the input buffer. This is called only when the buffer is empty.
1151 */ 1160 */
1152int fill_inbuf(eof_ok) 1161int fill_inbuf(eof_ok)
1153 int eof_ok; /* set if EOF acceptable as a result */ 1162int eof_ok; /* set if EOF acceptable as a result */
1154{ 1163{
1155 int len; 1164 int len;
1156 1165
1157 /* Read as much as possible */ 1166 /* Read as much as possible */
1158 insize = 0; 1167 insize = 0;
1159 errno = 0; 1168 errno = 0;
1160 do { 1169 do {
1161 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize); 1170 len = read(ifd, (char *) inbuf + insize, INBUFSIZ - insize);
1162 if (len == 0 || len == EOF) break; 1171 if (len == 0 || len == EOF)
1163 insize += len; 1172 break;
1164 } while (insize < INBUFSIZ); 1173 insize += len;
1165 1174 } while (insize < INBUFSIZ);
1166 if (insize == 0) { 1175
1167 if (eof_ok) return EOF; 1176 if (insize == 0) {
1168 read_error(); 1177 if (eof_ok)
1169 } 1178 return EOF;
1170 bytes_in += (ulg)insize; 1179 read_error();
1171 inptr = 1; 1180 }
1172 return inbuf[0]; 1181 bytes_in += (ulg) insize;
1182 inptr = 1;
1183 return inbuf[0];
1173} 1184}
1174 1185
1175/* =========================================================================== 1186/* ===========================================================================
@@ -1178,12 +1189,13 @@ int fill_inbuf(eof_ok)
1178 */ 1189 */
1179void flush_outbuf() 1190void flush_outbuf()
1180{ 1191{
1181 if (outcnt == 0) return; 1192 if (outcnt == 0)
1193 return;
1182 1194
1183 if (!test_mode) 1195 if (!test_mode)
1184 write_buf(ofd, (char *)outbuf, outcnt); 1196 write_buf(ofd, (char *) outbuf, outcnt);
1185 bytes_out += (ulg)outcnt; 1197 bytes_out += (ulg) outcnt;
1186 outcnt = 0; 1198 outcnt = 0;
1187} 1199}
1188 1200
1189/* =========================================================================== 1201/* ===========================================================================
@@ -1192,13 +1204,14 @@ void flush_outbuf()
1192 */ 1204 */
1193void flush_window() 1205void flush_window()
1194{ 1206{
1195 if (outcnt == 0) return; 1207 if (outcnt == 0)
1196 updcrc(window, outcnt); 1208 return;
1197 1209 updcrc(window, outcnt);
1198 if (!test_mode) 1210
1199 write_buf(ofd, (char *)window, outcnt); 1211 if (!test_mode)
1200 bytes_out += (ulg)outcnt; 1212 write_buf(ofd, (char *) window, outcnt);
1201 outcnt = 0; 1213 bytes_out += (ulg) outcnt;
1214 outcnt = 0;
1202} 1215}
1203 1216
1204/* =========================================================================== 1217/* ===========================================================================
@@ -1206,19 +1219,19 @@ void flush_window()
1206 * for error return. 1219 * for error return.
1207 */ 1220 */
1208void write_buf(fd, buf, cnt) 1221void write_buf(fd, buf, cnt)
1209 int fd; 1222int fd;
1210 voidp buf; 1223voidp buf;
1211 unsigned cnt; 1224unsigned cnt;
1212{ 1225{
1213 unsigned n; 1226 unsigned n;
1214 1227
1215 while ((n = write(fd, buf, cnt)) != cnt) { 1228 while ((n = write(fd, buf, cnt)) != cnt) {
1216 if (n == (unsigned)(-1)) { 1229 if (n == (unsigned) (-1)) {
1217 write_error(); 1230 write_error();
1231 }
1232 cnt -= n;
1233 buf = (voidp) ((char *) buf + n);
1218 } 1234 }
1219 cnt -= n;
1220 buf = (voidp)((char*)buf+n);
1221 }
1222} 1235}
1223 1236
1224#if defined(NO_STRING_H) && !defined(STDC_HEADERS) 1237#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
@@ -1229,7 +1242,7 @@ void write_buf(fd, buf, cnt)
1229# define const 1242# define const
1230# endif 1243# endif
1231 1244
1232int strspn OF((const char *s, const char *accept)); 1245int strspn OF((const char *s, const char *accept));
1233int strcspn OF((const char *s, const char *reject)); 1246int strcspn OF((const char *s, const char *reject));
1234 1247
1235/* ======================================================================== 1248/* ========================================================================
@@ -1237,21 +1250,23 @@ int strcspn OF((const char *s, const char *reject));
1237 * of s which contains only characters in accept. 1250 * of s which contains only characters in accept.
1238 */ 1251 */
1239int strspn(s, accept) 1252int strspn(s, accept)
1240 const char *s; 1253const char *s;
1241 const char *accept; 1254const char *accept;
1242{ 1255{
1243 register const char *p; 1256 register const char *p;
1244 register const char *a; 1257 register const char *a;
1245 register int count = 0; 1258 register int count = 0;
1246 1259
1247 for (p = s; *p != '\0'; ++p) { 1260 for (p = s; *p != '\0'; ++p) {
1248 for (a = accept; *a != '\0'; ++a) { 1261 for (a = accept; *a != '\0'; ++a) {
1249 if (*p == *a) break; 1262 if (*p == *a)
1263 break;
1264 }
1265 if (*a == '\0')
1266 return count;
1267 ++count;
1250 } 1268 }
1251 if (*a == '\0') return count; 1269 return count;
1252 ++count;
1253 }
1254 return count;
1255} 1270}
1256 1271
1257/* ======================================================================== 1272/* ========================================================================
@@ -1259,46 +1274,47 @@ int strspn(s, accept)
1259 * which contains no characters from reject. 1274 * which contains no characters from reject.
1260 */ 1275 */
1261int strcspn(s, reject) 1276int strcspn(s, reject)
1262 const char *s; 1277const char *s;
1263 const char *reject; 1278const char *reject;
1264{ 1279{
1265 register int count = 0; 1280 register int count = 0;
1266 1281
1267 while (*s != '\0') { 1282 while (*s != '\0') {
1268 if (strchr(reject, *s++) != NULL) return count; 1283 if (strchr(reject, *s++) != NULL)
1269 ++count; 1284 return count;
1270 } 1285 ++count;
1271 return count; 1286 }
1287 return count;
1272} 1288}
1273 1289
1274#endif /* NO_STRING_H */ 1290#endif /* NO_STRING_H */
1275 1291
1276 1292
1277/* ======================================================================== 1293/* ========================================================================
1278 * Error handlers. 1294 * Error handlers.
1279 */ 1295 */
1280void warn(a, b) 1296void warn(a, b)
1281 char *a, *b; /* message strings juxtaposed in output */ 1297char *a, *b; /* message strings juxtaposed in output */
1282{ 1298{
1283 WARN((stderr, "warning: %s%s\n", a, b)); 1299 WARN((stderr, "warning: %s%s\n", a, b));
1284} 1300}
1285 1301
1286void read_error() 1302void read_error()
1287{ 1303{
1288 fprintf(stderr, "\n"); 1304 fprintf(stderr, "\n");
1289 if (errno != 0) { 1305 if (errno != 0) {
1290 perror(""); 1306 perror("");
1291 } else { 1307 } else {
1292 fprintf(stderr, "unexpected end of file\n"); 1308 fprintf(stderr, "unexpected end of file\n");
1293 } 1309 }
1294 abort_gzip(); 1310 abort_gzip();
1295} 1311}
1296 1312
1297void write_error() 1313void write_error()
1298{ 1314{
1299 fprintf(stderr, "\n"); 1315 fprintf(stderr, "\n");
1300 perror(""); 1316 perror("");
1301 abort_gzip(); 1317 abort_gzip();
1302} 1318}
1303 1319
1304 1320
@@ -1306,59 +1322,60 @@ void write_error()
1306 * Table of CRC-32's of all single-byte values (made by makecrc.c) 1322 * Table of CRC-32's of all single-byte values (made by makecrc.c)
1307 */ 1323 */
1308static const ulg crc_32_tab[] = { 1324static const ulg crc_32_tab[] = {
1309 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 1325 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
1310 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 1326 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
1311 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 1327 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
1312 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 1328 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
1313 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 1329 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
1314 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 1330 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
1315 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 1331 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
1316 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 1332 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
1317 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 1333 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
1318 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 1334 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
1319 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 1335 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
1320 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 1336 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
1321 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 1337 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
1322 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 1338 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
1323 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 1339 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
1324 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 1340 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
1325 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 1341 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
1326 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 1342 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
1327 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 1343 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
1328 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 1344 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
1329 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 1345 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
1330 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 1346 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
1331 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 1347 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
1332 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 1348 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
1333 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 1349 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
1334 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 1350 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
1335 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 1351 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
1336 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 1352 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
1337 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 1353 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
1338 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 1354 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
1339 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 1355 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
1340 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 1356 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
1341 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 1357 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
1342 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 1358 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
1343 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 1359 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
1344 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 1360 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
1345 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 1361 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
1346 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 1362 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
1347 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 1363 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
1348 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 1364 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
1349 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 1365 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
1350 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 1366 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
1351 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 1367 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
1352 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 1368 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
1353 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 1369 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
1354 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 1370 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
1355 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 1371 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
1356 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 1372 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
1357 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 1373 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
1358 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 1374 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
1359 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 1375 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
1360 0x2d02ef8dL 1376 0x2d02ef8dL
1361}; 1377};
1378
1362/* inflate.c -- Not copyrighted 1992 by Mark Adler 1379/* inflate.c -- Not copyrighted 1992 by Mark Adler
1363 version c10p1, 10 January 1993 */ 1380 version c10p1, 10 January 1993 */
1364 1381
@@ -1474,18 +1491,18 @@ static const ulg crc_32_tab[] = {
1474 an unused code. If a code with e == 99 is looked up, this implies an 1491 an unused code. If a code with e == 99 is looked up, this implies an
1475 error in the data. */ 1492 error in the data. */
1476struct huft { 1493struct huft {
1477 uch e; /* number of extra bits or operation */ 1494 uch e; /* number of extra bits or operation */
1478 uch b; /* number of bits in this code or subcode */ 1495 uch b; /* number of bits in this code or subcode */
1479 union { 1496 union {
1480 ush n; /* literal, length base, or distance base */ 1497 ush n; /* literal, length base, or distance base */
1481 struct huft *t; /* pointer to next level of table */ 1498 struct huft *t; /* pointer to next level of table */
1482 } v; 1499 } v;
1483}; 1500};
1484 1501
1485 1502
1486/* Function prototypes */ 1503/* Function prototypes */
1487int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *, 1504int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
1488 struct huft **, int *)); 1505 struct huft **, int *));
1489int huft_free OF((struct huft *)); 1506int huft_free OF((struct huft *));
1490int inflate_codes OF((struct huft *, struct huft *, int, int)); 1507int inflate_codes OF((struct huft *, struct huft *, int, int));
1491int inflate_stored OF((void)); 1508int inflate_stored OF((void));
@@ -1508,23 +1525,29 @@ int inflate OF((void));
1508#define flush_output(w) (wp=(w),flush_window()) 1525#define flush_output(w) (wp=(w),flush_window())
1509 1526
1510/* Tables for deflate from PKZIP's appnote.txt. */ 1527/* Tables for deflate from PKZIP's appnote.txt. */
1511static unsigned border[] = { /* Order of the bit length code lengths */ 1528static unsigned border[] = { /* Order of the bit length code lengths */
1512 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 1529 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
1513static ush cplens[] = { /* Copy lengths for literal codes 257..285 */ 1530};
1514 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 1531static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
1515 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 1532 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
1516 /* note: see note #13 above about the 258 in this list. */ 1533 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
1517static ush cplext[] = { /* Extra bits for literal codes 257..285 */ 1534};
1518 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 1535
1519 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ 1536 /* note: see note #13 above about the 258 in this list. */
1520static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ 1537static ush cplext[] = { /* Extra bits for literal codes 257..285 */
1521 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1538 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
1522 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 1539 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
1523 8193, 12289, 16385, 24577}; 1540}; /* 99==invalid */
1524static ush cpdext[] = { /* Extra bits for distance codes */ 1541static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
1525 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 1542 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
1526 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 1543 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
1527 12, 12, 13, 13}; 1544 8193, 12289, 16385, 24577
1545};
1546static ush cpdext[] = { /* Extra bits for distance codes */
1547 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
1548 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
1549 12, 12, 13, 13
1550};
1528 1551
1529 1552
1530 1553
@@ -1558,17 +1581,18 @@ static ush cpdext[] = { /* Extra bits for distance codes */
1558 the stream. 1581 the stream.
1559 */ 1582 */
1560 1583
1561ulg bb; /* bit buffer */ 1584ulg bb; /* bit buffer */
1562unsigned bk; /* bits in bit buffer */ 1585unsigned bk; /* bits in bit buffer */
1563 1586
1564ush mask_bits[] = { 1587ush mask_bits[] = {
1565 0x0000, 1588 0x0000,
1566 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 1589 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
1567 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 1590 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
1568}; 1591};
1569 1592
1570#ifdef CRYPT 1593#ifdef CRYPT
1571 uch cc; 1594uch cc;
1595
1572# define NEXTBYTE() (cc = get_byte(), zdecode(cc), cc) 1596# define NEXTBYTE() (cc = get_byte(), zdecode(cc), cc)
1573#else 1597#else
1574# define NEXTBYTE() (uch)get_byte() 1598# define NEXTBYTE() (uch)get_byte()
@@ -1610,342 +1634,342 @@ ush mask_bits[] = {
1610 */ 1634 */
1611 1635
1612 1636
1613int lbits = 9; /* bits in base literal/length lookup table */ 1637int lbits = 9; /* bits in base literal/length lookup table */
1614int dbits = 6; /* bits in base distance lookup table */ 1638int dbits = 6; /* bits in base distance lookup table */
1615 1639
1616 1640
1617/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ 1641/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
1618#define BMAX 16 /* maximum bit length of any code (16 for explode) */ 1642#define BMAX 16 /* maximum bit length of any code (16 for explode) */
1619#define N_MAX 288 /* maximum number of codes in any set */ 1643#define N_MAX 288 /* maximum number of codes in any set */
1620 1644
1621 1645
1622unsigned hufts; /* track memory usage */ 1646unsigned hufts; /* track memory usage */
1623 1647
1624 1648
1625int huft_build(b, n, s, d, e, t, m) 1649int huft_build(b, n, s, d, e, t, m)
1626unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ 1650unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
1627unsigned n; /* number of codes (assumed <= N_MAX) */ 1651unsigned n; /* number of codes (assumed <= N_MAX) */
1628unsigned s; /* number of simple-valued codes (0..s-1) */ 1652unsigned s; /* number of simple-valued codes (0..s-1) */
1629ush *d; /* list of base values for non-simple codes */ 1653ush *d; /* list of base values for non-simple codes */
1630ush *e; /* list of extra bits for non-simple codes */ 1654ush *e; /* list of extra bits for non-simple codes */
1631struct huft **t; /* result: starting table */ 1655struct huft **t; /* result: starting table */
1632int *m; /* maximum lookup bits, returns actual */ 1656int *m; /* maximum lookup bits, returns actual */
1657
1633/* Given a list of code lengths and a maximum table size, make a set of 1658/* Given a list of code lengths and a maximum table size, make a set of
1634 tables to decode that set of codes. Return zero on success, one if 1659 tables to decode that set of codes. Return zero on success, one if
1635 the given code set is incomplete (the tables are still built in this 1660 the given code set is incomplete (the tables are still built in this
1636 case), two if the input is invalid (all zero length codes or an 1661 case), two if the input is invalid (all zero length codes or an
1637 oversubscribed set of lengths), and three if not enough memory. */ 1662 oversubscribed set of lengths), and three if not enough memory. */
1638{ 1663{
1639 unsigned a; /* counter for codes of length k */ 1664 unsigned a; /* counter for codes of length k */
1640 unsigned c[BMAX+1]; /* bit length count table */ 1665 unsigned c[BMAX + 1]; /* bit length count table */
1641 unsigned f; /* i repeats in table every f entries */ 1666 unsigned f; /* i repeats in table every f entries */
1642 int g; /* maximum code length */ 1667 int g; /* maximum code length */
1643 int h; /* table level */ 1668 int h; /* table level */
1644 register unsigned i; /* counter, current code */ 1669 register unsigned i; /* counter, current code */
1645 register unsigned j; /* counter */ 1670 register unsigned j; /* counter */
1646 register int k; /* number of bits in current code */ 1671 register int k; /* number of bits in current code */
1647 int l; /* bits per table (returned in m) */ 1672 int l; /* bits per table (returned in m) */
1648 register unsigned *p; /* pointer into c[], b[], or v[] */ 1673 register unsigned *p; /* pointer into c[], b[], or v[] */
1649 register struct huft *q; /* points to current table */ 1674 register struct huft *q; /* points to current table */
1650 struct huft r; /* table entry for structure assignment */ 1675 struct huft r; /* table entry for structure assignment */
1651 struct huft *u[BMAX]; /* table stack */ 1676 struct huft *u[BMAX]; /* table stack */
1652 unsigned v[N_MAX]; /* values in order of bit length */ 1677 unsigned v[N_MAX]; /* values in order of bit length */
1653 register int w; /* bits before this table == (l * h) */ 1678 register int w; /* bits before this table == (l * h) */
1654 unsigned x[BMAX+1]; /* bit offsets, then code stack */ 1679 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
1655 unsigned *xp; /* pointer into x */ 1680 unsigned *xp; /* pointer into x */
1656 int y; /* number of dummy codes added */ 1681 int y; /* number of dummy codes added */
1657 unsigned z; /* number of entries in current table */ 1682 unsigned z; /* number of entries in current table */
1658 1683
1659 1684
1660 /* Generate counts for each bit length */ 1685 /* Generate counts for each bit length */
1661 memzero(c, sizeof(c)); 1686 memzero(c, sizeof(c));
1662 p = b; i = n; 1687 p = b;
1663 do { 1688 i = n;
1664 Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 1689 do {
1665 n-i, *p)); 1690 Tracecv(*p,
1666 c[*p]++; /* assume all entries <= BMAX */ 1691 (stderr,
1667 p++; /* Can't combine with above line (Solaris bug) */ 1692 (n - i >= ' '
1668 } while (--i); 1693 && n - i <= '~' ? "%c %d\n" : "0x%x %d\n"), n - i, *p));
1669 if (c[0] == n) /* null input--all zero length codes */ 1694 c[*p]++; /* assume all entries <= BMAX */
1670 { 1695 p++; /* Can't combine with above line (Solaris bug) */
1671 *t = (struct huft *)NULL; 1696 } while (--i);
1672 *m = 0; 1697 if (c[0] == n) { /* null input--all zero length codes */
1673 return 0; 1698 *t = (struct huft *) NULL;
1674 } 1699 *m = 0;
1675 1700 return 0;
1676 1701 }
1677 /* Find minimum and maximum length, bound *m by those */ 1702
1678 l = *m; 1703
1679 for (j = 1; j <= BMAX; j++) 1704 /* Find minimum and maximum length, bound *m by those */
1680 if (c[j]) 1705 l = *m;
1681 break; 1706 for (j = 1; j <= BMAX; j++)
1682 k = j; /* minimum code length */ 1707 if (c[j])
1683 if ((unsigned)l < j) 1708 break;
1684 l = j; 1709 k = j; /* minimum code length */
1685 for (i = BMAX; i; i--) 1710 if ((unsigned) l < j)
1686 if (c[i]) 1711 l = j;
1687 break; 1712 for (i = BMAX; i; i--)
1688 g = i; /* maximum code length */ 1713 if (c[i])
1689 if ((unsigned)l > i) 1714 break;
1690 l = i; 1715 g = i; /* maximum code length */
1691 *m = l; 1716 if ((unsigned) l > i)
1692 1717 l = i;
1693 1718 *m = l;
1694 /* Adjust last length count to fill out codes, if needed */ 1719
1695 for (y = 1 << j; j < i; j++, y <<= 1) 1720
1696 if ((y -= c[j]) < 0) 1721 /* Adjust last length count to fill out codes, if needed */
1697 return 2; /* bad input: more codes than bits */ 1722 for (y = 1 << j; j < i; j++, y <<= 1)
1698 if ((y -= c[i]) < 0) 1723 if ((y -= c[j]) < 0)
1699 return 2; 1724 return 2; /* bad input: more codes than bits */
1700 c[i] += y; 1725 if ((y -= c[i]) < 0)
1701 1726 return 2;
1702 1727 c[i] += y;
1703 /* Generate starting offsets into the value table for each length */ 1728
1704 x[1] = j = 0; 1729
1705 p = c + 1; xp = x + 2; 1730 /* Generate starting offsets into the value table for each length */
1706 while (--i) { /* note that i == g from above */ 1731 x[1] = j = 0;
1707 *xp++ = (j += *p++); 1732 p = c + 1;
1708 } 1733 xp = x + 2;
1709 1734 while (--i) { /* note that i == g from above */
1710 1735 *xp++ = (j += *p++);
1711 /* Make a table of values in order of bit lengths */ 1736 }
1712 p = b; i = 0; 1737
1713 do { 1738
1714 if ((j = *p++) != 0) 1739 /* Make a table of values in order of bit lengths */
1715 v[x[j]++] = i; 1740 p = b;
1716 } while (++i < n); 1741 i = 0;
1717 1742 do {
1718 1743 if ((j = *p++) != 0)
1719 /* Generate the Huffman codes and for each, make the table entries */ 1744 v[x[j]++] = i;
1720 x[0] = i = 0; /* first Huffman code is zero */ 1745 } while (++i < n);
1721 p = v; /* grab values in bit order */ 1746
1722 h = -1; /* no tables yet--level -1 */ 1747
1723 w = -l; /* bits decoded == (l * h) */ 1748 /* Generate the Huffman codes and for each, make the table entries */
1724 u[0] = (struct huft *)NULL; /* just to keep compilers happy */ 1749 x[0] = i = 0; /* first Huffman code is zero */
1725 q = (struct huft *)NULL; /* ditto */ 1750 p = v; /* grab values in bit order */
1726 z = 0; /* ditto */ 1751 h = -1; /* no tables yet--level -1 */
1727 1752 w = -l; /* bits decoded == (l * h) */
1728 /* go through the bit lengths (k already is bits in shortest code) */ 1753 u[0] = (struct huft *) NULL; /* just to keep compilers happy */
1729 for (; k <= g; k++) 1754 q = (struct huft *) NULL; /* ditto */
1730 { 1755 z = 0; /* ditto */
1731 a = c[k]; 1756
1732 while (a--) 1757 /* go through the bit lengths (k already is bits in shortest code) */
1733 { 1758 for (; k <= g; k++) {
1734 /* here i is the Huffman code of length k bits for value *p */ 1759 a = c[k];
1735 /* make tables up to required level */ 1760 while (a--) {
1736 while (k > w + l) 1761 /* here i is the Huffman code of length k bits for value *p */
1737 { 1762 /* make tables up to required level */
1738 h++; 1763 while (k > w + l) {
1739 w += l; /* previous table always l bits */ 1764 h++;
1740 1765 w += l; /* previous table always l bits */
1741 /* compute minimum size table less than or equal to l bits */ 1766
1742 z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ 1767 /* compute minimum size table less than or equal to l bits */
1743 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ 1768 z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */
1744 { /* too few codes for k-w bit table */ 1769 if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table *//* too few codes for k-w bit table */
1745 f -= a + 1; /* deduct codes from patterns left */ 1770 f -= a + 1; /* deduct codes from patterns left */
1746 xp = c + k; 1771 xp = c + k;
1747 while (++j < z) /* try smaller tables up to z bits */ 1772 while (++j < z) { /* try smaller tables up to z bits */
1748 { 1773 if ((f <<= 1) <= *++xp)
1749 if ((f <<= 1) <= *++xp) 1774 break; /* enough codes to use up j bits */
1750 break; /* enough codes to use up j bits */ 1775 f -= *xp; /* else deduct codes from patterns */
1751 f -= *xp; /* else deduct codes from patterns */ 1776 }
1752 } 1777 }
1753 } 1778 z = 1 << j; /* table entries for j-bit table */
1754 z = 1 << j; /* table entries for j-bit table */ 1779
1755 1780 /* allocate and link in new table */
1756 /* allocate and link in new table */ 1781 if (
1757 if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == 1782 (q =
1758 (struct huft *)NULL) 1783 (struct huft *) malloc((z + 1) *
1759 { 1784 sizeof(struct huft))) ==
1760 if (h) 1785 (struct huft *) NULL) {
1761 huft_free(u[0]); 1786 if (h)
1762 return 3; /* not enough memory */ 1787 huft_free(u[0]);
1763 } 1788 return 3; /* not enough memory */
1764 hufts += z + 1; /* track memory usage */ 1789 }
1765 *t = q + 1; /* link to list for huft_free() */ 1790 hufts += z + 1; /* track memory usage */
1766 *(t = &(q->v.t)) = (struct huft *)NULL; 1791 *t = q + 1; /* link to list for huft_free() */
1767 u[h] = ++q; /* table starts after link */ 1792 *(t = &(q->v.t)) = (struct huft *) NULL;
1768 1793 u[h] = ++q; /* table starts after link */
1769 /* connect to last table, if there is one */ 1794
1770 if (h) 1795 /* connect to last table, if there is one */
1771 { 1796 if (h) {
1772 x[h] = i; /* save pattern for backing up */ 1797 x[h] = i; /* save pattern for backing up */
1773 r.b = (uch)l; /* bits to dump before this table */ 1798 r.b = (uch) l; /* bits to dump before this table */
1774 r.e = (uch)(16 + j); /* bits in this table */ 1799 r.e = (uch) (16 + j); /* bits in this table */
1775 r.v.t = q; /* pointer to this table */ 1800 r.v.t = q; /* pointer to this table */
1776 j = i >> (w - l); /* (get around Turbo C bug) */ 1801 j = i >> (w - l); /* (get around Turbo C bug) */
1777 u[h-1][j] = r; /* connect to last table */ 1802 u[h - 1][j] = r; /* connect to last table */
1778 } 1803 }
1779 } 1804 }
1780 1805
1781 /* set up table entry in r */ 1806 /* set up table entry in r */
1782 r.b = (uch)(k - w); 1807 r.b = (uch) (k - w);
1783 if (p >= v + n) 1808 if (p >= v + n)
1784 r.e = 99; /* out of values--invalid code */ 1809 r.e = 99; /* out of values--invalid code */
1785 else if (*p < s) 1810 else if (*p < s) {
1786 { 1811 r.e = (uch) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1787 r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ 1812 r.v.n = (ush) (*p); /* simple code is just the value */
1788 r.v.n = (ush)(*p); /* simple code is just the value */ 1813 p++; /* one compiler does not like *p++ */
1789 p++; /* one compiler does not like *p++ */ 1814 } else {
1790 } 1815 r.e = (uch) e[*p - s]; /* non-simple--look up in lists */
1791 else 1816 r.v.n = d[*p++ - s];
1792 { 1817 }
1793 r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ 1818
1794 r.v.n = d[*p++ - s]; 1819 /* fill code-like entries with r */
1795 } 1820 f = 1 << (k - w);
1796 1821 for (j = i >> w; j < z; j += f)
1797 /* fill code-like entries with r */ 1822 q[j] = r;
1798 f = 1 << (k - w); 1823
1799 for (j = i >> w; j < z; j += f) 1824 /* backwards increment the k-bit code i */
1800 q[j] = r; 1825 for (j = 1 << (k - 1); i & j; j >>= 1)
1801 1826 i ^= j;
1802 /* backwards increment the k-bit code i */ 1827 i ^= j;
1803 for (j = 1 << (k - 1); i & j; j >>= 1) 1828
1804 i ^= j; 1829 /* backup over finished tables */
1805 i ^= j; 1830 while ((i & ((1 << w) - 1)) != x[h]) {
1806 1831 h--; /* don't need to update q */
1807 /* backup over finished tables */ 1832 w -= l;
1808 while ((i & ((1 << w) - 1)) != x[h]) 1833 }
1809 { 1834 }
1810 h--; /* don't need to update q */ 1835 }
1811 w -= l; 1836
1812 } 1837
1813 } 1838 /* Return true (1) if we were given an incomplete table */
1814 } 1839 return y != 0 && g != 1;
1815
1816
1817 /* Return true (1) if we were given an incomplete table */
1818 return y != 0 && g != 1;
1819} 1840}
1820 1841
1821 1842
1822 1843
1823int huft_free(t) 1844int huft_free(t)
1824struct huft *t; /* table to free */ 1845struct huft *t; /* table to free */
1846
1825/* Free the malloc'ed tables built by huft_build(), which makes a linked 1847/* Free the malloc'ed tables built by huft_build(), which makes a linked
1826 list of the tables it made, with the links in a dummy first entry of 1848 list of the tables it made, with the links in a dummy first entry of
1827 each table. */ 1849 each table. */
1828{ 1850{
1829 register struct huft *p, *q; 1851 register struct huft *p, *q;
1830 1852
1831 1853
1832 /* Go through linked list, freeing from the malloced (t[-1]) address. */ 1854 /* Go through linked list, freeing from the malloced (t[-1]) address. */
1833 p = t; 1855 p = t;
1834 while (p != (struct huft *)NULL) 1856 while (p != (struct huft *) NULL) {
1835 { 1857 q = (--p)->v.t;
1836 q = (--p)->v.t; 1858 free((char *) p);
1837 free((char*)p); 1859 p = q;
1838 p = q; 1860 }
1839 } 1861 return 0;
1840 return 0;
1841} 1862}
1842 1863
1843 1864
1844int inflate_codes(tl, td, bl, bd) 1865int inflate_codes(tl, td, bl, bd)
1845struct huft *tl, *td; /* literal/length and distance decoder tables */ 1866struct huft *tl, *td; /* literal/length and distance decoder tables */
1846int bl, bd; /* number of bits decoded by tl[] and td[] */ 1867int bl, bd; /* number of bits decoded by tl[] and td[] */
1868
1847/* inflate (decompress) the codes in a deflated (compressed) block. 1869/* inflate (decompress) the codes in a deflated (compressed) block.
1848 Return an error code or zero if it all goes ok. */ 1870 Return an error code or zero if it all goes ok. */
1849{ 1871{
1850 register unsigned e; /* table entry flag/number of extra bits */ 1872 register unsigned e; /* table entry flag/number of extra bits */
1851 unsigned n, d; /* length and index for copy */ 1873 unsigned n, d; /* length and index for copy */
1852 unsigned w; /* current window position */ 1874 unsigned w; /* current window position */
1853 struct huft *t; /* pointer to table entry */ 1875 struct huft *t; /* pointer to table entry */
1854 unsigned ml, md; /* masks for bl and bd bits */ 1876 unsigned ml, md; /* masks for bl and bd bits */
1855 register ulg b; /* bit buffer */ 1877 register ulg b; /* bit buffer */
1856 register unsigned k; /* number of bits in bit buffer */ 1878 register unsigned k; /* number of bits in bit buffer */
1857 1879
1858 1880
1859 /* make local copies of globals */ 1881 /* make local copies of globals */
1860 b = bb; /* initialize bit buffer */ 1882 b = bb; /* initialize bit buffer */
1861 k = bk; 1883 k = bk;
1862 w = wp; /* initialize window position */ 1884 w = wp; /* initialize window position */
1863 1885
1864 /* inflate the coded data */ 1886 /* inflate the coded data */
1865 ml = mask_bits[bl]; /* precompute masks for speed */ 1887 ml = mask_bits[bl]; /* precompute masks for speed */
1866 md = mask_bits[bd]; 1888 md = mask_bits[bd];
1867 for (;;) /* do until end of block */ 1889 for (;;) { /* do until end of block */
1868 { 1890 NEEDBITS((unsigned) bl)
1869 NEEDBITS((unsigned)bl) 1891 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
1870 if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) 1892 do {
1871 do { 1893 if (e == 99)
1872 if (e == 99) 1894 return 1;
1873 return 1; 1895 DUMPBITS(t->b)
1874 DUMPBITS(t->b) 1896 e -= 16;
1875 e -= 16; 1897 NEEDBITS(e)
1876 NEEDBITS(e) 1898 } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
1877 } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); 1899 > 16);
1878 DUMPBITS(t->b) 1900 DUMPBITS(t->b)
1879 if (e == 16) /* then it's a literal */ 1901 if (e == 16) { /* then it's a literal */
1880 { 1902 slide[w++] = (uch) t->v.n;
1881 slide[w++] = (uch)t->v.n; 1903 Tracevv((stderr, "%c", slide[w - 1]));
1882 Tracevv((stderr, "%c", slide[w-1])); 1904 if (w == WSIZE) {
1883 if (w == WSIZE) 1905 flush_output(w);
1884 { 1906 w = 0;
1885 flush_output(w); 1907 }
1886 w = 0; 1908 } else { /* it's an EOB or a length */
1887 } 1909
1888 } 1910 /* exit if end of block */
1889 else /* it's an EOB or a length */ 1911 if (e == 15)
1890 { 1912 break;
1891 /* exit if end of block */ 1913
1892 if (e == 15) 1914 /* get length of block to copy */
1893 break; 1915 NEEDBITS(e)
1894 1916 n = t->v.n + ((unsigned) b & mask_bits[e]);
1895 /* get length of block to copy */ 1917 DUMPBITS(e);
1896 NEEDBITS(e) 1918
1897 n = t->v.n + ((unsigned)b & mask_bits[e]); 1919 /* decode distance of block to copy */
1898 DUMPBITS(e); 1920 NEEDBITS((unsigned) bd)
1899 1921 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
1900 /* decode distance of block to copy */ 1922 do {
1901 NEEDBITS((unsigned)bd) 1923 if (e == 99)
1902 if ((e = (t = td + ((unsigned)b & md))->e) > 16) 1924 return 1;
1903 do { 1925 DUMPBITS(t->b)
1904 if (e == 99) 1926 e -= 16;
1905 return 1; 1927 NEEDBITS(e)
1906 DUMPBITS(t->b) 1928 }
1907 e -= 16; 1929 while (
1908 NEEDBITS(e) 1930 (e =
1909 } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); 1931 (t =
1910 DUMPBITS(t->b) 1932 t->v.t + ((unsigned) b & mask_bits[e]))->e) >
1911 NEEDBITS(e) 1933 16);
1912 d = w - t->v.n - ((unsigned)b & mask_bits[e]); 1934 DUMPBITS(t->b)
1913 DUMPBITS(e) 1935 NEEDBITS(e)
1914 Tracevv((stderr,"\\[%d,%d]", w-d, n)); 1936 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
1915 1937 DUMPBITS(e)
1916 /* do the copy */ 1938 Tracevv((stderr, "\\[%d,%d]", w - d, n));
1917 do { 1939
1918 n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); 1940 /* do the copy */
1941 do {
1942 n -= (e =
1943 (e =
1944 WSIZE - ((d &= WSIZE - 1) > w ? d : w)) >
1945 n ? n : e);
1919#if !defined(NOMEMCPY) && !defined(DEBUG) 1946#if !defined(NOMEMCPY) && !defined(DEBUG)
1920 if (w - d >= e) /* (this test assumes unsigned comparison) */ 1947 if (w - d >= e) { /* (this test assumes unsigned comparison) */
1921 { 1948 memcpy(slide + w, slide + d, e);
1922 memcpy(slide + w, slide + d, e); 1949 w += e;
1923 w += e; 1950 d += e;
1924 d += e; 1951 } else /* do it slow to avoid memcpy() overlap */
1925 } 1952#endif /* !NOMEMCPY */
1926 else /* do it slow to avoid memcpy() overlap */ 1953 do {
1927#endif /* !NOMEMCPY */ 1954 slide[w++] = slide[d++];
1928 do { 1955 Tracevv((stderr, "%c", slide[w - 1]));
1929 slide[w++] = slide[d++]; 1956 } while (--e);
1930 Tracevv((stderr, "%c", slide[w-1])); 1957 if (w == WSIZE) {
1931 } while (--e); 1958 flush_output(w);
1932 if (w == WSIZE) 1959 w = 0;
1933 { 1960 }
1934 flush_output(w); 1961 } while (n);
1935 w = 0; 1962 }
1936 } 1963 }
1937 } while (n); 1964
1938 } 1965
1939 } 1966 /* restore the globals from the locals */
1940 1967 wp = w; /* restore global window pointer */
1941 1968 bb = b; /* restore global bit buffer */
1942 /* restore the globals from the locals */ 1969 bk = k;
1943 wp = w; /* restore global window pointer */ 1970
1944 bb = b; /* restore global bit buffer */ 1971 /* done */
1945 bk = k; 1972 return 0;
1946
1947 /* done */
1948 return 0;
1949} 1973}
1950 1974
1951 1975
@@ -1953,52 +1977,50 @@ int bl, bd; /* number of bits decoded by tl[] and td[] */
1953int inflate_stored() 1977int inflate_stored()
1954/* "decompress" an inflated type 0 (stored) block. */ 1978/* "decompress" an inflated type 0 (stored) block. */
1955{ 1979{
1956 unsigned n; /* number of bytes in block */ 1980 unsigned n; /* number of bytes in block */
1957 unsigned w; /* current window position */ 1981 unsigned w; /* current window position */
1958 register ulg b; /* bit buffer */ 1982 register ulg b; /* bit buffer */
1959 register unsigned k; /* number of bits in bit buffer */ 1983 register unsigned k; /* number of bits in bit buffer */
1960 1984
1961 1985
1962 /* make local copies of globals */ 1986 /* make local copies of globals */
1963 b = bb; /* initialize bit buffer */ 1987 b = bb; /* initialize bit buffer */
1964 k = bk; 1988 k = bk;
1965 w = wp; /* initialize window position */ 1989 w = wp; /* initialize window position */
1966 1990
1967 1991
1968 /* go to byte boundary */ 1992 /* go to byte boundary */
1969 n = k & 7; 1993 n = k & 7;
1970 DUMPBITS(n); 1994 DUMPBITS(n);
1971 1995
1972 1996
1973 /* get the length and its complement */ 1997 /* get the length and its complement */
1974 NEEDBITS(16) 1998 NEEDBITS(16)
1975 n = ((unsigned)b & 0xffff); 1999 n = ((unsigned) b & 0xffff);
1976 DUMPBITS(16) 2000 DUMPBITS(16)
1977 NEEDBITS(16) 2001 NEEDBITS(16)
1978 if (n != (unsigned)((~b) & 0xffff)) 2002 if (n != (unsigned) ((~b) & 0xffff))
1979 return 1; /* error in compressed data */ 2003 return 1; /* error in compressed data */
1980 DUMPBITS(16) 2004 DUMPBITS(16)
1981 2005
1982 2006
1983 /* read and output the compressed data */ 2007 /* read and output the compressed data */
1984 while (n--) 2008 while (n--) {
1985 { 2009 NEEDBITS(8)
1986 NEEDBITS(8) 2010 slide[w++] = (uch) b;
1987 slide[w++] = (uch)b; 2011 if (w == WSIZE) {
1988 if (w == WSIZE) 2012 flush_output(w);
1989 { 2013 w = 0;
1990 flush_output(w); 2014 }
1991 w = 0; 2015 DUMPBITS(8)
1992 } 2016 }
1993 DUMPBITS(8) 2017
1994 } 2018
1995 2019 /* restore the globals from the locals */
1996 2020 wp = w; /* restore global window pointer */
1997 /* restore the globals from the locals */ 2021 bb = b; /* restore global bit buffer */
1998 wp = w; /* restore global window pointer */ 2022 bk = k;
1999 bb = b; /* restore global bit buffer */ 2023 return 0;
2000 bk = k;
2001 return 0;
2002} 2024}
2003 2025
2004 2026
@@ -2008,48 +2030,47 @@ int inflate_fixed()
2008 either replace this with a custom decoder, or at least precompute the 2030 either replace this with a custom decoder, or at least precompute the
2009 Huffman tables. */ 2031 Huffman tables. */
2010{ 2032{
2011 int i; /* temporary variable */ 2033 int i; /* temporary variable */
2012 struct huft *tl; /* literal/length code table */ 2034 struct huft *tl; /* literal/length code table */
2013 struct huft *td; /* distance code table */ 2035 struct huft *td; /* distance code table */
2014 int bl; /* lookup bits for tl */ 2036 int bl; /* lookup bits for tl */
2015 int bd; /* lookup bits for td */ 2037 int bd; /* lookup bits for td */
2016 unsigned l[288]; /* length list for huft_build */ 2038 unsigned l[288]; /* length list for huft_build */
2017 2039
2018 2040
2019 /* set up literal table */ 2041 /* set up literal table */
2020 for (i = 0; i < 144; i++) 2042 for (i = 0; i < 144; i++)
2021 l[i] = 8; 2043 l[i] = 8;
2022 for (; i < 256; i++) 2044 for (; i < 256; i++)
2023 l[i] = 9; 2045 l[i] = 9;
2024 for (; i < 280; i++) 2046 for (; i < 280; i++)
2025 l[i] = 7; 2047 l[i] = 7;
2026 for (; i < 288; i++) /* make a complete, but wrong code set */ 2048 for (; i < 288; i++) /* make a complete, but wrong code set */
2027 l[i] = 8; 2049 l[i] = 8;
2028 bl = 7; 2050 bl = 7;
2029 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) 2051 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
2030 return i; 2052 return i;
2031 2053
2032 2054
2033 /* set up distance table */ 2055 /* set up distance table */
2034 for (i = 0; i < 30; i++) /* make an incomplete code set */ 2056 for (i = 0; i < 30; i++) /* make an incomplete code set */
2035 l[i] = 5; 2057 l[i] = 5;
2036 bd = 5; 2058 bd = 5;
2037 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) 2059 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
2038 { 2060 huft_free(tl);
2039 huft_free(tl); 2061 return i;
2040 return i; 2062 }
2041 } 2063
2042 2064
2043 2065 /* decompress until an end-of-block code */
2044 /* decompress until an end-of-block code */ 2066 if (inflate_codes(tl, td, bl, bd))
2045 if (inflate_codes(tl, td, bl, bd)) 2067 return 1;
2046 return 1; 2068
2047 2069
2048 2070 /* free the decoding tables, return */
2049 /* free the decoding tables, return */ 2071 huft_free(tl);
2050 huft_free(tl); 2072 huft_free(td);
2051 huft_free(td); 2073 return 0;
2052 return 0;
2053} 2074}
2054 2075
2055 2076
@@ -2057,209 +2078,202 @@ int inflate_fixed()
2057int inflate_dynamic() 2078int inflate_dynamic()
2058/* decompress an inflated type 2 (dynamic Huffman codes) block. */ 2079/* decompress an inflated type 2 (dynamic Huffman codes) block. */
2059{ 2080{
2060 int i; /* temporary variables */ 2081 int i; /* temporary variables */
2061 unsigned j; 2082 unsigned j;
2062 unsigned l; /* last length */ 2083 unsigned l; /* last length */
2063 unsigned m; /* mask for bit lengths table */ 2084 unsigned m; /* mask for bit lengths table */
2064 unsigned n; /* number of lengths to get */ 2085 unsigned n; /* number of lengths to get */
2065 struct huft *tl; /* literal/length code table */ 2086 struct huft *tl; /* literal/length code table */
2066 struct huft *td; /* distance code table */ 2087 struct huft *td; /* distance code table */
2067 int bl; /* lookup bits for tl */ 2088 int bl; /* lookup bits for tl */
2068 int bd; /* lookup bits for td */ 2089 int bd; /* lookup bits for td */
2069 unsigned nb; /* number of bit length codes */ 2090 unsigned nb; /* number of bit length codes */
2070 unsigned nl; /* number of literal/length codes */ 2091 unsigned nl; /* number of literal/length codes */
2071 unsigned nd; /* number of distance codes */ 2092 unsigned nd; /* number of distance codes */
2093
2072#ifdef PKZIP_BUG_WORKAROUND 2094#ifdef PKZIP_BUG_WORKAROUND
2073 unsigned ll[288+32]; /* literal/length and distance code lengths */ 2095 unsigned ll[288 + 32]; /* literal/length and distance code lengths */
2074#else 2096#else
2075 unsigned ll[286+30]; /* literal/length and distance code lengths */ 2097 unsigned ll[286 + 30]; /* literal/length and distance code lengths */
2076#endif 2098#endif
2077 register ulg b; /* bit buffer */ 2099 register ulg b; /* bit buffer */
2078 register unsigned k; /* number of bits in bit buffer */ 2100 register unsigned k; /* number of bits in bit buffer */
2079 2101
2080 2102
2081 /* make local bit buffer */ 2103 /* make local bit buffer */
2082 b = bb; 2104 b = bb;
2083 k = bk; 2105 k = bk;
2084 2106
2085 2107
2086 /* read in table lengths */ 2108 /* read in table lengths */
2087 NEEDBITS(5) 2109 NEEDBITS(5)
2088 nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ 2110 nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */
2089 DUMPBITS(5) 2111 DUMPBITS(5)
2090 NEEDBITS(5) 2112 NEEDBITS(5)
2091 nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ 2113 nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */
2092 DUMPBITS(5) 2114 DUMPBITS(5)
2093 NEEDBITS(4) 2115 NEEDBITS(4)
2094 nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ 2116 nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */
2095 DUMPBITS(4) 2117 DUMPBITS(4)
2096#ifdef PKZIP_BUG_WORKAROUND 2118#ifdef PKZIP_BUG_WORKAROUND
2097 if (nl > 288 || nd > 32) 2119 if (nl > 288 || nd > 32)
2098#else 2120#else
2099 if (nl > 286 || nd > 30) 2121 if (nl > 286 || nd > 30)
2100#endif 2122#endif
2101 return 1; /* bad lengths */ 2123 return 1; /* bad lengths */
2102 2124
2103 2125
2104 /* read in bit-length-code lengths */ 2126 /* read in bit-length-code lengths */
2105 for (j = 0; j < nb; j++) 2127 for (j = 0; j < nb; j++) {
2106 { 2128 NEEDBITS(3)
2107 NEEDBITS(3) 2129 ll[border[j]] = (unsigned) b & 7;
2108 ll[border[j]] = (unsigned)b & 7; 2130 DUMPBITS(3)
2109 DUMPBITS(3) 2131 }
2110 } 2132 for (; j < 19; j++)
2111 for (; j < 19; j++) 2133 ll[border[j]] = 0;
2112 ll[border[j]] = 0; 2134
2113 2135
2114 2136 /* build decoding table for trees--single level, 7 bit lookup */
2115 /* build decoding table for trees--single level, 7 bit lookup */ 2137 bl = 7;
2116 bl = 7; 2138 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) {
2117 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) 2139 if (i == 1)
2118 { 2140 huft_free(tl);
2119 if (i == 1) 2141 return i; /* incomplete code set */
2120 huft_free(tl); 2142 }
2121 return i; /* incomplete code set */ 2143
2122 } 2144
2123 2145 /* read in literal and distance code lengths */
2124 2146 n = nl + nd;
2125 /* read in literal and distance code lengths */ 2147 m = mask_bits[bl];
2126 n = nl + nd; 2148 i = l = 0;
2127 m = mask_bits[bl]; 2149 while ((unsigned) i < n) {
2128 i = l = 0; 2150 NEEDBITS((unsigned) bl)
2129 while ((unsigned)i < n) 2151 j = (td = tl + ((unsigned) b & m))->b;
2130 { 2152 DUMPBITS(j)
2131 NEEDBITS((unsigned)bl) 2153 j = td->v.n;
2132 j = (td = tl + ((unsigned)b & m))->b; 2154 if (j < 16) /* length of code in bits (0..15) */
2133 DUMPBITS(j) 2155 ll[i++] = l = j; /* save last length in l */
2134 j = td->v.n; 2156 else if (j == 16) { /* repeat last length 3 to 6 times */
2135 if (j < 16) /* length of code in bits (0..15) */ 2157 NEEDBITS(2)
2136 ll[i++] = l = j; /* save last length in l */ 2158 j = 3 + ((unsigned) b & 3);
2137 else if (j == 16) /* repeat last length 3 to 6 times */ 2159 DUMPBITS(2)
2138 { 2160 if ((unsigned) i + j > n)
2139 NEEDBITS(2) 2161 return 1;
2140 j = 3 + ((unsigned)b & 3); 2162 while (j--)
2141 DUMPBITS(2) 2163 ll[i++] = l;
2142 if ((unsigned)i + j > n) 2164 } else if (j == 17) { /* 3 to 10 zero length codes */
2143 return 1; 2165 NEEDBITS(3)
2144 while (j--) 2166 j = 3 + ((unsigned) b & 7);
2145 ll[i++] = l; 2167 DUMPBITS(3)
2146 } 2168 if ((unsigned) i + j > n)
2147 else if (j == 17) /* 3 to 10 zero length codes */ 2169 return 1;
2148 { 2170 while (j--)
2149 NEEDBITS(3) 2171 ll[i++] = 0;
2150 j = 3 + ((unsigned)b & 7); 2172 l = 0;
2151 DUMPBITS(3) 2173 } else { /* j == 18: 11 to 138 zero length codes */
2152 if ((unsigned)i + j > n) 2174
2153 return 1; 2175 NEEDBITS(7)
2154 while (j--) 2176 j = 11 + ((unsigned) b & 0x7f);
2155 ll[i++] = 0; 2177 DUMPBITS(7)
2156 l = 0; 2178 if ((unsigned) i + j > n)
2157 } 2179 return 1;
2158 else /* j == 18: 11 to 138 zero length codes */ 2180 while (j--)
2159 { 2181 ll[i++] = 0;
2160 NEEDBITS(7) 2182 l = 0;
2161 j = 11 + ((unsigned)b & 0x7f); 2183 }
2162 DUMPBITS(7) 2184 }
2163 if ((unsigned)i + j > n) 2185
2164 return 1; 2186
2165 while (j--) 2187 /* free decoding table for trees */
2166 ll[i++] = 0; 2188 huft_free(tl);
2167 l = 0; 2189
2168 } 2190
2169 } 2191 /* restore the global bit buffer */
2170 2192 bb = b;
2171 2193 bk = k;
2172 /* free decoding table for trees */ 2194
2173 huft_free(tl); 2195
2174 2196 /* build the decoding tables for literal/length and distance codes */
2175 2197 bl = lbits;
2176 /* restore the global bit buffer */ 2198 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
2177 bb = b; 2199 if (i == 1) {
2178 bk = k; 2200 fprintf(stderr, " incomplete literal tree\n");
2179 2201 huft_free(tl);
2180 2202 }
2181 /* build the decoding tables for literal/length and distance codes */ 2203 return i; /* incomplete code set */
2182 bl = lbits; 2204 }
2183 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) 2205 bd = dbits;
2184 { 2206 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
2185 if (i == 1) { 2207 if (i == 1) {
2186 fprintf(stderr, " incomplete literal tree\n"); 2208 fprintf(stderr, " incomplete distance tree\n");
2187 huft_free(tl);
2188 }
2189 return i; /* incomplete code set */
2190 }
2191 bd = dbits;
2192 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
2193 {
2194 if (i == 1) {
2195 fprintf(stderr, " incomplete distance tree\n");
2196#ifdef PKZIP_BUG_WORKAROUND 2209#ifdef PKZIP_BUG_WORKAROUND
2197 i = 0; 2210 i = 0;
2198 } 2211 }
2199#else 2212#else
2200 huft_free(td); 2213 huft_free(td);
2201 } 2214 }
2202 huft_free(tl); 2215 huft_free(tl);
2203 return i; /* incomplete code set */ 2216 return i; /* incomplete code set */
2204#endif 2217#endif
2205 } 2218 }
2206 2219
2207 2220
2208 /* decompress until an end-of-block code */ 2221 /* decompress until an end-of-block code */
2209 if (inflate_codes(tl, td, bl, bd)) 2222 if (inflate_codes(tl, td, bl, bd))
2210 return 1; 2223 return 1;
2211 2224
2212 2225
2213 /* free the decoding tables, return */ 2226 /* free the decoding tables, return */
2214 huft_free(tl); 2227 huft_free(tl);
2215 huft_free(td); 2228 huft_free(td);
2216 return 0; 2229 return 0;
2217} 2230}
2218 2231
2219 2232
2220 2233
2221int inflate_block(e) 2234int inflate_block(e)
2222int *e; /* last block flag */ 2235int *e; /* last block flag */
2236
2223/* decompress an inflated block */ 2237/* decompress an inflated block */
2224{ 2238{
2225 unsigned t; /* block type */ 2239 unsigned t; /* block type */
2226 register ulg b; /* bit buffer */ 2240 register ulg b; /* bit buffer */
2227 register unsigned k; /* number of bits in bit buffer */ 2241 register unsigned k; /* number of bits in bit buffer */
2228 2242
2229 2243
2230 /* make local bit buffer */ 2244 /* make local bit buffer */
2231 b = bb; 2245 b = bb;
2232 k = bk; 2246 k = bk;
2233 2247
2234 2248
2235 /* read in last block bit */ 2249 /* read in last block bit */
2236 NEEDBITS(1) 2250 NEEDBITS(1)
2237 *e = (int)b & 1; 2251 * e = (int) b & 1;
2238 DUMPBITS(1) 2252 DUMPBITS(1)
2239 2253
2240 2254
2241 /* read in block type */ 2255 /* read in block type */
2242 NEEDBITS(2) 2256 NEEDBITS(2)
2243 t = (unsigned)b & 3; 2257 t = (unsigned) b & 3;
2244 DUMPBITS(2) 2258 DUMPBITS(2)
2245 2259
2246 2260
2247 /* restore the global bit buffer */ 2261 /* restore the global bit buffer */
2248 bb = b; 2262 bb = b;
2249 bk = k; 2263 bk = k;
2250 2264
2251 2265
2252 /* inflate that block type */ 2266 /* inflate that block type */
2253 if (t == 2) 2267 if (t == 2)
2254 return inflate_dynamic(); 2268 return inflate_dynamic();
2255 if (t == 0) 2269 if (t == 0)
2256 return inflate_stored(); 2270 return inflate_stored();
2257 if (t == 1) 2271 if (t == 1)
2258 return inflate_fixed(); 2272 return inflate_fixed();
2259 2273
2260 2274
2261 /* bad block type */ 2275 /* bad block type */
2262 return 2; 2276 return 2;
2263} 2277}
2264 2278
2265 2279
@@ -2267,42 +2281,42 @@ int *e; /* last block flag */
2267int inflate() 2281int inflate()
2268/* decompress an inflated entry */ 2282/* decompress an inflated entry */
2269{ 2283{
2270 int e; /* last block flag */ 2284 int e; /* last block flag */
2271 int r; /* result code */ 2285 int r; /* result code */
2272 unsigned h; /* maximum struct huft's malloc'ed */ 2286 unsigned h; /* maximum struct huft's malloc'ed */
2273 2287
2274 2288
2275 /* initialize window, bit buffer */ 2289 /* initialize window, bit buffer */
2276 wp = 0; 2290 wp = 0;
2277 bk = 0; 2291 bk = 0;
2278 bb = 0; 2292 bb = 0;
2279 2293
2280 2294
2281 /* decompress until the last block */ 2295 /* decompress until the last block */
2282 h = 0; 2296 h = 0;
2283 do { 2297 do {
2284 hufts = 0; 2298 hufts = 0;
2285 if ((r = inflate_block(&e)) != 0) 2299 if ((r = inflate_block(&e)) != 0)
2286 return r; 2300 return r;
2287 if (hufts > h) 2301 if (hufts > h)
2288 h = hufts; 2302 h = hufts;
2289 } while (!e); 2303 } while (!e);
2290 2304
2291 /* Undo too much lookahead. The next read will be byte aligned so we 2305 /* Undo too much lookahead. The next read will be byte aligned so we
2292 * can discard unused bits in the last meaningful byte. 2306 * can discard unused bits in the last meaningful byte.
2293 */ 2307 */
2294 while (bk >= 8) { 2308 while (bk >= 8) {
2295 bk -= 8; 2309 bk -= 8;
2296 inptr--; 2310 inptr--;
2297 } 2311 }
2298 2312
2299 /* flush out slide */ 2313 /* flush out slide */
2300 flush_output(wp); 2314 flush_output(wp);
2301 2315
2302 2316
2303 /* return success */ 2317 /* return success */
2304#ifdef DEBUG 2318#ifdef DEBUG
2305 fprintf(stderr, "<%u> ", h); 2319 fprintf(stderr, "<%u> ", h);
2306#endif /* DEBUG */ 2320#endif /* DEBUG */
2307 return 0; 2321 return 0;
2308} 2322}
diff --git a/archival/gzip.c b/archival/gzip.c
index 3438ee42f..f132679f7 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* gzip.c -- this is a stripped down version of gzip I put into busybox, it does 2/* gzip.c -- this is a stripped down version of gzip I put into busybox, it does
2 * only standard in to standard out with -9 compression. It also requires the 3 * only standard in to standard out with -9 compression. It also requires the
3 * zcat module for some important functions. 4 * zcat module for some important functions.
@@ -12,11 +13,12 @@
12//#endif 13//#endif
13 14
14static const char gzip_usage[] = 15static const char gzip_usage[] =
15 "gzip [OPTION]... FILE\n\n" 16 "gzip [OPTION]... FILE\n\n"
16 "Compress FILE with maximum compression.\n" 17 "Compress FILE with maximum compression.\n"
17 "When FILE is -, reads standard input. Implies -c.\n\n" 18 "When FILE is -, reads standard input. Implies -c.\n\n"
18 "Options:\n" 19
19 "\t-c\tWrite output to standard output instead of FILE.gz\n"; 20 "Options:\n"
21 "\t-c\tWrite output to standard output instead of FILE.gz\n";
20 22
21 23
22/* gzip.h -- common declarations for all gzip modules 24/* gzip.h -- common declarations for all gzip modules
@@ -32,9 +34,9 @@ static const char gzip_usage[] =
32#endif 34#endif
33 35
34#ifdef __STDC__ 36#ifdef __STDC__
35 typedef void *voidp; 37typedef void *voidp;
36#else 38#else
37 typedef char *voidp; 39typedef char *voidp;
38#endif 40#endif
39 41
40/* I don't like nested includes, but the string and io functions are used 42/* I don't like nested includes, but the string and io functions are used
@@ -49,10 +51,10 @@ static const char gzip_usage[] =
49# define memzero(s, n) memset ((voidp)(s), 0, (n)) 51# define memzero(s, n) memset ((voidp)(s), 0, (n))
50#else 52#else
51# include <strings.h> 53# include <strings.h>
52# define strchr index 54# define strchr index
53# define strrchr rindex 55# define strrchr rindex
54# define memcpy(d, s, n) bcopy((s), (d), (n)) 56# define memcpy(d, s, n) bcopy((s), (d), (n))
55# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 57# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
56# define memzero(s, n) bzero((s), (n)) 58# define memzero(s, n) bzero((s), (n))
57#endif 59#endif
58 60
@@ -62,9 +64,9 @@ static const char gzip_usage[] =
62 64
63#define local static 65#define local static
64 66
65typedef unsigned char uch; 67typedef unsigned char uch;
66typedef unsigned short ush; 68typedef unsigned short ush;
67typedef unsigned long ulg; 69typedef unsigned long ulg;
68 70
69/* Return codes from gzip */ 71/* Return codes from gzip */
70#define OK 0 72#define OK 0
@@ -79,7 +81,7 @@ typedef unsigned long ulg;
79/* methods 4 to 7 reserved */ 81/* methods 4 to 7 reserved */
80#define DEFLATED 8 82#define DEFLATED 8
81#define MAX_METHODS 9 83#define MAX_METHODS 9
82extern int method; /* compression method */ 84extern int method; /* compression method */
83 85
84/* To save memory for 16 bit systems, some arrays are overlaid between 86/* To save memory for 16 bit systems, some arrays are overlaid between
85 * the various modules: 87 * the various modules:
@@ -94,27 +96,27 @@ extern int method; /* compression method */
94 96
95#ifndef INBUFSIZ 97#ifndef INBUFSIZ
96# ifdef SMALL_MEM 98# ifdef SMALL_MEM
97# define INBUFSIZ 0x2000 /* input buffer size */ 99# define INBUFSIZ 0x2000 /* input buffer size */
98# else 100# else
99# define INBUFSIZ 0x8000 /* input buffer size */ 101# define INBUFSIZ 0x8000 /* input buffer size */
100# endif 102# endif
101#endif 103#endif
102#define INBUF_EXTRA 64 /* required by unlzw() */ 104#define INBUF_EXTRA 64 /* required by unlzw() */
103 105
104#ifndef OUTBUFSIZ 106#ifndef OUTBUFSIZ
105# ifdef SMALL_MEM 107# ifdef SMALL_MEM
106# define OUTBUFSIZ 8192 /* output buffer size */ 108# define OUTBUFSIZ 8192 /* output buffer size */
107# else 109# else
108# define OUTBUFSIZ 16384 /* output buffer size */ 110# define OUTBUFSIZ 16384 /* output buffer size */
109# endif 111# endif
110#endif 112#endif
111#define OUTBUF_EXTRA 2048 /* required by unlzw() */ 113#define OUTBUF_EXTRA 2048 /* required by unlzw() */
112 114
113#ifndef DIST_BUFSIZE 115#ifndef DIST_BUFSIZE
114# ifdef SMALL_MEM 116# ifdef SMALL_MEM
115# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ 117# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
116# else 118# else
117# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ 119# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
118# endif 120# endif
119#endif 121#endif
120 122
@@ -133,60 +135,61 @@ extern int method; /* compression method */
133# define FREE(array) 135# define FREE(array)
134#endif 136#endif
135 137
136EXTERN(uch, inbuf); /* input buffer */ 138EXTERN(uch, inbuf); /* input buffer */
137EXTERN(uch, outbuf); /* output buffer */ 139EXTERN(uch, outbuf); /* output buffer */
138EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ 140EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
139EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ 141EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
140#define tab_suffix window 142#define tab_suffix window
141#ifndef MAXSEG_64K 143#ifndef MAXSEG_64K
142# define tab_prefix prev /* hash link (see deflate.c) */ 144# define tab_prefix prev /* hash link (see deflate.c) */
143# define head (prev+WSIZE) /* hash head (see deflate.c) */ 145# define head (prev+WSIZE) /* hash head (see deflate.c) */
144 EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ 146EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
145#else 147#else
146# define tab_prefix0 prev 148# define tab_prefix0 prev
147# define head tab_prefix1 149# define head tab_prefix1
148 EXTERN(ush, tab_prefix0); /* prefix for even codes */ 150EXTERN(ush, tab_prefix0); /* prefix for even codes */
149 EXTERN(ush, tab_prefix1); /* prefix for odd codes */ 151EXTERN(ush, tab_prefix1); /* prefix for odd codes */
150#endif 152#endif
151 153
152extern unsigned insize; /* valid bytes in inbuf */ 154extern unsigned insize; /* valid bytes in inbuf */
153extern unsigned inptr; /* index of next byte to be processed in inbuf */ 155extern unsigned inptr; /* index of next byte to be processed in inbuf */
154extern unsigned outcnt; /* bytes in output buffer */ 156extern unsigned outcnt; /* bytes in output buffer */
155 157
156extern long bytes_in; /* number of input bytes */ 158extern long bytes_in; /* number of input bytes */
157extern long bytes_out; /* number of output bytes */ 159extern long bytes_out; /* number of output bytes */
158extern long header_bytes;/* number of bytes in gzip header */ 160extern long header_bytes; /* number of bytes in gzip header */
159 161
160#define isize bytes_in 162#define isize bytes_in
161/* for compatibility with old zip sources (to be cleaned) */ 163/* for compatibility with old zip sources (to be cleaned) */
162 164
163extern int ifd; /* input file descriptor */ 165extern int ifd; /* input file descriptor */
164extern int ofd; /* output file descriptor */ 166extern int ofd; /* output file descriptor */
165extern char ifname[]; /* input file name or "stdin" */ 167extern char ifname[]; /* input file name or "stdin" */
166extern char ofname[]; /* output file name or "stdout" */ 168extern char ofname[]; /* output file name or "stdout" */
167extern char *progname; /* program name */ 169extern char *progname; /* program name */
170
171extern long time_stamp; /* original time stamp (modification time) */
172extern long ifile_size; /* input file size, -1 for devices (debug only) */
168 173
169extern long time_stamp; /* original time stamp (modification time) */ 174typedef int file_t; /* Do not use stdio */
170extern long ifile_size; /* input file size, -1 for devices (debug only) */
171 175
172typedef int file_t; /* Do not use stdio */ 176#define NO_FILE (-1) /* in memory compression */
173#define NO_FILE (-1) /* in memory compression */
174 177
175 178
176#define PACK_MAGIC "\037\036" /* Magic header for packed files */ 179#define PACK_MAGIC "\037\036" /* Magic header for packed files */
177#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ 180#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
178#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ 181#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
179#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/ 182#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files */
180#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */ 183#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */
181 184
182/* gzip flag byte */ 185/* gzip flag byte */
183#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 186#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
184#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 187#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
185#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 188#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
186#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 189#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
187#define COMMENT 0x10 /* bit 4 set: file comment present */ 190#define COMMENT 0x10 /* bit 4 set: file comment present */
188#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 191#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
189#define RESERVED 0xC0 /* bit 6,7: reserved */ 192#define RESERVED 0xC0 /* bit 6,7: reserved */
190 193
191/* internal file attribute */ 194/* internal file attribute */
192#define UNKNOWN 0xffff 195#define UNKNOWN 0xffff
@@ -194,8 +197,8 @@ typedef int file_t; /* Do not use stdio */
194#define ASCII 1 197#define ASCII 1
195 198
196#ifndef WSIZE 199#ifndef WSIZE
197# define WSIZE 0x8000 /* window size--must be a power of two, and */ 200# define WSIZE 0x8000 /* window size--must be a power of two, and */
198#endif /* at least 32K for zip's deflate method */ 201#endif /* at least 32K for zip's deflate method */
199 202
200#define MIN_MATCH 3 203#define MIN_MATCH 3
201#define MAX_MATCH 258 204#define MAX_MATCH 258
@@ -211,12 +214,12 @@ typedef int file_t; /* Do not use stdio */
211 * distances are limited to MAX_DIST instead of WSIZE. 214 * distances are limited to MAX_DIST instead of WSIZE.
212 */ 215 */
213 216
214extern int decrypt; /* flag to turn on decryption */ 217extern int decrypt; /* flag to turn on decryption */
215extern int exit_code; /* program exit code */ 218extern int exit_code; /* program exit code */
216extern int verbose; /* be verbose (-v) */ 219extern int verbose; /* be verbose (-v) */
217extern int quiet; /* be quiet (-q) */ 220extern int quiet; /* be quiet (-q) */
218extern int test; /* check .z file integrity */ 221extern int test; /* check .z file integrity */
219extern int save_orig_name; /* set if original name must be saved */ 222extern int save_orig_name; /* set if original name must be saved */
220 223
221#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) 224#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
222#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) 225#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
@@ -248,10 +251,10 @@ extern int save_orig_name; /* set if original name must be saved */
248 put_short(((ulg)(n)) >> 16); \ 251 put_short(((ulg)(n)) >> 16); \
249} 252}
250 253
251#define seekable() 0 /* force sequential output */ 254#define seekable() 0 /* force sequential output */
252#define translate_eol 0 /* no option -a yet */ 255#define translate_eol 0 /* no option -a yet */
253 256
254#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ 257#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
255 258
256/* Macros for getting two-byte and four-byte header values */ 259/* Macros for getting two-byte and four-byte header values */
257#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) 260#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
@@ -281,57 +284,58 @@ extern int save_orig_name; /* set if original name must be saved */
281 284
282 285
283 /* in zip.c: */ 286 /* in zip.c: */
284extern int zip OF((int in, int out)); 287extern int zip OF((int in, int out));
285extern int file_read OF((char *buf, unsigned size)); 288extern int file_read OF((char *buf, unsigned size));
286 289
287 /* in unzip.c */ 290 /* in unzip.c */
288extern int unzip OF((int in, int out)); 291extern int unzip OF((int in, int out));
289extern int check_zipfile OF((int in)); 292extern int check_zipfile OF((int in));
290 293
291 /* in unpack.c */ 294 /* in unpack.c */
292extern int unpack OF((int in, int out)); 295extern int unpack OF((int in, int out));
293 296
294 /* in unlzh.c */ 297 /* in unlzh.c */
295extern int unlzh OF((int in, int out)); 298extern int unlzh OF((int in, int out));
296 299
297 /* in gzip.c */ 300 /* in gzip.c */
298RETSIGTYPE abort_gzip OF((void)); 301RETSIGTYPE abort_gzip OF((void));
299 302
300 /* in deflate.c */ 303 /* in deflate.c */
301void lm_init OF((ush *flags)); 304void lm_init OF((ush * flags));
302ulg deflate OF((void)); 305ulg deflate OF((void));
303 306
304 /* in trees.c */ 307 /* in trees.c */
305void ct_init OF((ush *attr, int *method)); 308void ct_init OF((ush * attr, int *method));
306int ct_tally OF((int dist, int lc)); 309int ct_tally OF((int dist, int lc));
307ulg flush_block OF((char *buf, ulg stored_len, int eof)); 310ulg flush_block OF((char *buf, ulg stored_len, int eof));
308 311
309 /* in bits.c */ 312 /* in bits.c */
310void bi_init OF((file_t zipfile)); 313void bi_init OF((file_t zipfile));
311void send_bits OF((int value, int length)); 314void send_bits OF((int value, int length));
312unsigned bi_reverse OF((unsigned value, int length)); 315unsigned bi_reverse OF((unsigned value, int length));
313void bi_windup OF((void)); 316void bi_windup OF((void));
314void copy_block OF((char *buf, unsigned len, int header)); 317void copy_block OF((char *buf, unsigned len, int header));
315extern int (*read_buf) OF((char *buf, unsigned size)); 318extern int (*read_buf) OF((char *buf, unsigned size));
316 319
317 /* in util.c: */ 320 /* in util.c: */
318extern int copy OF((int in, int out)); 321extern int copy OF((int in, int out));
319extern ulg updcrc OF((uch *s, unsigned n)); 322extern ulg updcrc OF((uch * s, unsigned n));
320extern void clear_bufs OF((void)); 323extern void clear_bufs OF((void));
321extern int fill_inbuf OF((int eof_ok)); 324extern int fill_inbuf OF((int eof_ok));
322extern void flush_outbuf OF((void)); 325extern void flush_outbuf OF((void));
323extern void flush_window OF((void)); 326extern void flush_window OF((void));
324extern void write_buf OF((int fd, voidp buf, unsigned cnt)); 327extern void write_buf OF((int fd, voidp buf, unsigned cnt));
325extern char *strlwr OF((char *s)); 328extern char *strlwr OF((char *s));
326extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); 329extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
327extern void error OF((char *m)); 330extern void error OF((char *m));
328extern void warn OF((char *a, char *b)); 331extern void warn OF((char *a, char *b));
329extern void read_error OF((void)); 332extern void read_error OF((void));
330extern void write_error OF((void)); 333extern void write_error OF((void));
331extern void display_ratio OF((long num, long den, FILE *file)); 334extern void display_ratio OF((long num, long den, FILE * file));
332 335
333 /* in inflate.c */ 336 /* in inflate.c */
334extern int inflate OF((void)); 337extern int inflate OF((void));
338
335/* lzw.h -- define the lzw functions. 339/* lzw.h -- define the lzw functions.
336 * Copyright (C) 1992-1993 Jean-loup Gailly. 340 * Copyright (C) 1992-1993 Jean-loup Gailly.
337 * This is free software; you can redistribute it and/or modify it under the 341 * This is free software; you can redistribute it and/or modify it under the
@@ -345,9 +349,9 @@ extern int inflate OF((void));
345#ifndef BITS 349#ifndef BITS
346# define BITS 16 350# define BITS 16
347#endif 351#endif
348#define INIT_BITS 9 /* Initial number of bits per code */ 352#define INIT_BITS 9 /* Initial number of bits per code */
349 353
350#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ 354#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
351/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. 355/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
352 * It's a pity that old uncompress does not check bit 0x20. That makes 356 * It's a pity that old uncompress does not check bit 0x20. That makes
353 * extension of the format actually undesirable because old compress 357 * extension of the format actually undesirable because old compress
@@ -362,13 +366,13 @@ extern int inflate OF((void));
362 * clear the dictionary. 366 * clear the dictionary.
363 */ 367 */
364 368
365#define LZW_RESERVED 0x60 /* reserved bits */ 369#define LZW_RESERVED 0x60 /* reserved bits */
366 370
367#define CLEAR 256 /* flush the dictionary */ 371#define CLEAR 256 /* flush the dictionary */
368#define FIRST (CLEAR+1) /* first free entry */ 372#define FIRST (CLEAR+1) /* first free entry */
369 373
370extern int maxbits; /* max bits per code for LZW */ 374extern int maxbits; /* max bits per code for LZW */
371extern int block_mode; /* block compress mode -C compatible with 2.0 */ 375extern int block_mode; /* block compress mode -C compatible with 2.0 */
372 376
373/* revision.h -- define the version number 377/* revision.h -- define the version number
374 * Copyright (C) 1992-1993 Jean-loup Gailly. 378 * Copyright (C) 1992-1993 Jean-loup Gailly.
@@ -404,18 +408,18 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
404# define OS2 408# define OS2
405#endif 409#endif
406 410
407#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */ 411#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
408# undef MSDOS 412# undef MSDOS
409#endif 413#endif
410 414
411#ifdef MSDOS 415#ifdef MSDOS
412# ifdef __GNUC__ 416# ifdef __GNUC__
413 /* DJGPP version 1.09+ on MS-DOS. 417 /* DJGPP version 1.09+ on MS-DOS.
414 * The DJGPP 1.09 stat() function must be upgraded before gzip will 418 * The DJGPP 1.09 stat() function must be upgraded before gzip will
415 * fully work. 419 * fully work.
416 * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which 420 * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
417 * implies DIRENT. 421 * implies DIRENT.
418 */ 422 */
419# define near 423# define near
420# else 424# else
421# define MAXSEG_64K 425# define MAXSEG_64K
@@ -426,7 +430,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
426# else 430# else
427# define NO_UTIME 431# define NO_UTIME
428# endif 432# endif
429# else /* MSC */ 433# else /* MSC */
430# define HAVE_SYS_UTIME_H 434# define HAVE_SYS_UTIME_H
431# define NO_UTIME_H 435# define NO_UTIME_H
432# endif 436# endif
@@ -441,7 +445,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
441# define PROTO 445# define PROTO
442# define STDC_HEADERS 446# define STDC_HEADERS
443# define NO_SIZE_CHECK 447# define NO_SIZE_CHECK
444# define casemap(c) tolow(c) /* Force file names to lower case */ 448# define casemap(c) tolow(c) /* Force file names to lower case */
445# include <io.h> 449# include <io.h>
446# define OS_CODE 0x00 450# define OS_CODE 0x00
447# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) 451# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
@@ -494,7 +498,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
494# endif 498# endif
495#endif 499#endif
496 500
497#ifdef WIN32 /* Windows NT */ 501#ifdef WIN32 /* Windows NT */
498# define HAVE_SYS_UTIME_H 502# define HAVE_SYS_UTIME_H
499# define NO_UTIME_H 503# define NO_UTIME_H
500# define PATH_SEP2 '\\' 504# define PATH_SEP2 '\\'
@@ -510,7 +514,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
510# define NO_MULTIPLE_DOTS 514# define NO_MULTIPLE_DOTS
511# define MAX_EXT_CHARS 3 515# define MAX_EXT_CHARS 3
512# define Z_SUFFIX "z" 516# define Z_SUFFIX "z"
513# define casemap(c) tolow(c) /* Force file names to lower case */ 517# define casemap(c) tolow(c) /* Force file names to lower case */
514# endif 518# endif
515# define OS_CODE 0x0b 519# define OS_CODE 0x0b
516#endif 520#endif
@@ -519,10 +523,10 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
519# ifdef __TURBOC__ 523# ifdef __TURBOC__
520# include <alloc.h> 524# include <alloc.h>
521# define DYN_ALLOC 525# define DYN_ALLOC
522 /* Turbo C 2.0 does not accept static allocations of large arrays */ 526 /* Turbo C 2.0 does not accept static allocations of large arrays */
523 void * fcalloc (unsigned items, unsigned size); 527void *fcalloc(unsigned items, unsigned size);
524 void fcfree (void *ptr); 528void fcfree(void *ptr);
525# else /* MSC */ 529# else /* MSC */
526# include <malloc.h> 530# include <malloc.h>
527# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize)) 531# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
528# define fcfree(ptr) hfree(ptr) 532# define fcfree(ptr) hfree(ptr)
@@ -565,17 +569,18 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
565# ifdef __GNUC__ 569# ifdef __GNUC__
566# define DIRENT 570# define DIRENT
567# define HAVE_UNISTD_H 571# define HAVE_UNISTD_H
568# else /* SASC */ 572# else /* SASC */
569# define NO_STDIN_FSTAT 573# define NO_STDIN_FSTAT
570# define SYSDIR 574# define SYSDIR
571# define NO_SYMLINK 575# define NO_SYMLINK
572# define NO_CHOWN 576# define NO_CHOWN
573# define NO_FCNTL_H 577# define NO_FCNTL_H
574# include <fcntl.h> /* for read() and write() */ 578# include <fcntl.h> /* for read() and write() */
575# define direct dirent 579# define direct dirent
576 extern void _expand_args(int *argc, char ***argv); 580extern void _expand_args(int *argc, char ***argv);
581
577# define EXPAND(argc,argv) _expand_args(&argc,&argv); 582# define EXPAND(argc,argv) _expand_args(&argc,&argv);
578# undef O_BINARY /* disable useless --ascii option */ 583# undef O_BINARY /* disable useless --ascii option */
579# endif 584# endif
580#endif 585#endif
581 586
@@ -595,7 +600,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
595# define MAX_EXT_CHARS 3 600# define MAX_EXT_CHARS 3
596# define Z_SUFFIX "z" 601# define Z_SUFFIX "z"
597# define NO_CHOWN 602# define NO_CHOWN
598# define casemap(c) tolow(c) /* Force file names to lower case */ 603# define casemap(c) tolow(c) /* Force file names to lower case */
599# define NO_SYMLINK 604# define NO_SYMLINK
600# endif 605# endif
601#endif 606#endif
@@ -615,28 +620,28 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
615# endif 620# endif
616#endif 621#endif
617 622
618#ifdef __50SERIES /* Prime/PRIMOS */ 623#ifdef __50SERIES /* Prime/PRIMOS */
619# define PATH_SEP '>' 624# define PATH_SEP '>'
620# define STDC_HEADERS 625# define STDC_HEADERS
621# define NO_MEMORY_H 626# define NO_MEMORY_H
622# define NO_UTIME_H 627# define NO_UTIME_H
623# define NO_UTIME 628# define NO_UTIME
624# define NO_CHOWN 629# define NO_CHOWN
625# define NO_STDIN_FSTAT 630# define NO_STDIN_FSTAT
626# define NO_SIZE_CHECK 631# define NO_SIZE_CHECK
627# define NO_SYMLINK 632# define NO_SYMLINK
628# define RECORD_IO 1 633# define RECORD_IO 1
629# define casemap(c) tolow(c) /* Force file names to lower case */ 634# define casemap(c) tolow(c) /* Force file names to lower case */
630# define put_char(c) put_byte((c) & 0x7F) 635# define put_char(c) put_byte((c) & 0x7F)
631# define get_char(c) ascii2pascii(get_byte()) 636# define get_char(c) ascii2pascii(get_byte())
632# define OS_CODE 0x0F /* temporary, subject to change */ 637# define OS_CODE 0x0F /* temporary, subject to change */
633# ifdef SIGTERM 638# ifdef SIGTERM
634# undef SIGTERM /* We don't want a signal handler for SIGTERM */ 639# undef SIGTERM /* We don't want a signal handler for SIGTERM */
635# endif 640# endif
636#endif 641#endif
637 642
638#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */ 643#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */
639# define NOMEMCPY /* problem with overlapping copies */ 644# define NOMEMCPY /* problem with overlapping copies */
640#endif 645#endif
641 646
642#ifdef TOPS20 647#ifdef TOPS20
@@ -644,14 +649,14 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
644#endif 649#endif
645 650
646#ifndef unix 651#ifndef unix
647# define NO_ST_INO /* don't rely on inode numbers */ 652# define NO_ST_INO /* don't rely on inode numbers */
648#endif 653#endif
649 654
650 655
651 /* Common defaults */ 656 /* Common defaults */
652 657
653#ifndef OS_CODE 658#ifndef OS_CODE
654# define OS_CODE 0x03 /* assume Unix */ 659# define OS_CODE 0x03 /* assume Unix */
655#endif 660#endif
656 661
657#ifndef PATH_SEP 662#ifndef PATH_SEP
@@ -773,9 +778,10 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
773 * Local data used by the "bit string" routines. 778 * Local data used by the "bit string" routines.
774 */ 779 */
775 780
776local file_t zfile; /* output gzip file */ 781local file_t zfile; /* output gzip file */
777 782
778local unsigned short bi_buf; 783local unsigned short bi_buf;
784
779/* Output buffer. bits are inserted starting at the bottom (least significant 785/* Output buffer. bits are inserted starting at the bottom (least significant
780 * bits). 786 * bits).
781 */ 787 */
@@ -786,36 +792,38 @@ local unsigned short bi_buf;
786 */ 792 */
787 793
788local int bi_valid; 794local int bi_valid;
795
789/* Number of valid bits in bi_buf. All bits above the last valid bit 796/* Number of valid bits in bi_buf. All bits above the last valid bit
790 * are always zero. 797 * are always zero.
791 */ 798 */
792 799
793int (*read_buf) OF((char *buf, unsigned size)); 800int (*read_buf) OF((char *buf, unsigned size));
801
794/* Current input function. Set to mem_read for in-memory compression */ 802/* Current input function. Set to mem_read for in-memory compression */
795 803
796#ifdef DEBUG 804#ifdef DEBUG
797 ulg bits_sent; /* bit length of the compressed data */ 805ulg bits_sent; /* bit length of the compressed data */
798#endif 806#endif
799 807
800/* =========================================================================== 808/* ===========================================================================
801 * Initialize the bit string routines. 809 * Initialize the bit string routines.
802 */ 810 */
803void bi_init (zipfile) 811void bi_init(zipfile)
804 file_t zipfile; /* output zip file, NO_FILE for in-memory compression */ 812file_t zipfile; /* output zip file, NO_FILE for in-memory compression */
805{ 813{
806 zfile = zipfile; 814 zfile = zipfile;
807 bi_buf = 0; 815 bi_buf = 0;
808 bi_valid = 0; 816 bi_valid = 0;
809#ifdef DEBUG 817#ifdef DEBUG
810 bits_sent = 0L; 818 bits_sent = 0L;
811#endif 819#endif
812 820
813 /* Set the defaults for file compression. They are set by memcompress 821 /* Set the defaults for file compression. They are set by memcompress
814 * for in-memory compression. 822 * for in-memory compression.
815 */ 823 */
816 if (zfile != NO_FILE) { 824 if (zfile != NO_FILE) {
817 read_buf = file_read; 825 read_buf = file_read;
818 } 826 }
819} 827}
820 828
821/* =========================================================================== 829/* ===========================================================================
@@ -823,27 +831,27 @@ void bi_init (zipfile)
823 * IN assertion: length <= 16 and value fits in length bits. 831 * IN assertion: length <= 16 and value fits in length bits.
824 */ 832 */
825void send_bits(value, length) 833void send_bits(value, length)
826 int value; /* value to send */ 834int value; /* value to send */
827 int length; /* number of bits */ 835int length; /* number of bits */
828{ 836{
829#ifdef DEBUG 837#ifdef DEBUG
830 Tracev((stderr," l %2d v %4x ", length, value)); 838 Tracev((stderr, " l %2d v %4x ", length, value));
831 Assert(length > 0 && length <= 15, "invalid length"); 839 Assert(length > 0 && length <= 15, "invalid length");
832 bits_sent += (ulg)length; 840 bits_sent += (ulg) length;
833#endif 841#endif
834 /* If not enough room in bi_buf, use (valid) bits from bi_buf and 842 /* If not enough room in bi_buf, use (valid) bits from bi_buf and
835 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) 843 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
836 * unused bits in value. 844 * unused bits in value.
837 */ 845 */
838 if (bi_valid > (int)Buf_size - length) { 846 if (bi_valid > (int) Buf_size - length) {
839 bi_buf |= (value << bi_valid); 847 bi_buf |= (value << bi_valid);
840 put_short(bi_buf); 848 put_short(bi_buf);
841 bi_buf = (ush)value >> (Buf_size - bi_valid); 849 bi_buf = (ush) value >> (Buf_size - bi_valid);
842 bi_valid += length - Buf_size; 850 bi_valid += length - Buf_size;
843 } else { 851 } else {
844 bi_buf |= value << bi_valid; 852 bi_buf |= value << bi_valid;
845 bi_valid += length; 853 bi_valid += length;
846 } 854 }
847} 855}
848 856
849/* =========================================================================== 857/* ===========================================================================
@@ -852,15 +860,16 @@ void send_bits(value, length)
852 * IN assertion: 1 <= len <= 15 860 * IN assertion: 1 <= len <= 15
853 */ 861 */
854unsigned bi_reverse(code, len) 862unsigned bi_reverse(code, len)
855 unsigned code; /* the value to invert */ 863unsigned code; /* the value to invert */
856 int len; /* its bit length */ 864int len; /* its bit length */
857{ 865{
858 register unsigned res = 0; 866 register unsigned res = 0;
859 do { 867
860 res |= code & 1; 868 do {
861 code >>= 1, res <<= 1; 869 res |= code & 1;
862 } while (--len > 0); 870 code >>= 1, res <<= 1;
863 return res >> 1; 871 } while (--len > 0);
872 return res >> 1;
864} 873}
865 874
866/* =========================================================================== 875/* ===========================================================================
@@ -868,15 +877,15 @@ unsigned bi_reverse(code, len)
868 */ 877 */
869void bi_windup() 878void bi_windup()
870{ 879{
871 if (bi_valid > 8) { 880 if (bi_valid > 8) {
872 put_short(bi_buf); 881 put_short(bi_buf);
873 } else if (bi_valid > 0) { 882 } else if (bi_valid > 0) {
874 put_byte(bi_buf); 883 put_byte(bi_buf);
875 } 884 }
876 bi_buf = 0; 885 bi_buf = 0;
877 bi_valid = 0; 886 bi_valid = 0;
878#ifdef DEBUG 887#ifdef DEBUG
879 bits_sent = (bits_sent+7) & ~7; 888 bits_sent = (bits_sent + 7) & ~7;
880#endif 889#endif
881} 890}
882 891
@@ -885,30 +894,33 @@ void bi_windup()
885 * one's complement if requested. 894 * one's complement if requested.
886 */ 895 */
887void copy_block(buf, len, header) 896void copy_block(buf, len, header)
888 char *buf; /* the input data */ 897char *buf; /* the input data */
889 unsigned len; /* its length */ 898unsigned len; /* its length */
890 int header; /* true if block header must be written */ 899int header; /* true if block header must be written */
891{ 900{
892 bi_windup(); /* align on byte boundary */ 901 bi_windup(); /* align on byte boundary */
893 902
894 if (header) { 903 if (header) {
895 put_short((ush)len); 904 put_short((ush) len);
896 put_short((ush)~len); 905 put_short((ush) ~ len);
897#ifdef DEBUG 906#ifdef DEBUG
898 bits_sent += 2*16; 907 bits_sent += 2 * 16;
899#endif 908#endif
900 } 909 }
901#ifdef DEBUG 910#ifdef DEBUG
902 bits_sent += (ulg)len<<3; 911 bits_sent += (ulg) len << 3;
903#endif 912#endif
904 while (len--) { 913 while (len--) {
905#ifdef CRYPT 914#ifdef CRYPT
906 int t; 915 int t;
907 if (key) zencode(*buf, t); 916
917 if (key)
918 zencode(*buf, t);
908#endif 919#endif
909 put_byte(*buf++); 920 put_byte(*buf++);
910 } 921 }
911} 922}
923
912/* deflate.c -- compress data using the deflation algorithm 924/* deflate.c -- compress data using the deflation algorithm
913 * Copyright (C) 1992-1993 Jean-loup Gailly 925 * Copyright (C) 1992-1993 Jean-loup Gailly
914 * This is free software; you can redistribute it and/or modify it under the 926 * This is free software; you can redistribute it and/or modify it under the
@@ -987,7 +999,7 @@ void copy_block(buf, len, header)
987 */ 999 */
988 1000
989#ifdef SMALL_MEM 1001#ifdef SMALL_MEM
990# define HASH_BITS 13 /* Number of bits used to hash strings */ 1002# define HASH_BITS 13 /* Number of bits used to hash strings */
991#endif 1003#endif
992#ifdef MEDIUM_MEM 1004#ifdef MEDIUM_MEM
993# define HASH_BITS 14 1005# define HASH_BITS 14
@@ -1001,35 +1013,30 @@ void copy_block(buf, len, header)
1001 * window with tab_suffix. Check that we can do this: 1013 * window with tab_suffix. Check that we can do this:
1002 */ 1014 */
1003#if (WSIZE<<1) > (1<<BITS) 1015#if (WSIZE<<1) > (1<<BITS)
1004 error: cannot overlay window with tab_suffix and prev with tab_prefix0 1016error:cannot overlay window with tab_suffix and prev with tab_prefix0
1005#endif 1017#endif
1006#if HASH_BITS > BITS-1 1018#if HASH_BITS > BITS-1
1007 error: cannot overlay head with tab_prefix1 1019error:cannot overlay head with tab_prefix1
1008#endif 1020#endif
1009
1010#define HASH_SIZE (unsigned)(1<<HASH_BITS) 1021#define HASH_SIZE (unsigned)(1<<HASH_BITS)
1011#define HASH_MASK (HASH_SIZE-1) 1022#define HASH_MASK (HASH_SIZE-1)
1012#define WMASK (WSIZE-1) 1023#define WMASK (WSIZE-1)
1013/* HASH_SIZE and WSIZE must be powers of two */ 1024/* HASH_SIZE and WSIZE must be powers of two */
1014
1015#define NIL 0 1025#define NIL 0
1016/* Tail of hash chains */ 1026/* Tail of hash chains */
1017
1018#define FAST 4 1027#define FAST 4
1019#define SLOW 2 1028#define SLOW 2
1020/* speed options for the general purpose bit flag */ 1029/* speed options for the general purpose bit flag */
1021
1022#ifndef TOO_FAR 1030#ifndef TOO_FAR
1023# define TOO_FAR 4096 1031# define TOO_FAR 4096
1024#endif 1032#endif
1025/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ 1033/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
1026
1027/* =========================================================================== 1034/* ===========================================================================
1028 * Local data used by the "longest match" routines. 1035 * Local data used by the "longest match" routines.
1029 */ 1036 */
1030
1031typedef ush Pos; 1037typedef ush Pos;
1032typedef unsigned IPos; 1038typedef unsigned IPos;
1039
1033/* A Pos is an index in the character window. We use short instead of int to 1040/* A Pos is an index in the character window. We use short instead of int to
1034 * save space in the various tables. IPos is used only for parameter passing. 1041 * save space in the various tables. IPos is used only for parameter passing.
1035 */ 1042 */
@@ -1054,17 +1061,19 @@ typedef unsigned IPos;
1054/* DECLARE(Pos, head, 1<<HASH_BITS); */ 1061/* DECLARE(Pos, head, 1<<HASH_BITS); */
1055/* Heads of the hash chains or NIL. */ 1062/* Heads of the hash chains or NIL. */
1056 1063
1057ulg window_size = (ulg)2*WSIZE; 1064ulg window_size = (ulg) 2 * WSIZE;
1065
1058/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the 1066/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
1059 * input file length plus MIN_LOOKAHEAD. 1067 * input file length plus MIN_LOOKAHEAD.
1060 */ 1068 */
1061 1069
1062long block_start; 1070long block_start;
1071
1063/* window position at the beginning of the current output block. Gets 1072/* window position at the beginning of the current output block. Gets
1064 * negative when the window is moved backwards. 1073 * negative when the window is moved backwards.
1065 */ 1074 */
1066 1075
1067local unsigned ins_h; /* hash index of string to be inserted */ 1076local unsigned ins_h; /* hash index of string to be inserted */
1068 1077
1069#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH) 1078#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
1070/* Number of bits by which ins_h and del_h must be shifted at each 1079/* Number of bits by which ins_h and del_h must be shifted at each
@@ -1074,21 +1083,24 @@ local unsigned ins_h; /* hash index of string to be inserted */
1074 */ 1083 */
1075 1084
1076unsigned int near prev_length; 1085unsigned int near prev_length;
1086
1077/* Length of the best match at previous step. Matches not greater than this 1087/* Length of the best match at previous step. Matches not greater than this
1078 * are discarded. This is used in the lazy match evaluation. 1088 * are discarded. This is used in the lazy match evaluation.
1079 */ 1089 */
1080 1090
1081 unsigned near strstart; /* start of string to insert */ 1091unsigned near strstart; /* start of string to insert */
1082 unsigned near match_start; /* start of matching string */ 1092unsigned near match_start; /* start of matching string */
1083local int eofile; /* flag set at end of input file */ 1093local int eofile; /* flag set at end of input file */
1084local unsigned lookahead; /* number of valid bytes ahead in window */ 1094local unsigned lookahead; /* number of valid bytes ahead in window */
1085 1095
1086unsigned near max_chain_length; 1096unsigned near max_chain_length;
1097
1087/* To speed up deflation, hash chains are never searched beyond this length. 1098/* To speed up deflation, hash chains are never searched beyond this length.
1088 * A higher limit improves compression ratio but degrades the speed. 1099 * A higher limit improves compression ratio but degrades the speed.
1089 */ 1100 */
1090 1101
1091local unsigned int max_lazy_match; 1102local unsigned int max_lazy_match;
1103
1092/* Attempt to find a better match only when the current match is strictly 1104/* Attempt to find a better match only when the current match is strictly
1093 * smaller than this value. This mechanism is used only for compression 1105 * smaller than this value. This mechanism is used only for compression
1094 * levels >= 4. 1106 * levels >= 4.
@@ -1100,6 +1112,7 @@ local unsigned int max_lazy_match;
1100 */ 1112 */
1101 1113
1102unsigned near good_match; 1114unsigned near good_match;
1115
1103/* Use a faster search when the previous match is longer than this */ 1116/* Use a faster search when the previous match is longer than this */
1104 1117
1105 1118
@@ -1110,20 +1123,21 @@ unsigned near good_match;
1110 */ 1123 */
1111 1124
1112typedef struct config { 1125typedef struct config {
1113 ush good_length; /* reduce lazy search above this match length */ 1126 ush good_length; /* reduce lazy search above this match length */
1114 ush max_lazy; /* do not perform lazy search above this match length */ 1127 ush max_lazy; /* do not perform lazy search above this match length */
1115 ush nice_length; /* quit search above this match length */ 1128 ush nice_length; /* quit search above this match length */
1116 ush max_chain; 1129 ush max_chain;
1117} config; 1130} config;
1118 1131
1119#ifdef FULL_SEARCH 1132#ifdef FULL_SEARCH
1120# define nice_match MAX_MATCH 1133# define nice_match MAX_MATCH
1121#else 1134#else
1122 int near nice_match; /* Stop searching when current match exceeds this */ 1135int near nice_match; /* Stop searching when current match exceeds this */
1123#endif 1136#endif
1124 1137
1125local config configuration_table = 1138local config configuration_table =
1126/* 9 */ {32, 258, 258, 4096}; /* maximum compression */ 1139 /* 9 */ { 32, 258, 258, 4096 };
1140 /* maximum compression */
1127 1141
1128/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 1142/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
1129 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different 1143 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
@@ -1136,15 +1150,16 @@ local config configuration_table =
1136/* =========================================================================== 1150/* ===========================================================================
1137 * Prototypes for local functions. 1151 * Prototypes for local functions.
1138 */ 1152 */
1139local void fill_window OF((void)); 1153local void fill_window OF((void));
1154
1155int longest_match OF((IPos cur_match));
1140 1156
1141 int longest_match OF((IPos cur_match));
1142#ifdef ASMV 1157#ifdef ASMV
1143 void match_init OF((void)); /* asm code initialization */ 1158void match_init OF((void)); /* asm code initialization */
1144#endif 1159#endif
1145 1160
1146#ifdef DEBUG 1161#ifdef DEBUG
1147local void check_match OF((IPos start, IPos match, int length)); 1162local void check_match OF((IPos start, IPos match, int length));
1148#endif 1163#endif
1149 1164
1150/* =========================================================================== 1165/* ===========================================================================
@@ -1171,54 +1186,57 @@ local void check_match OF((IPos start, IPos match, int length));
1171/* =========================================================================== 1186/* ===========================================================================
1172 * Initialize the "longest match" routines for a new file 1187 * Initialize the "longest match" routines for a new file
1173 */ 1188 */
1174void lm_init (flags) 1189void lm_init(flags)
1175 ush *flags; /* general purpose bit flag */ 1190ush *flags; /* general purpose bit flag */
1176{ 1191{
1177 register unsigned j; 1192 register unsigned j;
1178 1193
1179 /* Initialize the hash table. */ 1194 /* Initialize the hash table. */
1180#if defined(MAXSEG_64K) && HASH_BITS == 15 1195#if defined(MAXSEG_64K) && HASH_BITS == 15
1181 for (j = 0; j < HASH_SIZE; j++) head[j] = NIL; 1196 for (j = 0; j < HASH_SIZE; j++)
1197 head[j] = NIL;
1182#else 1198#else
1183 memzero((char*)head, HASH_SIZE*sizeof(*head)); 1199 memzero((char *) head, HASH_SIZE * sizeof(*head));
1184#endif 1200#endif
1185 /* prev will be initialized on the fly */ 1201 /* prev will be initialized on the fly */
1186 1202
1187 /* Set the default configuration parameters: 1203 /* Set the default configuration parameters:
1188 */ 1204 */
1189 max_lazy_match = configuration_table.max_lazy; 1205 max_lazy_match = configuration_table.max_lazy;
1190 good_match = configuration_table.good_length; 1206 good_match = configuration_table.good_length;
1191#ifndef FULL_SEARCH 1207#ifndef FULL_SEARCH
1192 nice_match = configuration_table.nice_length; 1208 nice_match = configuration_table.nice_length;
1193#endif 1209#endif
1194 max_chain_length = configuration_table.max_chain; 1210 max_chain_length = configuration_table.max_chain;
1195 *flags |= SLOW; 1211 *flags |= SLOW;
1196 /* ??? reduce max_chain_length for binary files */ 1212 /* ??? reduce max_chain_length for binary files */
1197 1213
1198 strstart = 0; 1214 strstart = 0;
1199 block_start = 0L; 1215 block_start = 0L;
1200#ifdef ASMV 1216#ifdef ASMV
1201 match_init(); /* initialize the asm code */ 1217 match_init(); /* initialize the asm code */
1202#endif 1218#endif
1203 1219
1204 lookahead = read_buf((char*)window, 1220 lookahead = read_buf((char *) window,
1205 sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE); 1221 sizeof(int) <= 2 ? (unsigned) WSIZE : 2 * WSIZE);
1206 1222
1207 if (lookahead == 0 || lookahead == (unsigned)EOF) { 1223 if (lookahead == 0 || lookahead == (unsigned) EOF) {
1208 eofile = 1, lookahead = 0; 1224 eofile = 1, lookahead = 0;
1209 return; 1225 return;
1210 } 1226 }
1211 eofile = 0; 1227 eofile = 0;
1212 /* Make sure that we always have enough lookahead. This is important 1228 /* Make sure that we always have enough lookahead. This is important
1213 * if input comes from a device such as a tty. 1229 * if input comes from a device such as a tty.
1214 */ 1230 */
1215 while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); 1231 while (lookahead < MIN_LOOKAHEAD && !eofile)
1216 1232 fill_window();
1217 ins_h = 0; 1233
1218 for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]); 1234 ins_h = 0;
1219 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is 1235 for (j = 0; j < MIN_MATCH - 1; j++)
1220 * not important since only literal bytes will be emitted. 1236 UPDATE_HASH(ins_h, window[j]);
1221 */ 1237 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
1238 * not important since only literal bytes will be emitted.
1239 */
1222} 1240}
1223 1241
1224/* =========================================================================== 1242/* ===========================================================================
@@ -1235,151 +1253,157 @@ void lm_init (flags)
1235 * if desired. 1253 * if desired.
1236 */ 1254 */
1237int longest_match(cur_match) 1255int longest_match(cur_match)
1238 IPos cur_match; /* current match */ 1256IPos cur_match; /* current match */
1239{ 1257{
1240 unsigned chain_length = max_chain_length; /* max hash chain length */ 1258 unsigned chain_length = max_chain_length; /* max hash chain length */
1241 register uch *scan = window + strstart; /* current string */ 1259 register uch *scan = window + strstart; /* current string */
1242 register uch *match; /* matched string */ 1260 register uch *match; /* matched string */
1243 register int len; /* length of current match */ 1261 register int len; /* length of current match */
1244 int best_len = prev_length; /* best match length so far */ 1262 int best_len = prev_length; /* best match length so far */
1245 IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL; 1263 IPos limit =
1246 /* Stop when cur_match becomes <= limit. To simplify the code, 1264
1247 * we prevent matches with the string of window index 0. 1265 strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL;
1248 */ 1266 /* Stop when cur_match becomes <= limit. To simplify the code,
1267 * we prevent matches with the string of window index 0.
1268 */
1249 1269
1250/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 1270/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
1251 * It is easy to get rid of this optimization if necessary. 1271 * It is easy to get rid of this optimization if necessary.
1252 */ 1272 */
1253#if HASH_BITS < 8 || MAX_MATCH != 258 1273#if HASH_BITS < 8 || MAX_MATCH != 258
1254 error: Code too clever 1274 error:Code too clever
1255#endif 1275#endif
1256
1257#ifdef UNALIGNED_OK 1276#ifdef UNALIGNED_OK
1258 /* Compare two bytes at a time. Note: this is not always beneficial. 1277 /* Compare two bytes at a time. Note: this is not always beneficial.
1259 * Try with and without -DUNALIGNED_OK to check. 1278 * Try with and without -DUNALIGNED_OK to check.
1260 */ 1279 */
1261 register uch *strend = window + strstart + MAX_MATCH - 1; 1280 register uch *strend = window + strstart + MAX_MATCH - 1;
1262 register ush scan_start = *(ush*)scan; 1281 register ush scan_start = *(ush *) scan;
1263 register ush scan_end = *(ush*)(scan+best_len-1); 1282 register ush scan_end = *(ush *) (scan + best_len - 1);
1264#else 1283#else
1265 register uch *strend = window + strstart + MAX_MATCH; 1284 register uch *strend = window + strstart + MAX_MATCH;
1266 register uch scan_end1 = scan[best_len-1]; 1285 register uch scan_end1 = scan[best_len - 1];
1267 register uch scan_end = scan[best_len]; 1286 register uch scan_end = scan[best_len];
1268#endif 1287#endif
1269 1288
1270 /* Do not waste too much time if we already have a good match: */ 1289 /* Do not waste too much time if we already have a good match: */
1271 if (prev_length >= good_match) { 1290 if (prev_length >= good_match) {
1272 chain_length >>= 2; 1291 chain_length >>= 2;
1273 } 1292 }
1274 Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); 1293 Assert(strstart <= window_size - MIN_LOOKAHEAD,
1294 "insufficient lookahead");
1275 1295
1276 do { 1296 do {
1277 Assert(cur_match < strstart, "no future"); 1297 Assert(cur_match < strstart, "no future");
1278 match = window + cur_match; 1298 match = window + cur_match;
1279 1299
1280 /* Skip to next match if the match length cannot increase 1300 /* Skip to next match if the match length cannot increase
1281 * or if the match length is less than 2: 1301 * or if the match length is less than 2:
1282 */ 1302 */
1283#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) 1303#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
1284 /* This code assumes sizeof(unsigned short) == 2. Do not use 1304 /* This code assumes sizeof(unsigned short) == 2. Do not use
1285 * UNALIGNED_OK if your compiler uses a different size. 1305 * UNALIGNED_OK if your compiler uses a different size.
1286 */ 1306 */
1287 if (*(ush*)(match+best_len-1) != scan_end || 1307 if (*(ush *) (match + best_len - 1) != scan_end ||
1288 *(ush*)match != scan_start) continue; 1308 *(ush *) match != scan_start)
1289 1309 continue;
1290 /* It is not necessary to compare scan[2] and match[2] since they are 1310
1291 * always equal when the other bytes match, given that the hash keys 1311 /* It is not necessary to compare scan[2] and match[2] since they are
1292 * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at 1312 * always equal when the other bytes match, given that the hash keys
1293 * strstart+3, +5, ... up to strstart+257. We check for insufficient 1313 * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
1294 * lookahead only every 4th comparison; the 128th check will be made 1314 * strstart+3, +5, ... up to strstart+257. We check for insufficient
1295 * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is 1315 * lookahead only every 4th comparison; the 128th check will be made
1296 * necessary to put more guard bytes at the end of the window, or 1316 * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
1297 * to check more often for insufficient lookahead. 1317 * necessary to put more guard bytes at the end of the window, or
1298 */ 1318 * to check more often for insufficient lookahead.
1299 scan++, match++; 1319 */
1300 do { 1320 scan++, match++;
1301 } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && 1321 do {
1302 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1322 } while (*(ush *) (scan += 2) == *(ush *) (match += 2) &&
1303 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1323 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1304 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1324 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1305 scan < strend); 1325 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1306 /* The funny "do {}" generates better code on most compilers */ 1326 scan < strend);
1307 1327 /* The funny "do {}" generates better code on most compilers */
1308 /* Here, scan <= window+strstart+257 */ 1328
1309 Assert(scan <= window+(unsigned)(window_size-1), "wild scan"); 1329 /* Here, scan <= window+strstart+257 */
1310 if (*scan == *match) scan++; 1330 Assert(scan <= window + (unsigned) (window_size - 1), "wild scan");
1311 1331 if (*scan == *match)
1312 len = (MAX_MATCH - 1) - (int)(strend-scan); 1332 scan++;
1313 scan = strend - (MAX_MATCH-1); 1333
1314 1334 len = (MAX_MATCH - 1) - (int) (strend - scan);
1315#else /* UNALIGNED_OK */ 1335 scan = strend - (MAX_MATCH - 1);
1316 1336
1317 if (match[best_len] != scan_end || 1337#else /* UNALIGNED_OK */
1318 match[best_len-1] != scan_end1 || 1338
1319 *match != *scan || 1339 if (match[best_len] != scan_end ||
1320 *++match != scan[1]) continue; 1340 match[best_len - 1] != scan_end1 ||
1321 1341 *match != *scan || *++match != scan[1])
1322 /* The check at best_len-1 can be removed because it will be made 1342 continue;
1323 * again later. (This heuristic is not always a win.) 1343
1324 * It is not necessary to compare scan[2] and match[2] since they 1344 /* The check at best_len-1 can be removed because it will be made
1325 * are always equal when the other bytes match, given that 1345 * again later. (This heuristic is not always a win.)
1326 * the hash keys are equal and that HASH_BITS >= 8. 1346 * It is not necessary to compare scan[2] and match[2] since they
1327 */ 1347 * are always equal when the other bytes match, given that
1328 scan += 2, match++; 1348 * the hash keys are equal and that HASH_BITS >= 8.
1329 1349 */
1330 /* We check for insufficient lookahead only every 8th comparison; 1350 scan += 2, match++;
1331 * the 256th check will be made at strstart+258. 1351
1332 */ 1352 /* We check for insufficient lookahead only every 8th comparison;
1333 do { 1353 * the 256th check will be made at strstart+258.
1334 } while (*++scan == *++match && *++scan == *++match && 1354 */
1335 *++scan == *++match && *++scan == *++match && 1355 do {
1336 *++scan == *++match && *++scan == *++match && 1356 } while (*++scan == *++match && *++scan == *++match &&
1337 *++scan == *++match && *++scan == *++match && 1357 *++scan == *++match && *++scan == *++match &&
1338 scan < strend); 1358 *++scan == *++match && *++scan == *++match &&
1339 1359 *++scan == *++match && *++scan == *++match &&
1340 len = MAX_MATCH - (int)(strend - scan); 1360 scan < strend);
1341 scan = strend - MAX_MATCH; 1361
1342 1362 len = MAX_MATCH - (int) (strend - scan);
1343#endif /* UNALIGNED_OK */ 1363 scan = strend - MAX_MATCH;
1344 1364
1345 if (len > best_len) { 1365#endif /* UNALIGNED_OK */
1346 match_start = cur_match; 1366
1347 best_len = len; 1367 if (len > best_len) {
1348 if (len >= nice_match) break; 1368 match_start = cur_match;
1369 best_len = len;
1370 if (len >= nice_match)
1371 break;
1349#ifdef UNALIGNED_OK 1372#ifdef UNALIGNED_OK
1350 scan_end = *(ush*)(scan+best_len-1); 1373 scan_end = *(ush *) (scan + best_len - 1);
1351#else 1374#else
1352 scan_end1 = scan[best_len-1]; 1375 scan_end1 = scan[best_len - 1];
1353 scan_end = scan[best_len]; 1376 scan_end = scan[best_len];
1354#endif 1377#endif
1355 } 1378 }
1356 } while ((cur_match = prev[cur_match & WMASK]) > limit 1379 } while ((cur_match = prev[cur_match & WMASK]) > limit
1357 && --chain_length != 0); 1380 && --chain_length != 0);
1358 1381
1359 return best_len; 1382 return best_len;
1360} 1383}
1361#endif /* ASMV */ 1384#endif /* ASMV */
1362 1385
1363#ifdef DEBUG 1386#ifdef DEBUG
1364/* =========================================================================== 1387/* ===========================================================================
1365 * Check that the match at match_start is indeed a match. 1388 * Check that the match at match_start is indeed a match.
1366 */ 1389 */
1367local void check_match(start, match, length) 1390local void check_match(start, match, length)
1368 IPos start, match; 1391IPos start, match;
1369 int length; 1392int length;
1370{ 1393{
1371 /* check that the match is indeed a match */ 1394 /* check that the match is indeed a match */
1372 if (memcmp((char*)window + match, 1395 if (memcmp((char *) window + match,
1373 (char*)window + start, length) != EQUAL) { 1396 (char *) window + start, length) != EQUAL) {
1374 fprintf(stderr, 1397 fprintf(stderr,
1375 " start %d, match %d, length %d\n", 1398 " start %d, match %d, length %d\n", start, match, length);
1376 start, match, length); 1399 error("invalid match");
1377 error("invalid match"); 1400 }
1378 } 1401 if (verbose > 1) {
1379 if (verbose > 1) { 1402 fprintf(stderr, "\\[%d,%d]", start - match, length);
1380 fprintf(stderr,"\\[%d,%d]", start-match, length); 1403 do {
1381 do { putc(window[start++], stderr); } while (--length != 0); 1404 putc(window[start++], stderr);
1382 } 1405 } while (--length != 0);
1406 }
1383} 1407}
1384#else 1408#else
1385# define check_match(start, match, length) 1409# define check_match(start, match, length)
@@ -1395,52 +1419,54 @@ local void check_match(start, match, length)
1395 */ 1419 */
1396local void fill_window() 1420local void fill_window()
1397{ 1421{
1398 register unsigned n, m; 1422 register unsigned n, m;
1399 unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart); 1423 unsigned more =
1400 /* Amount of free space at the end of the window. */ 1424
1401 1425 (unsigned) (window_size - (ulg) lookahead - (ulg) strstart);
1402 /* If the window is almost full and there is insufficient lookahead, 1426 /* Amount of free space at the end of the window. */
1403 * move the upper half to the lower one to make room in the upper half. 1427
1404 */ 1428 /* If the window is almost full and there is insufficient lookahead,
1405 if (more == (unsigned)EOF) { 1429 * move the upper half to the lower one to make room in the upper half.
1406 /* Very unlikely, but possible on 16 bit machine if strstart == 0 1430 */
1407 * and lookahead == 1 (input done one byte at time) 1431 if (more == (unsigned) EOF) {
1408 */ 1432 /* Very unlikely, but possible on 16 bit machine if strstart == 0
1409 more--; 1433 * and lookahead == 1 (input done one byte at time)
1410 } else if (strstart >= WSIZE+MAX_DIST) { 1434 */
1411 /* By the IN assertion, the window is not empty so we can't confuse 1435 more--;
1412 * more == 0 with more == 64K on a 16 bit machine. 1436 } else if (strstart >= WSIZE + MAX_DIST) {
1413 */ 1437 /* By the IN assertion, the window is not empty so we can't confuse
1414 Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); 1438 * more == 0 with more == 64K on a 16 bit machine.
1415 1439 */
1416 memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE); 1440 Assert(window_size == (ulg) 2 * WSIZE, "no sliding with BIG_MEM");
1417 match_start -= WSIZE; 1441
1418 strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ 1442 memcpy((char *) window, (char *) window + WSIZE, (unsigned) WSIZE);
1419 1443 match_start -= WSIZE;
1420 block_start -= (long) WSIZE; 1444 strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
1421 1445
1422 for (n = 0; n < HASH_SIZE; n++) { 1446 block_start -= (long) WSIZE;
1423 m = head[n]; 1447
1424 head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1448 for (n = 0; n < HASH_SIZE; n++) {
1425 } 1449 m = head[n];
1426 for (n = 0; n < WSIZE; n++) { 1450 head[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1427 m = prev[n]; 1451 }
1428 prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1452 for (n = 0; n < WSIZE; n++) {
1429 /* If n is not on any hash chain, prev[n] is garbage but 1453 m = prev[n];
1430 * its value will never be used. 1454 prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1431 */ 1455 /* If n is not on any hash chain, prev[n] is garbage but
1432 } 1456 * its value will never be used.
1433 more += WSIZE; 1457 */
1434 } 1458 }
1435 /* At this point, more >= 2 */ 1459 more += WSIZE;
1436 if (!eofile) { 1460 }
1437 n = read_buf((char*)window+strstart+lookahead, more); 1461 /* At this point, more >= 2 */
1438 if (n == 0 || n == (unsigned)EOF) { 1462 if (!eofile) {
1439 eofile = 1; 1463 n = read_buf((char *) window + strstart + lookahead, more);
1440 } else { 1464 if (n == 0 || n == (unsigned) EOF) {
1441 lookahead += n; 1465 eofile = 1;
1442 } 1466 } else {
1443 } 1467 lookahead += n;
1468 }
1469 }
1444} 1470}
1445 1471
1446/* =========================================================================== 1472/* ===========================================================================
@@ -1458,105 +1484,114 @@ local void fill_window()
1458 */ 1484 */
1459ulg deflate() 1485ulg deflate()
1460{ 1486{
1461 IPos hash_head; /* head of hash chain */ 1487 IPos hash_head; /* head of hash chain */
1462 IPos prev_match; /* previous match */ 1488 IPos prev_match; /* previous match */
1463 int flush; /* set if current block must be flushed */ 1489 int flush; /* set if current block must be flushed */
1464 int match_available = 0; /* set if previous match exists */ 1490 int match_available = 0; /* set if previous match exists */
1465 register unsigned match_length = MIN_MATCH-1; /* length of best match */ 1491 register unsigned match_length = MIN_MATCH - 1; /* length of best match */
1492
1466#ifdef DEBUG 1493#ifdef DEBUG
1467 extern long isize; /* byte length of input file, for debug only */ 1494 extern long isize; /* byte length of input file, for debug only */
1468#endif 1495#endif
1469 1496
1470 /* Process the input block. */ 1497 /* Process the input block. */
1471 while (lookahead != 0) { 1498 while (lookahead != 0) {
1472 /* Insert the string window[strstart .. strstart+2] in the 1499 /* Insert the string window[strstart .. strstart+2] in the
1473 * dictionary, and set hash_head to the head of the hash chain: 1500 * dictionary, and set hash_head to the head of the hash chain:
1474 */ 1501 */
1475 INSERT_STRING(strstart, hash_head); 1502 INSERT_STRING(strstart, hash_head);
1476 1503
1477 /* Find the longest match, discarding those <= prev_length. 1504 /* Find the longest match, discarding those <= prev_length.
1478 */ 1505 */
1479 prev_length = match_length, prev_match = match_start; 1506 prev_length = match_length, prev_match = match_start;
1480 match_length = MIN_MATCH-1; 1507 match_length = MIN_MATCH - 1;
1481 1508
1482 if (hash_head != NIL && prev_length < max_lazy_match && 1509 if (hash_head != NIL && prev_length < max_lazy_match &&
1483 strstart - hash_head <= MAX_DIST) { 1510 strstart - hash_head <= MAX_DIST) {
1484 /* To simplify the code, we prevent matches with the string 1511 /* To simplify the code, we prevent matches with the string
1485 * of window index 0 (in particular we have to avoid a match 1512 * of window index 0 (in particular we have to avoid a match
1486 * of the string with itself at the start of the input file). 1513 * of the string with itself at the start of the input file).
1487 */ 1514 */
1488 match_length = longest_match (hash_head); 1515 match_length = longest_match(hash_head);
1489 /* longest_match() sets match_start */ 1516 /* longest_match() sets match_start */
1490 if (match_length > lookahead) match_length = lookahead; 1517 if (match_length > lookahead)
1491 1518 match_length = lookahead;
1492 /* Ignore a length 3 match if it is too distant: */ 1519
1493 if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){ 1520 /* Ignore a length 3 match if it is too distant: */
1494 /* If prev_match is also MIN_MATCH, match_start is garbage 1521 if (match_length == MIN_MATCH
1495 * but we will ignore the current match anyway. 1522 && strstart - match_start > TOO_FAR) {
1496 */ 1523 /* If prev_match is also MIN_MATCH, match_start is garbage
1497 match_length--; 1524 * but we will ignore the current match anyway.
1498 } 1525 */
1499 } 1526 match_length--;
1500 /* If there was a match at the previous step and the current 1527 }
1501 * match is not better, output the previous match: 1528 }
1502 */ 1529 /* If there was a match at the previous step and the current
1503 if (prev_length >= MIN_MATCH && match_length <= prev_length) { 1530 * match is not better, output the previous match:
1504 1531 */
1505 check_match(strstart-1, prev_match, prev_length); 1532 if (prev_length >= MIN_MATCH && match_length <= prev_length) {
1506 1533
1507 flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); 1534 check_match(strstart - 1, prev_match, prev_length);
1508 1535
1509 /* Insert in hash table all strings up to the end of the match. 1536 flush =
1510 * strstart-1 and strstart are already inserted. 1537 ct_tally(strstart - 1 - prev_match,
1511 */ 1538 prev_length - MIN_MATCH);
1512 lookahead -= prev_length-1; 1539
1513 prev_length -= 2; 1540 /* Insert in hash table all strings up to the end of the match.
1514 do { 1541 * strstart-1 and strstart are already inserted.
1515 strstart++; 1542 */
1516 INSERT_STRING(strstart, hash_head); 1543 lookahead -= prev_length - 1;
1517 /* strstart never exceeds WSIZE-MAX_MATCH, so there are 1544 prev_length -= 2;
1518 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH 1545 do {
1519 * these bytes are garbage, but it does not matter since the 1546 strstart++;
1520 * next lookahead bytes will always be emitted as literals. 1547 INSERT_STRING(strstart, hash_head);
1521 */ 1548 /* strstart never exceeds WSIZE-MAX_MATCH, so there are
1522 } while (--prev_length != 0); 1549 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
1523 match_available = 0; 1550 * these bytes are garbage, but it does not matter since the
1524 match_length = MIN_MATCH-1; 1551 * next lookahead bytes will always be emitted as literals.
1525 strstart++; 1552 */
1526 if (flush) FLUSH_BLOCK(0), block_start = strstart; 1553 } while (--prev_length != 0);
1527 1554 match_available = 0;
1528 } else if (match_available) { 1555 match_length = MIN_MATCH - 1;
1529 /* If there was no match at the previous position, output a 1556 strstart++;
1530 * single literal. If there was a match but the current match 1557 if (flush)
1531 * is longer, truncate the previous match to a single literal. 1558 FLUSH_BLOCK(0), block_start = strstart;
1532 */ 1559
1533 Tracevv((stderr,"%c",window[strstart-1])); 1560 } else if (match_available) {
1534 if (ct_tally (0, window[strstart-1])) { 1561 /* If there was no match at the previous position, output a
1535 FLUSH_BLOCK(0), block_start = strstart; 1562 * single literal. If there was a match but the current match
1536 } 1563 * is longer, truncate the previous match to a single literal.
1537 strstart++; 1564 */
1538 lookahead--; 1565 Tracevv((stderr, "%c", window[strstart - 1]));
1539 } else { 1566 if (ct_tally(0, window[strstart - 1])) {
1540 /* There is no previous match to compare with, wait for 1567 FLUSH_BLOCK(0), block_start = strstart;
1541 * the next step to decide. 1568 }
1542 */ 1569 strstart++;
1543 match_available = 1; 1570 lookahead--;
1544 strstart++; 1571 } else {
1545 lookahead--; 1572 /* There is no previous match to compare with, wait for
1546 } 1573 * the next step to decide.
1547 Assert (strstart <= isize && lookahead <= isize, "a bit too far"); 1574 */
1548 1575 match_available = 1;
1549 /* Make sure that we always have enough lookahead, except 1576 strstart++;
1550 * at the end of the input file. We need MAX_MATCH bytes 1577 lookahead--;
1551 * for the next match, plus MIN_MATCH bytes to insert the 1578 }
1552 * string following the next match. 1579 Assert(strstart <= isize && lookahead <= isize, "a bit too far");
1553 */ 1580
1554 while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); 1581 /* Make sure that we always have enough lookahead, except
1555 } 1582 * at the end of the input file. We need MAX_MATCH bytes
1556 if (match_available) ct_tally (0, window[strstart-1]); 1583 * for the next match, plus MIN_MATCH bytes to insert the
1557 1584 * string following the next match.
1558 return FLUSH_BLOCK(1); /* eof */ 1585 */
1586 while (lookahead < MIN_LOOKAHEAD && !eofile)
1587 fill_window();
1588 }
1589 if (match_available)
1590 ct_tally(0, window[strstart - 1]);
1591
1592 return FLUSH_BLOCK(1); /* eof */
1559} 1593}
1594
1560/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface 1595/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
1561 * Copyright (C) 1992-1993 Jean-loup Gailly 1596 * Copyright (C) 1992-1993 Jean-loup Gailly
1562 * The unzip code was written and put in the public domain by Mark Adler. 1597 * The unzip code was written and put in the public domain by Mark Adler.
@@ -1611,29 +1646,33 @@ ulg deflate()
1611#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 1646#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
1612# include <stdlib.h> 1647# include <stdlib.h>
1613#else 1648#else
1614 extern int errno; 1649extern int errno;
1615#endif 1650#endif
1616 1651
1617#if defined(DIRENT) 1652#if defined(DIRENT)
1618# include <dirent.h> 1653# include <dirent.h>
1619 typedef struct dirent dir_type; 1654typedef struct dirent dir_type;
1655
1620# define NLENGTH(dirent) ((int)strlen((dirent)->d_name)) 1656# define NLENGTH(dirent) ((int)strlen((dirent)->d_name))
1621# define DIR_OPT "DIRENT" 1657# define DIR_OPT "DIRENT"
1622#else 1658#else
1623# define NLENGTH(dirent) ((dirent)->d_namlen) 1659# define NLENGTH(dirent) ((dirent)->d_namlen)
1624# ifdef SYSDIR 1660# ifdef SYSDIR
1625# include <sys/dir.h> 1661# include <sys/dir.h>
1626 typedef struct direct dir_type; 1662typedef struct direct dir_type;
1663
1627# define DIR_OPT "SYSDIR" 1664# define DIR_OPT "SYSDIR"
1628# else 1665# else
1629# ifdef SYSNDIR 1666# ifdef SYSNDIR
1630# include <sys/ndir.h> 1667# include <sys/ndir.h>
1631 typedef struct direct dir_type; 1668typedef struct direct dir_type;
1669
1632# define DIR_OPT "SYSNDIR" 1670# define DIR_OPT "SYSNDIR"
1633# else 1671# else
1634# ifdef NDIR 1672# ifdef NDIR
1635# include <ndir.h> 1673# include <ndir.h>
1636 typedef struct direct dir_type; 1674typedef struct direct dir_type;
1675
1637# define DIR_OPT "NDIR" 1676# define DIR_OPT "NDIR"
1638# else 1677# else
1639# define NO_DIR 1678# define NO_DIR
@@ -1652,10 +1691,11 @@ ulg deflate()
1652# include <sys/utime.h> 1691# include <sys/utime.h>
1653# define TIME_OPT "SYS_UTIME" 1692# define TIME_OPT "SYS_UTIME"
1654# else 1693# else
1655 struct utimbuf { 1694struct utimbuf {
1656 time_t actime; 1695 time_t actime;
1657 time_t modtime; 1696 time_t modtime;
1658 }; 1697};
1698
1659# define TIME_OPT "" 1699# define TIME_OPT ""
1660# endif 1700# endif
1661# endif 1701# endif
@@ -1670,10 +1710,10 @@ ulg deflate()
1670# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 1710# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1671#endif 1711#endif
1672 1712
1673typedef RETSIGTYPE (*sig_type) OF((int)); 1713typedef RETSIGTYPE(*sig_type) OF((int));
1674 1714
1675#ifndef O_BINARY 1715#ifndef O_BINARY
1676# define O_BINARY 0 /* creation mode for open() */ 1716# define O_BINARY 0 /* creation mode for open() */
1677#endif 1717#endif
1678 1718
1679#ifndef O_CREAT 1719#ifndef O_CREAT
@@ -1693,10 +1733,10 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1693#ifndef S_IWUSR 1733#ifndef S_IWUSR
1694# define S_IWUSR 0200 1734# define S_IWUSR 0200
1695#endif 1735#endif
1696#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ 1736#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
1697 1737
1698#ifndef MAX_PATH_LEN 1738#ifndef MAX_PATH_LEN
1699# define MAX_PATH_LEN 1024 /* max pathname length */ 1739# define MAX_PATH_LEN 1024 /* max pathname length */
1700#endif 1740#endif
1701 1741
1702#ifndef SEEK_END 1742#ifndef SEEK_END
@@ -1704,8 +1744,8 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1704#endif 1744#endif
1705 1745
1706#ifdef NO_OFF_T 1746#ifdef NO_OFF_T
1707 typedef long off_t; 1747typedef long off_t;
1708 off_t lseek OF((int fd, off_t offset, int whence)); 1748off_t lseek OF((int fd, off_t offset, int whence));
1709#endif 1749#endif
1710 1750
1711/* Separator for file name parts (see shorten_name()) */ 1751/* Separator for file name parts (see shorten_name()) */
@@ -1717,48 +1757,48 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1717 1757
1718 /* global buffers */ 1758 /* global buffers */
1719 1759
1720DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 1760DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
1721DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 1761DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
1722DECLARE(ush, d_buf, DIST_BUFSIZE); 1762DECLARE(ush, d_buf, DIST_BUFSIZE);
1723DECLARE(uch, window, 2L*WSIZE); 1763DECLARE(uch, window, 2L * WSIZE);
1724#ifndef MAXSEG_64K 1764#ifndef MAXSEG_64K
1725 DECLARE(ush, tab_prefix, 1L<<BITS); 1765DECLARE(ush, tab_prefix, 1L << BITS);
1726#else 1766#else
1727 DECLARE(ush, tab_prefix0, 1L<<(BITS-1)); 1767DECLARE(ush, tab_prefix0, 1L << (BITS - 1));
1728 DECLARE(ush, tab_prefix1, 1L<<(BITS-1)); 1768DECLARE(ush, tab_prefix1, 1L << (BITS - 1));
1729#endif 1769#endif
1730 1770
1731 /* local variables */ 1771 /* local variables */
1732 1772
1733int ascii = 0; /* convert end-of-lines to local OS conventions */ 1773int ascii = 0; /* convert end-of-lines to local OS conventions */
1734int decompress = 0; /* decompress (-d) */ 1774int decompress = 0; /* decompress (-d) */
1735int no_name = -1; /* don't save or restore the original file name */ 1775int no_name = -1; /* don't save or restore the original file name */
1736int no_time = -1; /* don't save or restore the original file time */ 1776int no_time = -1; /* don't save or restore the original file time */
1737int foreground; /* set if program run in foreground */ 1777int foreground; /* set if program run in foreground */
1738char *progname; /* program name */ 1778char *progname; /* program name */
1739static int method = DEFLATED;/* compression method */ 1779static int method = DEFLATED; /* compression method */
1740static int exit_code = OK; /* program exit code */ 1780static int exit_code = OK; /* program exit code */
1741int save_orig_name; /* set if original name must be saved */ 1781int save_orig_name; /* set if original name must be saved */
1742int last_member; /* set for .zip and .Z files */ 1782int last_member; /* set for .zip and .Z files */
1743int part_nb; /* number of parts in .gz file */ 1783int part_nb; /* number of parts in .gz file */
1744long time_stamp; /* original time stamp (modification time) */ 1784long time_stamp; /* original time stamp (modification time) */
1745long ifile_size; /* input file size, -1 for devices (debug only) */ 1785long ifile_size; /* input file size, -1 for devices (debug only) */
1746char *env; /* contents of GZIP env variable */ 1786char *env; /* contents of GZIP env variable */
1747char **args = NULL; /* argv pointer if GZIP env variable defined */ 1787char **args = NULL; /* argv pointer if GZIP env variable defined */
1748char z_suffix[MAX_SUFFIX+1]; /* default suffix (can be set with --suffix) */ 1788char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */
1749int z_len; /* strlen(z_suffix) */ 1789int z_len; /* strlen(z_suffix) */
1750 1790
1751long bytes_in; /* number of input bytes */ 1791long bytes_in; /* number of input bytes */
1752long bytes_out; /* number of output bytes */ 1792long bytes_out; /* number of output bytes */
1753char ifname[MAX_PATH_LEN]; /* input file name */ 1793char ifname[MAX_PATH_LEN]; /* input file name */
1754char ofname[MAX_PATH_LEN]; /* output file name */ 1794char ofname[MAX_PATH_LEN]; /* output file name */
1755int remove_ofname = 0; /* remove output file on error */ 1795int remove_ofname = 0; /* remove output file on error */
1756struct stat istat; /* status for input file */ 1796struct stat istat; /* status for input file */
1757int ifd; /* input file descriptor */ 1797int ifd; /* input file descriptor */
1758int ofd; /* output file descriptor */ 1798int ofd; /* output file descriptor */
1759unsigned insize; /* valid bytes in inbuf */ 1799unsigned insize; /* valid bytes in inbuf */
1760unsigned inptr; /* index of next byte to be processed in inbuf */ 1800unsigned inptr; /* index of next byte to be processed in inbuf */
1761unsigned outcnt; /* bytes in output buffer */ 1801unsigned outcnt; /* bytes in output buffer */
1762 1802
1763/* local functions */ 1803/* local functions */
1764 1804
@@ -1768,148 +1808,148 @@ unsigned outcnt; /* bytes in output buffer */
1768// int main (argc, argv) 1808// int main (argc, argv)
1769// int argc; 1809// int argc;
1770// char **argv; 1810// char **argv;
1771int gzip_main(int argc, char ** argv) 1811int gzip_main(int argc, char **argv)
1772{ 1812{
1773 int result; 1813 int result;
1774 int inFileNum; 1814 int inFileNum;
1775 int outFileNum; 1815 int outFileNum;
1776 struct stat statBuf; 1816 struct stat statBuf;
1777 char* delFileName; 1817 char *delFileName;
1778 int tostdout = 0; 1818 int tostdout = 0;
1779 int fromstdin = 0; 1819 int fromstdin = 0;
1780 1820
1781 if (argc==1) 1821 if (argc == 1)
1782 usage(gzip_usage);
1783
1784 /* Parse any options */
1785 while (--argc > 0 && **(++argv) == '-') {
1786 if (*((*argv)+1) == '\0') {
1787 fromstdin = 1;
1788 tostdout = 1;
1789 }
1790 while (*(++(*argv))) {
1791 switch (**argv) {
1792 case 'c':
1793 tostdout = 1;
1794 break;
1795 default:
1796 usage(gzip_usage); 1822 usage(gzip_usage);
1797 } 1823
1824 /* Parse any options */
1825 while (--argc > 0 && **(++argv) == '-') {
1826 if (*((*argv) + 1) == '\0') {
1827 fromstdin = 1;
1828 tostdout = 1;
1829 }
1830 while (*(++(*argv))) {
1831 switch (**argv) {
1832 case 'c':
1833 tostdout = 1;
1834 break;
1835 default:
1836 usage(gzip_usage);
1837 }
1838 }
1798 } 1839 }
1799 }
1800 1840
1801 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; 1841 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
1802 if (foreground) { 1842 if (foreground) {
1803 (void) signal (SIGINT, (sig_type)abort_gzip); 1843 (void) signal(SIGINT, (sig_type) abort_gzip);
1804 } 1844 }
1805#ifdef SIGTERM 1845#ifdef SIGTERM
1806 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 1846 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
1807 (void) signal(SIGTERM, (sig_type)abort_gzip); 1847 (void) signal(SIGTERM, (sig_type) abort_gzip);
1808 } 1848 }
1809#endif 1849#endif
1810#ifdef SIGHUP 1850#ifdef SIGHUP
1811 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 1851 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
1812 (void) signal(SIGHUP, (sig_type)abort_gzip); 1852 (void) signal(SIGHUP, (sig_type) abort_gzip);
1813 } 1853 }
1814#endif 1854#endif
1815 1855
1816 strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1); 1856 strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1);
1817 z_len = strlen(z_suffix); 1857 z_len = strlen(z_suffix);
1818 1858
1819 /* Allocate all global buffers (for DYN_ALLOC option) */ 1859 /* Allocate all global buffers (for DYN_ALLOC option) */
1820 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 1860 ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
1821 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 1861 ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
1822 ALLOC(ush, d_buf, DIST_BUFSIZE); 1862 ALLOC(ush, d_buf, DIST_BUFSIZE);
1823 ALLOC(uch, window, 2L*WSIZE); 1863 ALLOC(uch, window, 2L * WSIZE);
1824#ifndef MAXSEG_64K 1864#ifndef MAXSEG_64K
1825 ALLOC(ush, tab_prefix, 1L<<BITS); 1865 ALLOC(ush, tab_prefix, 1L << BITS);
1826#else 1866#else
1827 ALLOC(ush, tab_prefix0, 1L<<(BITS-1)); 1867 ALLOC(ush, tab_prefix0, 1L << (BITS - 1));
1828 ALLOC(ush, tab_prefix1, 1L<<(BITS-1)); 1868 ALLOC(ush, tab_prefix1, 1L << (BITS - 1));
1829#endif 1869#endif
1830 1870
1831 if (fromstdin==1) { 1871 if (fromstdin == 1) {
1832 strcpy(ofname, "stdin"); 1872 strcpy(ofname, "stdin");
1833 1873
1834 inFileNum=fileno(stdin); 1874 inFileNum = fileno(stdin);
1835 time_stamp = 0; /* time unknown by default */ 1875 time_stamp = 0; /* time unknown by default */
1836 ifile_size = -1L; /* convention for unknown size */ 1876 ifile_size = -1L; /* convention for unknown size */
1837 } else { 1877 } else {
1838 /* Open up the input file */ 1878 /* Open up the input file */
1839 if (*argv=='\0') 1879 if (*argv == '\0')
1840 usage(gzip_usage); 1880 usage(gzip_usage);
1841 strncpy(ifname, *argv, MAX_PATH_LEN); 1881 strncpy(ifname, *argv, MAX_PATH_LEN);
1842 1882
1843 /* Open input fille */ 1883 /* Open input fille */
1844 inFileNum=open( ifname, O_RDONLY); 1884 inFileNum = open(ifname, O_RDONLY);
1845 if (inFileNum < 0) { 1885 if (inFileNum < 0) {
1846 perror(ifname); 1886 perror(ifname);
1847 do_exit(WARNING); 1887 do_exit(WARNING);
1848 } 1888 }
1849 /* Get the time stamp on the input file. */ 1889 /* Get the time stamp on the input file. */
1850 result = stat(ifname, &statBuf); 1890 result = stat(ifname, &statBuf);
1851 if (result < 0) { 1891 if (result < 0) {
1852 perror(ifname); 1892 perror(ifname);
1853 do_exit(WARNING); 1893 do_exit(WARNING);
1894 }
1895 time_stamp = statBuf.st_ctime;
1896 ifile_size = statBuf.st_size;
1854 } 1897 }
1855 time_stamp = statBuf.st_ctime;
1856 ifile_size = statBuf.st_size;
1857 }
1858 1898
1859 1899
1860 if (tostdout==1) { 1900 if (tostdout == 1) {
1861 /* And get to work */ 1901 /* And get to work */
1862 strcpy(ofname, "stdout"); 1902 strcpy(ofname, "stdout");
1863 outFileNum=fileno(stdout); 1903 outFileNum = fileno(stdout);
1864 SET_BINARY_MODE(fileno(stdout)); 1904 SET_BINARY_MODE(fileno(stdout));
1865 1905
1866 clear_bufs(); /* clear input and output buffers */ 1906 clear_bufs(); /* clear input and output buffers */
1867 part_nb = 0; 1907 part_nb = 0;
1868 1908
1869 /* Actually do the compression/decompression. */ 1909 /* Actually do the compression/decompression. */
1870 zip(inFileNum, outFileNum); 1910 zip(inFileNum, outFileNum);
1871 1911
1872 } else { 1912 } else {
1873 1913
1874 /* And get to work */ 1914 /* And get to work */
1875 strncpy(ofname, ifname, MAX_PATH_LEN-4); 1915 strncpy(ofname, ifname, MAX_PATH_LEN - 4);
1876 strcat(ofname, ".gz"); 1916 strcat(ofname, ".gz");
1877 1917
1878 1918
1879 /* Open output fille */ 1919 /* Open output fille */
1880#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 1920#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
1881 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW); 1921 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
1882#else 1922#else
1883 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL); 1923 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL);
1884#endif 1924#endif
1885 if (outFileNum < 0) { 1925 if (outFileNum < 0) {
1886 perror(ofname); 1926 perror(ofname);
1887 do_exit(WARNING); 1927 do_exit(WARNING);
1888 } 1928 }
1889 SET_BINARY_MODE(outFileNum); 1929 SET_BINARY_MODE(outFileNum);
1890 /* Set permissions on the file */ 1930 /* Set permissions on the file */
1891 fchmod(outFileNum, statBuf.st_mode); 1931 fchmod(outFileNum, statBuf.st_mode);
1892 1932
1893 clear_bufs(); /* clear input and output buffers */ 1933 clear_bufs(); /* clear input and output buffers */
1894 part_nb = 0; 1934 part_nb = 0;
1895 1935
1896 /* Actually do the compression/decompression. */ 1936 /* Actually do the compression/decompression. */
1897 result=zip(inFileNum, outFileNum); 1937 result = zip(inFileNum, outFileNum);
1898 close( outFileNum); 1938 close(outFileNum);
1899 close( inFileNum); 1939 close(inFileNum);
1900 /* Delete the original file */ 1940 /* Delete the original file */
1901 if (result == OK) 1941 if (result == OK)
1902 delFileName=ifname; 1942 delFileName = ifname;
1903 else 1943 else
1904 delFileName=ofname; 1944 delFileName = ofname;
1905 1945
1906 if (unlink (delFileName) < 0) { 1946 if (unlink(delFileName) < 0) {
1907 perror (delFileName); 1947 perror(delFileName);
1908 exit( FALSE); 1948 exit(FALSE);
1949 }
1909 } 1950 }
1910 }
1911 1951
1912 do_exit(exit_code); 1952 do_exit(exit_code);
1913} 1953}
1914 1954
1915/* trees.c -- output deflated data using Huffman coding 1955/* trees.c -- output deflated data using Huffman coding
@@ -1998,14 +2038,16 @@ int gzip_main(int argc, char ** argv)
1998/* number of codes used to transfer the bit lengths */ 2038/* number of codes used to transfer the bit lengths */
1999 2039
2000 2040
2001local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */ 2041local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */
2002 = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; 2042 = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2043 4, 4, 5, 5, 5, 5, 0 };
2003 2044
2004local int near extra_dbits[D_CODES] /* extra bits for each distance code */ 2045local int near extra_dbits[D_CODES] /* extra bits for each distance code */
2005 = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; 2046 = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
2047 10, 10, 11, 11, 12, 12, 13, 13 };
2006 2048
2007local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */ 2049local int near extra_blbits[BL_CODES] /* extra bits for each bit length code */
2008 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; 2050= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
2009 2051
2010#define STORED_BLOCK 0 2052#define STORED_BLOCK 0
2011#define STATIC_TREES 1 2053#define STATIC_TREES 1
@@ -2047,32 +2089,24 @@ local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */
2047 * if we rely on DIST_BUFSIZE == LIT_BUFSIZE. 2089 * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
2048 */ 2090 */
2049#if LIT_BUFSIZE > INBUFSIZ 2091#if LIT_BUFSIZE > INBUFSIZ
2050 error cannot overlay l_buf and inbuf 2092error cannot overlay l_buf and inbuf
2051#endif 2093#endif
2052
2053#define REP_3_6 16 2094#define REP_3_6 16
2054/* repeat previous bit length 3-6 times (2 bits of repeat count) */ 2095/* repeat previous bit length 3-6 times (2 bits of repeat count) */
2055
2056#define REPZ_3_10 17 2096#define REPZ_3_10 17
2057/* repeat a zero length 3-10 times (3 bits of repeat count) */ 2097/* repeat a zero length 3-10 times (3 bits of repeat count) */
2058
2059#define REPZ_11_138 18 2098#define REPZ_11_138 18
2060/* repeat a zero length 11-138 times (7 bits of repeat count) */ 2099/* repeat a zero length 11-138 times (7 bits of repeat count) *//* ===========================================================================
2061
2062/* ===========================================================================
2063 * Local data 2100 * Local data
2064 */ 2101 *//* Data structure describing a single value and its code string. */ typedef struct ct_data {
2065 2102 union {
2066/* Data structure describing a single value and its code string. */ 2103 ush freq; /* frequency count */
2067typedef struct ct_data { 2104 ush code; /* bit string */
2068 union { 2105 } fc;
2069 ush freq; /* frequency count */ 2106 union {
2070 ush code; /* bit string */ 2107 ush dad; /* father node in Huffman tree */
2071 } fc; 2108 ush len; /* length of bit string */
2072 union { 2109 } dl;
2073 ush dad; /* father node in Huffman tree */
2074 ush len; /* length of bit string */
2075 } dl;
2076} ct_data; 2110} ct_data;
2077 2111
2078#define Freq fc.freq 2112#define Freq fc.freq
@@ -2083,10 +2117,11 @@ typedef struct ct_data {
2083#define HEAP_SIZE (2*L_CODES+1) 2117#define HEAP_SIZE (2*L_CODES+1)
2084/* maximum heap size */ 2118/* maximum heap size */
2085 2119
2086local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */ 2120local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */
2087local ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */ 2121local ct_data near dyn_dtree[2 * D_CODES + 1]; /* distance tree */
2122
2123local ct_data near static_ltree[L_CODES + 2];
2088 2124
2089local ct_data near static_ltree[L_CODES+2];
2090/* The static literal tree. Since the bit lengths are imposed, there is no 2125/* The static literal tree. Since the bit lengths are imposed, there is no
2091 * need for the L_CODES extra codes used during heap construction. However 2126 * need for the L_CODES extra codes used during heap construction. However
2092 * The codes 286 and 287 are needed to build a canonical tree (see ct_init 2127 * The codes 286 and 287 are needed to build a canonical tree (see ct_init
@@ -2094,65 +2129,77 @@ local ct_data near static_ltree[L_CODES+2];
2094 */ 2129 */
2095 2130
2096local ct_data near static_dtree[D_CODES]; 2131local ct_data near static_dtree[D_CODES];
2132
2097/* The static distance tree. (Actually a trivial tree since all codes use 2133/* The static distance tree. (Actually a trivial tree since all codes use
2098 * 5 bits.) 2134 * 5 bits.)
2099 */ 2135 */
2100 2136
2101local ct_data near bl_tree[2*BL_CODES+1]; 2137local ct_data near bl_tree[2 * BL_CODES + 1];
2138
2102/* Huffman tree for the bit lengths */ 2139/* Huffman tree for the bit lengths */
2103 2140
2104typedef struct tree_desc { 2141typedef struct tree_desc {
2105 ct_data near *dyn_tree; /* the dynamic tree */ 2142 ct_data near *dyn_tree; /* the dynamic tree */
2106 ct_data near *static_tree; /* corresponding static tree or NULL */ 2143 ct_data near *static_tree; /* corresponding static tree or NULL */
2107 int near *extra_bits; /* extra bits for each code or NULL */ 2144 int near *extra_bits; /* extra bits for each code or NULL */
2108 int extra_base; /* base index for extra_bits */ 2145 int extra_base; /* base index for extra_bits */
2109 int elems; /* max number of elements in the tree */ 2146 int elems; /* max number of elements in the tree */
2110 int max_length; /* max bit length for the codes */ 2147 int max_length; /* max bit length for the codes */
2111 int max_code; /* largest code with non zero frequency */ 2148 int max_code; /* largest code with non zero frequency */
2112} tree_desc; 2149} tree_desc;
2113 2150
2114local tree_desc near l_desc = 2151local tree_desc near l_desc =
2115{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0}; 2152 { dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES,
2153 MAX_BITS, 0 };
2116 2154
2117local tree_desc near d_desc = 2155local tree_desc near d_desc =
2118{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0}; 2156 { dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 };
2119 2157
2120local tree_desc near bl_desc = 2158local tree_desc near bl_desc =
2121{bl_tree, (ct_data near *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0}; 2159 { bl_tree, (ct_data near *) 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS,
2160 0 };
2122 2161
2123 2162
2124local ush near bl_count[MAX_BITS+1]; 2163local ush near bl_count[MAX_BITS + 1];
2164
2125/* number of codes at each bit length for an optimal tree */ 2165/* number of codes at each bit length for an optimal tree */
2126 2166
2127local uch near bl_order[BL_CODES] 2167local uch near bl_order[BL_CODES]
2128 = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; 2168= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2169
2129/* The lengths of the bit length codes are sent in order of decreasing 2170/* The lengths of the bit length codes are sent in order of decreasing
2130 * probability, to avoid transmitting the lengths for unused bit length codes. 2171 * probability, to avoid transmitting the lengths for unused bit length codes.
2131 */ 2172 */
2132 2173
2133local int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ 2174local int near heap[2 * L_CODES + 1]; /* heap used to build the Huffman trees */
2134local int heap_len; /* number of elements in the heap */ 2175local int heap_len; /* number of elements in the heap */
2135local int heap_max; /* element of largest frequency */ 2176local int heap_max; /* element of largest frequency */
2177
2136/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. 2178/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
2137 * The same heap array is used to build all trees. 2179 * The same heap array is used to build all trees.
2138 */ 2180 */
2139 2181
2140local uch near depth[2*L_CODES+1]; 2182local uch near depth[2 * L_CODES + 1];
2183
2141/* Depth of each subtree used as tie breaker for trees of equal frequency */ 2184/* Depth of each subtree used as tie breaker for trees of equal frequency */
2142 2185
2143local uch length_code[MAX_MATCH-MIN_MATCH+1]; 2186local uch length_code[MAX_MATCH - MIN_MATCH + 1];
2187
2144/* length code for each normalized match length (0 == MIN_MATCH) */ 2188/* length code for each normalized match length (0 == MIN_MATCH) */
2145 2189
2146local uch dist_code[512]; 2190local uch dist_code[512];
2191
2147/* distance codes. The first 256 values correspond to the distances 2192/* distance codes. The first 256 values correspond to the distances
2148 * 3 .. 258, the last 256 values correspond to the top 8 bits of 2193 * 3 .. 258, the last 256 values correspond to the top 8 bits of
2149 * the 15 bit distances. 2194 * the 15 bit distances.
2150 */ 2195 */
2151 2196
2152local int near base_length[LENGTH_CODES]; 2197local int near base_length[LENGTH_CODES];
2198
2153/* First normalized length for each code (0 = MIN_MATCH) */ 2199/* First normalized length for each code (0 = MIN_MATCH) */
2154 2200
2155local int near base_dist[D_CODES]; 2201local int near base_dist[D_CODES];
2202
2156/* First normalized distance for each code (0 = distance of 1) */ 2203/* First normalized distance for each code (0 = distance of 1) */
2157 2204
2158#define l_buf inbuf 2205#define l_buf inbuf
@@ -2160,62 +2207,65 @@ local int near base_dist[D_CODES];
2160 2207
2161/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */ 2208/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
2162 2209
2163local uch near flag_buf[(LIT_BUFSIZE/8)]; 2210local uch near flag_buf[(LIT_BUFSIZE / 8)];
2211
2164/* flag_buf is a bit array distinguishing literals from lengths in 2212/* flag_buf is a bit array distinguishing literals from lengths in
2165 * l_buf, thus indicating the presence or absence of a distance. 2213 * l_buf, thus indicating the presence or absence of a distance.
2166 */ 2214 */
2167 2215
2168local unsigned last_lit; /* running index in l_buf */ 2216local unsigned last_lit; /* running index in l_buf */
2169local unsigned last_dist; /* running index in d_buf */ 2217local unsigned last_dist; /* running index in d_buf */
2170local unsigned last_flags; /* running index in flag_buf */ 2218local unsigned last_flags; /* running index in flag_buf */
2171local uch flags; /* current flags not yet saved in flag_buf */ 2219local uch flags; /* current flags not yet saved in flag_buf */
2172local uch flag_bit; /* current bit used in flags */ 2220local uch flag_bit; /* current bit used in flags */
2221
2173/* bits are filled in flags starting at bit 0 (least significant). 2222/* bits are filled in flags starting at bit 0 (least significant).
2174 * Note: these flags are overkill in the current code since we don't 2223 * Note: these flags are overkill in the current code since we don't
2175 * take advantage of DIST_BUFSIZE == LIT_BUFSIZE. 2224 * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
2176 */ 2225 */
2177 2226
2178local ulg opt_len; /* bit length of current block with optimal trees */ 2227local ulg opt_len; /* bit length of current block with optimal trees */
2179local ulg static_len; /* bit length of current block with static trees */ 2228local ulg static_len; /* bit length of current block with static trees */
2229
2230local ulg compressed_len; /* total bit length of compressed file */
2180 2231
2181local ulg compressed_len; /* total bit length of compressed file */ 2232local ulg input_len; /* total byte length of input file */
2182 2233
2183local ulg input_len; /* total byte length of input file */
2184/* input_len is for debugging only since we can get it by other means. */ 2234/* input_len is for debugging only since we can get it by other means. */
2185 2235
2186ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */ 2236ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */
2187int *file_method; /* pointer to DEFLATE or STORE */ 2237int *file_method; /* pointer to DEFLATE or STORE */
2188 2238
2189#ifdef DEBUG 2239#ifdef DEBUG
2190extern ulg bits_sent; /* bit length of the compressed data */ 2240extern ulg bits_sent; /* bit length of the compressed data */
2191extern long isize; /* byte length of input file */ 2241extern long isize; /* byte length of input file */
2192#endif 2242#endif
2193 2243
2194extern long block_start; /* window offset of current block */ 2244extern long block_start; /* window offset of current block */
2195extern unsigned near strstart; /* window offset of current string */ 2245extern unsigned near strstart; /* window offset of current string */
2196 2246
2197/* =========================================================================== 2247/* ===========================================================================
2198 * Local (static) routines in this file. 2248 * Local (static) routines in this file.
2199 */ 2249 */
2200 2250
2201local void init_block OF((void)); 2251local void init_block OF((void));
2202local void pqdownheap OF((ct_data near *tree, int k)); 2252local void pqdownheap OF((ct_data near * tree, int k));
2203local void gen_bitlen OF((tree_desc near *desc)); 2253local void gen_bitlen OF((tree_desc near * desc));
2204local void gen_codes OF((ct_data near *tree, int max_code)); 2254local void gen_codes OF((ct_data near * tree, int max_code));
2205local void build_tree OF((tree_desc near *desc)); 2255local void build_tree OF((tree_desc near * desc));
2206local void scan_tree OF((ct_data near *tree, int max_code)); 2256local void scan_tree OF((ct_data near * tree, int max_code));
2207local void send_tree OF((ct_data near *tree, int max_code)); 2257local void send_tree OF((ct_data near * tree, int max_code));
2208local int build_bl_tree OF((void)); 2258local int build_bl_tree OF((void));
2209local void send_all_trees OF((int lcodes, int dcodes, int blcodes)); 2259local void send_all_trees OF((int lcodes, int dcodes, int blcodes));
2210local void compress_block OF((ct_data near *ltree, ct_data near *dtree)); 2260local void compress_block OF((ct_data near * ltree, ct_data near * dtree));
2211local void set_file_type OF((void)); 2261local void set_file_type OF((void));
2212 2262
2213 2263
2214#ifndef DEBUG 2264#ifndef DEBUG
2215# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len) 2265# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
2216 /* Send a code of the given tree. c and tree must not have side effects */ 2266 /* Send a code of the given tree. c and tree must not have side effects */
2217 2267
2218#else /* DEBUG */ 2268#else /* DEBUG */
2219# define send_code(c, tree) \ 2269# define send_code(c, tree) \
2220 { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \ 2270 { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
2221 send_bits(tree[c].Code, tree[c].Len); } 2271 send_bits(tree[c].Code, tree[c].Len); }
@@ -2237,75 +2287,81 @@ local void set_file_type OF((void));
2237 * (DEFLATE/STORE). 2287 * (DEFLATE/STORE).
2238 */ 2288 */
2239void ct_init(attr, methodp) 2289void ct_init(attr, methodp)
2240 ush *attr; /* pointer to internal file attribute */ 2290ush *attr; /* pointer to internal file attribute */
2241 int *methodp; /* pointer to compression method */ 2291int *methodp; /* pointer to compression method */
2242{ 2292{
2243 int n; /* iterates over tree elements */ 2293 int n; /* iterates over tree elements */
2244 int bits; /* bit counter */ 2294 int bits; /* bit counter */
2245 int length; /* length value */ 2295 int length; /* length value */
2246 int code; /* code value */ 2296 int code; /* code value */
2247 int dist; /* distance index */ 2297 int dist; /* distance index */
2248 2298
2249 file_type = attr; 2299 file_type = attr;
2250 file_method = methodp; 2300 file_method = methodp;
2251 compressed_len = input_len = 0L; 2301 compressed_len = input_len = 0L;
2252 2302
2253 if (static_dtree[0].Len != 0) return; /* ct_init already called */ 2303 if (static_dtree[0].Len != 0)
2254 2304 return; /* ct_init already called */
2255 /* Initialize the mapping length (0..255) -> length code (0..28) */ 2305
2256 length = 0; 2306 /* Initialize the mapping length (0..255) -> length code (0..28) */
2257 for (code = 0; code < LENGTH_CODES-1; code++) { 2307 length = 0;
2258 base_length[code] = length; 2308 for (code = 0; code < LENGTH_CODES - 1; code++) {
2259 for (n = 0; n < (1<<extra_lbits[code]); n++) { 2309 base_length[code] = length;
2260 length_code[length++] = (uch)code; 2310 for (n = 0; n < (1 << extra_lbits[code]); n++) {
2261 } 2311 length_code[length++] = (uch) code;
2262 } 2312 }
2263 Assert (length == 256, "ct_init: length != 256"); 2313 }
2264 /* Note that the length 255 (match length 258) can be represented 2314 Assert(length == 256, "ct_init: length != 256");
2265 * in two different ways: code 284 + 5 bits or code 285, so we 2315 /* Note that the length 255 (match length 258) can be represented
2266 * overwrite length_code[255] to use the best encoding: 2316 * in two different ways: code 284 + 5 bits or code 285, so we
2267 */ 2317 * overwrite length_code[255] to use the best encoding:
2268 length_code[length-1] = (uch)code; 2318 */
2269 2319 length_code[length - 1] = (uch) code;
2270 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ 2320
2271 dist = 0; 2321 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
2272 for (code = 0 ; code < 16; code++) { 2322 dist = 0;
2273 base_dist[code] = dist; 2323 for (code = 0; code < 16; code++) {
2274 for (n = 0; n < (1<<extra_dbits[code]); n++) { 2324 base_dist[code] = dist;
2275 dist_code[dist++] = (uch)code; 2325 for (n = 0; n < (1 << extra_dbits[code]); n++) {
2276 } 2326 dist_code[dist++] = (uch) code;
2277 } 2327 }
2278 Assert (dist == 256, "ct_init: dist != 256"); 2328 }
2279 dist >>= 7; /* from now on, all distances are divided by 128 */ 2329 Assert(dist == 256, "ct_init: dist != 256");
2280 for ( ; code < D_CODES; code++) { 2330 dist >>= 7; /* from now on, all distances are divided by 128 */
2281 base_dist[code] = dist << 7; 2331 for (; code < D_CODES; code++) {
2282 for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { 2332 base_dist[code] = dist << 7;
2283 dist_code[256 + dist++] = (uch)code; 2333 for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
2284 } 2334 dist_code[256 + dist++] = (uch) code;
2285 } 2335 }
2286 Assert (dist == 256, "ct_init: 256+dist != 512"); 2336 }
2287 2337 Assert(dist == 256, "ct_init: 256+dist != 512");
2288 /* Construct the codes of the static literal tree */ 2338
2289 for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; 2339 /* Construct the codes of the static literal tree */
2290 n = 0; 2340 for (bits = 0; bits <= MAX_BITS; bits++)
2291 while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; 2341 bl_count[bits] = 0;
2292 while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; 2342 n = 0;
2293 while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; 2343 while (n <= 143)
2294 while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; 2344 static_ltree[n++].Len = 8, bl_count[8]++;
2295 /* Codes 286 and 287 do not exist, but we must include them in the 2345 while (n <= 255)
2296 * tree construction to get a canonical Huffman tree (longest code 2346 static_ltree[n++].Len = 9, bl_count[9]++;
2297 * all ones) 2347 while (n <= 279)
2298 */ 2348 static_ltree[n++].Len = 7, bl_count[7]++;
2299 gen_codes((ct_data near *)static_ltree, L_CODES+1); 2349 while (n <= 287)
2300 2350 static_ltree[n++].Len = 8, bl_count[8]++;
2301 /* The static distance tree is trivial: */ 2351 /* Codes 286 and 287 do not exist, but we must include them in the
2302 for (n = 0; n < D_CODES; n++) { 2352 * tree construction to get a canonical Huffman tree (longest code
2303 static_dtree[n].Len = 5; 2353 * all ones)
2304 static_dtree[n].Code = bi_reverse(n, 5); 2354 */
2305 } 2355 gen_codes((ct_data near *) static_ltree, L_CODES + 1);
2306 2356
2307 /* Initialize the first block of the first file: */ 2357 /* The static distance tree is trivial: */
2308 init_block(); 2358 for (n = 0; n < D_CODES; n++) {
2359 static_dtree[n].Len = 5;
2360 static_dtree[n].Code = bi_reverse(n, 5);
2361 }
2362
2363 /* Initialize the first block of the first file: */
2364 init_block();
2309} 2365}
2310 2366
2311/* =========================================================================== 2367/* ===========================================================================
@@ -2313,17 +2369,21 @@ void ct_init(attr, methodp)
2313 */ 2369 */
2314local void init_block() 2370local void init_block()
2315{ 2371{
2316 int n; /* iterates over tree elements */ 2372 int n; /* iterates over tree elements */
2317 2373
2318 /* Initialize the trees. */ 2374 /* Initialize the trees. */
2319 for (n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0; 2375 for (n = 0; n < L_CODES; n++)
2320 for (n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0; 2376 dyn_ltree[n].Freq = 0;
2321 for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0; 2377 for (n = 0; n < D_CODES; n++)
2322 2378 dyn_dtree[n].Freq = 0;
2323 dyn_ltree[END_BLOCK].Freq = 1; 2379 for (n = 0; n < BL_CODES; n++)
2324 opt_len = static_len = 0L; 2380 bl_tree[n].Freq = 0;
2325 last_lit = last_dist = last_flags = 0; 2381
2326 flags = 0; flag_bit = 1; 2382 dyn_ltree[END_BLOCK].Freq = 1;
2383 opt_len = static_len = 0L;
2384 last_lit = last_dist = last_flags = 0;
2385 flags = 0;
2386 flag_bit = 1;
2327} 2387}
2328 2388
2329#define SMALLEST 1 2389#define SMALLEST 1
@@ -2356,25 +2416,29 @@ local void init_block()
2356 * two sons). 2416 * two sons).
2357 */ 2417 */
2358local void pqdownheap(tree, k) 2418local void pqdownheap(tree, k)
2359 ct_data near *tree; /* the tree to restore */ 2419ct_data near *tree; /* the tree to restore */
2360 int k; /* node to move down */ 2420int k; /* node to move down */
2361{ 2421{
2362 int v = heap[k]; 2422 int v = heap[k];
2363 int j = k << 1; /* left son of k */ 2423 int j = k << 1; /* left son of k */
2364 while (j <= heap_len) { 2424
2365 /* Set j to the smallest of the two sons: */ 2425 while (j <= heap_len) {
2366 if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++; 2426 /* Set j to the smallest of the two sons: */
2367 2427 if (j < heap_len && smaller(tree, heap[j + 1], heap[j]))
2368 /* Exit if v is smaller than both sons */ 2428 j++;
2369 if (smaller(tree, v, heap[j])) break; 2429
2370 2430 /* Exit if v is smaller than both sons */
2371 /* Exchange v with the smallest son */ 2431 if (smaller(tree, v, heap[j]))
2372 heap[k] = heap[j]; k = j; 2432 break;
2373 2433
2374 /* And continue down the tree, setting j to the left son of k */ 2434 /* Exchange v with the smallest son */
2375 j <<= 1; 2435 heap[k] = heap[j];
2376 } 2436 k = j;
2377 heap[k] = v; 2437
2438 /* And continue down the tree, setting j to the left son of k */
2439 j <<= 1;
2440 }
2441 heap[k] = v;
2378} 2442}
2379 2443
2380/* =========================================================================== 2444/* ===========================================================================
@@ -2388,80 +2452,93 @@ local void pqdownheap(tree, k)
2388 * not null. 2452 * not null.
2389 */ 2453 */
2390local void gen_bitlen(desc) 2454local void gen_bitlen(desc)
2391 tree_desc near *desc; /* the tree descriptor */ 2455tree_desc near *desc; /* the tree descriptor */
2392{ 2456{
2393 ct_data near *tree = desc->dyn_tree; 2457 ct_data near *tree = desc->dyn_tree;
2394 int near *extra = desc->extra_bits; 2458 int near *extra = desc->extra_bits;
2395 int base = desc->extra_base; 2459 int base = desc->extra_base;
2396 int max_code = desc->max_code; 2460 int max_code = desc->max_code;
2397 int max_length = desc->max_length; 2461 int max_length = desc->max_length;
2398 ct_data near *stree = desc->static_tree; 2462 ct_data near *stree = desc->static_tree;
2399 int h; /* heap index */ 2463 int h; /* heap index */
2400 int n, m; /* iterate over the tree elements */ 2464 int n, m; /* iterate over the tree elements */
2401 int bits; /* bit length */ 2465 int bits; /* bit length */
2402 int xbits; /* extra bits */ 2466 int xbits; /* extra bits */
2403 ush f; /* frequency */ 2467 ush f; /* frequency */
2404 int overflow = 0; /* number of elements with bit length too large */ 2468 int overflow = 0; /* number of elements with bit length too large */
2405 2469
2406 for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; 2470 for (bits = 0; bits <= MAX_BITS; bits++)
2407 2471 bl_count[bits] = 0;
2408 /* In a first pass, compute the optimal bit lengths (which may 2472
2409 * overflow in the case of the bit length tree). 2473 /* In a first pass, compute the optimal bit lengths (which may
2410 */ 2474 * overflow in the case of the bit length tree).
2411 tree[heap[heap_max]].Len = 0; /* root of the heap */ 2475 */
2412 2476 tree[heap[heap_max]].Len = 0; /* root of the heap */
2413 for (h = heap_max+1; h < HEAP_SIZE; h++) { 2477
2414 n = heap[h]; 2478 for (h = heap_max + 1; h < HEAP_SIZE; h++) {
2415 bits = tree[tree[n].Dad].Len + 1; 2479 n = heap[h];
2416 if (bits > max_length) bits = max_length, overflow++; 2480 bits = tree[tree[n].Dad].Len + 1;
2417 tree[n].Len = (ush)bits; 2481 if (bits > max_length)
2418 /* We overwrite tree[n].Dad which is no longer needed */ 2482 bits = max_length, overflow++;
2419 2483 tree[n].Len = (ush) bits;
2420 if (n > max_code) continue; /* not a leaf node */ 2484 /* We overwrite tree[n].Dad which is no longer needed */
2421 2485
2422 bl_count[bits]++; 2486 if (n > max_code)
2423 xbits = 0; 2487 continue; /* not a leaf node */
2424 if (n >= base) xbits = extra[n-base]; 2488
2425 f = tree[n].Freq; 2489 bl_count[bits]++;
2426 opt_len += (ulg)f * (bits + xbits); 2490 xbits = 0;
2427 if (stree) static_len += (ulg)f * (stree[n].Len + xbits); 2491 if (n >= base)
2428 } 2492 xbits = extra[n - base];
2429 if (overflow == 0) return; 2493 f = tree[n].Freq;
2430 2494 opt_len += (ulg) f *(bits + xbits);
2431 Trace((stderr,"\nbit length overflow\n")); 2495
2432 /* This happens for example on obj2 and pic of the Calgary corpus */ 2496 if (stree)
2433 2497 static_len += (ulg) f *(stree[n].Len + xbits);
2434 /* Find the first bit length which could increase: */ 2498 }
2435 do { 2499 if (overflow == 0)
2436 bits = max_length-1; 2500 return;
2437 while (bl_count[bits] == 0) bits--; 2501
2438 bl_count[bits]--; /* move one leaf down the tree */ 2502 Trace((stderr, "\nbit length overflow\n"));
2439 bl_count[bits+1] += 2; /* move one overflow item as its brother */ 2503 /* This happens for example on obj2 and pic of the Calgary corpus */
2440 bl_count[max_length]--; 2504
2441 /* The brother of the overflow item also moves one step up, 2505 /* Find the first bit length which could increase: */
2442 * but this does not affect bl_count[max_length] 2506 do {
2443 */ 2507 bits = max_length - 1;
2444 overflow -= 2; 2508 while (bl_count[bits] == 0)
2445 } while (overflow > 0); 2509 bits--;
2446 2510 bl_count[bits]--; /* move one leaf down the tree */
2447 /* Now recompute all bit lengths, scanning in increasing frequency. 2511 bl_count[bits + 1] += 2; /* move one overflow item as its brother */
2448 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all 2512 bl_count[max_length]--;
2449 * lengths instead of fixing only the wrong ones. This idea is taken 2513 /* The brother of the overflow item also moves one step up,
2450 * from 'ar' written by Haruhiko Okumura.) 2514 * but this does not affect bl_count[max_length]
2451 */ 2515 */
2452 for (bits = max_length; bits != 0; bits--) { 2516 overflow -= 2;
2453 n = bl_count[bits]; 2517 } while (overflow > 0);
2454 while (n != 0) { 2518
2455 m = heap[--h]; 2519 /* Now recompute all bit lengths, scanning in increasing frequency.
2456 if (m > max_code) continue; 2520 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
2457 if (tree[m].Len != (unsigned) bits) { 2521 * lengths instead of fixing only the wrong ones. This idea is taken
2458 Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); 2522 * from 'ar' written by Haruhiko Okumura.)
2459 opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq; 2523 */
2460 tree[m].Len = (ush)bits; 2524 for (bits = max_length; bits != 0; bits--) {
2461 } 2525 n = bl_count[bits];
2462 n--; 2526 while (n != 0) {
2463 } 2527 m = heap[--h];
2464 } 2528 if (m > max_code)
2529 continue;
2530 if (tree[m].Len != (unsigned) bits) {
2531 Trace(
2532 (stderr, "code %d bits %d->%d\n", m, tree[m].Len,
2533 bits));
2534 opt_len +=
2535 ((long) bits -
2536 (long) tree[m].Len) * (long) tree[m].Freq;
2537 tree[m].Len = (ush) bits;
2538 }
2539 n--;
2540 }
2541 }
2465} 2542}
2466 2543
2467/* =========================================================================== 2544/* ===========================================================================
@@ -2472,37 +2549,41 @@ local void gen_bitlen(desc)
2472 * OUT assertion: the field code is set for all tree elements of non 2549 * OUT assertion: the field code is set for all tree elements of non
2473 * zero code length. 2550 * zero code length.
2474 */ 2551 */
2475local void gen_codes (tree, max_code) 2552local void gen_codes(tree, max_code)
2476 ct_data near *tree; /* the tree to decorate */ 2553ct_data near *tree; /* the tree to decorate */
2477 int max_code; /* largest code with non zero frequency */ 2554int max_code; /* largest code with non zero frequency */
2478{ 2555{
2479 ush next_code[MAX_BITS+1]; /* next code value for each bit length */ 2556 ush next_code[MAX_BITS + 1]; /* next code value for each bit length */
2480 ush code = 0; /* running code value */ 2557 ush code = 0; /* running code value */
2481 int bits; /* bit index */ 2558 int bits; /* bit index */
2482 int n; /* code index */ 2559 int n; /* code index */
2483 2560
2484 /* The distribution counts are first used to generate the code values 2561 /* The distribution counts are first used to generate the code values
2485 * without bit reversal. 2562 * without bit reversal.
2486 */ 2563 */
2487 for (bits = 1; bits <= MAX_BITS; bits++) { 2564 for (bits = 1; bits <= MAX_BITS; bits++) {
2488 next_code[bits] = code = (code + bl_count[bits-1]) << 1; 2565 next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
2489 } 2566 }
2490 /* Check that the bit counts in bl_count are consistent. The last code 2567 /* Check that the bit counts in bl_count are consistent. The last code
2491 * must be all ones. 2568 * must be all ones.
2492 */ 2569 */
2493 Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, 2570 Assert(code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
2494 "inconsistent bit counts"); 2571 "inconsistent bit counts");
2495 Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); 2572 Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
2496 2573
2497 for (n = 0; n <= max_code; n++) { 2574 for (n = 0; n <= max_code; n++) {
2498 int len = tree[n].Len; 2575 int len = tree[n].Len;
2499 if (len == 0) continue; 2576
2500 /* Now reverse the bits */ 2577 if (len == 0)
2501 tree[n].Code = bi_reverse(next_code[len]++, len); 2578 continue;
2502 2579 /* Now reverse the bits */
2503 Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", 2580 tree[n].Code = bi_reverse(next_code[len]++, len);
2504 n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); 2581
2505 } 2582 Tracec(tree != static_ltree,
2583 (stderr, "\nn %3d %c l %2d c %4x (%x) ", n,
2584 (isgraph(n) ? n : ' '), len, tree[n].Code,
2585 next_code[len] - 1));
2586 }
2506} 2587}
2507 2588
2508/* =========================================================================== 2589/* ===========================================================================
@@ -2514,84 +2595,89 @@ local void gen_codes (tree, max_code)
2514 * also updated if stree is not null. The field max_code is set. 2595 * also updated if stree is not null. The field max_code is set.
2515 */ 2596 */
2516local void build_tree(desc) 2597local void build_tree(desc)
2517 tree_desc near *desc; /* the tree descriptor */ 2598tree_desc near *desc; /* the tree descriptor */
2518{ 2599{
2519 ct_data near *tree = desc->dyn_tree; 2600 ct_data near *tree = desc->dyn_tree;
2520 ct_data near *stree = desc->static_tree; 2601 ct_data near *stree = desc->static_tree;
2521 int elems = desc->elems; 2602 int elems = desc->elems;
2522 int n, m; /* iterate over heap elements */ 2603 int n, m; /* iterate over heap elements */
2523 int max_code = -1; /* largest code with non zero frequency */ 2604 int max_code = -1; /* largest code with non zero frequency */
2524 int node = elems; /* next internal node of the tree */ 2605 int node = elems; /* next internal node of the tree */
2525 2606
2526 /* Construct the initial heap, with least frequent element in 2607 /* Construct the initial heap, with least frequent element in
2527 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. 2608 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
2528 * heap[0] is not used. 2609 * heap[0] is not used.
2529 */ 2610 */
2530 heap_len = 0, heap_max = HEAP_SIZE; 2611 heap_len = 0, heap_max = HEAP_SIZE;
2531 2612
2532 for (n = 0; n < elems; n++) { 2613 for (n = 0; n < elems; n++) {
2533 if (tree[n].Freq != 0) { 2614 if (tree[n].Freq != 0) {
2534 heap[++heap_len] = max_code = n; 2615 heap[++heap_len] = max_code = n;
2535 depth[n] = 0; 2616 depth[n] = 0;
2536 } else { 2617 } else {
2537 tree[n].Len = 0; 2618 tree[n].Len = 0;
2538 } 2619 }
2539 } 2620 }
2540 2621
2541 /* The pkzip format requires that at least one distance code exists, 2622 /* The pkzip format requires that at least one distance code exists,
2542 * and that at least one bit should be sent even if there is only one 2623 * and that at least one bit should be sent even if there is only one
2543 * possible code. So to avoid special checks later on we force at least 2624 * possible code. So to avoid special checks later on we force at least
2544 * two codes of non zero frequency. 2625 * two codes of non zero frequency.
2545 */ 2626 */
2546 while (heap_len < 2) { 2627 while (heap_len < 2) {
2547 int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0); 2628 int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
2548 tree[new].Freq = 1; 2629
2549 depth[new] = 0; 2630 tree[new].Freq = 1;
2550 opt_len--; if (stree) static_len -= stree[new].Len; 2631 depth[new] = 0;
2551 /* new is 0 or 1 so it does not have extra bits */ 2632 opt_len--;
2552 } 2633 if (stree)
2553 desc->max_code = max_code; 2634 static_len -= stree[new].Len;
2554 2635 /* new is 0 or 1 so it does not have extra bits */
2555 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, 2636 }
2556 * establish sub-heaps of increasing lengths: 2637 desc->max_code = max_code;
2557 */ 2638
2558 for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n); 2639 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
2559 2640 * establish sub-heaps of increasing lengths:
2560 /* Construct the Huffman tree by repeatedly combining the least two 2641 */
2561 * frequent nodes. 2642 for (n = heap_len / 2; n >= 1; n--)
2562 */ 2643 pqdownheap(tree, n);
2563 do { 2644
2564 pqremove(tree, n); /* n = node of least frequency */ 2645 /* Construct the Huffman tree by repeatedly combining the least two
2565 m = heap[SMALLEST]; /* m = node of next least frequency */ 2646 * frequent nodes.
2566 2647 */
2567 heap[--heap_max] = n; /* keep the nodes sorted by frequency */ 2648 do {
2568 heap[--heap_max] = m; 2649 pqremove(tree, n); /* n = node of least frequency */
2569 2650 m = heap[SMALLEST]; /* m = node of next least frequency */
2570 /* Create a new node father of n and m */ 2651
2571 tree[node].Freq = tree[n].Freq + tree[m].Freq; 2652 heap[--heap_max] = n; /* keep the nodes sorted by frequency */
2572 depth[node] = (uch) (MAX(depth[n], depth[m]) + 1); 2653 heap[--heap_max] = m;
2573 tree[n].Dad = tree[m].Dad = (ush)node; 2654
2655 /* Create a new node father of n and m */
2656 tree[node].Freq = tree[n].Freq + tree[m].Freq;
2657 depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
2658 tree[n].Dad = tree[m].Dad = (ush) node;
2574#ifdef DUMP_BL_TREE 2659#ifdef DUMP_BL_TREE
2575 if (tree == bl_tree) { 2660 if (tree == bl_tree) {
2576 fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", 2661 fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)",
2577 node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); 2662 node, tree[node].Freq, n, tree[n].Freq, m,
2578 } 2663 tree[m].Freq);
2664 }
2579#endif 2665#endif
2580 /* and insert the new node in the heap */ 2666 /* and insert the new node in the heap */
2581 heap[SMALLEST] = node++; 2667 heap[SMALLEST] = node++;
2582 pqdownheap(tree, SMALLEST); 2668 pqdownheap(tree, SMALLEST);
2583 2669
2584 } while (heap_len >= 2); 2670 } while (heap_len >= 2);
2585 2671
2586 heap[--heap_max] = heap[SMALLEST]; 2672 heap[--heap_max] = heap[SMALLEST];
2587 2673
2588 /* At this point, the fields freq and dad are set. We can now 2674 /* At this point, the fields freq and dad are set. We can now
2589 * generate the bit lengths. 2675 * generate the bit lengths.
2590 */ 2676 */
2591 gen_bitlen((tree_desc near *)desc); 2677 gen_bitlen((tree_desc near *) desc);
2592 2678
2593 /* The field len is now set, we can generate the bit codes */ 2679 /* The field len is now set, we can generate the bit codes */
2594 gen_codes ((ct_data near *)tree, max_code); 2680 gen_codes((ct_data near *) tree, max_code);
2595} 2681}
2596 2682
2597/* =========================================================================== 2683/* ===========================================================================
@@ -2600,94 +2686,107 @@ local void build_tree(desc)
2600 * counts. (The contribution of the bit length codes will be added later 2686 * counts. (The contribution of the bit length codes will be added later
2601 * during the construction of bl_tree.) 2687 * during the construction of bl_tree.)
2602 */ 2688 */
2603local void scan_tree (tree, max_code) 2689local void scan_tree(tree, max_code)
2604 ct_data near *tree; /* the tree to be scanned */ 2690ct_data near *tree; /* the tree to be scanned */
2605 int max_code; /* and its largest code of non zero frequency */ 2691int max_code; /* and its largest code of non zero frequency */
2606{ 2692{
2607 int n; /* iterates over all tree elements */ 2693 int n; /* iterates over all tree elements */
2608 int prevlen = -1; /* last emitted length */ 2694 int prevlen = -1; /* last emitted length */
2609 int curlen; /* length of current code */ 2695 int curlen; /* length of current code */
2610 int nextlen = tree[0].Len; /* length of next code */ 2696 int nextlen = tree[0].Len; /* length of next code */
2611 int count = 0; /* repeat count of the current code */ 2697 int count = 0; /* repeat count of the current code */
2612 int max_count = 7; /* max repeat count */ 2698 int max_count = 7; /* max repeat count */
2613 int min_count = 4; /* min repeat count */ 2699 int min_count = 4; /* min repeat count */
2614 2700
2615 if (nextlen == 0) max_count = 138, min_count = 3; 2701 if (nextlen == 0)
2616 tree[max_code+1].Len = (ush)0xffff; /* guard */ 2702 max_count = 138, min_count = 3;
2617 2703 tree[max_code + 1].Len = (ush) 0xffff; /* guard */
2618 for (n = 0; n <= max_code; n++) { 2704
2619 curlen = nextlen; nextlen = tree[n+1].Len; 2705 for (n = 0; n <= max_code; n++) {
2620 if (++count < max_count && curlen == nextlen) { 2706 curlen = nextlen;
2621 continue; 2707 nextlen = tree[n + 1].Len;
2622 } else if (count < min_count) { 2708 if (++count < max_count && curlen == nextlen) {
2623 bl_tree[curlen].Freq += count; 2709 continue;
2624 } else if (curlen != 0) { 2710 } else if (count < min_count) {
2625 if (curlen != prevlen) bl_tree[curlen].Freq++; 2711 bl_tree[curlen].Freq += count;
2626 bl_tree[REP_3_6].Freq++; 2712 } else if (curlen != 0) {
2627 } else if (count <= 10) { 2713 if (curlen != prevlen)
2628 bl_tree[REPZ_3_10].Freq++; 2714 bl_tree[curlen].Freq++;
2629 } else { 2715 bl_tree[REP_3_6].Freq++;
2630 bl_tree[REPZ_11_138].Freq++; 2716 } else if (count <= 10) {
2631 } 2717 bl_tree[REPZ_3_10].Freq++;
2632 count = 0; prevlen = curlen; 2718 } else {
2633 if (nextlen == 0) { 2719 bl_tree[REPZ_11_138].Freq++;
2634 max_count = 138, min_count = 3; 2720 }
2635 } else if (curlen == nextlen) { 2721 count = 0;
2636 max_count = 6, min_count = 3; 2722 prevlen = curlen;
2637 } else { 2723 if (nextlen == 0) {
2638 max_count = 7, min_count = 4; 2724 max_count = 138, min_count = 3;
2639 } 2725 } else if (curlen == nextlen) {
2640 } 2726 max_count = 6, min_count = 3;
2727 } else {
2728 max_count = 7, min_count = 4;
2729 }
2730 }
2641} 2731}
2642 2732
2643/* =========================================================================== 2733/* ===========================================================================
2644 * Send a literal or distance tree in compressed form, using the codes in 2734 * Send a literal or distance tree in compressed form, using the codes in
2645 * bl_tree. 2735 * bl_tree.
2646 */ 2736 */
2647local void send_tree (tree, max_code) 2737local void send_tree(tree, max_code)
2648 ct_data near *tree; /* the tree to be scanned */ 2738ct_data near *tree; /* the tree to be scanned */
2649 int max_code; /* and its largest code of non zero frequency */ 2739int max_code; /* and its largest code of non zero frequency */
2650{ 2740{
2651 int n; /* iterates over all tree elements */ 2741 int n; /* iterates over all tree elements */
2652 int prevlen = -1; /* last emitted length */ 2742 int prevlen = -1; /* last emitted length */
2653 int curlen; /* length of current code */ 2743 int curlen; /* length of current code */
2654 int nextlen = tree[0].Len; /* length of next code */ 2744 int nextlen = tree[0].Len; /* length of next code */
2655 int count = 0; /* repeat count of the current code */ 2745 int count = 0; /* repeat count of the current code */
2656 int max_count = 7; /* max repeat count */ 2746 int max_count = 7; /* max repeat count */
2657 int min_count = 4; /* min repeat count */ 2747 int min_count = 4; /* min repeat count */
2658 2748
2659 /* tree[max_code+1].Len = -1; */ /* guard already set */ 2749/* tree[max_code+1].Len = -1; *//* guard already set */
2660 if (nextlen == 0) max_count = 138, min_count = 3; 2750 if (nextlen == 0)
2661 2751 max_count = 138, min_count = 3;
2662 for (n = 0; n <= max_code; n++) { 2752
2663 curlen = nextlen; nextlen = tree[n+1].Len; 2753 for (n = 0; n <= max_code; n++) {
2664 if (++count < max_count && curlen == nextlen) { 2754 curlen = nextlen;
2665 continue; 2755 nextlen = tree[n + 1].Len;
2666 } else if (count < min_count) { 2756 if (++count < max_count && curlen == nextlen) {
2667 do { send_code(curlen, bl_tree); } while (--count != 0); 2757 continue;
2668 2758 } else if (count < min_count) {
2669 } else if (curlen != 0) { 2759 do {
2670 if (curlen != prevlen) { 2760 send_code(curlen, bl_tree);
2671 send_code(curlen, bl_tree); count--; 2761 } while (--count != 0);
2672 } 2762
2673 Assert(count >= 3 && count <= 6, " 3_6?"); 2763 } else if (curlen != 0) {
2674 send_code(REP_3_6, bl_tree); send_bits(count-3, 2); 2764 if (curlen != prevlen) {
2675 2765 send_code(curlen, bl_tree);
2676 } else if (count <= 10) { 2766 count--;
2677 send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3); 2767 }
2678 2768 Assert(count >= 3 && count <= 6, " 3_6?");
2679 } else { 2769 send_code(REP_3_6, bl_tree);
2680 send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7); 2770 send_bits(count - 3, 2);
2681 } 2771
2682 count = 0; prevlen = curlen; 2772 } else if (count <= 10) {
2683 if (nextlen == 0) { 2773 send_code(REPZ_3_10, bl_tree);
2684 max_count = 138, min_count = 3; 2774 send_bits(count - 3, 3);
2685 } else if (curlen == nextlen) { 2775
2686 max_count = 6, min_count = 3; 2776 } else {
2687 } else { 2777 send_code(REPZ_11_138, bl_tree);
2688 max_count = 7, min_count = 4; 2778 send_bits(count - 11, 7);
2689 } 2779 }
2690 } 2780 count = 0;
2781 prevlen = curlen;
2782 if (nextlen == 0) {
2783 max_count = 138, min_count = 3;
2784 } else if (curlen == nextlen) {
2785 max_count = 6, min_count = 3;
2786 } else {
2787 max_count = 7, min_count = 4;
2788 }
2789 }
2691} 2790}
2692 2791
2693/* =========================================================================== 2792/* ===========================================================================
@@ -2696,30 +2795,33 @@ local void send_tree (tree, max_code)
2696 */ 2795 */
2697local int build_bl_tree() 2796local int build_bl_tree()
2698{ 2797{
2699 int max_blindex; /* index of last bit length code of non zero freq */ 2798 int max_blindex; /* index of last bit length code of non zero freq */
2700 2799
2701 /* Determine the bit length frequencies for literal and distance trees */ 2800 /* Determine the bit length frequencies for literal and distance trees */
2702 scan_tree((ct_data near *)dyn_ltree, l_desc.max_code); 2801 scan_tree((ct_data near *) dyn_ltree, l_desc.max_code);
2703 scan_tree((ct_data near *)dyn_dtree, d_desc.max_code); 2802 scan_tree((ct_data near *) dyn_dtree, d_desc.max_code);
2704 2803
2705 /* Build the bit length tree: */ 2804 /* Build the bit length tree: */
2706 build_tree((tree_desc near *)(&bl_desc)); 2805 build_tree((tree_desc near *) (&bl_desc));
2707 /* opt_len now includes the length of the tree representations, except 2806 /* opt_len now includes the length of the tree representations, except
2708 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. 2807 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
2709 */ 2808 */
2710 2809
2711 /* Determine the number of bit length codes to send. The pkzip format 2810 /* Determine the number of bit length codes to send. The pkzip format
2712 * requires that at least 4 bit length codes be sent. (appnote.txt says 2811 * requires that at least 4 bit length codes be sent. (appnote.txt says
2713 * 3 but the actual value used is 4.) 2812 * 3 but the actual value used is 4.)
2714 */ 2813 */
2715 for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { 2814 for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
2716 if (bl_tree[bl_order[max_blindex]].Len != 0) break; 2815 if (bl_tree[bl_order[max_blindex]].Len != 0)
2717 } 2816 break;
2718 /* Update opt_len to include the bit length tree and counts */ 2817 }
2719 opt_len += 3*(max_blindex+1) + 5+5+4; 2818 /* Update opt_len to include the bit length tree and counts */
2720 Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len)); 2819 opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
2721 2820 Tracev(
2722 return max_blindex; 2821 (stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len,
2822 static_len));
2823
2824 return max_blindex;
2723} 2825}
2724 2826
2725/* =========================================================================== 2827/* ===========================================================================
@@ -2728,28 +2830,29 @@ local int build_bl_tree()
2728 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. 2830 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
2729 */ 2831 */
2730local void send_all_trees(lcodes, dcodes, blcodes) 2832local void send_all_trees(lcodes, dcodes, blcodes)
2731 int lcodes, dcodes, blcodes; /* number of codes for each tree */ 2833int lcodes, dcodes, blcodes; /* number of codes for each tree */
2732{ 2834{
2733 int rank; /* index in bl_order */ 2835 int rank; /* index in bl_order */
2734 2836
2735 Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); 2837 Assert(lcodes >= 257 && dcodes >= 1
2736 Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, 2838 && blcodes >= 4, "not enough codes");
2737 "too many codes"); 2839 Assert(lcodes <= L_CODES && dcodes <= D_CODES
2738 Tracev((stderr, "\nbl counts: ")); 2840 && blcodes <= BL_CODES, "too many codes");
2739 send_bits(lcodes-257, 5); /* not +255 as stated in appnote.txt */ 2841 Tracev((stderr, "\nbl counts: "));
2740 send_bits(dcodes-1, 5); 2842 send_bits(lcodes - 257, 5); /* not +255 as stated in appnote.txt */
2741 send_bits(blcodes-4, 4); /* not -3 as stated in appnote.txt */ 2843 send_bits(dcodes - 1, 5);
2742 for (rank = 0; rank < blcodes; rank++) { 2844 send_bits(blcodes - 4, 4); /* not -3 as stated in appnote.txt */
2743 Tracev((stderr, "\nbl code %2d ", bl_order[rank])); 2845 for (rank = 0; rank < blcodes; rank++) {
2744 send_bits(bl_tree[bl_order[rank]].Len, 3); 2846 Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
2745 } 2847 send_bits(bl_tree[bl_order[rank]].Len, 3);
2746 Tracev((stderr, "\nbl tree: sent %ld", bits_sent)); 2848 }
2747 2849 Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
2748 send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */ 2850
2749 Tracev((stderr, "\nlit tree: sent %ld", bits_sent)); 2851 send_tree((ct_data near *) dyn_ltree, lcodes - 1); /* send the literal tree */
2750 2852 Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
2751 send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */ 2853
2752 Tracev((stderr, "\ndist tree: sent %ld", bits_sent)); 2854 send_tree((ct_data near *) dyn_dtree, dcodes - 1); /* send the distance tree */
2855 Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
2753} 2856}
2754 2857
2755/* =========================================================================== 2858/* ===========================================================================
@@ -2758,204 +2861,222 @@ local void send_all_trees(lcodes, dcodes, blcodes)
2758 * returns the total compressed length for the file so far. 2861 * returns the total compressed length for the file so far.
2759 */ 2862 */
2760ulg flush_block(buf, stored_len, eof) 2863ulg flush_block(buf, stored_len, eof)
2761 char *buf; /* input block, or NULL if too old */ 2864char *buf; /* input block, or NULL if too old */
2762 ulg stored_len; /* length of input block */ 2865ulg stored_len; /* length of input block */
2763 int eof; /* true if this is the last block for a file */ 2866int eof; /* true if this is the last block for a file */
2764{ 2867{
2765 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ 2868 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
2766 int max_blindex; /* index of last bit length code of non zero freq */ 2869 int max_blindex; /* index of last bit length code of non zero freq */
2767 2870
2768 flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ 2871 flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
2769 2872
2770 /* Check if the file is ascii or binary */ 2873 /* Check if the file is ascii or binary */
2771 if (*file_type == (ush)UNKNOWN) set_file_type(); 2874 if (*file_type == (ush) UNKNOWN)
2772 2875 set_file_type();
2773 /* Construct the literal and distance trees */ 2876
2774 build_tree((tree_desc near *)(&l_desc)); 2877 /* Construct the literal and distance trees */
2775 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); 2878 build_tree((tree_desc near *) (&l_desc));
2776 2879 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
2777 build_tree((tree_desc near *)(&d_desc)); 2880
2778 Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len)); 2881 build_tree((tree_desc near *) (&d_desc));
2779 /* At this point, opt_len and static_len are the total bit lengths of 2882 Tracev(
2780 * the compressed block data, excluding the tree representations. 2883 (stderr, "\ndist data: dyn %ld, stat %ld", opt_len,
2781 */ 2884 static_len));
2782 2885 /* At this point, opt_len and static_len are the total bit lengths of
2783 /* Build the bit length tree for the above two trees, and get the index 2886 * the compressed block data, excluding the tree representations.
2784 * in bl_order of the last bit length code to send. 2887 */
2785 */ 2888
2786 max_blindex = build_bl_tree(); 2889 /* Build the bit length tree for the above two trees, and get the index
2787 2890 * in bl_order of the last bit length code to send.
2788 /* Determine the best encoding. Compute first the block length in bytes */ 2891 */
2789 opt_lenb = (opt_len+3+7)>>3; 2892 max_blindex = build_bl_tree();
2790 static_lenb = (static_len+3+7)>>3; 2893
2791 input_len += stored_len; /* for debugging only */ 2894 /* Determine the best encoding. Compute first the block length in bytes */
2792 2895 opt_lenb = (opt_len + 3 + 7) >> 3;
2793 Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", 2896 static_lenb = (static_len + 3 + 7) >> 3;
2794 opt_lenb, opt_len, static_lenb, static_len, stored_len, 2897 input_len += stored_len; /* for debugging only */
2795 last_lit, last_dist)); 2898
2796 2899 Trace(
2797 if (static_lenb <= opt_lenb) opt_lenb = static_lenb; 2900 (stderr,
2798 2901 "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
2799 /* If compression failed and this is the first and last block, 2902 opt_lenb, opt_len, static_lenb, static_len, stored_len,
2800 * and if the zip file can be seeked (to rewrite the local header), 2903 last_lit, last_dist));
2801 * the whole file is transformed into a stored file: 2904
2802 */ 2905 if (static_lenb <= opt_lenb)
2906 opt_lenb = static_lenb;
2907
2908 /* If compression failed and this is the first and last block,
2909 * and if the zip file can be seeked (to rewrite the local header),
2910 * the whole file is transformed into a stored file:
2911 */
2803#ifdef FORCE_METHOD 2912#ifdef FORCE_METHOD
2804#else 2913#else
2805 if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) { 2914 if (stored_len <= opt_lenb && eof && compressed_len == 0L
2915 && seekable()) {
2806#endif 2916#endif
2807 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ 2917 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
2808 if (buf == (char*)0) error ("block vanished"); 2918 if (buf == (char *) 0)
2919 error("block vanished");
2809 2920
2810 copy_block(buf, (unsigned)stored_len, 0); /* without header */ 2921 copy_block(buf, (unsigned) stored_len, 0); /* without header */
2811 compressed_len = stored_len << 3; 2922 compressed_len = stored_len << 3;
2812 *file_method = STORED; 2923 *file_method = STORED;
2813 2924
2814#ifdef FORCE_METHOD 2925#ifdef FORCE_METHOD
2815#else 2926#else
2816 } else if (stored_len+4 <= opt_lenb && buf != (char*)0) { 2927 } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
2817 /* 4: two words for the lengths */ 2928 /* 4: two words for the lengths */
2818#endif 2929#endif
2819 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. 2930 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
2820 * Otherwise we can't have processed more than WSIZE input bytes since 2931 * Otherwise we can't have processed more than WSIZE input bytes since
2821 * the last block flush, because compression would have been 2932 * the last block flush, because compression would have been
2822 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 2933 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
2823 * transform a block into a stored block. 2934 * transform a block into a stored block.
2824 */ 2935 */
2825 send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */ 2936 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */
2826 compressed_len = (compressed_len + 3 + 7) & ~7L; 2937 compressed_len = (compressed_len + 3 + 7) & ~7L;
2827 compressed_len += (stored_len + 4) << 3; 2938 compressed_len += (stored_len + 4) << 3;
2828 2939
2829 copy_block(buf, (unsigned)stored_len, 1); /* with header */ 2940 copy_block(buf, (unsigned) stored_len, 1); /* with header */
2830 2941
2831#ifdef FORCE_METHOD 2942#ifdef FORCE_METHOD
2832#else 2943#else
2833 } else if (static_lenb == opt_lenb) { 2944 } else if (static_lenb == opt_lenb) {
2834#endif 2945#endif
2835 send_bits((STATIC_TREES<<1)+eof, 3); 2946 send_bits((STATIC_TREES << 1) + eof, 3);
2836 compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree); 2947 compress_block((ct_data near *) static_ltree,
2837 compressed_len += 3 + static_len; 2948 (ct_data near *) static_dtree);
2838 } else { 2949 compressed_len += 3 + static_len;
2839 send_bits((DYN_TREES<<1)+eof, 3); 2950 } else {
2840 send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); 2951 send_bits((DYN_TREES << 1) + eof, 3);
2841 compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree); 2952 send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
2842 compressed_len += 3 + opt_len; 2953 max_blindex + 1);
2843 } 2954 compress_block((ct_data near *) dyn_ltree,
2844 Assert (compressed_len == bits_sent, "bad compressed size"); 2955 (ct_data near *) dyn_dtree);
2845 init_block(); 2956 compressed_len += 3 + opt_len;
2846 2957 }
2847 if (eof) { 2958 Assert(compressed_len == bits_sent, "bad compressed size");
2848 Assert (input_len == isize, "bad input size"); 2959 init_block();
2849 bi_windup(); 2960
2850 compressed_len += 7; /* align on byte boundary */ 2961 if (eof) {
2851 } 2962 Assert(input_len == isize, "bad input size");
2852 Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3, 2963 bi_windup();
2853 compressed_len-7*eof)); 2964 compressed_len += 7; /* align on byte boundary */
2854 2965 }
2855 return compressed_len >> 3; 2966 Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
2967 compressed_len - 7 * eof));
2968
2969 return compressed_len >> 3;
2856} 2970}
2857 2971
2858/* =========================================================================== 2972/* ===========================================================================
2859 * Save the match info and tally the frequency counts. Return true if 2973 * Save the match info and tally the frequency counts. Return true if
2860 * the current block must be flushed. 2974 * the current block must be flushed.
2861 */ 2975 */
2862int ct_tally (dist, lc) 2976int ct_tally(dist, lc)
2863 int dist; /* distance of matched string */ 2977int dist; /* distance of matched string */
2864 int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ 2978int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
2865{ 2979{
2866 l_buf[last_lit++] = (uch)lc; 2980 l_buf[last_lit++] = (uch) lc;
2867 if (dist == 0) { 2981 if (dist == 0) {
2868 /* lc is the unmatched char */ 2982 /* lc is the unmatched char */
2869 dyn_ltree[lc].Freq++; 2983 dyn_ltree[lc].Freq++;
2870 } else { 2984 } else {
2871 /* Here, lc is the match length - MIN_MATCH */ 2985 /* Here, lc is the match length - MIN_MATCH */
2872 dist--; /* dist = match distance - 1 */ 2986 dist--; /* dist = match distance - 1 */
2873 Assert((ush)dist < (ush)MAX_DIST && 2987 Assert((ush) dist < (ush) MAX_DIST &&
2874 (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && 2988 (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH) &&
2875 (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); 2989 (ush) d_code(dist) < (ush) D_CODES, "ct_tally: bad match");
2876 2990
2877 dyn_ltree[length_code[lc]+LITERALS+1].Freq++; 2991 dyn_ltree[length_code[lc] + LITERALS + 1].Freq++;
2878 dyn_dtree[d_code(dist)].Freq++; 2992 dyn_dtree[d_code(dist)].Freq++;
2879 2993
2880 d_buf[last_dist++] = (ush)dist; 2994 d_buf[last_dist++] = (ush) dist;
2881 flags |= flag_bit; 2995 flags |= flag_bit;
2882 } 2996 }
2883 flag_bit <<= 1; 2997 flag_bit <<= 1;
2884 2998
2885 /* Output the flags if they fill a byte: */ 2999 /* Output the flags if they fill a byte: */
2886 if ((last_lit & 7) == 0) { 3000 if ((last_lit & 7) == 0) {
2887 flag_buf[last_flags++] = flags; 3001 flag_buf[last_flags++] = flags;
2888 flags = 0, flag_bit = 1; 3002 flags = 0, flag_bit = 1;
2889 } 3003 }
2890 /* Try to guess if it is profitable to stop the current block here */ 3004 /* Try to guess if it is profitable to stop the current block here */
2891 if ((last_lit & 0xfff) == 0) { 3005 if ((last_lit & 0xfff) == 0) {
2892 /* Compute an upper bound for the compressed length */ 3006 /* Compute an upper bound for the compressed length */
2893 ulg out_length = (ulg)last_lit*8L; 3007 ulg out_length = (ulg) last_lit * 8L;
2894 ulg in_length = (ulg)strstart-block_start; 3008 ulg in_length = (ulg) strstart - block_start;
2895 int dcode; 3009 int dcode;
2896 for (dcode = 0; dcode < D_CODES; dcode++) { 3010
2897 out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]); 3011 for (dcode = 0; dcode < D_CODES; dcode++) {
2898 } 3012 out_length +=
2899 out_length >>= 3; 3013 (ulg) dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]);
2900 Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", 3014 }
2901 last_lit, last_dist, in_length, out_length, 3015 out_length >>= 3;
2902 100L - out_length*100L/in_length)); 3016 Trace(
2903 if (last_dist < last_lit/2 && out_length < in_length/2) return 1; 3017 (stderr,
2904 } 3018 "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
2905 return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE); 3019 last_lit, last_dist, in_length, out_length,
2906 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K 3020 100L - out_length * 100L / in_length));
2907 * on 16 bit machines and because stored blocks are restricted to 3021 if (last_dist < last_lit / 2 && out_length < in_length / 2)
2908 * 64K-1 bytes. 3022 return 1;
2909 */ 3023 }
3024 return (last_lit == LIT_BUFSIZE - 1 || last_dist == DIST_BUFSIZE);
3025 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
3026 * on 16 bit machines and because stored blocks are restricted to
3027 * 64K-1 bytes.
3028 */
2910} 3029}
2911 3030
2912/* =========================================================================== 3031/* ===========================================================================
2913 * Send the block data compressed using the given Huffman trees 3032 * Send the block data compressed using the given Huffman trees
2914 */ 3033 */
2915local void compress_block(ltree, dtree) 3034local void compress_block(ltree, dtree)
2916 ct_data near *ltree; /* literal tree */ 3035ct_data near *ltree; /* literal tree */
2917 ct_data near *dtree; /* distance tree */ 3036ct_data near *dtree; /* distance tree */
2918{ 3037{
2919 unsigned dist; /* distance of matched string */ 3038 unsigned dist; /* distance of matched string */
2920 int lc; /* match length or unmatched char (if dist == 0) */ 3039 int lc; /* match length or unmatched char (if dist == 0) */
2921 unsigned lx = 0; /* running index in l_buf */ 3040 unsigned lx = 0; /* running index in l_buf */
2922 unsigned dx = 0; /* running index in d_buf */ 3041 unsigned dx = 0; /* running index in d_buf */
2923 unsigned fx = 0; /* running index in flag_buf */ 3042 unsigned fx = 0; /* running index in flag_buf */
2924 uch flag = 0; /* current flags */ 3043 uch flag = 0; /* current flags */
2925 unsigned code; /* the code to send */ 3044 unsigned code; /* the code to send */
2926 int extra; /* number of extra bits to send */ 3045 int extra; /* number of extra bits to send */
2927 3046
2928 if (last_lit != 0) do { 3047 if (last_lit != 0)
2929 if ((lx & 7) == 0) flag = flag_buf[fx++]; 3048 do {
2930 lc = l_buf[lx++]; 3049 if ((lx & 7) == 0)
2931 if ((flag & 1) == 0) { 3050 flag = flag_buf[fx++];
2932 send_code(lc, ltree); /* send a literal byte */ 3051 lc = l_buf[lx++];
2933 Tracecv(isgraph(lc), (stderr," '%c' ", lc)); 3052 if ((flag & 1) == 0) {
2934 } else { 3053 send_code(lc, ltree); /* send a literal byte */
2935 /* Here, lc is the match length - MIN_MATCH */ 3054 Tracecv(isgraph(lc), (stderr, " '%c' ", lc));
2936 code = length_code[lc]; 3055 } else {
2937 send_code(code+LITERALS+1, ltree); /* send the length code */ 3056 /* Here, lc is the match length - MIN_MATCH */
2938 extra = extra_lbits[code]; 3057 code = length_code[lc];
2939 if (extra != 0) { 3058 send_code(code + LITERALS + 1, ltree); /* send the length code */
2940 lc -= base_length[code]; 3059 extra = extra_lbits[code];
2941 send_bits(lc, extra); /* send the extra length bits */ 3060 if (extra != 0) {
2942 } 3061 lc -= base_length[code];
2943 dist = d_buf[dx++]; 3062 send_bits(lc, extra); /* send the extra length bits */
2944 /* Here, dist is the match distance - 1 */ 3063 }
2945 code = d_code(dist); 3064 dist = d_buf[dx++];
2946 Assert (code < D_CODES, "bad d_code"); 3065 /* Here, dist is the match distance - 1 */
2947 3066 code = d_code(dist);
2948 send_code(code, dtree); /* send the distance code */ 3067 Assert(code < D_CODES, "bad d_code");
2949 extra = extra_dbits[code]; 3068
2950 if (extra != 0) { 3069 send_code(code, dtree); /* send the distance code */
2951 dist -= base_dist[code]; 3070 extra = extra_dbits[code];
2952 send_bits(dist, extra); /* send the extra distance bits */ 3071 if (extra != 0) {
2953 } 3072 dist -= base_dist[code];
2954 } /* literal or match pair ? */ 3073 send_bits(dist, extra); /* send the extra distance bits */
2955 flag >>= 1; 3074 }
2956 } while (lx < last_lit); 3075 } /* literal or match pair ? */
2957 3076 flag >>= 1;
2958 send_code(END_BLOCK, ltree); 3077 } while (lx < last_lit);
3078
3079 send_code(END_BLOCK, ltree);
2959} 3080}
2960 3081
2961/* =========================================================================== 3082/* ===========================================================================
@@ -2966,17 +3087,22 @@ local void compress_block(ltree, dtree)
2966 */ 3087 */
2967local void set_file_type() 3088local void set_file_type()
2968{ 3089{
2969 int n = 0; 3090 int n = 0;
2970 unsigned ascii_freq = 0; 3091 unsigned ascii_freq = 0;
2971 unsigned bin_freq = 0; 3092 unsigned bin_freq = 0;
2972 while (n < 7) bin_freq += dyn_ltree[n++].Freq; 3093
2973 while (n < 128) ascii_freq += dyn_ltree[n++].Freq; 3094 while (n < 7)
2974 while (n < LITERALS) bin_freq += dyn_ltree[n++].Freq; 3095 bin_freq += dyn_ltree[n++].Freq;
2975 *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; 3096 while (n < 128)
2976 if (*file_type == BINARY && translate_eol) { 3097 ascii_freq += dyn_ltree[n++].Freq;
2977 warn("-l used on binary file", ""); 3098 while (n < LITERALS)
2978 } 3099 bin_freq += dyn_ltree[n++].Freq;
3100 *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
3101 if (*file_type == BINARY && translate_eol) {
3102 warn("-l used on binary file", "");
3103 }
2979} 3104}
3105
2980/* util.c -- utility functions for gzip support 3106/* util.c -- utility functions for gzip support
2981 * Copyright (C) 1992-1993 Jean-loup Gailly 3107 * Copyright (C) 1992-1993 Jean-loup Gailly
2982 * This is free software; you can redistribute it and/or modify it under the 3108 * This is free software; you can redistribute it and/or modify it under the
@@ -2997,7 +3123,7 @@ local void set_file_type()
2997#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 3123#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
2998# include <stdlib.h> 3124# include <stdlib.h>
2999#else 3125#else
3000 extern int errno; 3126extern int errno;
3001#endif 3127#endif
3002 3128
3003/* =========================================================================== 3129/* ===========================================================================
@@ -3005,30 +3131,32 @@ local void set_file_type()
3005 * IN assertion: insize bytes have already been read in inbuf. 3131 * IN assertion: insize bytes have already been read in inbuf.
3006 */ 3132 */
3007int copy(in, out) 3133int copy(in, out)
3008 int in, out; /* input and output file descriptors */ 3134int in, out; /* input and output file descriptors */
3009{ 3135{
3010 errno = 0; 3136 errno = 0;
3011 while (insize != 0 && (int)insize != EOF) { 3137 while (insize != 0 && (int) insize != EOF) {
3012 write_buf(out, (char*)inbuf, insize); 3138 write_buf(out, (char *) inbuf, insize);
3013 bytes_out += insize; 3139 bytes_out += insize;
3014 insize = read(in, (char*)inbuf, INBUFSIZ); 3140 insize = read(in, (char *) inbuf, INBUFSIZ);
3015 } 3141 }
3016 if ((int)insize == EOF && errno != 0) { 3142 if ((int) insize == EOF && errno != 0) {
3017 read_error(); 3143 read_error();
3018 } 3144 }
3019 bytes_in = bytes_out; 3145 bytes_in = bytes_out;
3020 return OK; 3146 return OK;
3021} 3147}
3022 3148
3023/* ======================================================================== 3149/* ========================================================================
3024 * Put string s in lower case, return s. 3150 * Put string s in lower case, return s.
3025 */ 3151 */
3026char *strlwr(s) 3152char *strlwr(s)
3027 char *s; 3153char *s;
3028{ 3154{
3029 char *t; 3155 char *t;
3030 for (t = s; *t; t++) *t = tolow(*t); 3156
3031 return s; 3157 for (t = s; *t; t++)
3158 *t = tolow(*t);
3159 return s;
3032} 3160}
3033 3161
3034#if defined(NO_STRING_H) && !defined(STDC_HEADERS) 3162#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
@@ -3039,7 +3167,7 @@ char *strlwr(s)
3039# define const 3167# define const
3040# endif 3168# endif
3041 3169
3042int strspn OF((const char *s, const char *accept)); 3170int strspn OF((const char *s, const char *accept));
3043int strcspn OF((const char *s, const char *reject)); 3171int strcspn OF((const char *s, const char *reject));
3044 3172
3045/* ======================================================================== 3173/* ========================================================================
@@ -3047,21 +3175,23 @@ int strcspn OF((const char *s, const char *reject));
3047 * of s which contains only characters in accept. 3175 * of s which contains only characters in accept.
3048 */ 3176 */
3049int strspn(s, accept) 3177int strspn(s, accept)
3050 const char *s; 3178const char *s;
3051 const char *accept; 3179const char *accept;
3052{ 3180{
3053 register const char *p; 3181 register const char *p;
3054 register const char *a; 3182 register const char *a;
3055 register int count = 0; 3183 register int count = 0;
3056 3184
3057 for (p = s; *p != '\0'; ++p) { 3185 for (p = s; *p != '\0'; ++p) {
3058 for (a = accept; *a != '\0'; ++a) { 3186 for (a = accept; *a != '\0'; ++a) {
3059 if (*p == *a) break; 3187 if (*p == *a)
3188 break;
3189 }
3190 if (*a == '\0')
3191 return count;
3192 ++count;
3060 } 3193 }
3061 if (*a == '\0') return count; 3194 return count;
3062 ++count;
3063 }
3064 return count;
3065} 3195}
3066 3196
3067/* ======================================================================== 3197/* ========================================================================
@@ -3069,104 +3199,113 @@ int strspn(s, accept)
3069 * which contains no characters from reject. 3199 * which contains no characters from reject.
3070 */ 3200 */
3071int strcspn(s, reject) 3201int strcspn(s, reject)
3072 const char *s; 3202const char *s;
3073 const char *reject; 3203const char *reject;
3074{ 3204{
3075 register int count = 0; 3205 register int count = 0;
3076 3206
3077 while (*s != '\0') { 3207 while (*s != '\0') {
3078 if (strchr(reject, *s++) != NULL) return count; 3208 if (strchr(reject, *s++) != NULL)
3079 ++count; 3209 return count;
3080 } 3210 ++count;
3081 return count; 3211 }
3212 return count;
3082} 3213}
3083 3214
3084#endif /* NO_STRING_H */ 3215#endif /* NO_STRING_H */
3085 3216
3086/* ======================================================================== 3217/* ========================================================================
3087 * Add an environment variable (if any) before argv, and update argc. 3218 * Add an environment variable (if any) before argv, and update argc.
3088 * Return the expanded environment variable to be freed later, or NULL 3219 * Return the expanded environment variable to be freed later, or NULL
3089 * if no options were added to argv. 3220 * if no options were added to argv.
3090 */ 3221 */
3091#define SEPARATOR " \t" /* separators in env variable */ 3222#define SEPARATOR " \t" /* separators in env variable */
3092 3223
3093char *add_envopt(argcp, argvp, env) 3224char *add_envopt(argcp, argvp, env)
3094 int *argcp; /* pointer to argc */ 3225int *argcp; /* pointer to argc */
3095 char ***argvp; /* pointer to argv */ 3226char ***argvp; /* pointer to argv */
3096 char *env; /* name of environment variable */ 3227char *env; /* name of environment variable */
3097{ 3228{
3098 char *p; /* running pointer through env variable */ 3229 char *p; /* running pointer through env variable */
3099 char **oargv; /* runs through old argv array */ 3230 char **oargv; /* runs through old argv array */
3100 char **nargv; /* runs through new argv array */ 3231 char **nargv; /* runs through new argv array */
3101 int oargc = *argcp; /* old argc */ 3232 int oargc = *argcp; /* old argc */
3102 int nargc = 0; /* number of arguments in env variable */ 3233 int nargc = 0; /* number of arguments in env variable */
3103 3234
3104 env = (char*)getenv(env); 3235 env = (char *) getenv(env);
3105 if (env == NULL) return NULL; 3236 if (env == NULL)
3106 3237 return NULL;
3107 p = (char*)xmalloc(strlen(env)+1); 3238
3108 env = strcpy(p, env); /* keep env variable intact */ 3239 p = (char *) xmalloc(strlen(env) + 1);
3109 3240 env = strcpy(p, env); /* keep env variable intact */
3110 for (p = env; *p; nargc++ ) { /* move through env */ 3241
3111 p += strspn(p, SEPARATOR); /* skip leading separators */ 3242 for (p = env; *p; nargc++) { /* move through env */
3112 if (*p == '\0') break; 3243 p += strspn(p, SEPARATOR); /* skip leading separators */
3113 3244 if (*p == '\0')
3114 p += strcspn(p, SEPARATOR); /* find end of word */ 3245 break;
3115 if (*p) *p++ = '\0'; /* mark it */ 3246
3116 } 3247 p += strcspn(p, SEPARATOR); /* find end of word */
3117 if (nargc == 0) { 3248 if (*p)
3118 free(env); 3249 *p++ = '\0'; /* mark it */
3119 return NULL; 3250 }
3120 } 3251 if (nargc == 0) {
3121 *argcp += nargc; 3252 free(env);
3122 /* Allocate the new argv array, with an extra element just in case 3253 return NULL;
3123 * the original arg list did not end with a NULL. 3254 }
3124 */ 3255 *argcp += nargc;
3125 nargv = (char**)calloc(*argcp+1, sizeof(char *)); 3256 /* Allocate the new argv array, with an extra element just in case
3126 if (nargv == NULL) error("out of memory"); 3257 * the original arg list did not end with a NULL.
3127 oargv = *argvp; 3258 */
3128 *argvp = nargv; 3259 nargv = (char **) calloc(*argcp + 1, sizeof(char *));
3129 3260
3130 /* Copy the program name first */ 3261 if (nargv == NULL)
3131 if (oargc-- < 0) error("argc<=0"); 3262 error("out of memory");
3132 *(nargv++) = *(oargv++); 3263 oargv = *argvp;
3133 3264 *argvp = nargv;
3134 /* Then copy the environment args */ 3265
3135 for (p = env; nargc > 0; nargc--) { 3266 /* Copy the program name first */
3136 p += strspn(p, SEPARATOR); /* skip separators */ 3267 if (oargc-- < 0)
3137 *(nargv++) = p; /* store start */ 3268 error("argc<=0");
3138 while (*p++) ; /* skip over word */ 3269 *(nargv++) = *(oargv++);
3139 } 3270
3140 3271 /* Then copy the environment args */
3141 /* Finally copy the old args and add a NULL (usual convention) */ 3272 for (p = env; nargc > 0; nargc--) {
3142 while (oargc--) *(nargv++) = *(oargv++); 3273 p += strspn(p, SEPARATOR); /* skip separators */
3143 *nargv = NULL; 3274 *(nargv++) = p; /* store start */
3144 return env; 3275 while (*p++); /* skip over word */
3276 }
3277
3278 /* Finally copy the old args and add a NULL (usual convention) */
3279 while (oargc--)
3280 *(nargv++) = *(oargv++);
3281 *nargv = NULL;
3282 return env;
3145} 3283}
3284
3146/* ======================================================================== 3285/* ========================================================================
3147 * Display compression ratio on the given stream on 6 characters. 3286 * Display compression ratio on the given stream on 6 characters.
3148 */ 3287 */
3149void display_ratio(num, den, file) 3288void display_ratio(num, den, file)
3150 long num; 3289long num;
3151 long den; 3290long den;
3152 FILE *file; 3291FILE *file;
3153{ 3292{
3154 long ratio; /* 1000 times the compression ratio */ 3293 long ratio; /* 1000 times the compression ratio */
3155 3294
3156 if (den == 0) { 3295 if (den == 0) {
3157 ratio = 0; /* no compression */ 3296 ratio = 0; /* no compression */
3158 } else if (den < 2147483L) { /* (2**31 -1)/1000 */ 3297 } else if (den < 2147483L) { /* (2**31 -1)/1000 */
3159 ratio = 1000L*num/den; 3298 ratio = 1000L * num / den;
3160 } else { 3299 } else {
3161 ratio = num/(den/1000L); 3300 ratio = num / (den / 1000L);
3162 } 3301 }
3163 if (ratio < 0) { 3302 if (ratio < 0) {
3164 putc('-', file); 3303 putc('-', file);
3165 ratio = -ratio; 3304 ratio = -ratio;
3166 } else { 3305 } else {
3167 putc(' ', file); 3306 putc(' ', file);
3168 } 3307 }
3169 fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L); 3308 fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
3170} 3309}
3171 3310
3172 3311
@@ -3186,8 +3325,8 @@ void display_ratio(num, den, file)
3186# include <fcntl.h> 3325# include <fcntl.h>
3187#endif 3326#endif
3188 3327
3189local ulg crc; /* crc on uncompressed file data */ 3328local ulg crc; /* crc on uncompressed file data */
3190long header_bytes; /* number of bytes in gzip header */ 3329long header_bytes; /* number of bytes in gzip header */
3191 3330
3192/* =========================================================================== 3331/* ===========================================================================
3193 * Deflate in to out. 3332 * Deflate in to out.
@@ -3195,48 +3334,48 @@ long header_bytes; /* number of bytes in gzip header */
3195 * The variables time_stamp and save_orig_name are initialized. 3334 * The variables time_stamp and save_orig_name are initialized.
3196 */ 3335 */
3197int zip(in, out) 3336int zip(in, out)
3198 int in, out; /* input and output file descriptors */ 3337int in, out; /* input and output file descriptors */
3199{ 3338{
3200 uch flags = 0; /* general purpose bit flags */ 3339 uch flags = 0; /* general purpose bit flags */
3201 ush attr = 0; /* ascii/binary flag */ 3340 ush attr = 0; /* ascii/binary flag */
3202 ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ 3341 ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
3203 3342
3204 ifd = in; 3343 ifd = in;
3205 ofd = out; 3344 ofd = out;
3206 outcnt = 0; 3345 outcnt = 0;
3207 3346
3208 /* Write the header to the gzip file. See algorithm.doc for the format */ 3347 /* Write the header to the gzip file. See algorithm.doc for the format */
3209 3348
3210 3349
3211 method = DEFLATED; 3350 method = DEFLATED;
3212 put_byte(GZIP_MAGIC[0]); /* magic header */ 3351 put_byte(GZIP_MAGIC[0]); /* magic header */
3213 put_byte(GZIP_MAGIC[1]); 3352 put_byte(GZIP_MAGIC[1]);
3214 put_byte(DEFLATED); /* compression method */ 3353 put_byte(DEFLATED); /* compression method */
3215 3354
3216 put_byte(flags); /* general flags */ 3355 put_byte(flags); /* general flags */
3217 put_long(time_stamp); 3356 put_long(time_stamp);
3218 3357
3219 /* Write deflated file to zip file */ 3358 /* Write deflated file to zip file */
3220 crc = updcrc(0, 0); 3359 crc = updcrc(0, 0);
3221 3360
3222 bi_init(out); 3361 bi_init(out);
3223 ct_init(&attr, &method); 3362 ct_init(&attr, &method);
3224 lm_init(&deflate_flags); 3363 lm_init(&deflate_flags);
3225 3364
3226 put_byte((uch)deflate_flags); /* extra flags */ 3365 put_byte((uch) deflate_flags); /* extra flags */
3227 put_byte(OS_CODE); /* OS identifier */ 3366 put_byte(OS_CODE); /* OS identifier */
3228 3367
3229 header_bytes = (long)outcnt; 3368 header_bytes = (long) outcnt;
3230 3369
3231 (void)deflate(); 3370 (void) deflate();
3232 3371
3233 /* Write the crc and uncompressed size */ 3372 /* Write the crc and uncompressed size */
3234 put_long(crc); 3373 put_long(crc);
3235 put_long(isize); 3374 put_long(isize);
3236 header_bytes += 2*sizeof(long); 3375 header_bytes += 2 * sizeof(long);
3237 3376
3238 flush_outbuf(); 3377 flush_outbuf();
3239 return OK; 3378 return OK;
3240} 3379}
3241 3380
3242 3381
@@ -3246,18 +3385,19 @@ int zip(in, out)
3246 * IN assertion: size >= 2 (for end-of-line translation) 3385 * IN assertion: size >= 2 (for end-of-line translation)
3247 */ 3386 */
3248int file_read(buf, size) 3387int file_read(buf, size)
3249 char *buf; 3388char *buf;
3250 unsigned size; 3389unsigned size;
3251{ 3390{
3252 unsigned len; 3391 unsigned len;
3253 3392
3254 Assert(insize == 0, "inbuf not empty"); 3393 Assert(insize == 0, "inbuf not empty");
3255 3394
3256 len = read(ifd, buf, size); 3395 len = read(ifd, buf, size);
3257 if (len == (unsigned)(-1) || len == 0) return (int)len; 3396 if (len == (unsigned) (-1) || len == 0)
3397 return (int) len;
3258 3398
3259 crc = updcrc((uch*)buf, len); 3399 crc = updcrc((uch *) buf, len);
3260 isize += (ulg)len; 3400 isize += (ulg) len;
3261 return (int)len; 3401 return (int) len;
3262} 3402}
3263#endif 3403#endif
diff --git a/archival/tar.c b/archival/tar.c
index 6496231ae..87b5d2176 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tar implementation for busybox based on code taken from sash. 3 * Mini tar implementation for busybox based on code taken from sash.
3 * 4 *
@@ -40,27 +41,29 @@
40#include <utime.h> 41#include <utime.h>
41#include <sys/types.h> 42#include <sys/types.h>
42#include <sys/sysmacros.h> 43#include <sys/sysmacros.h>
43#include <sys/param.h> /* for PATH_MAX */ 44#include <sys/param.h> /* for PATH_MAX */
44 45
45 46
46#ifdef BB_FEATURE_TAR_CREATE 47#ifdef BB_FEATURE_TAR_CREATE
47 48
48static const char tar_usage[] = 49static const char tar_usage[] =
49"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" 50 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
50"Create, extract, or list files from a tar file.\n\n" 51 "Create, extract, or list files from a tar file.\n\n"
51"Options:\n" 52 "Options:\n"
52"\tc=create, x=extract, t=list contents, v=verbose,\n" 53
53"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 54 "\tc=create, x=extract, t=list contents, v=verbose,\n"
55 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
54 56
55#else 57#else
56 58
57static const char tar_usage[] = 59static const char tar_usage[] =
58"tar -[xtvOf] [tarFileName] [FILE] ...\n\n" 60 "tar -[xtvOf] [tarFileName] [FILE] ...\n\n"
59"Extract, or list files stored in a tar file. This\n" 61 "Extract, or list files stored in a tar file. This\n"
60"version of tar does not support creation of tar files.\n\n" 62 "version of tar does not support creation of tar files.\n\n"
61"Options:\n" 63 "Options:\n"
62"\tx=extract, t=list contents, v=verbose,\n" 64
63"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 65 "\tx=extract, t=list contents, v=verbose,\n"
66 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
64 67
65#endif 68#endif
66 69
@@ -78,22 +81,22 @@ static const char tar_usage[] =
78 * with zero padding. We only process this information minimally. 81 * with zero padding. We only process this information minimally.
79 */ 82 */
80typedef struct { 83typedef struct {
81 char name[TAR_NAME_SIZE]; 84 char name[TAR_NAME_SIZE];
82 char mode[8]; 85 char mode[8];
83 char uid[8]; 86 char uid[8];
84 char gid[8]; 87 char gid[8];
85 char size[12]; 88 char size[12];
86 char mtime[12]; 89 char mtime[12];
87 char checkSum[8]; 90 char checkSum[8];
88 char typeFlag; 91 char typeFlag;
89 char linkName[TAR_NAME_SIZE]; 92 char linkName[TAR_NAME_SIZE];
90 char magic[6]; 93 char magic[6];
91 char version[2]; 94 char version[2];
92 char uname[32]; 95 char uname[32];
93 char gname[32]; 96 char gname[32];
94 char devMajor[8]; 97 char devMajor[8];
95 char devMinor[8]; 98 char devMinor[8];
96 char prefix[155]; 99 char prefix[155];
97} TarHeader; 100} TarHeader;
98 101
99#define TAR_MAGIC "ustar" 102#define TAR_MAGIC "ustar"
@@ -113,7 +116,7 @@ static int createFlag;
113static int verboseFlag; 116static int verboseFlag;
114static int tostdoutFlag; 117static int tostdoutFlag;
115 118
116static int inHeader; // <- check me 119static int inHeader; // <- check me
117static int badHeader; 120static int badHeader;
118static int errorFlag; 121static int errorFlag;
119static int skipFileFlag; 122static int skipFileFlag;
@@ -140,141 +143,145 @@ static ino_t tarInode;
140/* 143/*
141 * Local procedures to restore files from a tar file. 144 * Local procedures to restore files from a tar file.
142 */ 145 */
143static void readTarFile (int fileCount, char **fileTable); 146static void readTarFile(int fileCount, char **fileTable);
144static void readData (const char *cp, int count); 147static void readData(const char *cp, int count);
145static long getOctal (const char *cp, int len); 148static long getOctal(const char *cp, int len);
149
150static void readHeader(const TarHeader * hp,
146 151
147static void readHeader (const TarHeader * hp, 152 int fileCount, char **fileTable);
148 int fileCount, char **fileTable);
149 153
150static int wantFileName (const char *fileName, 154static int wantFileName(const char *fileName,
151 int fileCount, char **fileTable); 155
156 int fileCount, char **fileTable);
152 157
153#ifdef BB_FEATURE_TAR_CREATE 158#ifdef BB_FEATURE_TAR_CREATE
154/* 159/*
155 * Local procedures to save files into a tar file. 160 * Local procedures to save files into a tar file.
156 */ 161 */
157static void saveFile (const char *fileName, int seeLinks); 162static void saveFile(const char *fileName, int seeLinks);
163
164static void saveRegularFile(const char *fileName,
158 165
159static void saveRegularFile (const char *fileName, 166 const struct stat *statbuf);
160 const struct stat *statbuf);
161 167
162static void saveDirectory (const char *fileName, 168static void saveDirectory(const char *fileName,
163 const struct stat *statbuf);
164 169
165static void writeHeader (const char *fileName, const struct stat *statbuf); 170 const struct stat *statbuf);
166 171
167static void writeTarFile (int fileCount, char **fileTable); 172static void writeHeader(const char *fileName, const struct stat *statbuf);
168static void writeTarBlock (const char *buf, int len); 173
169static int putOctal (char *cp, int len, long value); 174static void writeTarFile(int fileCount, char **fileTable);
175static void writeTarBlock(const char *buf, int len);
176static int putOctal(char *cp, int len, long value);
170 177
171#endif 178#endif
172 179
173 180
174extern int tar_main (int argc, char **argv) 181extern int tar_main(int argc, char **argv)
175{ 182{
176 const char *options; 183 const char *options;
177 184
178 argc--; 185 argc--;
179 argv++; 186 argv++;
180 187
181 if (argc < 1) 188 if (argc < 1)
182 usage( tar_usage); 189 usage(tar_usage);
183 190
184 191
185 errorFlag = FALSE; 192 errorFlag = FALSE;
186 extractFlag = FALSE; 193 extractFlag = FALSE;
187 createFlag = FALSE; 194 createFlag = FALSE;
188 listFlag = FALSE; 195 listFlag = FALSE;
189 verboseFlag = FALSE; 196 verboseFlag = FALSE;
190 tostdoutFlag = FALSE; 197 tostdoutFlag = FALSE;
191 tarName = NULL; 198 tarName = NULL;
192 tarDev = 0; 199 tarDev = 0;
193 tarInode = 0; 200 tarInode = 0;
194 tarFd = -1; 201 tarFd = -1;
195 202
196 /* 203 /*
197 * Parse the options. 204 * Parse the options.
198 */ 205 */
199 if (**argv == '-') 206 if (**argv == '-')
200 options = (*argv++) + 1; 207 options = (*argv++) + 1;
201 else 208 else
202 options = (*argv++); 209 options = (*argv++);
203 argc--; 210 argc--;
204 211
205 for (; *options; options++) { 212 for (; *options; options++) {
206 switch (*options) { 213 switch (*options) {
207 case 'f': 214 case 'f':
208 if (tarName != NULL) { 215 if (tarName != NULL) {
209 fprintf (stderr, "Only one 'f' option allowed\n"); 216 fprintf(stderr, "Only one 'f' option allowed\n");
210 217
211 exit (FALSE); 218 exit(FALSE);
212 } 219 }
213 220
214 tarName = *argv++; 221 tarName = *argv++;
215 argc--; 222 argc--;
216 223
217 break; 224 break;
218 225
219 case 't': 226 case 't':
220 if (extractFlag == TRUE || createFlag == TRUE ) 227 if (extractFlag == TRUE || createFlag == TRUE)
221 goto flagError; 228 goto flagError;
222 listFlag = TRUE; 229 listFlag = TRUE;
223 break; 230 break;
224 231
225 case 'x': 232 case 'x':
226 if (listFlag == TRUE || createFlag == TRUE ) 233 if (listFlag == TRUE || createFlag == TRUE)
227 goto flagError; 234 goto flagError;
228 extractFlag = TRUE; 235 extractFlag = TRUE;
229 break; 236 break;
230 case 'c': 237 case 'c':
231 if (extractFlag == TRUE || listFlag == TRUE) 238 if (extractFlag == TRUE || listFlag == TRUE)
232 goto flagError; 239 goto flagError;
233 createFlag = TRUE; 240 createFlag = TRUE;
234 break; 241 break;
235 242
236 case 'v': 243 case 'v':
237 verboseFlag = TRUE; 244 verboseFlag = TRUE;
238 break; 245 break;
239 246
240 case 'O': 247 case 'O':
241 tostdoutFlag = TRUE; 248 tostdoutFlag = TRUE;
242 break; 249 break;
243 250
244 case '-': 251 case '-':
245 usage( tar_usage); 252 usage(tar_usage);
246 break; 253 break;
247 254
248 default: 255 default:
249 fprintf (stderr, "Unknown tar flag '%c'\n" 256 fprintf(stderr, "Unknown tar flag '%c'\n"
250 "Try `tar --help' for more information\n", 257 "Try `tar --help' for more information\n", *options);
251 *options); 258 exit(FALSE);
252 exit (FALSE); 259 }
253 } 260 }
254 }
255 261
256 /* 262 /*
257 * Do the correct type of action supplying the rest of the 263 * Do the correct type of action supplying the rest of the
258 * command line arguments as the list of files to process. 264 * command line arguments as the list of files to process.
259 */ 265 */
260 if (createFlag==TRUE) { 266 if (createFlag == TRUE) {
261#ifndef BB_FEATURE_TAR_CREATE 267#ifndef BB_FEATURE_TAR_CREATE
262 fprintf (stderr, "This version of tar was not compiled with tar creation support.\n" ); 268 fprintf(stderr,
263 exit (FALSE); 269 "This version of tar was not compiled with tar creation support.\n");
270 exit(FALSE);
264#else 271#else
265 writeTarFile (argc, argv); 272 writeTarFile(argc, argv);
266#endif 273#endif
267 } else { 274 } else {
268 readTarFile (argc, argv); 275 readTarFile(argc, argv);
269 } 276 }
270 if (errorFlag==TRUE) { 277 if (errorFlag == TRUE) {
271 fprintf (stderr, "\n"); 278 fprintf(stderr, "\n");
272 } 279 }
273 exit (!errorFlag); 280 exit(!errorFlag);
274 281
275flagError: 282 flagError:
276 fprintf (stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); 283 fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n");
277 exit (FALSE); 284 exit(FALSE);
278} 285}
279 286
280 287
@@ -282,120 +289,120 @@ flagError:
282 * Read a tar file and extract or list the specified files within it. 289 * Read a tar file and extract or list the specified files within it.
283 * If the list is empty than all files are extracted or listed. 290 * If the list is empty than all files are extracted or listed.
284 */ 291 */
285static void readTarFile (int fileCount, char **fileTable) 292static void readTarFile(int fileCount, char **fileTable)
286{ 293{
287 const char *cp; 294 const char *cp;
288 int cc; 295 int cc;
289 int inCc; 296 int inCc;
290 int blockSize; 297 int blockSize;
291 char buf[BUF_SIZE]; 298 char buf[BUF_SIZE];
292 299
293 skipFileFlag = FALSE; 300 skipFileFlag = FALSE;
294 badHeader = FALSE; 301 badHeader = FALSE;
295 warnedRoot = FALSE; 302 warnedRoot = FALSE;
296 eofFlag = FALSE; 303 eofFlag = FALSE;
297 inHeader = TRUE; 304 inHeader = TRUE;
298 inCc = 0; 305 inCc = 0;
299 dataCc = 0; 306 dataCc = 0;
300 outFd = -1; 307 outFd = -1;
301 blockSize = sizeof (buf); 308 blockSize = sizeof(buf);
302 cp = buf; 309 cp = buf;
303 310
304 /*
305 * Open the tar file for reading.
306 */
307 if ((tarName == NULL) || !strcmp (tarName, "-")) {
308 tarFd = fileno(stdin);
309 } else
310 tarFd = open (tarName, O_RDONLY);
311
312 if (tarFd < 0) {
313 perror (tarName);
314 errorFlag = TRUE;
315 return;
316 }
317
318 /*
319 * Read blocks from the file until an end of file header block
320 * has been seen. (A real end of file from a read is an error.)
321 */
322 while (eofFlag==FALSE) {
323 /* 311 /*
324 * Read the next block of data if necessary. 312 * Open the tar file for reading.
325 * This will be a large block if possible, which we will
326 * then process in the small tar blocks.
327 */ 313 */
328 if (inCc <= 0) { 314 if ((tarName == NULL) || !strcmp(tarName, "-")) {
329 cp = buf; 315 tarFd = fileno(stdin);
330 inCc = fullRead (tarFd, buf, blockSize); 316 } else
331 317 tarFd = open(tarName, O_RDONLY);
332 if (inCc < 0) {
333 perror (tarName);
334 errorFlag = TRUE;
335 goto done;
336 }
337 318
338 if (inCc == 0) { 319 if (tarFd < 0) {
339 fprintf (stderr, 320 perror(tarName);
340 "Unexpected end of file from \"%s\"", tarName);
341 errorFlag = TRUE; 321 errorFlag = TRUE;
342 goto done; 322 return;
343 }
344 } 323 }
345 324
346 /* 325 /*
347 * If we are expecting a header block then examine it. 326 * Read blocks from the file until an end of file header block
327 * has been seen. (A real end of file from a read is an error.)
348 */ 328 */
349 if (inHeader==TRUE) { 329 while (eofFlag == FALSE) {
350 readHeader ((const TarHeader *) cp, fileCount, fileTable); 330 /*
351 331 * Read the next block of data if necessary.
352 cp += TAR_BLOCK_SIZE; 332 * This will be a large block if possible, which we will
353 inCc -= TAR_BLOCK_SIZE; 333 * then process in the small tar blocks.
354 334 */
355 continue; 335 if (inCc <= 0) {
336 cp = buf;
337 inCc = fullRead(tarFd, buf, blockSize);
338
339 if (inCc < 0) {
340 perror(tarName);
341 errorFlag = TRUE;
342 goto done;
343 }
344
345 if (inCc == 0) {
346 fprintf(stderr,
347 "Unexpected end of file from \"%s\"", tarName);
348 errorFlag = TRUE;
349 goto done;
350 }
351 }
352
353 /*
354 * If we are expecting a header block then examine it.
355 */
356 if (inHeader == TRUE) {
357 readHeader((const TarHeader *) cp, fileCount, fileTable);
358
359 cp += TAR_BLOCK_SIZE;
360 inCc -= TAR_BLOCK_SIZE;
361
362 continue;
363 }
364
365 /*
366 * We are currently handling the data for a file.
367 * Process the minimum of the amount of data we have available
368 * and the amount left to be processed for the file.
369 */
370 cc = inCc;
371
372 if (cc > dataCc)
373 cc = dataCc;
374
375 readData(cp, cc);
376
377 /*
378 * If the amount left isn't an exact multiple of the tar block
379 * size then round it up to the next block boundary since there
380 * is padding at the end of the file.
381 */
382 if (cc % TAR_BLOCK_SIZE)
383 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
384
385 cp += cc;
386 inCc -= cc;
356 } 387 }
357 388
389 done:
358 /* 390 /*
359 * We are currently handling the data for a file. 391 * Close the tar file if needed.
360 * Process the minimum of the amount of data we have available
361 * and the amount left to be processed for the file.
362 */ 392 */
363 cc = inCc; 393 if ((tarFd >= 0) && (close(tarFd) < 0))
364 394 perror(tarName);
365 if (cc > dataCc)
366 cc = dataCc;
367
368 readData (cp, cc);
369 395
370 /* 396 /*
371 * If the amount left isn't an exact multiple of the tar block 397 * Close the output file if needed.
372 * size then round it up to the next block boundary since there 398 * This is only done here on a previous error and so no
373 * is padding at the end of the file. 399 * message is required on errors.
374 */ 400 */
375 if (cc % TAR_BLOCK_SIZE) 401 if (tostdoutFlag == FALSE) {
376 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE); 402 if (outFd >= 0) {
377 403 close(outFd);
378 cp += cc; 404 }
379 inCc -= cc;
380 }
381
382 done:
383 /*
384 * Close the tar file if needed.
385 */
386 if ((tarFd >= 0) && (close (tarFd) < 0))
387 perror (tarName);
388
389 /*
390 * Close the output file if needed.
391 * This is only done here on a previous error and so no
392 * message is required on errors.
393 */
394 if (tostdoutFlag == FALSE) {
395 if (outFd >= 0) {
396 close (outFd);
397 } 405 }
398 }
399} 406}
400 407
401 408
@@ -405,304 +412,305 @@ static void readTarFile (int fileCount, char **fileTable)
405 * the end of the tar file. 412 * the end of the tar file.
406 */ 413 */
407static void 414static void
408readHeader (const TarHeader * hp, int fileCount, char **fileTable) 415readHeader(const TarHeader * hp, int fileCount, char **fileTable)
409{ 416{
410 int checkSum; 417 int checkSum;
411 int cc; 418 int cc;
412 int hardLink; 419 int hardLink;
413 int softLink; 420 int softLink;
414 int devFileFlag; 421 int devFileFlag;
415 unsigned int major; 422 unsigned int major;
416 unsigned int minor; 423 unsigned int minor;
417 long size; 424 long size;
418 struct utimbuf utb; 425 struct utimbuf utb;
419 426
420 /* 427 /*
421 * If the block is completely empty, then this is the end of the 428 * If the block is completely empty, then this is the end of the
422 * archive file. If the name is null, then just skip this header. 429 * archive file. If the name is null, then just skip this header.
423 */ 430 */
424 outName = hp->name; 431 outName = hp->name;
425 432
426 if (*outName == '\0') { 433 if (*outName == '\0') {
427 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { 434 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
428 if (*outName++) 435 if (*outName++)
436 return;
437 }
438
439 eofFlag = TRUE;
440
429 return; 441 return;
430 } 442 }
431 443
432 eofFlag = TRUE; 444 /*
433 445 * There is another file in the archive to examine.
434 return; 446 * Extract the encoded information and check it.
435 } 447 */
436 448 mode = getOctal(hp->mode, sizeof(hp->mode));
437 /* 449 uid = getOctal(hp->uid, sizeof(hp->uid));
438 * There is another file in the archive to examine. 450 gid = getOctal(hp->gid, sizeof(hp->gid));
439 * Extract the encoded information and check it. 451 size = getOctal(hp->size, sizeof(hp->size));
440 */ 452 mtime = getOctal(hp->mtime, sizeof(hp->mtime));
441 mode = getOctal (hp->mode, sizeof (hp->mode)); 453 checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum));
442 uid = getOctal (hp->uid, sizeof (hp->uid)); 454 major = getOctal(hp->devMajor, sizeof(hp->devMajor));
443 gid = getOctal (hp->gid, sizeof (hp->gid)); 455 minor = getOctal(hp->devMinor, sizeof(hp->devMinor));
444 size = getOctal (hp->size, sizeof (hp->size));
445 mtime = getOctal (hp->mtime, sizeof (hp->mtime));
446 checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum));
447 major = getOctal (hp->devMajor, sizeof (hp->devMajor));
448 minor = getOctal (hp->devMinor, sizeof (hp->devMinor));
449
450 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
451 if (badHeader==FALSE)
452 fprintf (stderr, "Bad tar header, skipping\n");
453
454 badHeader = TRUE;
455
456 return;
457 }
458
459 badHeader = FALSE;
460 skipFileFlag = FALSE;
461 devFileFlag = FALSE;
462
463 /*
464 * Check for the file modes.
465 */
466 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
467 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
468
469 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
470 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
471
472 /*
473 * Check for a directory.
474 */
475 if (outName[strlen (outName) - 1] == '/')
476 mode |= S_IFDIR;
477
478 /*
479 * Check for absolute paths in the file.
480 * If we find any, then warn the user and make them relative.
481 */
482 if (*outName == '/') {
483 while (*outName == '/')
484 outName++;
485
486 if (warnedRoot==FALSE) {
487 fprintf (stderr,
488 "Absolute path detected, removing leading slashes\n");
489 }
490 456
491 warnedRoot = TRUE; 457 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
492 } 458 if (badHeader == FALSE)
493 459 fprintf(stderr, "Bad tar header, skipping\n");
494 /*
495 * See if we want this file to be restored.
496 * If not, then set up to skip it.
497 */
498 if (wantFileName (outName, fileCount, fileTable) == FALSE) {
499 if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode)
500 || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) {
501 inHeader = (size == 0)? TRUE : FALSE;
502 dataCc = size;
503 }
504 460
505 skipFileFlag = TRUE; 461 badHeader = TRUE;
506 462
507 return; 463 return;
508 }
509
510 /*
511 * This file is to be handled.
512 * If we aren't extracting then just list information about the file.
513 */
514 if (extractFlag==FALSE) {
515 if (verboseFlag==TRUE) {
516 printf ("%s %3d/%-d ", modeString (mode), uid, gid);
517 if( S_ISCHR (mode) || S_ISBLK (mode) )
518 printf ("%4d,%4d %s ", major,minor, timeString (mtime));
519 else
520 printf ("%9ld %s ", size, timeString (mtime));
521 }
522 printf ("%s", outName);
523
524 if (hardLink)
525 printf (" (link to \"%s\")", hp->linkName);
526 else if (softLink)
527 printf (" (symlink to \"%s\")", hp->linkName);
528 else if (S_ISREG (mode) || S_ISCHR (mode) || S_ISBLK (mode) ||
529 S_ISSOCK(mode) || S_ISFIFO(mode) ) {
530 inHeader = (size == 0)? TRUE : FALSE;
531 dataCc = size;
532 } 464 }
533 465
534 printf ("\n"); 466 badHeader = FALSE;
467 skipFileFlag = FALSE;
468 devFileFlag = FALSE;
535 469
536 return; 470 /*
537 } 471 * Check for the file modes.
472 */
473 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
474 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
475
476 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
477 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
478
479 /*
480 * Check for a directory.
481 */
482 if (outName[strlen(outName) - 1] == '/')
483 mode |= S_IFDIR;
484
485 /*
486 * Check for absolute paths in the file.
487 * If we find any, then warn the user and make them relative.
488 */
489 if (*outName == '/') {
490 while (*outName == '/')
491 outName++;
538 492
539 /* 493 if (warnedRoot == FALSE) {
540 * We really want to extract the file. 494 fprintf(stderr,
541 */ 495 "Absolute path detected, removing leading slashes\n");
542 if (verboseFlag==TRUE) 496 }
543 printf ("x %s\n", outName);
544 497
545 if (hardLink) { 498 warnedRoot = TRUE;
546 if (link (hp->linkName, outName) < 0) {
547 perror (outName);
548 return;
549 } 499 }
550 /* Set the file time */ 500
551 utb.actime = mtime; 501 /*
552 utb.modtime = mtime; 502 * See if we want this file to be restored.
553 utime (outName, &utb); 503 * If not, then set up to skip it.
554 /* Set the file permissions */ 504 */
555 chown(outName, uid, gid); 505 if (wantFileName(outName, fileCount, fileTable) == FALSE) {
556 chmod(outName, mode); 506 if (!hardLink && !softLink && (S_ISREG(mode) || S_ISCHR(mode)
557 return; 507 || S_ISBLK(mode) || S_ISSOCK(mode)
558 } 508 || S_ISFIFO(mode))) {
559 509 inHeader = (size == 0) ? TRUE : FALSE;
560 if (softLink) { 510 dataCc = size;
561#ifdef S_ISLNK 511 }
562 if (symlink (hp->linkName, outName) < 0) { 512
563 perror (outName); 513 skipFileFlag = TRUE;
564 return; 514
515 return;
565 } 516 }
566 /* Try to change ownership of the symlink. 517
567 * If libs doesn't support that, don't bother. 518 /*
568 * Changing the pointed-to file is the Wrong Thing(tm). 519 * This file is to be handled.
520 * If we aren't extracting then just list information about the file.
569 */ 521 */
522 if (extractFlag == FALSE) {
523 if (verboseFlag == TRUE) {
524 printf("%s %3d/%-d ", modeString(mode), uid, gid);
525 if (S_ISCHR(mode) || S_ISBLK(mode))
526 printf("%4d,%4d %s ", major, minor, timeString(mtime));
527 else
528 printf("%9ld %s ", size, timeString(mtime));
529 }
530 printf("%s", outName);
531
532 if (hardLink)
533 printf(" (link to \"%s\")", hp->linkName);
534 else if (softLink)
535 printf(" (symlink to \"%s\")", hp->linkName);
536 else if (S_ISREG(mode) || S_ISCHR(mode) || S_ISBLK(mode) ||
537 S_ISSOCK(mode) || S_ISFIFO(mode)) {
538 inHeader = (size == 0) ? TRUE : FALSE;
539 dataCc = size;
540 }
541
542 printf("\n");
543
544 return;
545 }
546
547 /*
548 * We really want to extract the file.
549 */
550 if (verboseFlag == TRUE)
551 printf("x %s\n", outName);
552
553 if (hardLink) {
554 if (link(hp->linkName, outName) < 0) {
555 perror(outName);
556 return;
557 }
558 /* Set the file time */
559 utb.actime = mtime;
560 utb.modtime = mtime;
561 utime(outName, &utb);
562 /* Set the file permissions */
563 chown(outName, uid, gid);
564 chmod(outName, mode);
565 return;
566 }
567
568 if (softLink) {
569#ifdef S_ISLNK
570 if (symlink(hp->linkName, outName) < 0) {
571 perror(outName);
572 return;
573 }
574 /* Try to change ownership of the symlink.
575 * If libs doesn't support that, don't bother.
576 * Changing the pointed-to file is the Wrong Thing(tm).
577 */
570#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 578#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
571 lchown(outName, uid, gid); 579 lchown(outName, uid, gid);
572#endif 580#endif
573 581
574 /* Do not change permissions or date on symlink, 582 /* Do not change permissions or date on symlink,
575 * since it changes the pointed to file instead. duh. */ 583 * since it changes the pointed to file instead. duh. */
576#else 584#else
577 fprintf (stderr, "Cannot create symbolic links\n"); 585 fprintf(stderr, "Cannot create symbolic links\n");
578#endif 586#endif
579 return; 587 return;
580 }
581
582 /* Set the umask for this process so it doesn't
583 * screw things up. */
584 umask(0);
585
586 /*
587 * If the file is a directory, then just create the path.
588 */
589 if (S_ISDIR (mode)) {
590 if (createPath (outName, mode)==TRUE) {
591 /* Set the file time */
592 utb.actime = mtime;
593 utb.modtime = mtime;
594 utime (outName, &utb);
595 /* Set the file permissions */
596 chown(outName, uid, gid);
597 chmod(outName, mode);
598 return;
599 } 588 }
600 return; 589
601 } 590 /* Set the umask for this process so it doesn't
602 591 * screw things up. */
603 /* 592 umask(0);
604 * There is a file to write. 593
605 * First create the path to it if necessary with default permissions. 594 /*
606 */ 595 * If the file is a directory, then just create the path.
607 createPath (outName, 0777); 596 */
608 597 if (S_ISDIR(mode)) {
609 inHeader = (size == 0)? TRUE : FALSE; 598 if (createPath(outName, mode) == TRUE) {
610 dataCc = size; 599 /* Set the file time */
611 600 utb.actime = mtime;
612 /* 601 utb.modtime = mtime;
613 * Start the output file. 602 utime(outName, &utb);
614 */ 603 /* Set the file permissions */
615 if (tostdoutFlag == TRUE) 604 chown(outName, uid, gid);
616 outFd = fileno(stdout); 605 chmod(outName, mode);
617 else { 606 return;
618 if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { 607 }
619 devFileFlag = TRUE; 608 return;
620 outFd = mknod (outName, mode, makedev(major, minor) );
621 } 609 }
622 else if (S_ISFIFO(mode) ) { 610
623 devFileFlag = TRUE; 611 /*
624 outFd = mkfifo(outName, mode); 612 * There is a file to write.
625 } else { 613 * First create the path to it if necessary with default permissions.
626 outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode); 614 */
615 createPath(outName, 0777);
616
617 inHeader = (size == 0) ? TRUE : FALSE;
618 dataCc = size;
619
620 /*
621 * Start the output file.
622 */
623 if (tostdoutFlag == TRUE)
624 outFd = fileno(stdout);
625 else {
626 if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode)) {
627 devFileFlag = TRUE;
628 outFd = mknod(outName, mode, makedev(major, minor));
629 } else if (S_ISFIFO(mode)) {
630 devFileFlag = TRUE;
631 outFd = mkfifo(outName, mode);
632 } else {
633 outFd = open(outName, O_WRONLY | O_CREAT | O_TRUNC, mode);
634 }
635 if (outFd < 0) {
636 perror(outName);
637 skipFileFlag = TRUE;
638 return;
639 }
640 /* Set the file time */
641 utb.actime = mtime;
642 utb.modtime = mtime;
643 utime(outName, &utb);
644 /* Set the file permissions */
645 chown(outName, uid, gid);
646 chmod(outName, mode);
627 } 647 }
628 if (outFd < 0) { 648
629 perror (outName); 649
630 skipFileFlag = TRUE; 650 /*
631 return; 651 * If the file is empty, then that's all we need to do.
652 */
653 if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
654 close(outFd);
655 outFd = -1;
632 } 656 }
633 /* Set the file time */
634 utb.actime = mtime;
635 utb.modtime = mtime;
636 utime (outName, &utb);
637 /* Set the file permissions */
638 chown(outName, uid, gid);
639 chmod(outName, mode);
640 }
641
642
643 /*
644 * If the file is empty, then that's all we need to do.
645 */
646 if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
647 close (outFd);
648 outFd = -1;
649 }
650} 657}
651 658
652 659
653/* 660/*
654 * Handle a data block of some specified size that was read. 661 * Handle a data block of some specified size that was read.
655 */ 662 */
656static void readData (const char *cp, int count) 663static void readData(const char *cp, int count)
657{ 664{
658 /* 665 /*
659 * Reduce the amount of data left in this file. 666 * Reduce the amount of data left in this file.
660 * If there is no more data left, then we need to read 667 * If there is no more data left, then we need to read
661 * the header again. 668 * the header again.
662 */ 669 */
663 dataCc -= count; 670 dataCc -= count;
664
665 if (dataCc <= 0)
666 inHeader = TRUE;
667 671
668 /* 672 if (dataCc <= 0)
669 * If we aren't extracting files or this file is being 673 inHeader = TRUE;
670 * skipped then do nothing more. 674
671 */ 675 /*
672 if (extractFlag==FALSE || skipFileFlag==TRUE) 676 * If we aren't extracting files or this file is being
673 return; 677 * skipped then do nothing more.
674 678 */
675 /* 679 if (extractFlag == FALSE || skipFileFlag == TRUE)
676 * Write the data to the output file. 680 return;
677 */ 681
678 if (fullWrite (outFd, cp, count) < 0) { 682 /*
679 perror (outName); 683 * Write the data to the output file.
680 if (tostdoutFlag == FALSE) { 684 */
681 close (outFd); 685 if (fullWrite(outFd, cp, count) < 0) {
682 outFd = -1; 686 perror(outName);
687 if (tostdoutFlag == FALSE) {
688 close(outFd);
689 outFd = -1;
690 }
691 skipFileFlag = TRUE;
692 return;
683 } 693 }
684 skipFileFlag = TRUE;
685 return;
686 }
687
688 /*
689 * Check if we are done writing to the file now.
690 */
691 if (dataCc <= 0 && tostdoutFlag == FALSE) {
692 struct utimbuf utb;
693 if (close (outFd))
694 perror (outName);
695 694
696 /* Set the file time */ 695 /*
697 utb.actime = mtime; 696 * Check if we are done writing to the file now.
698 utb.modtime = mtime; 697 */
699 utime (outName, &utb); 698 if (dataCc <= 0 && tostdoutFlag == FALSE) {
700 /* Set the file permissions */ 699 struct utimbuf utb;
701 chown(outName, uid, gid); 700
702 chmod(outName, mode); 701 if (close(outFd))
702 perror(outName);
703 703
704 outFd = -1; 704 /* Set the file time */
705 } 705 utb.actime = mtime;
706 utb.modtime = mtime;
707 utime(outName, &utb);
708 /* Set the file permissions */
709 chown(outName, uid, gid);
710 chmod(outName, mode);
711
712 outFd = -1;
713 }
706} 714}
707 715
708 716
@@ -712,40 +720,40 @@ static void readData (const char *cp, int count)
712 * Returns TRUE if the file is selected. 720 * Returns TRUE if the file is selected.
713 */ 721 */
714static int 722static int
715wantFileName (const char *fileName, int fileCount, char **fileTable) 723wantFileName(const char *fileName, int fileCount, char **fileTable)
716{ 724{
717 const char *pathName; 725 const char *pathName;
718 int fileLength; 726 int fileLength;
719 int pathLength; 727 int pathLength;
720 728
721 /* 729 /*
722 * If there are no files in the list, then the file is wanted. 730 * If there are no files in the list, then the file is wanted.
723 */ 731 */
724 if (fileCount == 0) 732 if (fileCount == 0)
725 return TRUE; 733 return TRUE;
726 734
727 fileLength = strlen (fileName); 735 fileLength = strlen(fileName);
728 736
729 /* 737 /*
730 * Check each of the test paths. 738 * Check each of the test paths.
731 */ 739 */
732 while (fileCount-- > 0) { 740 while (fileCount-- > 0) {
733 pathName = *fileTable++; 741 pathName = *fileTable++;
734 742
735 pathLength = strlen (pathName); 743 pathLength = strlen(pathName);
736 744
737 if (fileLength < pathLength) 745 if (fileLength < pathLength)
738 continue; 746 continue;
739 747
740 if (memcmp (fileName, pathName, pathLength) != 0) 748 if (memcmp(fileName, pathName, pathLength) != 0)
741 continue; 749 continue;
742 750
743 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) { 751 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) {
744 return TRUE; 752 return TRUE;
753 }
745 } 754 }
746 }
747 755
748 return FALSE; 756 return FALSE;
749} 757}
750 758
751/* 759/*
@@ -753,34 +761,34 @@ wantFileName (const char *fileName, int fileCount, char **fileTable)
753 * spaces on both sides of the number and with an optional null character 761 * spaces on both sides of the number and with an optional null character
754 * at the end. Returns -1 on an illegal format. 762 * at the end. Returns -1 on an illegal format.
755 */ 763 */
756static long getOctal (const char *cp, int len) 764static long getOctal(const char *cp, int len)
757{ 765{
758 long val; 766 long val;
759 767
760 while ((len > 0) && (*cp == ' ')) { 768 while ((len > 0) && (*cp == ' ')) {
761 cp++; 769 cp++;
762 len--; 770 len--;
763 } 771 }
764 772
765 if ((len == 0) || !isOctal (*cp)) 773 if ((len == 0) || !isOctal(*cp))
766 return -1; 774 return -1;
767 775
768 val = 0; 776 val = 0;
769 777
770 while ((len > 0) && isOctal (*cp)) { 778 while ((len > 0) && isOctal(*cp)) {
771 val = val * 8 + *cp++ - '0'; 779 val = val * 8 + *cp++ - '0';
772 len--; 780 len--;
773 } 781 }
774 782
775 while ((len > 0) && (*cp == ' ')) { 783 while ((len > 0) && (*cp == ' ')) {
776 cp++; 784 cp++;
777 len--; 785 len--;
778 } 786 }
779 787
780 if ((len > 0) && *cp) 788 if ((len > 0) && *cp)
781 return -1; 789 return -1;
782 790
783 return val; 791 return val;
784} 792}
785 793
786 794
@@ -795,65 +803,65 @@ static long getOctal (const char *cp, int len)
795/* 803/*
796 * Write a tar file containing the specified files. 804 * Write a tar file containing the specified files.
797 */ 805 */
798static void writeTarFile (int fileCount, char **fileTable) 806static void writeTarFile(int fileCount, char **fileTable)
799{ 807{
800 struct stat statbuf; 808 struct stat statbuf;
801 809
802 /* 810 /*
803 * Make sure there is at least one file specified. 811 * Make sure there is at least one file specified.
804 */ 812 */
805 if (fileCount <= 0) { 813 if (fileCount <= 0) {
806 fprintf (stderr, "No files specified to be saved\n"); 814 fprintf(stderr, "No files specified to be saved\n");
807 errorFlag = TRUE; 815 errorFlag = TRUE;
808 } 816 }
809 817
810 /* 818 /*
811 * Create the tar file for writing. 819 * Create the tar file for writing.
812 */ 820 */
813 if ((tarName == NULL) || !strcmp (tarName, "-")) { 821 if ((tarName == NULL) || !strcmp(tarName, "-")) {
814 tostdoutFlag = TRUE; 822 tostdoutFlag = TRUE;
815 tarFd = fileno(stdout); 823 tarFd = fileno(stdout);
816 } else 824 } else
817 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); 825 tarFd = open(tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
818 826
819 if (tarFd < 0) { 827 if (tarFd < 0) {
820 perror (tarName); 828 perror(tarName);
821 errorFlag = TRUE; 829 errorFlag = TRUE;
822 return; 830 return;
823 } 831 }
824 832
825 /* 833 /*
826 * Get the device and inode of the tar file for checking later. 834 * Get the device and inode of the tar file for checking later.
827 */ 835 */
828 if (fstat (tarFd, &statbuf) < 0) { 836 if (fstat(tarFd, &statbuf) < 0) {
829 perror (tarName); 837 perror(tarName);
830 errorFlag = TRUE; 838 errorFlag = TRUE;
831 goto done; 839 goto done;
832 } 840 }
833 841
834 tarDev = statbuf.st_dev; 842 tarDev = statbuf.st_dev;
835 tarInode = statbuf.st_ino; 843 tarInode = statbuf.st_ino;
836 844
837 /* 845 /*
838 * Append each file name into the archive file. 846 * Append each file name into the archive file.
839 * Follow symbolic links for these top level file names. 847 * Follow symbolic links for these top level file names.
840 */ 848 */
841 while (errorFlag==FALSE && (fileCount-- > 0)) { 849 while (errorFlag == FALSE && (fileCount-- > 0)) {
842 saveFile (*fileTable++, FALSE); 850 saveFile(*fileTable++, FALSE);
843 } 851 }
844 852
845 /* 853 /*
846 * Now write an empty block of zeroes to end the archive. 854 * Now write an empty block of zeroes to end the archive.
847 */ 855 */
848 writeTarBlock ("", 1); 856 writeTarBlock("", 1);
849 857
850 858
851 done: 859 done:
852 /* 860 /*
853 * Close the tar file and check for errors if it was opened. 861 * Close the tar file and check for errors if it was opened.
854 */ 862 */
855 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0)) 863 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close(tarFd) < 0))
856 perror (tarName); 864 perror(tarName);
857} 865}
858 866
859/* 867/*
@@ -863,73 +871,73 @@ static void writeTarFile (int fileCount, char **fileTable)
863 * flag indicates whether or not we want to see symbolic links as 871 * flag indicates whether or not we want to see symbolic links as
864 * they really are, instead of blindly following them. 872 * they really are, instead of blindly following them.
865 */ 873 */
866static void saveFile (const char *fileName, int seeLinks) 874static void saveFile(const char *fileName, int seeLinks)
867{ 875{
868 int status; 876 int status;
869 struct stat statbuf; 877 struct stat statbuf;
870 878
871 if (verboseFlag==TRUE) 879 if (verboseFlag == TRUE)
872 printf ("a %s\n", fileName); 880 printf("a %s\n", fileName);
873 881
874 /* 882 /*
875 * Check that the file name will fit in the header. 883 * Check that the file name will fit in the header.
876 */ 884 */
877 if (strlen (fileName) >= TAR_NAME_SIZE) { 885 if (strlen(fileName) >= TAR_NAME_SIZE) {
878 fprintf (stderr, "%s: File name is too long\n", fileName); 886 fprintf(stderr, "%s: File name is too long\n", fileName);
879 887
880 return; 888 return;
881 } 889 }
882 890
883 /* 891 /*
884 * Find out about the file. 892 * Find out about the file.
885 */ 893 */
886#ifdef S_ISLNK 894#ifdef S_ISLNK
887 if (seeLinks==TRUE) 895 if (seeLinks == TRUE)
888 status = lstat (fileName, &statbuf); 896 status = lstat(fileName, &statbuf);
889 else 897 else
890#endif 898#endif
891 status = stat (fileName, &statbuf); 899 status = stat(fileName, &statbuf);
892 900
893 if (status < 0) { 901 if (status < 0) {
894 perror (fileName); 902 perror(fileName);
903
904 return;
905 }
895 906
896 return; 907 /*
897 } 908 * Make sure we aren't trying to save our file into itself.
909 */
910 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
911 fprintf(stderr, "Skipping saving of archive file itself\n");
898 912
899 /* 913 return;
900 * Make sure we aren't trying to save our file into itself. 914 }
901 */
902 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
903 fprintf (stderr, "Skipping saving of archive file itself\n");
904 915
905 return; 916 /*
906 } 917 * Check the type of file.
918 */
919 mode = statbuf.st_mode;
907 920
908 /* 921 if (S_ISDIR(mode)) {
909 * Check the type of file. 922 saveDirectory(fileName, &statbuf);
910 */
911 mode = statbuf.st_mode;
912 923
913 if (S_ISDIR (mode)) { 924 return;
914 saveDirectory (fileName, &statbuf); 925 }
926 if (S_ISREG(mode)) {
927 saveRegularFile(fileName, &statbuf);
915 928
916 return; 929 return;
917 } 930 }
918 if (S_ISREG (mode)) {
919 saveRegularFile (fileName, &statbuf);
920 931
921 return; 932 /* Some day add support for tarring these up... but not today. :) */
922 }
923
924 /* Some day add support for tarring these up... but not today. :) */
925// if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) { 933// if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) {
926// fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName); 934// fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName);
927// } 935// }
928 936
929 /* 937 /*
930 * The file is a strange type of file, ignore it. 938 * The file is a strange type of file, ignore it.
931 */ 939 */
932 fprintf (stderr, "%s: not a directory or regular file\n", fileName); 940 fprintf(stderr, "%s: not a directory or regular file\n", fileName);
933} 941}
934 942
935 943
@@ -937,173 +945,172 @@ static void saveFile (const char *fileName, int seeLinks)
937 * Save a regular file to the tar file. 945 * Save a regular file to the tar file.
938 */ 946 */
939static void 947static void
940saveRegularFile (const char *fileName, const struct stat *statbuf) 948saveRegularFile(const char *fileName, const struct stat *statbuf)
941{ 949{
942 int sawEof; 950 int sawEof;
943 int fileFd; 951 int fileFd;
944 int cc; 952 int cc;
945 int dataCount; 953 int dataCount;
946 long fullDataCount; 954 long fullDataCount;
947 char data[TAR_BLOCK_SIZE * 16]; 955 char data[TAR_BLOCK_SIZE * 16];
948
949 /*
950 * Open the file for reading.
951 */
952 fileFd = open (fileName, O_RDONLY);
953
954 if (fileFd < 0) {
955 perror (fileName);
956
957 return;
958 }
959
960 /*
961 * Write out the header for the file.
962 */
963 writeHeader (fileName, statbuf);
964
965 /*
966 * Write the data blocks of the file.
967 * We must be careful to write the amount of data that the stat
968 * buffer indicated, even if the file has changed size. Otherwise
969 * the tar file will be incorrect.
970 */
971 fullDataCount = statbuf->st_size;
972 sawEof = FALSE;
973
974 while (fullDataCount > 0) {
975 /*
976 * Get the amount to write this iteration which is
977 * the minumum of the amount left to write and the
978 * buffer size.
979 */
980 dataCount = sizeof (data);
981
982 if (dataCount > fullDataCount)
983 dataCount = (int) fullDataCount;
984 956
985 /* 957 /*
986 * Read the data from the file if we haven't seen the 958 * Open the file for reading.
987 * end of file yet.
988 */ 959 */
989 cc = 0; 960 fileFd = open(fileName, O_RDONLY);
990
991 if (sawEof==FALSE) {
992 cc = fullRead (fileFd, data, dataCount);
993 961
994 if (cc < 0) { 962 if (fileFd < 0) {
995 perror (fileName); 963 perror(fileName);
996
997 (void) close (fileFd);
998 errorFlag = TRUE;
999 964
1000 return; 965 return;
1001 }
1002
1003 /*
1004 * If the file ended too soon, complain and set
1005 * a flag so we will zero fill the rest of it.
1006 */
1007 if (cc < dataCount) {
1008 fprintf (stderr,
1009 "%s: Short read - zero filling", fileName);
1010
1011 sawEof = TRUE;
1012 }
1013 } 966 }
1014 967
1015 /* 968 /*
1016 * Zero fill the rest of the data if necessary. 969 * Write out the header for the file.
1017 */ 970 */
1018 if (cc < dataCount) 971 writeHeader(fileName, statbuf);
1019 memset (data + cc, 0, dataCount - cc);
1020 972
1021 /* 973 /*
1022 * Write the buffer to the TAR file. 974 * Write the data blocks of the file.
975 * We must be careful to write the amount of data that the stat
976 * buffer indicated, even if the file has changed size. Otherwise
977 * the tar file will be incorrect.
1023 */ 978 */
1024 writeTarBlock (data, dataCount); 979 fullDataCount = statbuf->st_size;
1025 980 sawEof = FALSE;
1026 fullDataCount -= dataCount; 981
1027 } 982 while (fullDataCount > 0) {
983 /*
984 * Get the amount to write this iteration which is
985 * the minumum of the amount left to write and the
986 * buffer size.
987 */
988 dataCount = sizeof(data);
989
990 if (dataCount > fullDataCount)
991 dataCount = (int) fullDataCount;
992
993 /*
994 * Read the data from the file if we haven't seen the
995 * end of file yet.
996 */
997 cc = 0;
998
999 if (sawEof == FALSE) {
1000 cc = fullRead(fileFd, data, dataCount);
1001
1002 if (cc < 0) {
1003 perror(fileName);
1004
1005 (void) close(fileFd);
1006 errorFlag = TRUE;
1007
1008 return;
1009 }
1010
1011 /*
1012 * If the file ended too soon, complain and set
1013 * a flag so we will zero fill the rest of it.
1014 */
1015 if (cc < dataCount) {
1016 fprintf(stderr, "%s: Short read - zero filling", fileName);
1017
1018 sawEof = TRUE;
1019 }
1020 }
1021
1022 /*
1023 * Zero fill the rest of the data if necessary.
1024 */
1025 if (cc < dataCount)
1026 memset(data + cc, 0, dataCount - cc);
1027
1028 /*
1029 * Write the buffer to the TAR file.
1030 */
1031 writeTarBlock(data, dataCount);
1032
1033 fullDataCount -= dataCount;
1034 }
1028 1035
1029 /* 1036 /*
1030 * Close the file. 1037 * Close the file.
1031 */ 1038 */
1032 if ((tostdoutFlag == FALSE) && close (fileFd) < 0) 1039 if ((tostdoutFlag == FALSE) && close(fileFd) < 0)
1033 fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno)); 1040 fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno));
1034} 1041}
1035 1042
1036 1043
1037/* 1044/*
1038 * Save a directory and all of its files to the tar file. 1045 * Save a directory and all of its files to the tar file.
1039 */ 1046 */
1040static void saveDirectory (const char *dirName, const struct stat *statbuf) 1047static void saveDirectory(const char *dirName, const struct stat *statbuf)
1041{ 1048{
1042 DIR *dir; 1049 DIR *dir;
1043 struct dirent *entry; 1050 struct dirent *entry;
1044 int needSlash; 1051 int needSlash;
1045 char fullName[PATH_MAX + 1]; 1052 char fullName[PATH_MAX + 1];
1046 1053
1047 /* 1054 /*
1048 * Construct the directory name as used in the tar file by appending 1055 * Construct the directory name as used in the tar file by appending
1049 * a slash character to it. 1056 * a slash character to it.
1050 */ 1057 */
1051 strcpy (fullName, dirName); 1058 strcpy(fullName, dirName);
1052 strcat (fullName, "/"); 1059 strcat(fullName, "/");
1053 1060
1054 /* 1061 /*
1055 * Write out the header for the directory entry. 1062 * Write out the header for the directory entry.
1056 */ 1063 */
1057 writeHeader (fullName, statbuf); 1064 writeHeader(fullName, statbuf);
1058
1059 /*
1060 * Open the directory.
1061 */
1062 dir = opendir (dirName);
1063
1064 if (dir == NULL) {
1065 fprintf (stderr, "Cannot read directory \"%s\": %s\n",
1066 dirName, strerror (errno));
1067
1068 return;
1069 }
1070
1071 /*
1072 * See if a slash is needed.
1073 */
1074 needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/'));
1075
1076 /*
1077 * Read all of the directory entries and check them,
1078 * except for the current and parent directory entries.
1079 */
1080 while (errorFlag==FALSE && ((entry = readdir (dir)) != NULL)) {
1081 if ((strcmp (entry->d_name, ".") == 0) ||
1082 (strcmp (entry->d_name, "..") == 0)) {
1083 continue;
1084 }
1085 1065
1086 /* 1066 /*
1087 * Build the full path name to the file. 1067 * Open the directory.
1088 */ 1068 */
1089 strcpy (fullName, dirName); 1069 dir = opendir(dirName);
1070
1071 if (dir == NULL) {
1072 fprintf(stderr, "Cannot read directory \"%s\": %s\n",
1073 dirName, strerror(errno));
1090 1074
1091 if (needSlash) 1075 return;
1092 strcat (fullName, "/"); 1076 }
1093 1077
1094 strcat (fullName, entry->d_name); 1078 /*
1079 * See if a slash is needed.
1080 */
1081 needSlash = (*dirName && (dirName[strlen(dirName) - 1] != '/'));
1095 1082
1096 /* 1083 /*
1097 * Write this file to the tar file, noticing whether or not 1084 * Read all of the directory entries and check them,
1098 * the file is a symbolic link. 1085 * except for the current and parent directory entries.
1099 */ 1086 */
1100 saveFile (fullName, TRUE); 1087 while (errorFlag == FALSE && ((entry = readdir(dir)) != NULL)) {
1101 } 1088 if ((strcmp(entry->d_name, ".") == 0) ||
1089 (strcmp(entry->d_name, "..") == 0)) {
1090 continue;
1091 }
1092
1093 /*
1094 * Build the full path name to the file.
1095 */
1096 strcpy(fullName, dirName);
1097
1098 if (needSlash)
1099 strcat(fullName, "/");
1100
1101 strcat(fullName, entry->d_name);
1102
1103 /*
1104 * Write this file to the tar file, noticing whether or not
1105 * the file is a symbolic link.
1106 */
1107 saveFile(fullName, TRUE);
1108 }
1102 1109
1103 /* 1110 /*
1104 * All done, close the directory. 1111 * All done, close the directory.
1105 */ 1112 */
1106 closedir (dir); 1113 closedir(dir);
1107} 1114}
1108 1115
1109 1116
@@ -1111,54 +1118,54 @@ static void saveDirectory (const char *dirName, const struct stat *statbuf)
1111 * Write a tar header for the specified file name and status. 1118 * Write a tar header for the specified file name and status.
1112 * It is assumed that the file name fits. 1119 * It is assumed that the file name fits.
1113 */ 1120 */
1114static void writeHeader (const char *fileName, const struct stat *statbuf) 1121static void writeHeader(const char *fileName, const struct stat *statbuf)
1115{ 1122{
1116 long checkSum; 1123 long checkSum;
1117 const unsigned char *cp; 1124 const unsigned char *cp;
1118 int len; 1125 int len;
1119 TarHeader header; 1126 TarHeader header;
1120 1127
1121 /* 1128 /*
1122 * Zero the header block in preparation for filling it in. 1129 * Zero the header block in preparation for filling it in.
1123 */ 1130 */
1124 memset ((char *) &header, 0, sizeof (header)); 1131 memset((char *) &header, 0, sizeof(header));
1125 1132
1126 /* 1133 /*
1127 * Fill in the header. 1134 * Fill in the header.
1128 */ 1135 */
1129 strcpy (header.name, fileName); 1136 strcpy(header.name, fileName);
1130 1137
1131 strncpy (header.magic, TAR_MAGIC, sizeof (header.magic)); 1138 strncpy(header.magic, TAR_MAGIC, sizeof(header.magic));
1132 strncpy (header.version, TAR_VERSION, sizeof (header.version)); 1139 strncpy(header.version, TAR_VERSION, sizeof(header.version));
1133 1140
1134 putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777); 1141 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777);
1135 putOctal (header.uid, sizeof (header.uid), statbuf->st_uid); 1142 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
1136 putOctal (header.gid, sizeof (header.gid), statbuf->st_gid); 1143 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
1137 putOctal (header.size, sizeof (header.size), statbuf->st_size); 1144 putOctal(header.size, sizeof(header.size), statbuf->st_size);
1138 putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime); 1145 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
1139 1146
1140 header.typeFlag = TAR_TYPE_REGULAR; 1147 header.typeFlag = TAR_TYPE_REGULAR;
1141 1148
1142 /* 1149 /*
1143 * Calculate and store the checksum. 1150 * Calculate and store the checksum.
1144 * This is the sum of all of the bytes of the header, 1151 * This is the sum of all of the bytes of the header,
1145 * with the checksum field itself treated as blanks. 1152 * with the checksum field itself treated as blanks.
1146 */ 1153 */
1147 memset (header.checkSum, ' ', sizeof (header.checkSum)); 1154 memset(header.checkSum, ' ', sizeof(header.checkSum));
1148 1155
1149 cp = (const unsigned char *) &header; 1156 cp = (const unsigned char *) &header;
1150 len = sizeof (header); 1157 len = sizeof(header);
1151 checkSum = 0; 1158 checkSum = 0;
1152 1159
1153 while (len-- > 0) 1160 while (len-- > 0)
1154 checkSum += *cp++; 1161 checkSum += *cp++;
1155 1162
1156 putOctal (header.checkSum, sizeof (header.checkSum), checkSum); 1163 putOctal(header.checkSum, sizeof(header.checkSum), checkSum);
1157 1164
1158 /* 1165 /*
1159 * Write the tar header. 1166 * Write the tar header.
1160 */ 1167 */
1161 writeTarBlock ((const char *) &header, sizeof (header)); 1168 writeTarBlock((const char *) &header, sizeof(header));
1162} 1169}
1163 1170
1164 1171
@@ -1167,56 +1174,56 @@ static void writeHeader (const char *fileName, const struct stat *statbuf)
1167 * The data is always padded out to a multiple of TAR_BLOCK_SIZE. 1174 * The data is always padded out to a multiple of TAR_BLOCK_SIZE.
1168 * The errorFlag static variable is set on an error. 1175 * The errorFlag static variable is set on an error.
1169 */ 1176 */
1170static void writeTarBlock (const char *buf, int len) 1177static void writeTarBlock(const char *buf, int len)
1171{ 1178{
1172 int partialLength; 1179 int partialLength;
1173 int completeLength; 1180 int completeLength;
1174 char fullBlock[TAR_BLOCK_SIZE]; 1181 char fullBlock[TAR_BLOCK_SIZE];
1175 1182
1176 /* 1183 /*
1177 * If we had a write error before, then do nothing more. 1184 * If we had a write error before, then do nothing more.
1178 */ 1185 */
1179 if (errorFlag==TRUE) 1186 if (errorFlag == TRUE)
1180 return; 1187 return;
1181 1188
1182 /* 1189 /*
1183 * Get the amount of complete and partial blocks. 1190 * Get the amount of complete and partial blocks.
1184 */ 1191 */
1185 partialLength = len % TAR_BLOCK_SIZE; 1192 partialLength = len % TAR_BLOCK_SIZE;
1186 completeLength = len - partialLength; 1193 completeLength = len - partialLength;
1187 1194
1188 /* 1195 /*
1189 * Write all of the complete blocks. 1196 * Write all of the complete blocks.
1190 */ 1197 */
1191 if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) { 1198 if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) {
1192 perror (tarName); 1199 perror(tarName);
1193 1200
1194 errorFlag = TRUE; 1201 errorFlag = TRUE;
1195 1202
1196 return; 1203 return;
1197 } 1204 }
1198 1205
1199 /* 1206 /*
1200 * If there are no partial blocks left, we are done. 1207 * If there are no partial blocks left, we are done.
1201 */ 1208 */
1202 if (partialLength == 0) 1209 if (partialLength == 0)
1203 return; 1210 return;
1204 1211
1205 /* 1212 /*
1206 * Copy the partial data into a complete block, and pad the rest 1213 * Copy the partial data into a complete block, and pad the rest
1207 * of it with zeroes. 1214 * of it with zeroes.
1208 */ 1215 */
1209 memcpy (fullBlock, buf + completeLength, partialLength); 1216 memcpy(fullBlock, buf + completeLength, partialLength);
1210 memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); 1217 memset(fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength);
1211 1218
1212 /* 1219 /*
1213 * Write the last complete block. 1220 * Write the last complete block.
1214 */ 1221 */
1215 if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) { 1222 if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) {
1216 perror (tarName); 1223 perror(tarName);
1217 1224
1218 errorFlag = TRUE; 1225 errorFlag = TRUE;
1219 } 1226 }
1220} 1227}
1221 1228
1222 1229
@@ -1225,48 +1232,48 @@ static void writeTarBlock (const char *buf, int len)
1225 * The number is zero and space padded and possibly null padded. 1232 * The number is zero and space padded and possibly null padded.
1226 * Returns TRUE if successful. 1233 * Returns TRUE if successful.
1227 */ 1234 */
1228static int putOctal (char *cp, int len, long value) 1235static int putOctal(char *cp, int len, long value)
1229{ 1236{
1230 int tempLength; 1237 int tempLength;
1231 char *tempString; 1238 char *tempString;
1232 char tempBuffer[32]; 1239 char tempBuffer[32];
1233
1234 /*
1235 * Create a string of the specified length with an initial space,
1236 * leading zeroes and the octal number, and a trailing null.
1237 */
1238 tempString = tempBuffer;
1239
1240 sprintf (tempString, " %0*lo", len - 2, value);
1241
1242 tempLength = strlen (tempString) + 1;
1243
1244 /*
1245 * If the string is too large, suppress the leading space.
1246 */
1247 if (tempLength > len) {
1248 tempLength--;
1249 tempString++;
1250 }
1251
1252 /*
1253 * If the string is still too large, suppress the trailing null.
1254 */
1255 if (tempLength > len)
1256 tempLength--;
1257
1258 /*
1259 * If the string is still too large, fail.
1260 */
1261 if (tempLength > len)
1262 return FALSE;
1263 1240
1264 /* 1241 /*
1265 * Copy the string to the field. 1242 * Create a string of the specified length with an initial space,
1266 */ 1243 * leading zeroes and the octal number, and a trailing null.
1267 memcpy (cp, tempString, len); 1244 */
1245 tempString = tempBuffer;
1268 1246
1269 return TRUE; 1247 sprintf(tempString, " %0*lo", len - 2, value);
1248
1249 tempLength = strlen(tempString) + 1;
1250
1251 /*
1252 * If the string is too large, suppress the leading space.
1253 */
1254 if (tempLength > len) {
1255 tempLength--;
1256 tempString++;
1257 }
1258
1259 /*
1260 * If the string is still too large, suppress the trailing null.
1261 */
1262 if (tempLength > len)
1263 tempLength--;
1264
1265 /*
1266 * If the string is still too large, fail.
1267 */
1268 if (tempLength > len)
1269 return FALSE;
1270
1271 /*
1272 * Copy the string to the field.
1273 */
1274 memcpy(cp, tempString, len);
1275
1276 return TRUE;
1270} 1277}
1271#endif 1278#endif
1272 1279
diff --git a/busybox.c b/busybox.c
index e2c2e0393..8bbe6a22e 100644
--- a/busybox.c
+++ b/busybox.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
@@ -16,329 +17,342 @@ static int been_there_done_that = 0;
16 * replacement may be in order 17 * replacement may be in order
17 */ 18 */
18#if 0 19#if 0
19void exit (int status) __attribute__ ((noreturn)); 20void exit(int status) __attribute__ ((noreturn));
20void exit (int status) { _exit(status); }; 21void exit(int status)
21void abort (void) __attribute__ ((__noreturn__)); 22{
22void abort (void) { _exit(0); }; 23 _exit(status);
23int atexit (void (*__func) (void)) { _exit(0); }; 24};
25void abort(void) __attribute__ ((__noreturn__));
26void abort(void)
27{
28 _exit(0);
29};
30int atexit(void (*__func) (void))
31{
32 _exit(0);
33};
24void *__libc_stack_end; 34void *__libc_stack_end;
25#endif 35#endif
26 36
27 37
28static const struct Applet applets[] = { 38static const struct Applet applets[] = {
29 39
30#ifdef BB_BUSYBOX //bin 40#ifdef BB_BUSYBOX //bin
31 {"busybox", busybox_main}, 41 {"busybox", busybox_main},
42#endif
43#ifdef BB_BLOCK_DEVICE //sbin
44 {"block_device", block_device_main},
32#endif 45#endif
33#ifdef BB_BLOCK_DEVICE //sbin 46#ifdef BB_CAT //bin
34 {"block_device", block_device_main}, 47 {"cat", cat_main},
35#endif 48#endif
36#ifdef BB_CAT //bin 49#ifdef BB_CHMOD_CHOWN_CHGRP //bin
37 {"cat", cat_main}, 50 {"chmod", chmod_chown_chgrp_main},
51 {"chown", chmod_chown_chgrp_main},
52 {"chgrp", chmod_chown_chgrp_main},
38#endif 53#endif
39#ifdef BB_CHMOD_CHOWN_CHGRP //bin 54#ifdef BB_CHROOT //sbin
40 {"chmod", chmod_chown_chgrp_main}, 55 {"chroot", chroot_main},
41 {"chown", chmod_chown_chgrp_main},
42 {"chgrp", chmod_chown_chgrp_main},
43#endif 56#endif
44#ifdef BB_CHROOT //sbin 57#ifdef BB_CLEAR //usr/bin
45 {"chroot", chroot_main}, 58 {"clear", clear_main},
46#endif 59#endif
47#ifdef BB_CLEAR //usr/bin 60#ifdef BB_CHVT //usr/bin
48 {"clear", clear_main}, 61 {"chvt", chvt_main},
49#endif 62#endif
50#ifdef BB_CHVT //usr/bin 63#ifdef BB_CP_MV //bin
51 {"chvt", chvt_main}, 64 {"cp", cp_mv_main},
65 {"mv", cp_mv_main},
52#endif 66#endif
53#ifdef BB_CP_MV //bin 67#ifdef BB_DATE //bin
54 {"cp", cp_mv_main}, 68 {"date", date_main},
55 {"mv", cp_mv_main},
56#endif 69#endif
57#ifdef BB_DATE //bin 70#ifdef BB_DD //bin
58 {"date", date_main}, 71 {"dd", dd_main},
59#endif 72#endif
60#ifdef BB_DD //bin 73#ifdef BB_DF //bin
61 {"dd", dd_main}, 74 {"df", df_main},
62#endif 75#endif
63#ifdef BB_DF //bin 76#ifdef BB_DMESG //bin
64 {"df", df_main}, 77 {"dmesg", dmesg_main},
65#endif 78#endif
66#ifdef BB_DMESG //bin 79#ifdef BB_DU //bin
67 {"dmesg", dmesg_main}, 80 {"du", du_main},
68#endif 81#endif
69#ifdef BB_DU //bin 82#ifdef BB_DUTMP //usr/sbin
70 {"du", du_main}, 83 {"dutmp", dutmp_main},
71#endif 84#endif
72#ifdef BB_DUTMP //usr/sbin 85#ifdef BB_FBSET //usr/sbin
73 {"dutmp", dutmp_main}, 86 {"fbset", fbset_main},
74#endif 87#endif
75#ifdef BB_FBSET //usr/sbin 88#ifdef BB_FDFLUSH //bin
76 {"fbset", fbset_main}, 89 {"fdflush", fdflush_main},
77#endif 90#endif
78#ifdef BB_FDFLUSH //bin 91#ifdef BB_FIND //usr/bin
79 {"fdflush", fdflush_main}, 92 {"find", find_main},
80#endif 93#endif
81#ifdef BB_FIND //usr/bin 94#ifdef BB_FREE //usr/bin
82 {"find", find_main}, 95 {"free", free_main},
83#endif 96#endif
84#ifdef BB_FREE //usr/bin 97#ifdef BB_DEALLOCVT //usr/bin
85 {"free", free_main}, 98 {"deallocvt", deallocvt_main},
86#endif 99#endif
87#ifdef BB_DEALLOCVT //usr/bin 100#ifdef BB_FSCK_MINIX //sbin
88 {"deallocvt", deallocvt_main}, 101 {"fsck.minix", fsck_minix_main},
89#endif 102#endif
90#ifdef BB_FSCK_MINIX //sbin 103#ifdef BB_MKFS_MINIX //sbin
91 {"fsck.minix", fsck_minix_main}, 104 {"mkfs.minix", mkfs_minix_main},
92#endif 105#endif
93#ifdef BB_MKFS_MINIX //sbin 106#ifdef BB_GREP //bin
94 {"mkfs.minix", mkfs_minix_main}, 107 {"grep", grep_main},
95#endif 108#endif
96#ifdef BB_GREP //bin 109#ifdef BB_HALT //sbin
97 {"grep", grep_main}, 110 {"halt", halt_main},
98#endif 111#endif
99#ifdef BB_HALT //sbin 112#ifdef BB_HEAD //bin
100 {"halt", halt_main}, 113 {"head", head_main},
101#endif 114#endif
102#ifdef BB_HEAD //bin 115#ifdef BB_HOSTID //usr/bin
103 {"head", head_main}, 116 {"hostid", hostid_main},
104#endif 117#endif
105#ifdef BB_HOSTID //usr/bin 118#ifdef BB_HOSTNAME //bin
106 {"hostid", hostid_main}, 119 {"hostname", hostname_main},
107#endif 120#endif
108#ifdef BB_HOSTNAME //bin 121#ifdef BB_INIT //sbin
109 {"hostname", hostname_main}, 122 {"init", init_main},
110#endif 123#endif
111#ifdef BB_INIT //sbin 124#ifdef BB_INSMOD //sbin
112 {"init", init_main}, 125 {"insmod", insmod_main},
113#endif 126#endif
114#ifdef BB_INSMOD //sbin 127#ifdef BB_FEATURE_LINUXRC //
115 {"insmod", insmod_main}, 128 {"linuxrc", init_main},
116#endif 129#endif
117#ifdef BB_FEATURE_LINUXRC // 130#ifdef BB_KILL //bin
118 {"linuxrc", init_main}, 131 {"kill", kill_main},
119#endif 132#endif
120#ifdef BB_KILL //bin 133#ifdef BB_LENGTH //usr/bin
121 {"kill", kill_main}, 134 {"length", length_main},
122#endif 135#endif
123#ifdef BB_LENGTH //usr/bin 136#ifdef BB_LN //bin
124 {"length", length_main}, 137 {"ln", ln_main},
125#endif 138#endif
126#ifdef BB_LN //bin 139#ifdef BB_LOADACM //usr/bin
127 {"ln", ln_main}, 140 {"loadacm", loadacm_main},
128#endif 141#endif
129#ifdef BB_LOADACM //usr/bin 142#ifdef BB_LOADFONT //usr/bin
130 {"loadacm", loadacm_main}, 143 {"loadfont", loadfont_main},
131#endif
132#ifdef BB_LOADFONT //usr/bin
133 {"loadfont", loadfont_main},
134#endif 144#endif
135#ifdef BB_LOADKMAP //sbin 145#ifdef BB_LOADKMAP //sbin
136 {"loadkmap", loadkmap_main}, 146 {"loadkmap", loadkmap_main},
137#endif 147#endif
138#ifdef BB_LS //bin 148#ifdef BB_LS //bin
139 {"ls", ls_main}, 149 {"ls", ls_main},
140#endif 150#endif
141#ifdef BB_LSMOD //sbin 151#ifdef BB_LSMOD //sbin
142 {"lsmod", lsmod_main}, 152 {"lsmod", lsmod_main},
143#endif 153#endif
144#ifdef BB_MAKEDEVS //sbin 154#ifdef BB_MAKEDEVS //sbin
145 {"makedevs", makedevs_main}, 155 {"makedevs", makedevs_main},
146#endif 156#endif
147#ifdef BB_MATH //usr/bin 157#ifdef BB_MATH //usr/bin
148 {"math", math_main}, 158 {"math", math_main},
149#endif 159#endif
150#ifdef BB_MKDIR //bin 160#ifdef BB_MKDIR //bin
151 {"mkdir", mkdir_main}, 161 {"mkdir", mkdir_main},
152#endif 162#endif
153#ifdef BB_MKFIFO //usr/bin 163#ifdef BB_MKFIFO //usr/bin
154 {"mkfifo", mkfifo_main}, 164 {"mkfifo", mkfifo_main},
155#endif 165#endif
156#ifdef BB_MKNOD //bin 166#ifdef BB_MKNOD //bin
157 {"mknod", mknod_main}, 167 {"mknod", mknod_main},
158#endif 168#endif
159#ifdef BB_MKSWAP //sbin 169#ifdef BB_MKSWAP //sbin
160 {"mkswap", mkswap_main}, 170 {"mkswap", mkswap_main},
161#endif 171#endif
162#ifdef BB_MNC //usr/bin 172#ifdef BB_MNC //usr/bin
163 {"mnc", mnc_main}, 173 {"mnc", mnc_main},
164#endif 174#endif
165#ifdef BB_MORE //bin 175#ifdef BB_MORE //bin
166 {"more", more_main}, 176 {"more", more_main},
167#endif 177#endif
168#ifdef BB_MOUNT //bin 178#ifdef BB_MOUNT //bin
169 {"mount", mount_main}, 179 {"mount", mount_main},
170#endif 180#endif
171#ifdef BB_MT //bin 181#ifdef BB_MT //bin
172 {"mt", mt_main}, 182 {"mt", mt_main},
173#endif 183#endif
174#ifdef BB_NSLOOKUP //usr/bin 184#ifdef BB_NSLOOKUP //usr/bin
175 {"nslookup", nslookup_main}, 185 {"nslookup", nslookup_main},
176#endif 186#endif
177#ifdef BB_PING //bin 187#ifdef BB_PING //bin
178 {"ping", ping_main}, 188 {"ping", ping_main},
179#endif 189#endif
180#ifdef BB_POWEROFF //sbin 190#ifdef BB_POWEROFF //sbin
181 {"poweroff", poweroff_main}, 191 {"poweroff", poweroff_main},
182#endif 192#endif
183#ifdef BB_PRINTF //usr/bin 193#ifdef BB_PRINTF //usr/bin
184 {"printf", printf_main}, 194 {"printf", printf_main},
185#endif 195#endif
186#ifdef BB_PS //bin 196#ifdef BB_PS //bin
187 {"ps", ps_main}, 197 {"ps", ps_main},
188#endif 198#endif
189#ifdef BB_PWD //bin 199#ifdef BB_PWD //bin
190 {"pwd", pwd_main}, 200 {"pwd", pwd_main},
191#endif 201#endif
192#ifdef BB_REBOOT //sbin 202#ifdef BB_REBOOT //sbin
193 {"reboot", reboot_main}, 203 {"reboot", reboot_main},
194#endif 204#endif
195#ifdef BB_RM //bin 205#ifdef BB_RM //bin
196 {"rm", rm_main}, 206 {"rm", rm_main},
197#endif 207#endif
198#ifdef BB_RMDIR //bin 208#ifdef BB_RMDIR //bin
199 {"rmdir", rmdir_main}, 209 {"rmdir", rmdir_main},
200#endif 210#endif
201#ifdef BB_RMMOD //sbin 211#ifdef BB_RMMOD //sbin
202 {"rmmod", rmmod_main}, 212 {"rmmod", rmmod_main},
203#endif 213#endif
204#ifdef BB_SFDISK //sbin 214#ifdef BB_SFDISK //sbin
205 {"fdisk", sfdisk_main}, 215 {"fdisk", sfdisk_main},
206 {"sfdisk", sfdisk_main}, 216 {"sfdisk", sfdisk_main},
207#endif 217#endif
208#ifdef BB_SED //bin 218#ifdef BB_SED //bin
209 {"sed", sed_main}, 219 {"sed", sed_main},
210#endif 220#endif
211#ifdef BB_SLEEP //bin 221#ifdef BB_SLEEP //bin
212 {"sleep", sleep_main}, 222 {"sleep", sleep_main},
213#endif 223#endif
214#ifdef BB_SORT //bin 224#ifdef BB_SORT //bin
215 {"sort", sort_main}, 225 {"sort", sort_main},
216#endif 226#endif
217#ifdef BB_SYNC //bin 227#ifdef BB_SYNC //bin
218 {"sync", sync_main}, 228 {"sync", sync_main},
219#endif 229#endif
220#ifdef BB_SYSLOGD //sbin 230#ifdef BB_SYSLOGD //sbin
221 {"syslogd", syslogd_main}, 231 {"syslogd", syslogd_main},
222#endif 232#endif
223#ifdef BB_LOGGER //usr/bin 233#ifdef BB_LOGGER //usr/bin
224 {"logger", logger_main}, 234 {"logger", logger_main},
225#endif 235#endif
226#ifdef BB_LOGNAME //usr/bin 236#ifdef BB_LOGNAME //usr/bin
227 {"logname", logname_main}, 237 {"logname", logname_main},
228#endif 238#endif
229#ifdef BB_SWAPONOFF //sbin 239#ifdef BB_SWAPONOFF //sbin
230 {"swapon", swap_on_off_main}, 240 {"swapon", swap_on_off_main},
231 {"swapoff", swap_on_off_main}, 241 {"swapoff", swap_on_off_main},
232#endif 242#endif
233#ifdef BB_TAIL //usr/bin 243#ifdef BB_TAIL //usr/bin
234 {"tail", tail_main}, 244 {"tail", tail_main},
235#endif 245#endif
236#ifdef BB_TAR //bin 246#ifdef BB_TAR //bin
237 {"tar", tar_main}, 247 {"tar", tar_main},
238#endif 248#endif
239#ifdef BB_TEE //bin 249#ifdef BB_TEE //bin
240 {"tee", tee_main}, 250 {"tee", tee_main},
241#endif 251#endif
242#ifdef BB_TOUCH //usr/bin 252#ifdef BB_TOUCH //usr/bin
243 {"touch", touch_main}, 253 {"touch", touch_main},
244#endif 254#endif
245#ifdef BB_TRUE_FALSE //bin 255#ifdef BB_TRUE_FALSE //bin
246 {"true", true_main}, 256 {"true", true_main},
247 {"false", false_main}, 257 {"false", false_main},
248#endif 258#endif
249#ifdef BB_TTY //usr/bin 259#ifdef BB_TTY //usr/bin
250 {"tty", tty_main}, 260 {"tty", tty_main},
251#endif 261#endif
252#ifdef BB_UNAME //bin 262#ifdef BB_UNAME //bin
253 {"uname", uname_main}, 263 {"uname", uname_main},
254#endif 264#endif
255#ifdef BB_UMOUNT //bin 265#ifdef BB_UMOUNT //bin
256 {"umount", umount_main}, 266 {"umount", umount_main},
257#endif 267#endif
258#ifdef BB_UNIQ //bin 268#ifdef BB_UNIQ //bin
259 {"uniq", uniq_main}, 269 {"uniq", uniq_main},
260#endif 270#endif
261#ifdef BB_UPDATE //sbin 271#ifdef BB_UPDATE //sbin
262 {"update", update_main}, 272 {"update", update_main},
263#endif 273#endif
264#ifdef BB_WC //usr/bin 274#ifdef BB_WC //usr/bin
265 {"wc", wc_main}, 275 {"wc", wc_main},
266#endif 276#endif
267#ifdef BB_WHOAMI //usr/bin 277#ifdef BB_WHOAMI //usr/bin
268 {"whoami", whoami_main}, 278 {"whoami", whoami_main},
269#endif 279#endif
270#ifdef BB_YES //usr/bin 280#ifdef BB_YES //usr/bin
271 {"yes", yes_main}, 281 {"yes", yes_main},
272#endif 282#endif
273#ifdef BB_GUNZIP //bin 283#ifdef BB_GUNZIP //bin
274 {"zcat", gunzip_main}, 284 {"zcat", gunzip_main},
275 {"gunzip", gunzip_main}, 285 {"gunzip", gunzip_main},
276#endif 286#endif
277#ifdef BB_GZIP //bin 287#ifdef BB_GZIP //bin
278 {"gzip", gzip_main}, 288 {"gzip", gzip_main},
279#endif 289#endif
280 {0} 290 {0}
281}; 291};
282 292
283 293
284 294
285int main(int argc, char **argv) 295int main(int argc, char **argv)
286{ 296{
287 char *s = argv[0]; 297 char *s = argv[0];
288 char *name = argv[0]; 298 char *name = argv[0];
289 const struct Applet *a = applets; 299 const struct Applet *a = applets;
290 300
291 while (*s != '\0') { 301 while (*s != '\0') {
292 if (*s++ == '/') 302 if (*s++ == '/')
293 name = s; 303 name = s;
294 } 304 }
295 305
296 while (a->name != 0) { 306 while (a->name != 0) {
297 if (strcmp(name, a->name) == 0) { 307 if (strcmp(name, a->name) == 0) {
298 int status; 308 int status;
299 309
300 status = ((*(a->main)) (argc, argv)); 310 status = ((*(a->main)) (argc, argv));
301 if (status < 0) { 311 if (status < 0) {
302 fprintf(stderr, "%s: %s\n", a->name, strerror(errno)); 312 fprintf(stderr, "%s: %s\n", a->name, strerror(errno));
303 } 313 }
304 fprintf(stderr, "\n"); 314 fprintf(stderr, "\n");
305 exit(status); 315 exit(status);
316 }
317 a++;
306 } 318 }
307 a++; 319 exit(busybox_main(argc, argv));
308 }
309 exit (busybox_main(argc, argv));
310} 320}
311 321
312 322
313int busybox_main(int argc, char **argv) 323int busybox_main(int argc, char **argv)
314{ 324{
315 int col=0; 325 int col = 0;
316 argc--;
317 argv++;
318 326
319 if (been_there_done_that == 1 || argc < 1) { 327 argc--;
320 const struct Applet *a = applets; 328 argv++;
321 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
322 BB_VER, BB_BT);
323 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
324 fprintf(stderr, " or: [function] [arguments]...\n\n");
325 fprintf(stderr,
326 "\tMost people will create a symlink to busybox for each\n"
327 "\tfunction name, and busybox will act like whatever you invoke it as.\n");
328 fprintf(stderr, "\nCurrently defined functions:\n");
329 329
330 while (a->name != 0) { 330 if (been_there_done_that == 1 || argc < 1) {
331 col+=fprintf(stderr, "%s%s", ((col==0)? "\t":", "), (a++)->name); 331 const struct Applet *a = applets;
332 if (col>60 && a->name != 0) { 332
333 fprintf(stderr, ",\n"); 333 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
334 col=0; 334 BB_VER, BB_BT);
335 } 335 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
336 fprintf(stderr, " or: [function] [arguments]...\n\n");
337 fprintf(stderr,
338 "\tMost people will create a symlink to busybox for each\n"
339 "\tfunction name, and busybox will act like whatever you invoke it as.\n");
340 fprintf(stderr, "\nCurrently defined functions:\n");
341
342 while (a->name != 0) {
343 col +=
344 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
345 (a++)->name);
346 if (col > 60 && a->name != 0) {
347 fprintf(stderr, ",\n");
348 col = 0;
349 }
350 }
351 fprintf(stderr, "\n\n");
352 exit(-1);
353 } else {
354 /* If we've already been here once, exit now */
355 been_there_done_that = 1;
356 return (main(argc, argv));
336 } 357 }
337 fprintf(stderr, "\n\n");
338 exit(-1);
339 } else {
340 /* If we've already been here once, exit now */
341 been_there_done_that = 1;
342 return (main(argc, argv));
343 }
344} 358}
diff --git a/busybox.def.h b/busybox.def.h
index 8e26b1492..f8c6e6e07 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1// This file defines the feature set to be compiled into busybox. 2// This file defines the feature set to be compiled into busybox.
2// When you turn things off here, they won't be compiled in at all. 3// When you turn things off here, they won't be compiled in at all.
3// 4//
diff --git a/cat.c b/cat.c
index 0d32efe84..86f85fe8e 100644
--- a/cat.c
+++ b/cat.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini Cat implementation for busybox 3 * Mini Cat implementation for busybox
3 * 4 *
@@ -24,36 +25,37 @@
24#include <stdio.h> 25#include <stdio.h>
25 26
26 27
27static void print_file( FILE *file) 28static void print_file(FILE * file)
28{ 29{
29 int c; 30 int c;
30 while ((c = getc(file)) != EOF) 31
31 putc(c, stdout); 32 while ((c = getc(file)) != EOF)
32 fclose(file); 33 putc(c, stdout);
33 fflush(stdout); 34 fclose(file);
35 fflush(stdout);
34} 36}
35 37
36extern int cat_main(int argc, char **argv) 38extern int cat_main(int argc, char **argv)
37{ 39{
38 FILE *file; 40 FILE *file;
39 41
40 if (argc==1) { 42 if (argc == 1) {
41 print_file( stdin); 43 print_file(stdin);
42 exit( TRUE); 44 exit(TRUE);
43 } 45 }
44 46
45 if ( **(argv+1) == '-' ) { 47 if (**(argv + 1) == '-') {
46 usage ("cat [file ...]\n"); 48 usage("cat [file ...]\n");
47 } 49 }
48 argc--; 50 argc--;
49 51
50 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv) ) { 52 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv)) {
51 file = fopen(*argv, "r"); 53 file = fopen(*argv, "r");
52 if (file == NULL) { 54 if (file == NULL) {
53 perror(*argv); 55 perror(*argv);
54 exit(FALSE); 56 exit(FALSE);
57 }
58 print_file(file);
55 } 59 }
56 print_file( file); 60 exit(TRUE);
57 }
58 exit(TRUE);
59} 61}
diff --git a/chmod_chown_chgrp.c b/chmod_chown_chgrp.c
index b4c5da936..d5e67b599 100644
--- a/chmod_chown_chgrp.c
+++ b/chmod_chown_chgrp.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini chown/chmod/chgrp implementation for busybox 3 * Mini chown/chmod/chgrp implementation for busybox
3 * 4 *
@@ -34,8 +35,8 @@
34static uid_t uid = -1; 35static uid_t uid = -1;
35static gid_t gid = -1; 36static gid_t gid = -1;
36static int whichApp; 37static int whichApp;
37static char* invocationName=NULL; 38static char *invocationName = NULL;
38static char* theMode=NULL; 39static char *theMode = NULL;
39 40
40 41
41#define CHGRP_APP 1 42#define CHGRP_APP 1
@@ -43,130 +44,147 @@ static char* theMode=NULL;
43#define CHMOD_APP 3 44#define CHMOD_APP 3
44 45
45static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n\n" 46static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n\n"
46 "Change the group membership of each FILE to GROUP.\n" 47 "Change the group membership of each FILE to GROUP.\n"
47 "\nOptions:\n\t-R\tchange files and directories recursively\n"; 48
48static const char chown_usage[] = "chown [OPTION]... OWNER[.[GROUP] FILE...\n\n" 49 "\nOptions:\n\t-R\tchange files and directories recursively\n";
49 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" 50static const char chown_usage[] =
50 "\nOptions:\n\t-R\tchange files and directories recursively\n"; 51 "chown [OPTION]... OWNER[.[GROUP] FILE...\n\n"
51static const char chmod_usage[] = "chmod [-R] MODE[,MODE]... FILE...\n\n" 52 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
52"Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" 53
53"one or more of the letters rwxst.\n\n" 54 "\nOptions:\n\t-R\tchange files and directories recursively\n";
54 "\nOptions:\n\t-R\tchange files and directories recursively.\n"; 55static const char chmod_usage[] =
55 56 "chmod [-R] MODE[,MODE]... FILE...\n\n"
56 57 "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n"
57static int fileAction(const char *fileName, struct stat* statbuf) 58
59 "one or more of the letters rwxst.\n\n"
60 "\nOptions:\n\t-R\tchange files and directories recursively.\n";
61
62
63static int fileAction(const char *fileName, struct stat *statbuf)
58{ 64{
59 switch (whichApp) { 65 switch (whichApp) {
60 case CHGRP_APP: 66 case CHGRP_APP:
61 case CHOWN_APP: 67 case CHOWN_APP:
62#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 68#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
63 if (lchown(fileName, (whichApp==CHOWN_APP)? uid : statbuf->st_uid, 69 if (lchown
64 (gid==-1)? statbuf->st_gid : gid) == 0) 70 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
71 (gid == -1) ? statbuf->st_gid : gid) == 0)
65#else 72#else
66 if (chown(fileName, (whichApp==CHOWN_APP)? uid : statbuf->st_uid, 73 if (chown
67 (gid==-1)? statbuf->st_gid : gid) == 0) 74 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
75 (gid == -1) ? statbuf->st_gid : gid) == 0)
68#endif 76#endif
69 { 77 {
70 return( TRUE); 78 return (TRUE);
71 } 79 }
72 break; 80 break;
73 case CHMOD_APP: 81 case CHMOD_APP:
74 /* Parse the specified modes */ 82 /* Parse the specified modes */
75 if ( parse_mode(theMode, &(statbuf->st_mode)) == FALSE ) { 83 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
76 fprintf(stderr, "%s: unknown mode: %s\n", invocationName, theMode); 84 fprintf(stderr, "%s: unknown mode: %s\n", invocationName,
77 exit( FALSE); 85 theMode);
78 } 86 exit(FALSE);
79 if (chmod(fileName, statbuf->st_mode) == 0) 87 }
80 return( TRUE); 88 if (chmod(fileName, statbuf->st_mode) == 0)
81 break; 89 return (TRUE);
82 } 90 break;
83 perror(fileName); 91 }
84 return( FALSE); 92 perror(fileName);
93 return (FALSE);
85} 94}
86 95
87int chmod_chown_chgrp_main(int argc, char **argv) 96int chmod_chown_chgrp_main(int argc, char **argv)
88{ 97{
89 int recursiveFlag=FALSE; 98 int recursiveFlag = FALSE;
90 char *groupName; 99 char *groupName;
91 char *p; 100 char *p;
92 const char *appUsage; 101 const char *appUsage;
93 102
94 whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP; 103 whichApp =
95 104 (strcmp(*argv, "chown") ==
96 appUsage = (whichApp==CHOWN_APP)? chown_usage : (whichApp==CHMOD_APP)? chmod_usage : chgrp_usage; 105 0) ? CHOWN_APP : (strcmp(*argv,
97 106 "chmod") == 0) ? CHMOD_APP : CHGRP_APP;
98 if (argc < 2) 107
99 usage( appUsage); 108 appUsage =
100 invocationName = *argv; 109 (whichApp == CHOWN_APP) ? chown_usage : (whichApp ==
101 argc--; 110 CHMOD_APP) ? chmod_usage :
102 argv++; 111 chgrp_usage;
103 112
104 /* Parse options */ 113 if (argc < 2)
105 while (**argv == '-') { 114 usage(appUsage);
106 while (*++(*argv)) switch (**argv) { 115 invocationName = *argv;
107 case 'R':
108 recursiveFlag = TRUE;
109 break;
110 default:
111 fprintf(stderr, invalid_option, invocationName, **argv);
112 usage( appUsage);
113 }
114 argc--; 116 argc--;
115 argv++; 117 argv++;
116 } 118
117 119 /* Parse options */
118 if ( whichApp == CHMOD_APP ) { 120 while (**argv == '-') {
119 theMode = *argv; 121 while (*++(*argv))
120 } else { 122 switch (**argv) {
121 123 case 'R':
122 /* Find the selected group */ 124 recursiveFlag = TRUE;
123 if ( whichApp==CHGRP_APP ) { 125 break;
124 groupName = *argv; 126 default:
125 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */ 127 fprintf(stderr, invalid_option, invocationName, **argv);
126 if (groupName == p) 128 usage(appUsage);
127 gid = my_getgrnam(groupName); 129 }
128 if (gid == -1) 130 argc--;
129 goto bad_group; 131 argv++;
130 } else {
131 groupName = strchr(*argv, '.');
132 if (groupName) {
133 *groupName++ = '\0';
134 gid = strtoul(groupName, &p, 10);
135 if (groupName == p)
136 gid = my_getgrnam(groupName);
137 if (gid == -1)
138 goto bad_group;
139 } else
140 gid = -1;
141 } 132 }
142 133
134 if (whichApp == CHMOD_APP) {
135 theMode = *argv;
136 } else {
143 137
144 /* Find the selected user (if appropriate) */ 138 /* Find the selected group */
145 if (whichApp==CHOWN_APP) { 139 if (whichApp == CHGRP_APP) {
146 uid = strtoul(*argv, &p, 10); /* if numeric ...*/ 140 groupName = *argv;
147 if (*argv == p) 141 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */
148 uid = my_getpwnam(*argv); 142 if (groupName == p)
149 if (uid == -1) { 143 gid = my_getgrnam(groupName);
150 fprintf(stderr, "%s: unknown user name: %s\n", invocationName, *argv); 144 if (gid == -1)
151 exit( FALSE); 145 goto bad_group;
152 } 146 } else {
147 groupName = strchr(*argv, '.');
148 if (groupName) {
149 *groupName++ = '\0';
150 gid = strtoul(groupName, &p, 10);
151 if (groupName == p)
152 gid = my_getgrnam(groupName);
153 if (gid == -1)
154 goto bad_group;
155 } else
156 gid = -1;
157 }
158
159
160 /* Find the selected user (if appropriate) */
161 if (whichApp == CHOWN_APP) {
162 uid = strtoul(*argv, &p, 10); /* if numeric ... */
163 if (*argv == p)
164 uid = my_getpwnam(*argv);
165 if (uid == -1) {
166 fprintf(stderr, "%s: unknown user name: %s\n",
167 invocationName, *argv);
168 exit(FALSE);
169 }
170 }
153 } 171 }
154 }
155
156 /* Ok, ready to do the deed now */
157 if (argc <= 1) {
158 fprintf(stderr, "%s: too few arguments\n", invocationName);
159 exit( FALSE);
160 }
161 while (argc-- > 1) {
162 if (recursiveAction( *(++argv), recursiveFlag, TRUE, FALSE, fileAction, fileAction)==FALSE)
163 exit( FALSE);
164 }
165 exit(TRUE);
166
167bad_group:
168 fprintf(stderr, "%s: unknown group name: %s\n", invocationName, groupName);
169 exit( FALSE);
170}
171 172
173 /* Ok, ready to do the deed now */
174 if (argc <= 1) {
175 fprintf(stderr, "%s: too few arguments\n", invocationName);
176 exit(FALSE);
177 }
178 while (argc-- > 1) {
179 if (recursiveAction
180 (*(++argv), recursiveFlag, TRUE, FALSE, fileAction,
181 fileAction) == FALSE)
182 exit(FALSE);
183 }
184 exit(TRUE);
172 185
186 bad_group:
187 fprintf(stderr, "%s: unknown group name: %s\n", invocationName,
188 groupName);
189 exit(FALSE);
190}
diff --git a/chroot.c b/chroot.c
index 16524d92e..6a01be603 100644
--- a/chroot.c
+++ b/chroot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini chroot implementation for busybox 3 * Mini chroot implementation for busybox
3 * 4 *
@@ -28,39 +29,39 @@
28 29
29 30
30static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n" 31static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n"
31"Run COMMAND with root directory set to NEWROOT.\n"; 32
33 "Run COMMAND with root directory set to NEWROOT.\n";
32 34
33 35
34 36
35int chroot_main(int argc, char **argv) 37int chroot_main(int argc, char **argv)
36{ 38{
37 if ( (argc < 2) || (**(argv+1) == '-') ) { 39 if ((argc < 2) || (**(argv + 1) == '-')) {
38 usage( chroot_usage); 40 usage(chroot_usage);
39 } 41 }
40 argc--; 42 argc--;
41 argv++; 43 argv++;
42 44
43 if (chroot (*argv) || (chdir ("/"))) { 45 if (chroot(*argv) || (chdir("/"))) {
44 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n", 46 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n",
45 *argv, strerror(errno)); 47 *argv, strerror(errno));
46 exit( FALSE); 48 exit(FALSE);
47 } 49 }
48 50
49 argc--; 51 argc--;
50 argv++; 52 argv++;
51 if (argc >= 1) { 53 if (argc >= 1) {
52 fprintf(stderr, "command: %s\n", *argv); 54 fprintf(stderr, "command: %s\n", *argv);
53 execvp (*argv, argv); 55 execvp(*argv, argv);
54 } 56 } else {
55 else { 57 char *prog;
56 char *prog;
57 prog = getenv ("SHELL");
58 if (!prog)
59 prog = "/bin/sh";
60 execlp (prog, prog, NULL);
61 }
62 fprintf(stderr, "chroot: cannot execute %s: %s\n",
63 *argv, strerror(errno));
64 exit( FALSE);
65}
66 58
59 prog = getenv("SHELL");
60 if (!prog)
61 prog = "/bin/sh";
62 execlp(prog, prog, NULL);
63 }
64 fprintf(stderr, "chroot: cannot execute %s: %s\n",
65 *argv, strerror(errno));
66 exit(FALSE);
67}
diff --git a/chvt.c b/chvt.c
index bea00ea83..a32bd3e78 100644
--- a/chvt.c
+++ b/chvt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * chvt.c - aeb - 940227 - Change virtual terminal 3 * chvt.c - aeb - 940227 - Change virtual terminal
3 * 4 *
@@ -13,24 +14,23 @@
13 14
14extern int getfd(void); 15extern int getfd(void);
15 16
16int 17int chvt_main(int argc, char **argv)
17chvt_main(int argc, char** argv)
18{ 18{
19 int fd, num; 19 int fd, num;
20 20
21 if ( ( argc != 2) || (**(argv+1) == '-' ) ) { 21 if ((argc != 2) || (**(argv + 1) == '-')) {
22 usage ("chvt N\n\nChange foreground virtual terminal to /dev/ttyN\n"); 22 usage
23 } 23 ("chvt N\n\nChange foreground virtual terminal to /dev/ttyN\n");
24 fd = get_console_fd("/dev/console"); 24 }
25 num = atoi(argv[1]); 25 fd = get_console_fd("/dev/console");
26 if (ioctl(fd,VT_ACTIVATE,num)) { 26 num = atoi(argv[1]);
27 perror("VT_ACTIVATE"); 27 if (ioctl(fd, VT_ACTIVATE, num)) {
28 exit(FALSE); 28 perror("VT_ACTIVATE");
29 } 29 exit(FALSE);
30 if (ioctl(fd,VT_WAITACTIVE,num)) { 30 }
31 perror("VT_WAITACTIVE"); 31 if (ioctl(fd, VT_WAITACTIVE, num)) {
32 exit(FALSE); 32 perror("VT_WAITACTIVE");
33 } 33 exit(FALSE);
34 exit( TRUE); 34 }
35 exit(TRUE);
35} 36}
36
diff --git a/clear.c b/clear.c
index 67a3af983..899840a8a 100644
--- a/clear.c
+++ b/clear.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini clear implementation for busybox 3 * Mini clear implementation for busybox
3 * 4 *
@@ -25,9 +26,8 @@
25#include <stdio.h> 26#include <stdio.h>
26 27
27 28
28extern int 29extern int clear_main(int argc, char **argv)
29clear_main(int argc, char** argv)
30{ 30{
31 printf("\033[H\033[J"); 31 printf("\033[H\033[J");
32 exit( TRUE); 32 exit(TRUE);
33} 33}
diff --git a/console-tools/chvt.c b/console-tools/chvt.c
index bea00ea83..a32bd3e78 100644
--- a/console-tools/chvt.c
+++ b/console-tools/chvt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * chvt.c - aeb - 940227 - Change virtual terminal 3 * chvt.c - aeb - 940227 - Change virtual terminal
3 * 4 *
@@ -13,24 +14,23 @@
13 14
14extern int getfd(void); 15extern int getfd(void);
15 16
16int 17int chvt_main(int argc, char **argv)
17chvt_main(int argc, char** argv)
18{ 18{
19 int fd, num; 19 int fd, num;
20 20
21 if ( ( argc != 2) || (**(argv+1) == '-' ) ) { 21 if ((argc != 2) || (**(argv + 1) == '-')) {
22 usage ("chvt N\n\nChange foreground virtual terminal to /dev/ttyN\n"); 22 usage
23 } 23 ("chvt N\n\nChange foreground virtual terminal to /dev/ttyN\n");
24 fd = get_console_fd("/dev/console"); 24 }
25 num = atoi(argv[1]); 25 fd = get_console_fd("/dev/console");
26 if (ioctl(fd,VT_ACTIVATE,num)) { 26 num = atoi(argv[1]);
27 perror("VT_ACTIVATE"); 27 if (ioctl(fd, VT_ACTIVATE, num)) {
28 exit(FALSE); 28 perror("VT_ACTIVATE");
29 } 29 exit(FALSE);
30 if (ioctl(fd,VT_WAITACTIVE,num)) { 30 }
31 perror("VT_WAITACTIVE"); 31 if (ioctl(fd, VT_WAITACTIVE, num)) {
32 exit(FALSE); 32 perror("VT_WAITACTIVE");
33 } 33 exit(FALSE);
34 exit( TRUE); 34 }
35 exit(TRUE);
35} 36}
36
diff --git a/console-tools/clear.c b/console-tools/clear.c
index 67a3af983..899840a8a 100644
--- a/console-tools/clear.c
+++ b/console-tools/clear.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini clear implementation for busybox 3 * Mini clear implementation for busybox
3 * 4 *
@@ -25,9 +26,8 @@
25#include <stdio.h> 26#include <stdio.h>
26 27
27 28
28extern int 29extern int clear_main(int argc, char **argv)
29clear_main(int argc, char** argv)
30{ 30{
31 printf("\033[H\033[J"); 31 printf("\033[H\033[J");
32 exit( TRUE); 32 exit(TRUE);
33} 33}
diff --git a/console-tools/deallocvt.c b/console-tools/deallocvt.c
index 1e13ff69c..141062edc 100644
--- a/console-tools/deallocvt.c
+++ b/console-tools/deallocvt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s) 3 * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s)
3 * Renamed deallocvt. 4 * Renamed deallocvt.
@@ -13,38 +14,39 @@
13extern int getfd(void); 14extern int getfd(void);
14char *progname; 15char *progname;
15 16
16int 17int deallocvt_main(int argc, char *argv[])
17deallocvt_main(int argc, char *argv[]) { 18{
18 int fd, num, i; 19 int fd, num, i;
19 20
20 if ( ( argc != 2) || (**(argv+1) == '-' ) ) { 21 if ((argc != 2) || (**(argv + 1) == '-')) {
21 usage ("deallocvt N\n\nDeallocate unused virtual terminal /dev/ttyN\n"); 22 usage
22 } 23 ("deallocvt N\n\nDeallocate unused virtual terminal /dev/ttyN\n");
24 }
23 25
24 progname = argv[0]; 26 progname = argv[0];
25 27
26 fd = get_console_fd("/dev/console"); 28 fd = get_console_fd("/dev/console");
27 29
28 if (argc == 1) { 30 if (argc == 1) {
29 /* deallocate all unused consoles */ 31 /* deallocate all unused consoles */
30 if (ioctl(fd,VT_DISALLOCATE,0)) { 32 if (ioctl(fd, VT_DISALLOCATE, 0)) {
31 perror("VT_DISALLOCATE"); 33 perror("VT_DISALLOCATE");
32 exit(1); 34 exit(1);
33 } 35 }
34 } else 36 } else
35 for (i = 1; i < argc; i++) { 37 for (i = 1; i < argc; i++) {
36 num = atoi(argv[i]); 38 num = atoi(argv[i]);
37 if (num == 0) 39 if (num == 0)
38 fprintf(stderr, "%s: 0: illegal VT number\n", progname); 40 fprintf(stderr, "%s: 0: illegal VT number\n", progname);
39 else if (num == 1) 41 else if (num == 1)
40 fprintf(stderr, "%s: VT 1 cannot be deallocated\n", progname); 42 fprintf(stderr, "%s: VT 1 cannot be deallocated\n",
41 else 43 progname);
42 if (ioctl(fd,VT_DISALLOCATE,num)) { 44 else if (ioctl(fd, VT_DISALLOCATE, num)) {
43 perror("VT_DISALLOCATE"); 45 perror("VT_DISALLOCATE");
44 fprintf(stderr, "%s: could not deallocate console %d\n", 46 fprintf(stderr, "%s: could not deallocate console %d\n",
45 progname, num); 47 progname, num);
46 exit(1); 48 exit(1);
47 } 49 }
48 } 50 }
49 exit(0); 51 exit(0);
50} 52}
diff --git a/console-tools/loadacm.c b/console-tools/loadacm.c
index 491bc5ce8..072562f6b 100644
--- a/console-tools/loadacm.c
+++ b/console-tools/loadacm.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Derived from 3 * Derived from
3 * mapscrn.c - version 0.92 4 * mapscrn.c - version 0.92
@@ -23,120 +24,115 @@
23typedef unsigned short unicode; 24typedef unsigned short unicode;
24 25
25static long int ctoi(unsigned char *s, int *is_unicode); 26static long int ctoi(unsigned char *s, int *is_unicode);
26int old_screen_map_read_ascii(FILE *fp, unsigned char buf[]); 27int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]);
27int uni_screen_map_read_ascii(FILE *fp, unicode buf[], int* is_unicode); 28int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode);
28unicode utf8_to_ucs2 (char* buf); 29unicode utf8_to_ucs2(char *buf);
29int screen_map_load(int fd, FILE *fp); 30int screen_map_load(int fd, FILE * fp);
30 31
31int loadacm_main(int argc, char **argv) 32int loadacm_main(int argc, char **argv)
32{ 33{
33 int fd; 34 int fd;
34 35
35 fd = open("/dev/tty", O_RDWR); 36 fd = open("/dev/tty", O_RDWR);
36 if (fd < 0) { 37 if (fd < 0) {
37 fprintf(stderr, "Error opening /dev/tty1: %s\n", strerror(errno)); 38 fprintf(stderr, "Error opening /dev/tty1: %s\n", strerror(errno));
38 return 1; 39 return 1;
39 } 40 }
40 41
41 if (screen_map_load(fd, stdin)) 42 if (screen_map_load(fd, stdin)) {
42 { 43 fprintf(stderr, "Error loading acm: %s\n", strerror(errno));
43 fprintf(stderr, "Error loading acm: %s\n", strerror(errno)); 44 return 1;
44 return 1; 45 }
45 } 46
46 47 write(fd, "\033(K", 3);
47 write(fd, "\033(K", 3); 48
48 49 return 0;
49 return 0;
50} 50}
51 51
52int screen_map_load(int fd, FILE *fp) 52int screen_map_load(int fd, FILE * fp)
53{ 53{
54 struct stat stbuf; 54 struct stat stbuf;
55 unicode wbuf[E_TABSZ]; 55 unicode wbuf[E_TABSZ];
56 unsigned char buf[E_TABSZ]; 56 unsigned char buf[E_TABSZ];
57 int parse_failed = 0; 57 int parse_failed = 0;
58 int is_unicode; 58 int is_unicode;
59 59
60 if (fstat(fp->_fileno, &stbuf)) 60 if (fstat(fp->_fileno, &stbuf))
61 perror("Cannot stat map file"), exit(1); 61 perror("Cannot stat map file"), exit(1);
62 62
63 /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */ 63 /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */
64 if (!(parse_failed = (-1 == uni_screen_map_read_ascii(fp,wbuf,&is_unicode))) || 64 if (!
65 (S_ISREG(stbuf.st_mode) && 65 (parse_failed =
66 (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) /* test for binary UTF map by size */ 66 (-1 == uni_screen_map_read_ascii(fp, wbuf, &is_unicode)))
67 { 67|| (S_ISREG(stbuf.st_mode) && (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) { /* test for binary UTF map by size */
68 if (parse_failed) 68 if (parse_failed) {
69 { 69 if (-1 == fseek(fp, 0, SEEK_SET)) {
70 if (-1 == fseek (fp, 0, SEEK_SET)) 70 if (errno == ESPIPE)
71 { 71 fprintf(stderr,
72 if (errno == ESPIPE) 72 "16bit screen-map MUST be a regular file.\n"),
73 fprintf (stderr, "16bit screen-map MUST be a regular file.\n"), exit (1); 73 exit(1);
74 else 74 else
75 perror ("fseek failed reading binary 16bit screen-map"), exit (1); 75 perror("fseek failed reading binary 16bit screen-map"),
76 } 76 exit(1);
77 77 }
78 if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) 78
79 perror("Cannot read [new] map from file"), exit(1); 79 if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1)
80 perror("Cannot read [new] map from file"), exit(1);
80#if 0 81#if 0
81 else 82 else
82 fprintf(stderr, "Input screen-map is binary.\n"); 83 fprintf(stderr, "Input screen-map is binary.\n");
83#endif 84#endif
85 }
86
87 /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */
88 /* same if it was binary, ie. if parse_failed */
89 if (parse_failed || is_unicode) {
90 if (ioctl(fd, PIO_UNISCRNMAP, wbuf))
91 perror("PIO_UNISCRNMAP ioctl"), exit(1);
92 else
93 return 0;
94 }
84 } 95 }
85 96
86 /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */ 97 /* rewind... */
87 /* same if it was binary, ie. if parse_failed */ 98 if (-1 == fseek(fp, 0, SEEK_SET)) {
88 if (parse_failed || is_unicode) 99 if (errno == ESPIPE)
89 { 100 fprintf(stderr,
90 if (ioctl(fd,PIO_UNISCRNMAP,wbuf)) 101 "Assuming 8bit screen-map - MUST be a regular file.\n"),
91 perror("PIO_UNISCRNMAP ioctl"), exit(1); 102 exit(1);
92 else 103 else
93 return 0; 104 perror("fseek failed assuming 8bit screen-map"), exit(1);
94 } 105 }
95 } 106
96 107 /* ... and try an old 8-bit screen-map */
97 /* rewind... */ 108 if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp, buf))) ||
98 if (-1 == fseek (fp, 0, SEEK_SET)) 109 (S_ISREG(stbuf.st_mode) && (stbuf.st_size == E_TABSZ))) { /* test for binary old 8-bit map by size */
99 { 110 if (parse_failed) {
100 if (errno == ESPIPE) 111 if (-1 == fseek(fp, 0, SEEK_SET)) {
101 fprintf (stderr, "Assuming 8bit screen-map - MUST be a regular file.\n"), exit (1); 112 if (errno == ESPIPE)
102 else 113 /* should not - it succedeed above */
103 perror ("fseek failed assuming 8bit screen-map"), exit (1); 114 fprintf(stderr, "fseek() returned ESPIPE !\n"),
104 } 115 exit(1);
105 116 else
106 /* ... and try an old 8-bit screen-map */ 117 perror("fseek for binary 8bit screen-map"), exit(1);
107 if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp,buf))) || 118 }
108 (S_ISREG(stbuf.st_mode) && 119
109 (stbuf.st_size == E_TABSZ))) /* test for binary old 8-bit map by size */ 120 if (fread(buf, E_TABSZ, 1, fp) != 1)
110 { 121 perror("Cannot read [old] map from file"), exit(1);
111 if (parse_failed)
112 {
113 if (-1 == fseek (fp, 0, SEEK_SET))
114 {
115 if (errno == ESPIPE)
116 /* should not - it succedeed above */
117 fprintf (stderr, "fseek() returned ESPIPE !\n"), exit (1);
118 else
119 perror ("fseek for binary 8bit screen-map"), exit (1);
120 }
121
122 if (fread(buf,E_TABSZ,1,fp) != 1)
123 perror("Cannot read [old] map from file"), exit(1);
124#if 0 122#if 0
125 else 123 else
126 fprintf(stderr, "Input screen-map is binary.\n"); 124 fprintf(stderr, "Input screen-map is binary.\n");
127#endif 125#endif
126 }
127
128 if (ioctl(fd, PIO_SCRNMAP, buf))
129 perror("PIO_SCRNMAP ioctl"), exit(1);
130 else
131 return 0;
132 } else {
133 fprintf(stderr, "Error parsing symbolic map\n");
134 exit(1);
128 } 135 }
129
130 if (ioctl(fd,PIO_SCRNMAP,buf))
131 perror("PIO_SCRNMAP ioctl"), exit(1);
132 else
133 return 0;
134 }
135 else
136 {
137 fprintf(stderr, "Error parsing symbolic map\n");
138 exit(1);
139 }
140} 136}
141 137
142 138
@@ -149,116 +145,111 @@ int screen_map_load(int fd, FILE *fp)
149 * 145 *
150 * FIXME: ignores everything after second word 146 * FIXME: ignores everything after second word
151 */ 147 */
152int uni_screen_map_read_ascii(FILE *fp, unicode buf[], int *is_unicode) 148int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode)
153{ 149{
154 char buffer[256]; /* line buffer reading file */ 150 char buffer[256]; /* line buffer reading file */
155 char *p, *q; /* 1st + 2nd words in line */ 151 char *p, *q; /* 1st + 2nd words in line */
156 int in, on; /* the same, as numbers */ 152 int in, on; /* the same, as numbers */
157 int tmp_is_unicode; /* tmp for is_unicode calculation */ 153 int tmp_is_unicode; /* tmp for is_unicode calculation */
158 int i; /* loop index - result holder */ 154 int i; /* loop index - result holder */
159 int ret_code = 0; /* return code */ 155 int ret_code = 0; /* return code */
160 sigset_t sigset, old_sigset; 156 sigset_t sigset, old_sigset;
161 157
162 assert (is_unicode); 158 assert(is_unicode);
163 159
164 *is_unicode = 0; 160 *is_unicode = 0;
165 161
166 /* first 128 codes defaults to ASCII */ 162 /* first 128 codes defaults to ASCII */
167 for (i=0; i<128; i++) buf[i] = i; 163 for (i = 0; i < 128; i++)
168 /* remaining defaults to replacement char (usually E_TABSZ = 256) */ 164 buf[i] = i;
169 for ( ; i<E_TABSZ; i++) buf[i] = 0xfffd; 165 /* remaining defaults to replacement char (usually E_TABSZ = 256) */
170 166 for (; i < E_TABSZ; i++)
171 /* block SIGCHLD */ 167 buf[i] = 0xfffd;
172 sigemptyset (&sigset); 168
173 sigaddset (&sigset, SIGCHLD); 169 /* block SIGCHLD */
174 sigprocmask (SIG_BLOCK, &sigset, &old_sigset); 170 sigemptyset(&sigset);
175 171 sigaddset(&sigset, SIGCHLD);
176 do 172 sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
177 { 173
178 if (NULL == fgets(buffer, sizeof(buffer),fp)) 174 do {
179 { 175 if (NULL == fgets(buffer, sizeof(buffer), fp)) {
180 if (feof (fp)) 176 if (feof(fp))
181 break; 177 break;
182 else 178 else {
183 { 179 perror("uni_screen_map_read_ascii() can't read line");
184 perror ("uni_screen_map_read_ascii() can't read line"); 180 exit(2);
185 exit (2); 181 }
186 } 182 }
187 } 183
188 184 /* get "charset-relative charcode", stripping leading spaces */
189 /* get "charset-relative charcode", stripping leading spaces */ 185 p = strtok(buffer, " \t\n");
190 p = strtok(buffer," \t\n"); 186
191 187 /* skip empty lines and comments */
192 /* skip empty lines and comments */ 188 if (!p || *p == '#')
193 if (!p || *p == '#') 189 continue;
194 continue; 190
195 191 /* get unicode mapping */
196 /* get unicode mapping */ 192 q = strtok(NULL, " \t\n");
197 q = strtok(NULL," \t\n"); 193 if (q) {
198 if (q) 194 in = ctoi(p, NULL);
199 { 195 if (in < 0 || in > 255) {
200 in = ctoi(p, NULL); 196 ret_code = -1;
201 if (in < 0 || in > 255) 197 break;
202 { 198 }
203 ret_code = -1; 199
204 break; 200 on = ctoi(q, &tmp_is_unicode);
205 } 201 if (in < 0 && on > 65535) {
206 202 ret_code = -1;
207 on = ctoi(q, &tmp_is_unicode); 203 break;
208 if (in < 0 && on > 65535) 204 }
209 { 205
210 ret_code = -1; 206 *is_unicode |= tmp_is_unicode;
211 break; 207 buf[in] = on;
212 } 208 } else {
213 209 ret_code = -1;
214 *is_unicode |= tmp_is_unicode; 210 break;
215 buf[in] = on; 211 }
216 } 212 }
217 else 213 while (1); /* terminated by break on feof() */
218 {
219 ret_code = -1;
220 break;
221 }
222 }
223 while (1); /* terminated by break on feof() */
224 214
225 /* restore sig mask */ 215 /* restore sig mask */
226 sigprocmask (SIG_SETMASK, &old_sigset, NULL); 216 sigprocmask(SIG_SETMASK, &old_sigset, NULL);
227 217
228 return ret_code; 218 return ret_code;
229} 219}
230 220
231 221
232int old_screen_map_read_ascii(FILE *fp, unsigned char buf[]) 222int old_screen_map_read_ascii(FILE * fp, unsigned char buf[])
233{ 223{
234 char buffer[256]; 224 char buffer[256];
235 int in, on; 225 int in, on;
236 char *p, *q; 226 char *p, *q;
237 227
238 for (in=0; in<256; in++) buf[in]=in; 228 for (in = 0; in < 256; in++)
239 229 buf[in] = in;
240 while (fgets(buffer,sizeof(buffer)-1,fp)) 230
241 { 231 while (fgets(buffer, sizeof(buffer) - 1, fp)) {
242 p = strtok(buffer," \t\n"); 232 p = strtok(buffer, " \t\n");
243 233
244 if (!p || *p == '#') 234 if (!p || *p == '#')
245 continue; 235 continue;
246 236
247 q = strtok(NULL," \t\n#"); 237 q = strtok(NULL, " \t\n#");
248 if (q) 238 if (q) {
249 { 239 in = ctoi(p, NULL);
250 in = ctoi(p, NULL); 240 if (in < 0 || in > 255)
251 if (in < 0 || in > 255) return -1; 241 return -1;
252 242
253 on = ctoi(q, NULL); 243 on = ctoi(q, NULL);
254 if (in < 0 && on > 255) return -1; 244 if (in < 0 && on > 255)
255 245 return -1;
256 buf[in] = on; 246
247 buf[in] = on;
248 } else
249 return -1;
257 } 250 }
258 else return -1; 251
259 } 252 return (0);
260
261 return(0);
262} 253}
263 254
264 255
@@ -270,172 +261,145 @@ int old_screen_map_read_ascii(FILE *fp, unsigned char buf[])
270 * 261 *
271 * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones. 262 * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones.
272 */ 263 */
273long int ctoi(unsigned char *s, int *is_unicode) 264long int ctoi(unsigned char *s, int *is_unicode)
274{ 265{
275 int i; 266 int i;
276 size_t ls; 267 size_t ls;
277 268
278 ls = strlen(s); 269 ls = strlen(s);
279 if (is_unicode) *is_unicode = 0; 270 if (is_unicode)
280 271 *is_unicode = 0;
281 /* hex-specified UCS2 */ 272
282 if ((strncmp(s,"U+",2) == 0) && 273 /* hex-specified UCS2 */
283 (strspn(s+2,"0123456789abcdefABCDEF") == ls-2)) 274 if ((strncmp(s, "U+", 2) == 0) &&
284 { 275 (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) {
285 sscanf(s+2,"%x",&i); 276 sscanf(s + 2, "%x", &i);
286 if (is_unicode) *is_unicode = 1; 277 if (is_unicode)
287 } 278 *is_unicode = 1;
288 279 }
289 /* hex-specified byte */ 280
290 else if ((ls <= 4) && (strncmp(s,"0x",2) == 0) && 281 /* hex-specified byte */
291 (strspn(s+2,"0123456789abcdefABCDEF") == ls-2)) 282 else if ((ls <= 4) && (strncmp(s, "0x", 2) == 0) &&
292 sscanf(s+2,"%x",&i); 283 (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2))
293 284 sscanf(s + 2, "%x", &i);
294 /* oct-specified number (byte) */ 285
295 else if ((*s == '0') && 286 /* oct-specified number (byte) */
296 (strspn(s,"01234567") == ls)) 287 else if ((*s == '0') && (strspn(s, "01234567") == ls))
297 sscanf(s,"%o",&i); 288 sscanf(s, "%o", &i);
298 289
299 /* dec-specified number (byte) */ 290 /* dec-specified number (byte) */
300 else if (strspn(s,"0123456789") == ls) 291 else if (strspn(s, "0123456789") == ls)
301 sscanf(s,"%d",&i); 292 sscanf(s, "%d", &i);
302 293
303 /* single-byte quoted char */ 294 /* single-byte quoted char */
304 else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\'')) 295 else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\''))
305 i=s[1]; 296 i = s[1];
306 297
307 /* multi-byte UTF8 quoted char */ 298 /* multi-byte UTF8 quoted char */
308 else if ((s[0] == '\'') && (s[ls-1] == '\'')) 299 else if ((s[0] == '\'') && (s[ls - 1] == '\'')) {
309 { 300 s[ls - 1] = 0; /* ensure we'll not "parse UTF too far" */
310 s[ls-1] = 0; /* ensure we'll not "parse UTF too far" */ 301 i = utf8_to_ucs2(s + 1);
311 i = utf8_to_ucs2(s+1); 302 if (is_unicode)
312 if (is_unicode) *is_unicode = 1; 303 *is_unicode = 1;
313 } 304 } else
314 else 305 return (-1);
315 return(-1); 306
316 307 return (i);
317 return(i);
318} 308}
319 309
320 310
321void saveoldmap(int fd, char *omfil) 311void saveoldmap(int fd, char *omfil)
322{ 312{
323 FILE *fp; 313 FILE *fp;
324 char buf[E_TABSZ]; 314 char buf[E_TABSZ];
315
325#ifdef GIO_UNISCRNMAP 316#ifdef GIO_UNISCRNMAP
326 unicode xbuf[E_TABSZ]; 317 unicode xbuf[E_TABSZ];
327 int is_old_map = 0; 318 int is_old_map = 0;
328 319
329 if (ioctl(fd,GIO_UNISCRNMAP,xbuf)) 320 if (ioctl(fd, GIO_UNISCRNMAP, xbuf)) {
330 { 321 perror("GIO_UNISCRNMAP ioctl error");
331 perror("GIO_UNISCRNMAP ioctl error");
332#endif 322#endif
333 if (ioctl(fd,GIO_SCRNMAP,buf)) 323 if (ioctl(fd, GIO_SCRNMAP, buf)) {
334 { 324 perror("GIO_SCRNMAP ioctl error");
335 perror("GIO_SCRNMAP ioctl error"); 325 exit(1);
336 exit(1); 326 } else
337 } 327 is_old_map = 1;
338 else
339 is_old_map = 1;
340#ifdef GIO_UNISCRNMAP 328#ifdef GIO_UNISCRNMAP
341 } 329 }
342#endif 330#endif
343
344 if ((fp = fopen(omfil, "w")) == NULL)
345 {
346 perror(omfil);
347 exit(1);
348 }
349 331
332 if ((fp = fopen(omfil, "w")) == NULL) {
333 perror(omfil);
334 exit(1);
335 }
350#ifdef GIO_UNISCRNMAP 336#ifdef GIO_UNISCRNMAP
351 if (is_old_map) 337 if (is_old_map) {
352 {
353#endif 338#endif
354 if (fwrite(buf,E_TABSZ,1,fp) != 1) 339 if (fwrite(buf, E_TABSZ, 1, fp) != 1) {
355 { 340 perror("Error writing map to file");
356 perror("Error writing map to file"); 341 exit(1);
357 exit(1); 342 }
358 }
359#ifdef GIO_UNISCRNMAP 343#ifdef GIO_UNISCRNMAP
360 } 344 } else if (fwrite(xbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) {
361 else 345 perror("Error writing map to file");
362 if (fwrite(xbuf, sizeof(unicode) * E_TABSZ,1,fp) != 1) 346 exit(1);
363 {
364 perror("Error writing map to file");
365 exit(1);
366 } 347 }
367#endif 348#endif
368 349
369 fclose(fp); 350 fclose(fp);
370} 351}
371 352
372unicode utf8_to_ucs2 (char* buf) 353unicode utf8_to_ucs2(char *buf)
373{ 354{
374 int utf_count = 0; 355 int utf_count = 0;
375 long utf_char; 356 long utf_char;
376 unicode tc; 357 unicode tc;
377 unsigned char c; 358 unsigned char c;
378 359
379 do 360 do {
380 { 361 c = *buf;
381 c = *buf; 362 buf++;
382 buf++; 363
383 364 /* if byte should be part of multi-byte sequence */
384 /* if byte should be part of multi-byte sequence */ 365 if (c & 0x80) {
385 if(c & 0x80) 366 /* if we have already started to parse a UTF8 sequence */
386 { 367 if (utf_count > 0 && (c & 0xc0) == 0x80) {
387 /* if we have already started to parse a UTF8 sequence */ 368 utf_char = (utf_char << 6) | (c & 0x3f);
388 if (utf_count > 0 && (c & 0xc0) == 0x80) 369 utf_count--;
389 { 370 if (utf_count == 0)
390 utf_char = (utf_char << 6) | (c & 0x3f); 371 tc = utf_char;
391 utf_count--; 372 else
392 if (utf_count == 0) 373 continue;
393 tc = utf_char; 374 } else { /* Possibly 1st char of a UTF8 sequence */
394 else 375
395 continue; 376 if ((c & 0xe0) == 0xc0) {
396 } 377 utf_count = 1;
397 else /* Possibly 1st char of a UTF8 sequence */ 378 utf_char = (c & 0x1f);
398 { 379 } else if ((c & 0xf0) == 0xe0) {
399 if ((c & 0xe0) == 0xc0) 380 utf_count = 2;
400 { 381 utf_char = (c & 0x0f);
401 utf_count = 1; 382 } else if ((c & 0xf8) == 0xf0) {
402 utf_char = (c & 0x1f); 383 utf_count = 3;
403 } 384 utf_char = (c & 0x07);
404 else if ((c & 0xf0) == 0xe0) 385 } else if ((c & 0xfc) == 0xf8) {
405 { 386 utf_count = 4;
406 utf_count = 2; 387 utf_char = (c & 0x03);
407 utf_char = (c & 0x0f); 388 } else if ((c & 0xfe) == 0xfc) {
408 } 389 utf_count = 5;
409 else if ((c & 0xf8) == 0xf0) 390 utf_char = (c & 0x01);
410 { 391 } else
411 utf_count = 3; 392 utf_count = 0;
412 utf_char = (c & 0x07); 393 continue;
413 } 394 }
414 else if ((c & 0xfc) == 0xf8) 395 } else { /* not part of multi-byte sequence - treat as ASCII
415 { 396 * this makes incomplete sequences to be ignored
416 utf_count = 4; 397 */
417 utf_char = (c & 0x03); 398 tc = c;
418 } 399 utf_count = 0;
419 else if ((c & 0xfe) == 0xfc) 400 }
420 { 401 }
421 utf_count = 5; 402 while (utf_count);
422 utf_char = (c & 0x01);
423 }
424 else
425 utf_count = 0;
426 continue;
427 }
428 }
429 else /* not part of multi-byte sequence - treat as ASCII
430 * this makes incomplete sequences to be ignored
431 */
432 {
433 tc = c;
434 utf_count = 0;
435 }
436 }
437 while (utf_count);
438
439 return tc;
440}
441 403
404 return tc;
405}
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
index e44525d9c..64b725610 100644
--- a/console-tools/loadfont.c
+++ b/console-tools/loadfont.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * loadfont.c - Eugene Crosser & Andries Brouwer 3 * loadfont.c - Eugene Crosser & Andries Brouwer
3 * 4 *
@@ -30,72 +31,69 @@
30#define PSF_SEPARATOR 0xFFFF 31#define PSF_SEPARATOR 0xFFFF
31 32
32static const char loadfont_usage[] = "loadfont\n" 33static const char loadfont_usage[] = "loadfont\n"
33"\n" 34 "\n" "\tLoad a console font from standard input.\n" "\n";
34"\tLoad a console font from standard input.\n"
35"\n";
36 35
37struct psf_header 36struct psf_header {
38{ 37 unsigned char magic1, magic2; /* Magic number */
39 unsigned char magic1, magic2; /* Magic number */ 38 unsigned char mode; /* PSF font mode */
40 unsigned char mode; /* PSF font mode */ 39 unsigned char charsize; /* Character size */
41 unsigned char charsize; /* Character size */
42}; 40};
43 41
44#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) 42#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
45 43
46static void loadnewfont(int fd); 44static void loadnewfont(int fd);
47 45
48extern int 46extern int loadfont_main(int argc, char **argv)
49loadfont_main(int argc, char **argv)
50{ 47{
51 int fd; 48 int fd;
52 49
53 fd = open("/dev/tty0", O_RDWR); 50 fd = open("/dev/tty0", O_RDWR);
54 if (fd < 0) { 51 if (fd < 0) {
55 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno)); 52 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
56 return 1; 53 return 1;
57 } 54 }
58 loadnewfont(fd); 55 loadnewfont(fd);
59 56
60 return 0; 57 return 0;
61} 58}
62 59
63static void 60static void do_loadfont(int fd, char *inbuf, int unit, int fontsize)
64do_loadfont(int fd, char *inbuf, int unit, int fontsize) { 61{
65 char buf[16384]; 62 char buf[16384];
66 int i; 63 int i;
67 64
68 memset(buf,0,sizeof(buf)); 65 memset(buf, 0, sizeof(buf));
69 66
70 if (unit < 1 || unit > 32) { 67 if (unit < 1 || unit > 32) {
71 fprintf(stderr, "Bad character size %d\n", unit); 68 fprintf(stderr, "Bad character size %d\n", unit);
72 exit(1); 69 exit(1);
73 } 70 }
74 71
75 for (i = 0; i < fontsize; i++) 72 for (i = 0; i < fontsize; i++)
76 memcpy(buf+(32*i), inbuf+(unit*i), unit); 73 memcpy(buf + (32 * i), inbuf + (unit * i), unit);
77 74
78#if defined( PIO_FONTX ) && !defined( __sparc__ ) 75#if defined( PIO_FONTX ) && !defined( __sparc__ )
79 { 76 {
80 struct consolefontdesc cfd; 77 struct consolefontdesc cfd;
81 78
82 cfd.charcount = fontsize; 79 cfd.charcount = fontsize;
83 cfd.charheight = unit; 80 cfd.charheight = unit;
84 cfd.chardata = buf; 81 cfd.chardata = buf;
85 82
86 if (ioctl(fd, PIO_FONTX, &cfd) == 0) 83 if (ioctl(fd, PIO_FONTX, &cfd) == 0)
87 return; /* success */ 84 return; /* success */
88 perror("PIO_FONTX ioctl error (trying PIO_FONT)"); 85 perror("PIO_FONTX ioctl error (trying PIO_FONT)");
89 } 86 }
90#endif 87#endif
91 if (ioctl(fd, PIO_FONT, buf)) { 88 if (ioctl(fd, PIO_FONT, buf)) {
92 perror("PIO_FONT ioctl error"); 89 perror("PIO_FONT ioctl error");
93 exit(1); 90 exit(1);
94 } 91 }
95} 92}
96 93
97static void 94static void
98do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) { 95do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
96{
99 struct unimapinit advice; 97 struct unimapinit advice;
100 struct unimapdesc ud; 98 struct unimapdesc ud;
101 struct unipair *up; 99 struct unipair *up;
@@ -103,23 +101,24 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) {
103 int glyph; 101 int glyph;
104 u_short unicode; 102 u_short unicode;
105 103
106 maxct = tailsz; /* more than enough */ 104 maxct = tailsz; /* more than enough */
107 up = (struct unipair *) malloc(maxct * sizeof(struct unipair)); 105 up = (struct unipair *) malloc(maxct * sizeof(struct unipair));
106
108 if (!up) { 107 if (!up) {
109 fprintf(stderr, "Out of memory?\n"); 108 fprintf(stderr, "Out of memory?\n");
110 exit(1); 109 exit(1);
111 } 110 }
112 for (glyph = 0; glyph < fontsize; glyph++) { 111 for (glyph = 0; glyph < fontsize; glyph++) {
113 while (tailsz >= 2) { 112 while (tailsz >= 2) {
114 unicode = (((u_short) inbuf[1]) << 8) + inbuf[0]; 113 unicode = (((u_short) inbuf[1]) << 8) + inbuf[0];
115 tailsz -= 2; 114 tailsz -= 2;
116 inbuf += 2; 115 inbuf += 2;
117 if (unicode == PSF_SEPARATOR) 116 if (unicode == PSF_SEPARATOR)
118 break; 117 break;
119 up[ct].unicode = unicode; 118 up[ct].unicode = unicode;
120 up[ct].fontpos = glyph; 119 up[ct].fontpos = glyph;
121 ct++; 120 ct++;
122 } 121 }
123 } 122 }
124 123
125 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP 124 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
@@ -128,33 +127,33 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) {
128 advice.advised_hashsize = 0; 127 advice.advised_hashsize = 0;
129 advice.advised_hashstep = 0; 128 advice.advised_hashstep = 0;
130 advice.advised_hashlevel = 0; 129 advice.advised_hashlevel = 0;
131 if(ioctl(fd, PIO_UNIMAPCLR, &advice)) { 130 if (ioctl(fd, PIO_UNIMAPCLR, &advice)) {
132#ifdef ENOIOCTLCMD 131#ifdef ENOIOCTLCMD
133 if (errno == ENOIOCTLCMD) { 132 if (errno == ENOIOCTLCMD) {
134 fprintf(stderr, "It seems this kernel is older than 1.1.92\n"); 133 fprintf(stderr, "It seems this kernel is older than 1.1.92\n");
135 fprintf(stderr, "No Unicode mapping table loaded.\n"); 134 fprintf(stderr, "No Unicode mapping table loaded.\n");
136 } else 135 } else
137#endif 136#endif
138 perror("PIO_UNIMAPCLR"); 137 perror("PIO_UNIMAPCLR");
139 exit(1); 138 exit(1);
140 } 139 }
141 ud.entry_ct = ct; 140 ud.entry_ct = ct;
142 ud.entries = up; 141 ud.entries = up;
143 if(ioctl(fd, PIO_UNIMAP, &ud)) { 142 if (ioctl(fd, PIO_UNIMAP, &ud)) {
144#if 0 143#if 0
145 if (errno == ENOMEM) { 144 if (errno == ENOMEM) {
146 /* change advice parameters */ 145 /* change advice parameters */
147 } 146 }
148#endif 147#endif
149 perror("PIO_UNIMAP"); 148 perror("PIO_UNIMAP");
150 exit(1); 149 exit(1);
151 } 150 }
152} 151}
153 152
154static void 153static void loadnewfont(int fd)
155loadnewfont(int fd) { 154{
156 int unit; 155 int unit;
157 char inbuf[32768]; /* primitive */ 156 char inbuf[32768]; /* primitive */
158 int inputlth, offset; 157 int inputlth, offset;
159 158
160 /* 159 /*
@@ -178,57 +177,58 @@ loadnewfont(int fd) {
178 177
179 /* test for psf first */ 178 /* test for psf first */
180 { 179 {
181 struct psf_header psfhdr; 180 struct psf_header psfhdr;
182 int fontsize; 181 int fontsize;
183 int hastable; 182 int hastable;
184 int head0, head; 183 int head0, head;
185 184
186 if (inputlth < sizeof(struct psf_header)) 185 if (inputlth < sizeof(struct psf_header))
187 goto no_psf; 186 goto no_psf;
188 187
189 psfhdr = * (struct psf_header *) &inbuf[0]; 188 psfhdr = *(struct psf_header *) &inbuf[0];
190 189
191 if (!PSF_MAGIC_OK(psfhdr)) 190 if (!PSF_MAGIC_OK(psfhdr))
192 goto no_psf; 191 goto no_psf;
193 192
194 if (psfhdr.mode > PSF_MAXMODE) { 193 if (psfhdr.mode > PSF_MAXMODE) {
195 fprintf(stderr, "Unsupported psf file mode\n"); 194 fprintf(stderr, "Unsupported psf file mode\n");
196 exit(1); 195 exit(1);
197 } 196 }
198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); 197 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
199#if !defined( PIO_FONTX ) || defined( __sparc__ ) 198#if !defined( PIO_FONTX ) || defined( __sparc__ )
200 if (fontsize != 256) { 199 if (fontsize != 256) {
201 fprintf(stderr, "Only fontsize 256 supported\n"); 200 fprintf(stderr, "Only fontsize 256 supported\n");
202 exit(1); 201 exit(1);
203 } 202 }
204#endif 203#endif
205 hastable = (psfhdr.mode & PSF_MODEHASTAB); 204 hastable = (psfhdr.mode & PSF_MODEHASTAB);
206 unit = psfhdr.charsize; 205 unit = psfhdr.charsize;
207 head0 = sizeof(struct psf_header); 206 head0 = sizeof(struct psf_header);
208 head = head0 + fontsize*unit; 207
209 if (head > inputlth || (!hastable && head != inputlth)) { 208 head = head0 + fontsize * unit;
210 fprintf(stderr, "Input file: bad length\n"); 209 if (head > inputlth || (!hastable && head != inputlth)) {
211 exit(1); 210 fprintf(stderr, "Input file: bad length\n");
212 } 211 exit(1);
213 do_loadfont(fd, inbuf + head0, unit, fontsize); 212 }
214 if (hastable) 213 do_loadfont(fd, inbuf + head0, unit, fontsize);
215 do_loadtable(fd, inbuf + head, inputlth-head, fontsize); 214 if (hastable)
216 return; 215 do_loadtable(fd, inbuf + head, inputlth - head, fontsize);
216 return;
217 } 217 }
218 no_psf: 218 no_psf:
219 219
220 /* file with three code pages? */ 220 /* file with three code pages? */
221 if (inputlth == 9780) { 221 if (inputlth == 9780) {
222 offset = 40; 222 offset = 40;
223 unit = 16; 223 unit = 16;
224 } else { 224 } else {
225 /* bare font */ 225 /* bare font */
226 if (inputlth & 0377) { 226 if (inputlth & 0377) {
227 fprintf(stderr, "Bad input file size\n"); 227 fprintf(stderr, "Bad input file size\n");
228 exit(1); 228 exit(1);
229 } 229 }
230 offset = 0; 230 offset = 0;
231 unit = inputlth/256; 231 unit = inputlth / 256;
232 } 232 }
233 do_loadfont(fd, inbuf+offset, unit, 256); 233 do_loadfont(fd, inbuf + offset, unit, 256);
234} 234}
diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c
index a228ca460..aa4f6bbc8 100644
--- a/console-tools/loadkmap.c
+++ b/console-tools/loadkmap.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini loadkmap implementation for busybox 3 * Mini loadkmap implementation for busybox
3 * 4 *
@@ -29,61 +30,63 @@
29 30
30 31
31static const char loadkmap_usage[] = "loadkmap\n" 32static const char loadkmap_usage[] = "loadkmap\n"
32"\n" 33 "\n"
33"\tLoad a binary keyboard translation table from standard input.\n"
34"\n";
35 34
35 "\tLoad a binary keyboard translation table from standard input.\n"
36 "\n";
36 37
37int
38loadkmap_main(int argc, char * * argv)
39{
40 struct kbentry ke;
41 u_short *ibuff;
42 int i,j,fd,readsz,pos,ibuffsz=NR_KEYS * sizeof(u_short);
43 char flags[MAX_NR_KEYMAPS],magic[]="bkeymap",buff[7];
44 38
45 fd = open("/dev/tty0", O_RDWR); 39int loadkmap_main(int argc, char **argv)
46 if (fd < 0) { 40{
47 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno)); 41 struct kbentry ke;
48 return 1; 42 u_short *ibuff;
49 } 43 int i, j, fd, readsz, pos, ibuffsz = NR_KEYS * sizeof(u_short);
44 char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap", buff[7];
50 45
51 read(0,buff,7); 46 fd = open("/dev/tty0", O_RDWR);
52 if (0 != strncmp(buff,magic,7)) { 47 if (fd < 0) {
53 fprintf(stderr, "This is not a valid binary keymap.\n"); 48 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
54 return 1; 49 return 1;
55 } 50 }
56 51
57 if ( MAX_NR_KEYMAPS != read(0,flags,MAX_NR_KEYMAPS) ) { 52 read(0, buff, 7);
58 fprintf(stderr, "Error reading keymap flags: %s\n", strerror(errno)); 53 if (0 != strncmp(buff, magic, 7)) {
59 return 1; 54 fprintf(stderr, "This is not a valid binary keymap.\n");
60 } 55 return 1;
56 }
61 57
62 ibuff=(u_short *) malloc(ibuffsz); 58 if (MAX_NR_KEYMAPS != read(0, flags, MAX_NR_KEYMAPS)) {
63 if (!ibuff) { 59 fprintf(stderr, "Error reading keymap flags: %s\n",
64 fprintf(stderr, "Out of memory.\n"); 60 strerror(errno));
65 return 1; 61 return 1;
66 } 62 }
63
64 ibuff = (u_short *) malloc(ibuffsz);
65 if (!ibuff) {
66 fprintf(stderr, "Out of memory.\n");
67 return 1;
68 }
67 69
68 for(i=0; i<MAX_NR_KEYMAPS; i++) { 70 for (i = 0; i < MAX_NR_KEYMAPS; i++) {
69 if (flags[i]==1){ 71 if (flags[i] == 1) {
70 pos=0; 72 pos = 0;
71 while (pos < ibuffsz) { 73 while (pos < ibuffsz) {
72 if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) { 74 if ((readsz = read(0, (char *) ibuff + pos, ibuffsz - pos))
73 fprintf(stderr, "Error reading keymap: %s\n", 75 < 0) {
74 strerror(errno)); 76 fprintf(stderr, "Error reading keymap: %s\n",
75 return 1; 77 strerror(errno));
76 } 78 return 1;
77 pos += readsz; 79 }
78 } 80 pos += readsz;
79 for(j=0; j<NR_KEYS; j++) { 81 }
80 ke.kb_index = j; 82 for (j = 0; j < NR_KEYS; j++) {
81 ke.kb_table = i; 83 ke.kb_index = j;
82 ke.kb_value = ibuff[j]; 84 ke.kb_table = i;
83 ioctl(fd, KDSKBENT, &ke); 85 ke.kb_value = ibuff[j];
84 } 86 ioctl(fd, KDSKBENT, &ke);
87 }
88 }
85 } 89 }
86 } 90 close(fd);
87 close (fd); 91 return 0;
88 return 0;
89} 92}
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 0d32efe84..86f85fe8e 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini Cat implementation for busybox 3 * Mini Cat implementation for busybox
3 * 4 *
@@ -24,36 +25,37 @@
24#include <stdio.h> 25#include <stdio.h>
25 26
26 27
27static void print_file( FILE *file) 28static void print_file(FILE * file)
28{ 29{
29 int c; 30 int c;
30 while ((c = getc(file)) != EOF) 31
31 putc(c, stdout); 32 while ((c = getc(file)) != EOF)
32 fclose(file); 33 putc(c, stdout);
33 fflush(stdout); 34 fclose(file);
35 fflush(stdout);
34} 36}
35 37
36extern int cat_main(int argc, char **argv) 38extern int cat_main(int argc, char **argv)
37{ 39{
38 FILE *file; 40 FILE *file;
39 41
40 if (argc==1) { 42 if (argc == 1) {
41 print_file( stdin); 43 print_file(stdin);
42 exit( TRUE); 44 exit(TRUE);
43 } 45 }
44 46
45 if ( **(argv+1) == '-' ) { 47 if (**(argv + 1) == '-') {
46 usage ("cat [file ...]\n"); 48 usage("cat [file ...]\n");
47 } 49 }
48 argc--; 50 argc--;
49 51
50 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv) ) { 52 while (argc-- > 0 && *(argv++) != '\0' && strlen(*argv)) {
51 file = fopen(*argv, "r"); 53 file = fopen(*argv, "r");
52 if (file == NULL) { 54 if (file == NULL) {
53 perror(*argv); 55 perror(*argv);
54 exit(FALSE); 56 exit(FALSE);
57 }
58 print_file(file);
55 } 59 }
56 print_file( file); 60 exit(TRUE);
57 }
58 exit(TRUE);
59} 61}
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index 16524d92e..6a01be603 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini chroot implementation for busybox 3 * Mini chroot implementation for busybox
3 * 4 *
@@ -28,39 +29,39 @@
28 29
29 30
30static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n" 31static const char chroot_usage[] = "chroot NEWROOT [COMMAND...]\n\n"
31"Run COMMAND with root directory set to NEWROOT.\n"; 32
33 "Run COMMAND with root directory set to NEWROOT.\n";
32 34
33 35
34 36
35int chroot_main(int argc, char **argv) 37int chroot_main(int argc, char **argv)
36{ 38{
37 if ( (argc < 2) || (**(argv+1) == '-') ) { 39 if ((argc < 2) || (**(argv + 1) == '-')) {
38 usage( chroot_usage); 40 usage(chroot_usage);
39 } 41 }
40 argc--; 42 argc--;
41 argv++; 43 argv++;
42 44
43 if (chroot (*argv) || (chdir ("/"))) { 45 if (chroot(*argv) || (chdir("/"))) {
44 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n", 46 fprintf(stderr, "chroot: cannot change root directory to %s: %s\n",
45 *argv, strerror(errno)); 47 *argv, strerror(errno));
46 exit( FALSE); 48 exit(FALSE);
47 } 49 }
48 50
49 argc--; 51 argc--;
50 argv++; 52 argv++;
51 if (argc >= 1) { 53 if (argc >= 1) {
52 fprintf(stderr, "command: %s\n", *argv); 54 fprintf(stderr, "command: %s\n", *argv);
53 execvp (*argv, argv); 55 execvp(*argv, argv);
54 } 56 } else {
55 else { 57 char *prog;
56 char *prog;
57 prog = getenv ("SHELL");
58 if (!prog)
59 prog = "/bin/sh";
60 execlp (prog, prog, NULL);
61 }
62 fprintf(stderr, "chroot: cannot execute %s: %s\n",
63 *argv, strerror(errno));
64 exit( FALSE);
65}
66 58
59 prog = getenv("SHELL");
60 if (!prog)
61 prog = "/bin/sh";
62 execlp(prog, prog, NULL);
63 }
64 fprintf(stderr, "chroot: cannot execute %s: %s\n",
65 *argv, strerror(errno));
66 exit(FALSE);
67}
diff --git a/coreutils/date.c b/coreutils/date.c
index a3528921d..b4c3e7153 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini date implementation for busybox 3 * Mini date implementation for busybox
3 * 4 *
@@ -38,12 +39,13 @@
38 an RFC 822 complient date output for shell scripting 39 an RFC 822 complient date output for shell scripting
39 mail commands */ 40 mail commands */
40 41
41static const char date_usage[] = "date [OPTION]... [+FORMAT]\n" 42static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
42" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n" 43 " or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n"
43"Display the current time in the given FORMAT, or set the system date.\n" 44 "Display the current time in the given FORMAT, or set the system date.\n"
44"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" 45 "\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n"
45"\t-s\t\tset time described by STRING\n" 46 "\t-s\t\tset time described by STRING\n"
46"\t-u\t\tprint or set Coordinated Universal Time\n"; 47
48 "\t-u\t\tprint or set Coordinated Universal Time\n";
47 49
48 50
49/* Input parsing code is always bulky - used heavy duty libc stuff as 51/* Input parsing code is always bulky - used heavy duty libc stuff as
@@ -51,240 +53,233 @@ static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
51 53
52/* Default input handling to save suprising some people */ 54/* Default input handling to save suprising some people */
53 55
54struct tm * 56struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
55date_conv_time(struct tm *tm_time, const char *t_string) { 57{
56 int nr; 58 int nr;
57 59
58 nr = sscanf(t_string, "%2d%2d%2d%2d%d", 60 nr = sscanf(t_string, "%2d%2d%2d%2d%d",
59 &(tm_time->tm_mon), 61 &(tm_time->tm_mon),
60 &(tm_time->tm_mday), 62 &(tm_time->tm_mday),
61 &(tm_time->tm_hour), 63 &(tm_time->tm_hour),
62 &(tm_time->tm_min), 64 &(tm_time->tm_min), &(tm_time->tm_year));
63 &(tm_time->tm_year)); 65
64 66 if (nr < 4 || nr > 5) {
65 if(nr < 4 || nr > 5) { 67 fprintf(stderr, invalid_date, "date", t_string);
66 fprintf(stderr, invalid_date, "date", t_string); 68 exit(FALSE);
67 exit( FALSE); 69 }
68 } 70
69 71 /* correct for century - minor Y2K problem here? */
70 /* correct for century - minor Y2K problem here? */ 72 if (tm_time->tm_year >= 1900)
71 if(tm_time->tm_year >= 1900) 73 tm_time->tm_year -= 1900;
72 tm_time->tm_year -= 1900; 74 /* adjust date */
73 /* adjust date */ 75 tm_time->tm_mon -= 1;
74 tm_time->tm_mon -= 1; 76
75 77 return (tm_time);
76 return(tm_time);
77 78
78} 79}
79 80
80 81
81/* The new stuff for LRP */ 82/* The new stuff for LRP */
82 83
83struct tm * 84struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
84date_conv_ftime(struct tm *tm_time, const char *t_string) { 85{
85 struct tm itm_time, jtm_time, ktm_time, \ 86 struct tm itm_time, jtm_time, ktm_time, ltm_time, mtm_time, ntm_time;
86 ltm_time, mtm_time, ntm_time; 87
87 88 itm_time = *tm_time;
88 itm_time = *tm_time; 89 jtm_time = *tm_time;
89 jtm_time = *tm_time; 90 ktm_time = *tm_time;
90 ktm_time = *tm_time; 91 ltm_time = *tm_time;
91 ltm_time = *tm_time; 92 mtm_time = *tm_time;
92 mtm_time = *tm_time; 93 ntm_time = *tm_time;
93 ntm_time = *tm_time; 94
94 95 /* Parse input and assign appropriately to tm_time */
95 /* Parse input and assign appropriately to tm_time */ 96
96 97 if (sscanf(t_string, "%d:%d:%d",
97 if(sscanf(t_string, "%d:%d:%d", 98 &itm_time.tm_hour, &itm_time.tm_min, &itm_time.tm_sec) == 3) {
98 &itm_time.tm_hour, 99
99 &itm_time.tm_min, 100 *tm_time = itm_time;
100 &itm_time.tm_sec) == 3 ) { 101 return (tm_time);
101 102
102 *tm_time = itm_time; 103 } else if (sscanf(t_string, "%d:%d",
103 return(tm_time); 104 &jtm_time.tm_hour, &jtm_time.tm_min) == 2) {
104 105
105 } else if (sscanf(t_string, "%d:%d", 106 *tm_time = jtm_time;
106 &jtm_time.tm_hour, 107 return (tm_time);
107 &jtm_time.tm_min) == 2) { 108
108 109 } else if (sscanf(t_string, "%d.%d-%d:%d:%d",
109 *tm_time = jtm_time; 110 &ktm_time.tm_mon,
110 return(tm_time); 111 &ktm_time.tm_mday,
111 112 &ktm_time.tm_hour,
112 } else if (sscanf(t_string, "%d.%d-%d:%d:%d", 113 &ktm_time.tm_min, &ktm_time.tm_sec) == 5) {
113 &ktm_time.tm_mon, 114
114 &ktm_time.tm_mday, 115 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
115 &ktm_time.tm_hour, 116 *tm_time = ktm_time;
116 &ktm_time.tm_min, 117 return (tm_time);
117 &ktm_time.tm_sec) == 5) { 118
118 119 } else if (sscanf(t_string, "%d.%d-%d:%d",
119 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 120 &ltm_time.tm_mon,
120 *tm_time = ktm_time; 121 &ltm_time.tm_mday,
121 return(tm_time); 122 &ltm_time.tm_hour, &ltm_time.tm_min) == 4) {
122 123
123 } else if (sscanf(t_string, "%d.%d-%d:%d", 124 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
124 &ltm_time.tm_mon, 125 *tm_time = ltm_time;
125 &ltm_time.tm_mday, 126 return (tm_time);
126 &ltm_time.tm_hour, 127
127 &ltm_time.tm_min) == 4) { 128 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
128 129 &mtm_time.tm_year,
129 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 130 &mtm_time.tm_mon,
130 *tm_time = ltm_time; 131 &mtm_time.tm_mday,
131 return(tm_time); 132 &mtm_time.tm_hour,
132 133 &mtm_time.tm_min, &mtm_time.tm_sec) == 6) {
133 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d", 134
134 &mtm_time.tm_year, 135 mtm_time.tm_year -= 1900; /* Adjust years */
135 &mtm_time.tm_mon, 136 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
136 &mtm_time.tm_mday, 137 *tm_time = mtm_time;
137 &mtm_time.tm_hour, 138 return (tm_time);
138 &mtm_time.tm_min, 139
139 &mtm_time.tm_sec) == 6) { 140 } else if (sscanf(t_string, "%d.%d.%d-%d:%d",
140 141 &ntm_time.tm_year,
141 mtm_time.tm_year -= 1900; /* Adjust years */ 142 &ntm_time.tm_mon,
142 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 143 &ntm_time.tm_mday,
143 *tm_time = mtm_time; 144 &ntm_time.tm_hour, &ntm_time.tm_min) == 5) {
144 return(tm_time); 145 ntm_time.tm_year -= 1900; /* Adjust years */
145 146 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
146 } else if (sscanf(t_string, "%d.%d.%d-%d:%d", 147 *tm_time = ntm_time;
147 &ntm_time.tm_year, 148 return (tm_time);
148 &ntm_time.tm_mon, 149
149 &ntm_time.tm_mday, 150 }
150 &ntm_time.tm_hour, 151
151 &ntm_time.tm_min) == 5) { 152 fprintf(stderr, invalid_date, "date", t_string);
152 ntm_time.tm_year -= 1900; /* Adjust years */ 153
153 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 154 exit(FALSE);
154 *tm_time = ntm_time;
155 return(tm_time);
156
157 }
158
159 fprintf(stderr, invalid_date, "date", t_string);
160
161 exit( FALSE);
162 155
163} 156}
164 157
165 158
166int 159int date_main(int argc, char **argv)
167date_main(int argc, char * * argv)
168{ 160{
169 char *date_str = NULL; 161 char *date_str = NULL;
170 char *date_fmt = NULL; 162 char *date_fmt = NULL;
171 char *t_buff; 163 char *t_buff;
172 int i; 164 int i;
173 int set_time = 0; 165 int set_time = 0;
174 int rfc822 = 0; 166 int rfc822 = 0;
175 int utc = 0; 167 int utc = 0;
176 int use_arg = 0; 168 int use_arg = 0;
177 time_t tm; 169 time_t tm;
178 struct tm tm_time; 170 struct tm tm_time;
179 171
180 /* Interpret command line args */ 172 /* Interpret command line args */
181 i = --argc; 173 i = --argc;
182 argv++; 174 argv++;
183 while (i > 0 && **argv) { 175 while (i > 0 && **argv) {
184 if (**argv == '-') { 176 if (**argv == '-') {
185 while (i>0 && *++(*argv)) switch (**argv) { 177 while (i > 0 && *++(*argv))
186 case 'R': 178 switch (**argv) {
187 rfc822 = 1; 179 case 'R':
188 break; 180 rfc822 = 1;
189 case 's': 181 break;
190 set_time = 1; 182 case 's':
191 if(date_str != NULL) usage ( date_usage); 183 set_time = 1;
192 date_str = optarg; 184 if (date_str != NULL)
193 break; 185 usage(date_usage);
194 case 'u': 186 date_str = optarg;
195 utc = 1; 187 break;
196 if (putenv ("TZ=UTC0") != 0) { 188 case 'u':
197 fprintf(stderr, memory_exhausted, "date"); 189 utc = 1;
198 exit( FALSE); 190 if (putenv("TZ=UTC0") != 0) {
191 fprintf(stderr, memory_exhausted, "date");
192 exit(FALSE);
193 }
194 /* Look ma, no break. Don't fix it either. */
195 case 'd':
196 use_arg = 1;
197 if (date_str != NULL)
198 usage(date_usage);
199 date_str = optarg;
200 break;
201 case '-':
202 usage(date_usage);
203 }
204 } else {
205 if ((date_fmt == NULL) && (strcmp(*argv, "+") == 0))
206 date_fmt = *argv;
207 else if (date_str == NULL) {
208 set_time = 1;
209 date_str = *argv;
210 } else {
211 usage(date_usage);
212 }
199 } 213 }
200 /* Look ma, no break. Don't fix it either. */ 214 i--;
201 case 'd': 215 argv++;
202 use_arg = 1;
203 if(date_str != NULL) usage ( date_usage);
204 date_str = optarg;
205 break;
206 case '-':
207 usage ( date_usage);
208 }
209 } else {
210 if ( (date_fmt == NULL) && (strcmp(*argv, "+")==0) )
211 date_fmt=*argv;
212 else if (date_str == NULL) {
213 set_time = 1;
214 date_str=*argv;
215 } else {
216 usage ( date_usage);
217 }
218 } 216 }
219 i--; 217
220 argv++; 218
221 } 219 /* Now we have parsed all the information except the date format
222 220 which depends on whether the clock is being set or read */
223 221
224 /* Now we have parsed all the information except the date format 222 time(&tm);
225 which depends on whether the clock is being set or read */ 223 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
226 224 /* Zero out fields - take her back to midnight! */
227 time(&tm); 225 if (date_str != NULL) {
228 memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); 226 tm_time.tm_sec = 0;
229 /* Zero out fields - take her back to midnight!*/ 227 tm_time.tm_min = 0;
230 if(date_str != NULL) { 228 tm_time.tm_hour = 0;
231 tm_time.tm_sec = 0; 229 }
232 tm_time.tm_min = 0; 230
233 tm_time.tm_hour = 0; 231 /* Process any date input to UNIX time since 1 Jan 1970 */
234 } 232 if (date_str != NULL) {
235 233
236 /* Process any date input to UNIX time since 1 Jan 1970 */ 234 if (strchr(date_str, ':') != NULL) {
237 if(date_str != NULL) { 235 date_conv_ftime(&tm_time, date_str);
238 236 } else {
239 if(strchr(date_str, ':') != NULL) { 237 date_conv_time(&tm_time, date_str);
240 date_conv_ftime(&tm_time, date_str); 238 }
241 } else { 239
242 date_conv_time(&tm_time, date_str); 240 /* Correct any day of week and day of year etc fields */
243 } 241 tm = mktime(&tm_time);
244 242 if (tm < 0) {
245 /* Correct any day of week and day of year etc fields */ 243 fprintf(stderr, invalid_date, "date", date_str);
246 tm = mktime(&tm_time); 244 exit(FALSE);
247 if (tm < 0 ) { 245 }
248 fprintf(stderr, invalid_date, "date", date_str); 246
249 exit( FALSE); 247 /* if setting time, set it */
250 } 248 if (set_time) {
251 249 if (stime(&tm) < 0) {
252 /* if setting time, set it */ 250 fprintf(stderr, "date: can't set date.\n");
253 if(set_time) { 251 exit(FALSE);
254 if( stime(&tm) < 0) { 252 }
255 fprintf(stderr, "date: can't set date.\n"); 253 }
256 exit( FALSE); 254 }
257 } 255
258 } 256 /* Display output */
259 } 257
260 258 /* Deal with format string */
261 /* Display output */ 259 if (date_fmt == NULL) {
262 260 date_fmt = (rfc822
263 /* Deal with format string */ 261 ? (utc
264 if(date_fmt == NULL) { 262 ? "%a, %_d %b %Y %H:%M:%S GMT"
265 date_fmt = (rfc822 263 : "%a, %_d %b %Y %H:%M:%S %z")
266 ? (utc 264 : "%a %b %e %H:%M:%S %Z %Y");
267 ? "%a, %_d %b %Y %H:%M:%S GMT" 265
268 : "%a, %_d %b %Y %H:%M:%S %z") 266 } else if (*date_fmt == '\0') {
269 : "%a %b %e %H:%M:%S %Z %Y"); 267 /* Imitate what GNU 'date' does with NO format string! */
270 268 printf("\n");
271 } else if ( *date_fmt == '\0' ) { 269 exit(TRUE);
272 /* Imitate what GNU 'date' does with NO format string! */ 270 }
273 printf ("\n"); 271
274 exit( TRUE); 272 /* Handle special conversions */
275 } 273
276 274 if (strncmp(date_fmt, "%f", 2) == 0) {
277 /* Handle special conversions */ 275 date_fmt = "%Y.%m.%d-%H:%M:%S";
278 276 }
279 if( strncmp( date_fmt, "%f", 2) == 0 ) { 277
280 date_fmt = "%Y.%m.%d-%H:%M:%S"; 278 /* Print OUTPUT (after ALL that!) */
281 } 279 t_buff = malloc(201);
282 280 strftime(t_buff, 200, date_fmt, &tm_time);
283 /* Print OUTPUT (after ALL that!) */ 281 printf("%s\n", t_buff);
284 t_buff = malloc(201); 282
285 strftime(t_buff, 200, date_fmt, &tm_time); 283 exit(TRUE);
286 printf("%s\n", t_buff);
287
288 exit( TRUE);
289 284
290} 285}
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 3e1024a60..0d5b3e8ab 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini dd implementation for busybox 3 * Mini dd implementation for busybox
3 * 4 *
@@ -40,164 +41,159 @@ typedef unsigned long long int uintmax_t;
40#endif 41#endif
41 42
42static const char dd_usage[] = 43static const char dd_usage[] =
43"dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n" 44 "dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n"
44"Copy a file, converting and formatting according to options\n\n" 45 "Copy a file, converting and formatting according to options\n\n"
45"\tif=FILE\tread from FILE instead of stdin\n" 46 "\tif=FILE\tread from FILE instead of stdin\n"
46"\tof=FILE\twrite to FILE instead of stdout\n" 47 "\tof=FILE\twrite to FILE instead of stdout\n"
47"\tbs=n\tread and write n bytes at a time\n" 48 "\tbs=n\tread and write n bytes at a time\n"
48"\tcount=n\tcopy only n input blocks\n" 49 "\tcount=n\tcopy only n input blocks\n"
49"\tskip=n\tskip n input blocks\n" 50 "\tskip=n\tskip n input blocks\n"
50"\tseek=n\tskip n output blocks\n" 51 "\tseek=n\tskip n output blocks\n"
51"\n"
52"Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
53 52
53 "\n"
54 "Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
54 55
55 56
56extern int dd_main (int argc, char **argv) 57
58extern int dd_main(int argc, char **argv)
57{ 59{
58 const char *inFile = NULL; 60 const char *inFile = NULL;
59 const char *outFile = NULL; 61 const char *outFile = NULL;
60 char *cp; 62 char *cp;
61 int inFd; 63 int inFd;
62 int outFd; 64 int outFd;
63 int inCc = 0; 65 int inCc = 0;
64 int outCc; 66 int outCc;
65 long blockSize = 512; 67 long blockSize = 512;
66 uintmax_t skipBlocks = 0; 68 uintmax_t skipBlocks = 0;
67 uintmax_t seekBlocks = 0; 69 uintmax_t seekBlocks = 0;
68 uintmax_t count = (uintmax_t)-1; 70 uintmax_t count = (uintmax_t) - 1;
69 uintmax_t intotal; 71 uintmax_t intotal;
70 uintmax_t outTotal; 72 uintmax_t outTotal;
71 unsigned char *buf; 73 unsigned char *buf;
72 74
73 argc--; 75 argc--;
74 argv++; 76 argv++;
75
76 /* Parse any options */
77 while (argc) {
78 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
79 inFile=((strchr(*argv, '='))+1);
80 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
81 outFile=((strchr(*argv, '='))+1);
82 else if (strncmp("count", *argv, 5) == 0) {
83 count = getNum ((strchr(*argv, '='))+1);
84 if (count <= 0) {
85 fprintf (stderr, "Bad count value %s\n", *argv);
86 goto usage;
87 }
88 }
89 else if (strncmp(*argv, "bs", 2) == 0) {
90 blockSize = getNum ((strchr(*argv, '='))+1);
91 if (blockSize <= 0) {
92 fprintf (stderr, "Bad block size value %s\n", *argv);
93 goto usage;
94 }
95 }
96 else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum ((strchr(*argv, '='))+1);
98 if (skipBlocks <= 0) {
99 fprintf (stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102 77
78 /* Parse any options */
79 while (argc) {
80 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
81 inFile = ((strchr(*argv, '=')) + 1);
82 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
83 outFile = ((strchr(*argv, '=')) + 1);
84 else if (strncmp("count", *argv, 5) == 0) {
85 count = getNum((strchr(*argv, '=')) + 1);
86 if (count <= 0) {
87 fprintf(stderr, "Bad count value %s\n", *argv);
88 goto usage;
89 }
90 } else if (strncmp(*argv, "bs", 2) == 0) {
91 blockSize = getNum((strchr(*argv, '=')) + 1);
92 if (blockSize <= 0) {
93 fprintf(stderr, "Bad block size value %s\n", *argv);
94 goto usage;
95 }
96 } else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum((strchr(*argv, '=')) + 1);
98 if (skipBlocks <= 0) {
99 fprintf(stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102
103 } else if (strncmp(*argv, "seek", 4) == 0) {
104 seekBlocks = getNum((strchr(*argv, '=')) + 1);
105 if (seekBlocks <= 0) {
106 fprintf(stderr, "Bad seek value %s\n", *argv);
107 goto usage;
108 }
109
110 } else {
111 goto usage;
112 }
113 argc--;
114 argv++;
103 } 115 }
104 else if (strncmp(*argv, "seek", 4) == 0) {
105 seekBlocks = getNum ((strchr(*argv, '='))+1);
106 if (seekBlocks <= 0) {
107 fprintf (stderr, "Bad seek value %s\n", *argv);
108 goto usage;
109 }
110 116
117 buf = malloc(blockSize);
118 if (buf == NULL) {
119 fprintf(stderr, "Cannot allocate buffer\n");
120 exit(FALSE);
111 } 121 }
112 else { 122
113 goto usage; 123 intotal = 0;
124 outTotal = 0;
125
126 if (inFile == NULL)
127 inFd = fileno(stdin);
128 else
129 inFd = open(inFile, 0);
130
131 if (inFd < 0) {
132 perror(inFile);
133 free(buf);
134 exit(FALSE);
114 } 135 }
115 argc--; 136
116 argv++; 137 if (outFile == NULL)
117 } 138 outFd = fileno(stdout);
118 139 else
119 buf = malloc (blockSize); 140 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
120 if (buf == NULL) { 141
121 fprintf (stderr, "Cannot allocate buffer\n"); 142 if (outFd < 0) {
122 exit( FALSE); 143 perror(outFile);
123 } 144 close(inFd);
124 145 free(buf);
125 intotal = 0; 146 exit(FALSE);
126 outTotal = 0;
127
128 if (inFile == NULL)
129 inFd = fileno(stdin);
130 else
131 inFd = open (inFile, 0);
132
133 if (inFd < 0) {
134 perror (inFile);
135 free (buf);
136 exit( FALSE);
137 }
138
139 if (outFile == NULL)
140 outFd = fileno(stdout);
141 else
142 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
143
144 if (outFd < 0) {
145 perror (outFile);
146 close (inFd);
147 free (buf);
148 exit( FALSE);
149 }
150
151 lseek(inFd, skipBlocks*blockSize, SEEK_SET);
152 lseek(outFd, seekBlocks*blockSize, SEEK_SET);
153 //
154 //TODO: Convert to using fullRead & fullWrite
155 // from utility.c
156 // -Erik
157 while (outTotal < count * blockSize) {
158 inCc = read (inFd, buf, blockSize);
159 if (inCc < 0) {
160 perror (inFile);
161 goto cleanup;
162 } else if (inCc == 0) {
163 goto cleanup;
164 } 147 }
165 intotal += inCc; 148
166 cp = buf; 149 lseek(inFd, skipBlocks * blockSize, SEEK_SET);
167 150 lseek(outFd, seekBlocks * blockSize, SEEK_SET);
168 while (intotal > outTotal) { 151 //
169 if (outTotal + inCc > count * blockSize) 152 //TODO: Convert to using fullRead & fullWrite
170 inCc = count * blockSize - outTotal; 153 // from utility.c
171 outCc = write (outFd, cp, inCc); 154 // -Erik
172 if (outCc < 0) { 155 while (outTotal < count * blockSize) {
173 perror (outFile); 156 inCc = read(inFd, buf, blockSize);
174 goto cleanup; 157 if (inCc < 0) {
175 } else if (outCc == 0) { 158 perror(inFile);
176 goto cleanup; 159 goto cleanup;
177 } 160 } else if (inCc == 0) {
178 161 goto cleanup;
179 inCc -= outCc; 162 }
180 cp += outCc; 163 intotal += inCc;
181 outTotal += outCc; 164 cp = buf;
165
166 while (intotal > outTotal) {
167 if (outTotal + inCc > count * blockSize)
168 inCc = count * blockSize - outTotal;
169 outCc = write(outFd, cp, inCc);
170 if (outCc < 0) {
171 perror(outFile);
172 goto cleanup;
173 } else if (outCc == 0) {
174 goto cleanup;
175 }
176
177 inCc -= outCc;
178 cp += outCc;
179 outTotal += outCc;
180 }
182 } 181 }
183 }
184 182
185 if (inCc < 0) 183 if (inCc < 0)
186 perror (inFile); 184 perror(inFile);
187 185
188 cleanup: 186 cleanup:
189 close (inFd); 187 close(inFd);
190 close (outFd); 188 close(outFd);
191 free (buf); 189 free(buf);
192 190
193 printf ("%ld+%d records in\n", (long)(intotal / blockSize), 191 printf("%ld+%d records in\n", (long) (intotal / blockSize),
194 (intotal % blockSize) != 0); 192 (intotal % blockSize) != 0);
195 printf ("%ld+%d records out\n", (long)(outTotal / blockSize), 193 printf("%ld+%d records out\n", (long) (outTotal / blockSize),
196 (outTotal % blockSize) != 0); 194 (outTotal % blockSize) != 0);
197 exit( TRUE); 195 exit(TRUE);
198 usage: 196 usage:
199 197
200 usage( dd_usage); 198 usage(dd_usage);
201} 199}
202
203
diff --git a/coreutils/df.c b/coreutils/df.c
index 24c94a246..43d5d26e7 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini df implementation for busybox 3 * Mini df implementation for busybox
3 * 4 *
@@ -29,81 +30,81 @@
29#include <fstab.h> 30#include <fstab.h>
30 31
31static const char df_usage[] = "df [filesystem ...]\n" 32static const char df_usage[] = "df [filesystem ...]\n"
32 "\n" "\tPrint the filesystem space used and space available.\n";
33 33
34extern const char mtab_file[]; /* Defined in utility.c */ 34 "\n" "\tPrint the filesystem space used and space available.\n";
35
36extern const char mtab_file[]; /* Defined in utility.c */
35 37
36static int df(char *device, const char *mountPoint) 38static int df(char *device, const char *mountPoint)
37{ 39{
38 struct statfs s; 40 struct statfs s;
39 long blocks_used; 41 long blocks_used;
40 long blocks_percent_used; 42 long blocks_percent_used;
41 struct fstab* fstabItem; 43 struct fstab *fstabItem;
42
43 if (statfs(mountPoint, &s) != 0) {
44 perror(mountPoint);
45 return FALSE;
46 }
47 44
48 if (s.f_blocks > 0) { 45 if (statfs(mountPoint, &s) != 0) {
49 blocks_used = s.f_blocks - s.f_bfree; 46 perror(mountPoint);
50 blocks_percent_used = (long) 47 return FALSE;
51 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
52 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
53 if (strcmp (device, "/dev/root") == 0) {
54 fstabItem = getfsfile ("/");
55 if (fstabItem != NULL)
56 device = fstabItem->fs_spec;
57 } 48 }
58 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
59 device,
60 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
61 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
62 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
63 blocks_percent_used, mountPoint);
64 49
65 } 50 if (s.f_blocks > 0) {
51 blocks_used = s.f_blocks - s.f_bfree;
52 blocks_percent_used = (long)
53 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
54 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
55 if (strcmp(device, "/dev/root") == 0) {
56 fstabItem = getfsfile("/");
57 if (fstabItem != NULL)
58 device = fstabItem->fs_spec;
59 }
60 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
61 device,
62 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
63 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
64 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
65 blocks_percent_used, mountPoint);
66
67 }
66 68
67 return TRUE; 69 return TRUE;
68} 70}
69 71
70extern int df_main(int argc, char **argv) 72extern int df_main(int argc, char **argv)
71{ 73{
72 printf("%-20s %-14s %s %s %s %s\n", "Filesystem", 74 printf("%-20s %-14s %s %s %s %s\n", "Filesystem",
73 "1k-blocks", "Used", "Available", "Use%", "Mounted on"); 75 "1k-blocks", "Used", "Available", "Use%", "Mounted on");
74 76
75 if (argc > 1) { 77 if (argc > 1) {
76 struct mntent *mountEntry; 78 struct mntent *mountEntry;
77 int status; 79 int status;
78 80
79 while (argc > 1) { 81 while (argc > 1) {
80 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 82 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 0) {
81 0) { 83 fprintf(stderr, "%s: can't find mount point.\n", argv[1]);
82 fprintf(stderr, "%s: can't find mount point.\n", argv[1]); 84 exit(FALSE);
83 exit( FALSE); 85 }
84 } 86 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
85 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 87 if (status != 0)
86 if (status != 0) 88 exit(status);
87 exit( status); 89 argc--;
88 argc--; 90 argv++;
89 argv++; 91 }
90 } 92 exit(TRUE);
91 exit( TRUE); 93 } else {
92 } else { 94 FILE *mountTable;
93 FILE *mountTable; 95 struct mntent *mountEntry;
94 struct mntent *mountEntry;
95 96
96 mountTable = setmntent(mtab_file, "r"); 97 mountTable = setmntent(mtab_file, "r");
97 if (mountTable == 0) { 98 if (mountTable == 0) {
98 perror(mtab_file); 99 perror(mtab_file);
99 exit(FALSE); 100 exit(FALSE);
100 } 101 }
101 102
102 while ((mountEntry = getmntent(mountTable))) { 103 while ((mountEntry = getmntent(mountTable))) {
103 df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 104 df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
105 }
106 endmntent(mountTable);
104 } 107 }
105 endmntent(mountTable);
106 }
107 108
108 exit( TRUE); 109 exit(TRUE);
109} 110}
diff --git a/coreutils/du.c b/coreutils/du.c
index e2cf3f7c0..7151e3a9c 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini du implementation for busybox 3 * Mini du implementation for busybox
3 * 4 *
@@ -31,119 +32,121 @@
31#include <dirent.h> 32#include <dirent.h>
32#include <stdio.h> 33#include <stdio.h>
33#include <errno.h> 34#include <errno.h>
34#include <sys/param.h> /* for PATH_MAX */ 35#include <sys/param.h> /* for PATH_MAX */
35 36
36typedef void (Display)(long, char *); 37typedef void (Display) (long, char *);
37 38
38static const char du_usage[] = 39static const char du_usage[] =
39"du [OPTION]... [FILE]...\n\n"
40"\t-s\tdisplay only a total for each argument\n"
41;
42 40
43static int du_depth = 0; 41 "du [OPTION]... [FILE]...\n\n"
42 "\t-s\tdisplay only a total for each argument\n";
44 43
45static Display *print; 44static int du_depth = 0;
46 45
47static void 46static Display *print;
48print_normal(long size, char *filename) 47
48static void print_normal(long size, char *filename)
49{ 49{
50 fprintf(stdout, "%-7ld %s\n", size, filename); 50 fprintf(stdout, "%-7ld %s\n", size, filename);
51} 51}
52 52
53static void 53static void print_summary(long size, char *filename)
54print_summary(long size, char *filename)
55{ 54{
56 if (du_depth == 1) { 55 if (du_depth == 1) {
57 print_normal(size, filename); 56 print_normal(size, filename);
58 } 57 }
59} 58}
60 59
61 60
62/* tiny recursive du */ 61/* tiny recursive du */
63static long 62static long du(char *filename)
64du(char *filename)
65{ 63{
66 struct stat statbuf; 64 struct stat statbuf;
67 long sum; 65 long sum;
68 66
69 if ((lstat(filename, &statbuf)) != 0) { 67 if ((lstat(filename, &statbuf)) != 0) {
70 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno)); 68 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno));
71 return 0; 69 return 0;
72 }
73
74 du_depth++;
75 sum = statbuf.st_blocks;
76
77 if (S_ISDIR(statbuf.st_mode)) {
78 DIR *dir;
79 struct dirent *entry;
80
81 dir = opendir(filename);
82 if (!dir) { return 0; }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ( (strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0))
89 { continue; }
90
91 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
92 fprintf(stderr, name_too_long, "du");
93 return 0;
94 }
95 sprintf(newfile, "%s/%s", filename, name);
96
97 sum += du(newfile);
98 } 70 }
99 closedir(dir); 71
100 print(sum, filename); 72 du_depth++;
101 } 73 sum = statbuf.st_blocks;
102 du_depth--; 74
103 return sum; 75 if (S_ISDIR(statbuf.st_mode)) {
76 DIR *dir;
77 struct dirent *entry;
78
79 dir = opendir(filename);
80 if (!dir) {
81 return 0;
82 }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ((strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0)) {
89 continue;
90 }
91
92 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
93 fprintf(stderr, name_too_long, "du");
94 return 0;
95 }
96 sprintf(newfile, "%s/%s", filename, name);
97
98 sum += du(newfile);
99 }
100 closedir(dir);
101 print(sum, filename);
102 }
103 du_depth--;
104 return sum;
104} 105}
105 106
106int 107int du_main(int argc, char **argv)
107du_main(int argc, char **argv)
108{ 108{
109 int i; 109 int i;
110 char opt; 110 char opt;
111 111
112 /* default behaviour */ 112 /* default behaviour */
113 print = print_normal; 113 print = print_normal;
114 114
115 /* parse argv[] */ 115 /* parse argv[] */
116 for (i = 1; i < argc; i++) { 116 for (i = 1; i < argc; i++) {
117 if (argv[i][0] == '-') { 117 if (argv[i][0] == '-') {
118 opt = argv[i][1]; 118 opt = argv[i][1];
119 switch (opt) { 119 switch (opt) {
120 case 's': 120 case 's':
121 print = print_summary; 121 print = print_summary;
122 break; 122 break;
123 case 'h': 123 case 'h':
124 usage(du_usage); 124 usage(du_usage);
125 break; 125 break;
126 default: 126 default:
127 fprintf(stderr, "du: invalid option -- %c\n", opt); 127 fprintf(stderr, "du: invalid option -- %c\n", opt);
128 usage(du_usage); 128 usage(du_usage);
129 } 129 }
130 } else { 130 } else {
131 break; 131 break;
132 }
132 } 133 }
133 }
134 134
135 /* go through remaining args (if any) */ 135 /* go through remaining args (if any) */
136 if (i >= argc) { 136 if (i >= argc) {
137 du("."); 137 du(".");
138 } else { 138 } else {
139 long sum; 139 long sum;
140 for ( ; i < argc; i++) { 140
141 sum = du(argv[i]); 141 for (; i < argc; i++) {
142 if ((sum) && (isDirectory(argv[i], FALSE))) { print_normal(sum, argv[i]); } 142 sum = du(argv[i]);
143 if ((sum) && (isDirectory(argv[i], FALSE))) {
144 print_normal(sum, argv[i]);
145 }
146 }
143 } 147 }
144 }
145 148
146 exit(0); 149 exit(0);
147} 150}
148 151
149/* $Id: du.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 152/* $Id: du.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/head.c b/coreutils/head.c
index b80d06580..82a73de2a 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini head implementation for busybox 3 * Mini head implementation for busybox
3 * 4 *
@@ -26,83 +27,86 @@
26#include <stdio.h> 27#include <stdio.h>
27 28
28const char head_usage[] = 29const char head_usage[] =
29"head [OPTION] [FILE]...\n\n" 30 "head [OPTION] [FILE]...\n\n"
30"Print first 10 lines of each FILE to standard output.\n" 31 "Print first 10 lines of each FILE to standard output.\n"
31"With more than one FILE, precede each with a header giving the\n" 32 "With more than one FILE, precede each with a header giving the\n"
32"file name. With no FILE, or when FILE is -, read standard input.\n\n" 33 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
33"Options:\n"
34"\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
35 34
36int 35 "Options:\n" "\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
37head(int len, FILE *src) 36
37int head(int len, FILE * src)
38{ 38{
39 int i; 39 int i;
40 char buffer[1024]; 40 char buffer[1024];
41 41
42 for (i = 0; i < len; i++) { 42 for (i = 0; i < len; i++) {
43 fgets(buffer, 1024, src); 43 fgets(buffer, 1024, src);
44 if (feof(src)) { break; } 44 if (feof(src)) {
45 fputs(buffer, stdout); 45 break;
46 } 46 }
47 return 0; 47 fputs(buffer, stdout);
48 }
49 return 0;
48} 50}
49 51
50/* BusyBoxed head(1) */ 52/* BusyBoxed head(1) */
51int 53int head_main(int argc, char **argv)
52head_main(int argc, char **argv)
53{ 54{
54 char opt; 55 char opt;
55 int len = 10, tmplen, i; 56 int len = 10, tmplen, i;
56 57
57 /* parse argv[] */ 58 /* parse argv[] */
58 for (i = 1; i < argc; i++) { 59 for (i = 1; i < argc; i++) {
59 if (argv[i][0] == '-') { 60 if (argv[i][0] == '-') {
60 opt = argv[i][1]; 61 opt = argv[i][1];
61 switch (opt) { 62 switch (opt) {
62 case 'n': 63 case 'n':
63 tmplen = 0; 64 tmplen = 0;
64 if (++i < argc) 65 if (++i < argc)
65 tmplen = atoi(argv[i]); 66 tmplen = atoi(argv[i]);
66 if (tmplen < 1) 67 if (tmplen < 1)
67 usage(head_usage); 68 usage(head_usage);
68 len = tmplen; 69 len = tmplen;
69 break; 70 break;
70 case '-': 71 case '-':
71 case 'h': 72 case 'h':
72 usage(head_usage); 73 usage(head_usage);
73 default: 74 default:
74 fprintf(stderr, "head: invalid option -- %c\n", opt); 75 fprintf(stderr, "head: invalid option -- %c\n", opt);
75 usage(head_usage); 76 usage(head_usage);
76 } 77 }
77 } else { 78 } else {
78 break; 79 break;
80 }
79 } 81 }
80 }
81 82
82 /* get rest of argv[] or stdin if nothing's left */ 83 /* get rest of argv[] or stdin if nothing's left */
83 if (i >= argc) { 84 if (i >= argc) {
84 head(len, stdin); 85 head(len, stdin);
85 86
86 } else { 87 } else {
87 int need_headers = ((argc - i) > 1); 88 int need_headers = ((argc - i) > 1);
88 for ( ; i < argc; i++) { 89
89 FILE *src; 90 for (; i < argc; i++) {
90 src = fopen(argv[i], "r"); 91 FILE *src;
91 if (!src) { 92
92 fprintf(stderr,"head: %s: %s\n", argv[i], strerror(errno)); 93 src = fopen(argv[i], "r");
93 } else { 94 if (!src) {
94 /* emulating GNU behaviour */ 95 fprintf(stderr, "head: %s: %s\n", argv[i],
95 if (need_headers) { 96 strerror(errno));
96 fprintf(stdout, "==> %s <==\n", argv[i]); 97 } else {
97 } 98 /* emulating GNU behaviour */
98 head(len, src); 99 if (need_headers) {
99 if (i < argc - 1) { 100 fprintf(stdout, "==> %s <==\n", argv[i]);
100 fprintf(stdout, "\n"); 101 }
102 head(len, src);
103 if (i < argc - 1) {
104 fprintf(stdout, "\n");
105 }
106 }
101 } 107 }
102 }
103 } 108 }
104 } 109 exit(0);
105 exit(0);
106} 110}
107 111
108/* $Id: head.c,v 1.7 2000/02/07 05:29:42 erik Exp $ */ 112/* $Id: head.c,v 1.8 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/hostid.c b/coreutils/hostid.c
index f8d5862ae..9e503e598 100644
--- a/coreutils/hostid.c
+++ b/coreutils/hostid.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini hostid implementation for busybox 3 * Mini hostid implementation for busybox
3 * 4 *
@@ -22,7 +23,8 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int hostid_main(int argc, char **argv) { 26extern int hostid_main(int argc, char **argv)
26 printf ("%lx\n", gethostid()); 27{
27 exit( TRUE); 28 printf("%lx\n", gethostid());
29 exit(TRUE);
28} 30}
diff --git a/coreutils/length.c b/coreutils/length.c
index 2c83cdfd2..00e5a171b 100644
--- a/coreutils/length.c
+++ b/coreutils/length.c
@@ -1,14 +1,14 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
4#include <stdio.h> 5#include <stdio.h>
5 6
6extern int 7extern int length_main(int argc, char **argv)
7length_main(int argc, char * * argv)
8{ 8{
9 if ( argc != 2 || **(argv+1) == '-' ) { 9 if (argc != 2 || **(argv + 1) == '-') {
10 usage("length string\n"); 10 usage("length string\n");
11 } 11 }
12 printf("%d\n", strlen(argv[1])); 12 printf("%d\n", strlen(argv[1]));
13 return( TRUE); 13 return (TRUE);
14} 14}
diff --git a/coreutils/ln.c b/coreutils/ln.c
index f20b340ea..bc51cb0d5 100644
--- a/coreutils/ln.c
+++ b/coreutils/ln.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini ln implementation for busybox 3 * Mini ln implementation for busybox
3 * 4 *
@@ -30,15 +31,16 @@
30#include <stdio.h> 31#include <stdio.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <errno.h> 33#include <errno.h>
33#include <sys/param.h> /* for PATH_MAX */ 34#include <sys/param.h> /* for PATH_MAX */
34 35
35static const char ln_usage[] = 36static const char ln_usage[] =
36 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n" 37 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n"
37 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n" 38 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n"
38 "Options:\n" 39 "Options:\n"
39 "\t-s\tmake symbolic links instead of hard links\n" 40 "\t-s\tmake symbolic links instead of hard links\n"
40 "\t-f\tremove existing destination files\n" 41
41 "\t-n\tno dereference symlinks - treat like normal file\n"; 42 "\t-f\tremove existing destination files\n"
43 "\t-n\tno dereference symlinks - treat like normal file\n";
42 44
43static int symlinkFlag = FALSE; 45static int symlinkFlag = FALSE;
44static int removeoldFlag = FALSE; 46static int removeoldFlag = FALSE;
@@ -46,83 +48,83 @@ static int followLinks = TRUE;
46 48
47extern int ln_main(int argc, char **argv) 49extern int ln_main(int argc, char **argv)
48{ 50{
49 char *linkName; 51 char *linkName;
50 int linkIntoDirFlag; 52 int linkIntoDirFlag;
51 53
52 if (argc < 3) { 54 if (argc < 3) {
53 usage (ln_usage); 55 usage(ln_usage);
54 } 56 }
55 argc--;
56 argv++;
57
58 /* Parse any options */
59 while (**argv == '-') {
60 while (*++(*argv))
61 switch (**argv) {
62 case 's':
63 symlinkFlag = TRUE;
64 break;
65 case 'f':
66 removeoldFlag = TRUE;
67 break;
68 case 'n':
69 followLinks = FALSE;
70 break;
71 default:
72 usage (ln_usage);
73 }
74 argc--; 57 argc--;
75 argv++; 58 argv++;
76 }
77
78 linkName = argv[argc - 1];
79
80 if (strlen(linkName) > PATH_MAX) {
81 fprintf(stderr, name_too_long, "ln");
82 exit FALSE;
83 }
84 59
85 linkIntoDirFlag = isDirectory(linkName, TRUE); 60 /* Parse any options */
86 61 while (**argv == '-') {
87 if ((argc > 3) && !linkIntoDirFlag) { 62 while (*++(*argv))
88 fprintf(stderr, not_a_directory, "ln", linkName); 63 switch (**argv) {
89 exit FALSE; 64 case 's':
90 } 65 symlinkFlag = TRUE;
66 break;
67 case 'f':
68 removeoldFlag = TRUE;
69 break;
70 case 'n':
71 followLinks = FALSE;
72 break;
73 default:
74 usage(ln_usage);
75 }
76 argc--;
77 argv++;
78 }
91 79
92 while (argc-- >= 2) { 80 linkName = argv[argc - 1];
93 char srcName[PATH_MAX + 1];
94 int nChars, status;
95 81
96 if (strlen(*argv) > PATH_MAX) { 82 if (strlen(linkName) > PATH_MAX) {
97 fprintf(stderr, name_too_long, "ln"); 83 fprintf(stderr, name_too_long, "ln");
98 exit FALSE; 84 exit FALSE;
99 } 85 }
100 86
101 if (followLinks == FALSE) { 87 linkIntoDirFlag = isDirectory(linkName, TRUE);
102 strcpy(srcName, *argv);
103 } else {
104 /* Warning! This can silently truncate if > PATH_MAX, but
105 I don't think that there can be one > PATH_MAX anyway. */
106 nChars = readlink(*argv, srcName, PATH_MAX);
107 srcName[nChars] = '\0';
108 }
109 88
110 if (removeoldFlag == TRUE) { 89 if ((argc > 3) && !linkIntoDirFlag) {
111 status = ( unlink(linkName) && errno != ENOENT ); 90 fprintf(stderr, not_a_directory, "ln", linkName);
112 if (status != 0) {
113 perror(linkName);
114 exit FALSE; 91 exit FALSE;
115 }
116 } 92 }
117 93
118 if (symlinkFlag == TRUE) 94 while (argc-- >= 2) {
119 status = symlink(*argv, linkName); 95 char srcName[PATH_MAX + 1];
120 else 96 int nChars, status;
121 status = link(*argv, linkName); 97
122 if (status != 0) { 98 if (strlen(*argv) > PATH_MAX) {
123 perror(linkName); 99 fprintf(stderr, name_too_long, "ln");
124 exit FALSE; 100 exit FALSE;
101 }
102
103 if (followLinks == FALSE) {
104 strcpy(srcName, *argv);
105 } else {
106 /* Warning! This can silently truncate if > PATH_MAX, but
107 I don't think that there can be one > PATH_MAX anyway. */
108 nChars = readlink(*argv, srcName, PATH_MAX);
109 srcName[nChars] = '\0';
110 }
111
112 if (removeoldFlag == TRUE) {
113 status = (unlink(linkName) && errno != ENOENT);
114 if (status != 0) {
115 perror(linkName);
116 exit FALSE;
117 }
118 }
119
120 if (symlinkFlag == TRUE)
121 status = symlink(*argv, linkName);
122 else
123 status = link(*argv, linkName);
124 if (status != 0) {
125 perror(linkName);
126 exit FALSE;
127 }
125 } 128 }
126 } 129 exit TRUE;
127 exit TRUE;
128} 130}
diff --git a/coreutils/logname.c b/coreutils/logname.c
index 5c8275ab4..182f40ed2 100644
--- a/coreutils/logname.c
+++ b/coreutils/logname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini logname implementation for busybox 3 * Mini logname implementation for busybox
3 * 4 *
@@ -23,18 +24,21 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char logname_usage[] = "logname\n\n" 26static const char logname_usage[] = "logname\n\n"
26"Print the name of the current user.\n";
27 27
28extern int logname_main(int argc, char **argv) { 28 "Print the name of the current user.\n";
29
30extern int logname_main(int argc, char **argv)
31{
29 char *cp; 32 char *cp;
30 33
31 if (argc > 1) usage (logname_usage); 34 if (argc > 1)
35 usage(logname_usage);
32 36
33 cp = getlogin (); 37 cp = getlogin();
34 if (cp) { 38 if (cp) {
35 puts (cp); 39 puts(cp);
36 exit (TRUE); 40 exit(TRUE);
37 } 41 }
38 fprintf (stderr, "%s: no login name\n", argv[0]); 42 fprintf(stderr, "%s: no login name\n", argv[0]);
39 exit (FALSE); 43 exit(FALSE);
40} 44}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 450ea1814..f23c1e086 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * tiny-ls.c version 0.1.0: A minimalist 'ls' 3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
3 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
@@ -40,18 +41,18 @@
40 * 1. requires lstat (BSD) - how do you do it without? 41 * 1. requires lstat (BSD) - how do you do it without?
41 */ 42 */
42 43
43#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */ 44#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */
44#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */ 45#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */
45#define COLUMN_GAP 2 /* includes the file type char, if present */ 46#define COLUMN_GAP 2 /* includes the file type char, if present */
46#define HAS_REWINDDIR 47#define HAS_REWINDDIR
47 48
48/************************************************************************/ 49/************************************************************************/
49 50
50#include "internal.h" 51#include "internal.h"
51#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 52#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
52# include <linux/types.h> 53# include <linux/types.h>
53#else 54#else
54# include <sys/types.h> 55# include <sys/types.h>
55#endif 56#endif
56#include <sys/stat.h> 57#include <sys/stat.h>
57#include <stdio.h> 58#include <stdio.h>
@@ -75,28 +76,28 @@
75#endif 76#endif
76 77
77#define FMT_AUTO 0 78#define FMT_AUTO 0
78#define FMT_LONG 1 /* one record per line, extended info */ 79#define FMT_LONG 1 /* one record per line, extended info */
79#define FMT_SINGLE 2 /* one record per line */ 80#define FMT_SINGLE 2 /* one record per line */
80#define FMT_ROWS 3 /* print across rows */ 81#define FMT_ROWS 3 /* print across rows */
81#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */ 82#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */
82 83
83#define TIME_MOD 0 84#define TIME_MOD 0
84#define TIME_CHANGE 1 85#define TIME_CHANGE 1
85#define TIME_ACCESS 2 86#define TIME_ACCESS 2
86 87
87#define DISP_FTYPE 1 /* show character for file type */ 88#define DISP_FTYPE 1 /* show character for file type */
88#define DISP_EXEC 2 /* show '*' if regular executable file */ 89#define DISP_EXEC 2 /* show '*' if regular executable file */
89#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */ 90#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */
90#define DISP_DOT 8 /* show . and .. */ 91#define DISP_DOT 8 /* show . and .. */
91#define DISP_NUMERIC 16 /* numeric uid and gid */ 92#define DISP_NUMERIC 16 /* numeric uid and gid */
92#define DISP_FULLTIME 32 /* show extended time display */ 93#define DISP_FULLTIME 32 /* show extended time display */
93#define DIR_NOLIST 64 /* show directory as itself, not contents */ 94#define DIR_NOLIST 64 /* show directory as itself, not contents */
94#define DISP_DIRNAME 128 /* show directory name (for internal use) */ 95#define DISP_DIRNAME 128 /* show directory name (for internal use) */
95#define DIR_RECURSE 256 /* -R (not yet implemented) */ 96#define DIR_RECURSE 256 /* -R (not yet implemented) */
96 97
97static unsigned char display_fmt = FMT_AUTO; 98static unsigned char display_fmt = FMT_AUTO;
98static unsigned short opts = 0; 99static unsigned short opts = 0;
99static unsigned short column = 0; 100static unsigned short column = 0;
100 101
101#ifdef BB_FEATURE_AUTOWIDTH 102#ifdef BB_FEATURE_AUTOWIDTH
102static unsigned short terminal_width = 0, column_width = 0; 103static unsigned short terminal_width = 0, column_width = 0;
@@ -113,13 +114,14 @@ static unsigned char time_fmt = TIME_MOD;
113 114
114static void writenum(long val, short minwidth) 115static void writenum(long val, short minwidth)
115{ 116{
116 char scratch[128]; 117 char scratch[128];
117 118
118 char *p = scratch + sizeof(scratch); 119 char *p = scratch + sizeof(scratch);
119 short len = 0; 120 short len = 0;
120 short neg = (val < 0); 121 short neg = (val < 0);
121 122
122 if (neg) val = -val; 123 if (neg)
124 val = -val;
123 do 125 do
124 *--p = (val % 10) + '0', len++, val /= 10; 126 *--p = (val % 10) + '0', len++, val /= 10;
125 while (val); 127 while (val);
@@ -142,8 +144,9 @@ static void newline(void)
142static void tab(short col) 144static void tab(short col)
143{ 145{
144 static const char spaces[] = " "; 146 static const char spaces[] = " ";
145 #define nspaces ((sizeof spaces)-1) /* null terminator! */ 147
146 148#define nspaces ((sizeof spaces)-1) /* null terminator! */
149
147 short n = col - column; 150 short n = col - column;
148 151
149 if (n > 0) { 152 if (n > 0) {
@@ -155,7 +158,7 @@ static void tab(short col)
155 /* must be 1...(sizeof spaces) left */ 158 /* must be 1...(sizeof spaces) left */
156 wr(spaces, n); 159 wr(spaces, n);
157 } 160 }
158 #undef nspaces 161#undef nspaces
159} 162}
160 163
161#ifdef BB_FEATURE_LS_FILETYPES 164#ifdef BB_FEATURE_LS_FILETYPES
@@ -163,8 +166,8 @@ static char append_char(mode_t mode)
163{ 166{
164 if (!(opts & DISP_FTYPE)) 167 if (!(opts & DISP_FTYPE))
165 return '\0'; 168 return '\0';
166 if ((opts & DISP_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH))) 169 if ((opts & DISP_EXEC) && S_ISREG(mode)
167 return '*'; 170 && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*';
168 return APPCHAR(mode); 171 return APPCHAR(mode);
169} 172}
170#endif 173#endif
@@ -176,89 +179,93 @@ static char append_char(mode_t mode)
176 ** 179 **
177 **/ 180 **/
178 181
179static void list_single(const char *name, struct stat *info, const char *fullname) 182static void list_single(const char *name, struct stat *info,
183 const char *fullname)
180{ 184{
181 char scratch[PATH_MAX + 1]; 185 char scratch[PATH_MAX + 1];
182 short len = strlen(name); 186 short len = strlen(name);
187
183#ifdef BB_FEATURE_LS_FILETYPES 188#ifdef BB_FEATURE_LS_FILETYPES
184 char append = append_char(info->st_mode); 189 char append = append_char(info->st_mode);
185#endif 190#endif
186 191
187 if (display_fmt == FMT_LONG) { 192 if (display_fmt == FMT_LONG) {
188 mode_t mode = info->st_mode; 193 mode_t mode = info->st_mode;
194
189 newline(); 195 newline();
190 wr(modeString(mode), 10); 196 wr(modeString(mode), 10);
191 column=10; 197 column = 10;
192 writenum((long)info->st_nlink,(short)5); 198 writenum((long) info->st_nlink, (short) 5);
193 fputs(" ", stdout); 199 fputs(" ", stdout);
194#ifdef BB_FEATURE_LS_USERNAME 200#ifdef BB_FEATURE_LS_USERNAME
195 if (!(opts & DISP_NUMERIC)) { 201 if (!(opts & DISP_NUMERIC)) {
196 memset ( scratch, 0, sizeof (scratch)); 202 memset(scratch, 0, sizeof(scratch));
197 my_getpwuid( scratch, info->st_uid); 203 my_getpwuid(scratch, info->st_uid);
198 if (*scratch) { 204 if (*scratch) {
199 fputs(scratch, stdout); 205 fputs(scratch, stdout);
200 if ( strlen( scratch) <= 8 ) 206 if (strlen(scratch) <= 8)
201 wr(" ", 9-strlen( scratch)); 207 wr(" ", 9 - strlen(scratch));
202 } 208 } else {
203 else { 209 writenum((long) info->st_uid, (short) 8);
204 writenum((long) info->st_uid,(short)8);
205 fputs(" ", stdout); 210 fputs(" ", stdout);
206 } 211 }
207 } else 212 } else
208#endif 213#endif
209 { 214 {
210 writenum((long) info->st_uid,(short)8); 215 writenum((long) info->st_uid, (short) 8);
211 fputs(" ", stdout); 216 fputs(" ", stdout);
212 } 217 }
213#ifdef BB_FEATURE_LS_USERNAME 218#ifdef BB_FEATURE_LS_USERNAME
214 if (!(opts & DISP_NUMERIC)) { 219 if (!(opts & DISP_NUMERIC)) {
215 memset ( scratch, 0, sizeof (scratch)); 220 memset(scratch, 0, sizeof(scratch));
216 my_getgrgid( scratch, info->st_gid); 221 my_getgrgid(scratch, info->st_gid);
217 if (*scratch) { 222 if (*scratch) {
218 fputs(scratch, stdout); 223 fputs(scratch, stdout);
219 if ( strlen( scratch) <= 8 ) 224 if (strlen(scratch) <= 8)
220 wr(" ", 8-strlen( scratch)); 225 wr(" ", 8 - strlen(scratch));
221 } 226 } else
222 else 227 writenum((long) info->st_gid, (short) 8);
223 writenum((long) info->st_gid,(short)8);
224 } else 228 } else
225#endif 229#endif
226 writenum((long) info->st_gid,(short)8); 230 writenum((long) info->st_gid, (short) 8);
227 //tab(26); 231 //tab(26);
228 if (S_ISBLK(mode) || S_ISCHR(mode)) { 232 if (S_ISBLK(mode) || S_ISCHR(mode)) {
229 writenum((long)MAJOR(info->st_rdev),(short)3); 233 writenum((long) MAJOR(info->st_rdev), (short) 3);
230 fputs(", ", stdout); 234 fputs(", ", stdout);
231 writenum((long)MINOR(info->st_rdev),(short)3); 235 writenum((long) MINOR(info->st_rdev), (short) 3);
232 } 236 } else
233 else 237 writenum((long) info->st_size, (short) 8);
234 writenum((long)info->st_size,(short)8);
235 fputs(" ", stdout); 238 fputs(" ", stdout);
236 //tab(32); 239 //tab(32);
237#ifdef BB_FEATURE_LS_TIMESTAMPS 240#ifdef BB_FEATURE_LS_TIMESTAMPS
238 { 241 {
239 time_t cal; 242 time_t cal;
240 char *string; 243 char *string;
241 244
242 switch(time_fmt) { 245 switch (time_fmt) {
243 case TIME_CHANGE: 246 case TIME_CHANGE:
244 cal=info->st_ctime; break; 247 cal = info->st_ctime;
248 break;
245 case TIME_ACCESS: 249 case TIME_ACCESS:
246 cal=info->st_atime; break; 250 cal = info->st_atime;
251 break;
247 default: 252 default:
248 cal=info->st_mtime; break; 253 cal = info->st_mtime;
254 break;
249 } 255 }
250 string=ctime(&cal); 256 string = ctime(&cal);
251 if (opts & DISP_FULLTIME) 257 if (opts & DISP_FULLTIME)
252 wr(string,24); 258 wr(string, 24);
253 else { 259 else {
254 time_t age = time(NULL) - cal; 260 time_t age = time(NULL) - cal;
255 wr(string+4,7); /* mmm_dd_ */ 261
256 if(age < 3600L*24*365/2 && age > -15*60) 262 wr(string + 4, 7); /* mmm_dd_ */
263 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60)
257 /* hh:mm if less than 6 months old */ 264 /* hh:mm if less than 6 months old */
258 wr(string+11,5); 265 wr(string + 11, 5);
259 else 266 else
260 /* _yyyy otherwise */ 267 /* _yyyy otherwise */
261 wr(string+19,5); 268 wr(string + 19, 5);
262 } 269 }
263 wr(" ", 1); 270 wr(" ", 1);
264 } 271 }
@@ -269,7 +276,8 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
269 if (S_ISLNK(mode)) { 276 if (S_ISLNK(mode)) {
270 wr(" -> ", 4); 277 wr(" -> ", 4);
271 len = readlink(fullname, scratch, sizeof scratch); 278 len = readlink(fullname, scratch, sizeof scratch);
272 if (len > 0) fwrite(scratch, 1, len, stdout); 279 if (len > 0)
280 fwrite(scratch, 1, len, stdout);
273#ifdef BB_FEATURE_LS_FILETYPES 281#ifdef BB_FEATURE_LS_FILETYPES
274 /* show type of destination */ 282 /* show type of destination */
275 if (opts & DISP_FTYPE) { 283 if (opts & DISP_FTYPE) {
@@ -287,18 +295,17 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
287#endif 295#endif
288 } else { 296 } else {
289 static short nexttab = 0; 297 static short nexttab = 0;
290 298
291 /* sort out column alignment */ 299 /* sort out column alignment */
292 if (column == 0) 300 if (column == 0); /* nothing to do */
293 ; /* nothing to do */
294 else if (display_fmt == FMT_SINGLE) 301 else if (display_fmt == FMT_SINGLE)
295 newline(); 302 newline();
296 else { 303 else {
297 if (nexttab + column_width > terminal_width 304 if (nexttab + column_width > terminal_width
298#ifndef BB_FEATURE_AUTOWIDTH 305#ifndef BB_FEATURE_AUTOWIDTH
299 || nexttab + len >= terminal_width 306 || nexttab + len >= terminal_width
300#endif 307#endif
301 ) 308 )
302 newline(); 309 newline();
303 else 310 else
304 tab(nexttab); 311 tab(nexttab);
@@ -336,32 +343,33 @@ static int list_item(const char *name)
336 struct stat info; 343 struct stat info;
337 DIR *dir; 344 DIR *dir;
338 struct dirent *entry; 345 struct dirent *entry;
339 char fullname[MAXNAMLEN+1], *fnend; 346 char fullname[MAXNAMLEN + 1], *fnend;
340 347
341 if (lstat(name, &info)) 348 if (lstat(name, &info))
342 goto listerr; 349 goto listerr;
343 350
344 if (!S_ISDIR(info.st_mode) || 351 if (!S_ISDIR(info.st_mode) || (opts & DIR_NOLIST)) {
345 (opts & DIR_NOLIST)) {
346 list_single(name, &info, name); 352 list_single(name, &info, name);
347 return 0; 353 return 0;
348 } 354 }
349 355
350 /* Otherwise, it's a directory we want to list the contents of */ 356 /* Otherwise, it's a directory we want to list the contents of */
351 357
352 if (opts & DISP_DIRNAME) { /* identify the directory */ 358 if (opts & DISP_DIRNAME) { /* identify the directory */
353 if (column) 359 if (column)
354 wr("\n\n", 2), column = 0; 360 wr("\n\n", 2), column = 0;
355 wr(name, strlen(name)); 361 wr(name, strlen(name));
356 wr(":\n", 2); 362 wr(":\n", 2);
357 } 363 }
358 364
359 dir = opendir(name); 365 dir = opendir(name);
360 if (!dir) goto listerr; 366 if (!dir)
367 goto listerr;
361#ifdef BB_FEATURE_AUTOWIDTH 368#ifdef BB_FEATURE_AUTOWIDTH
362 column_width = 0; 369 column_width = 0;
363 while ((entry = readdir(dir)) != NULL) { 370 while ((entry = readdir(dir)) != NULL) {
364 short w = strlen(entry->d_name); 371 short w = strlen(entry->d_name);
372
365 if (column_width < w) 373 if (column_width < w)
366 column_width = w; 374 column_width = w;
367 } 375 }
@@ -370,39 +378,40 @@ static int list_item(const char *name)
370#else 378#else
371 closedir(dir); 379 closedir(dir);
372 dir = opendir(name); 380 dir = opendir(name);
373 if (!dir) goto listerr; 381 if (!dir)
382 goto listerr;
374#endif 383#endif
375#endif 384#endif
376 385
377 /* List the contents */ 386 /* List the contents */
378 387
379 strcpy(fullname,name); /* *** ignore '.' by itself */ 388 strcpy(fullname, name); /* *** ignore '.' by itself */
380 fnend=fullname+strlen(fullname); 389 fnend = fullname + strlen(fullname);
381 if (fnend[-1] != '/') 390 if (fnend[-1] != '/')
382 *fnend++ = '/'; 391 *fnend++ = '/';
383 392
384 while ((entry = readdir(dir)) != NULL) { 393 while ((entry = readdir(dir)) != NULL) {
385 const char *en=entry->d_name; 394 const char *en = entry->d_name;
395
386 if (en[0] == '.') { 396 if (en[0] == '.') {
387 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */ 397 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */
388 if (!(opts & DISP_DOT)) 398 if (!(opts & DISP_DOT))
389 continue; 399 continue;
390 } 400 } else if (!(opts & DISP_HIDDEN))
391 else if (!(opts & DISP_HIDDEN))
392 continue; 401 continue;
393 } 402 }
394 /* FIXME: avoid stat if not required */ 403 /* FIXME: avoid stat if not required */
395 strcpy(fnend, entry->d_name); 404 strcpy(fnend, entry->d_name);
396 if (lstat(fullname, &info)) 405 if (lstat(fullname, &info))
397 goto direrr; /* (shouldn't fail) */ 406 goto direrr; /* (shouldn't fail) */
398 list_single(entry->d_name, &info, fullname); 407 list_single(entry->d_name, &info, fullname);
399 } 408 }
400 closedir(dir); 409 closedir(dir);
401 return 0; 410 return 0;
402 411
403direrr: 412 direrr:
404 closedir(dir); 413 closedir(dir);
405listerr: 414 listerr:
406 newline(); 415 newline();
407 perror(name); 416 perror(name);
408 return 1; 417 return 1;
@@ -432,50 +441,79 @@ static const char ls_usage[] = "ls [-1a"
432#endif 441#endif
433 "] [filenames...]\n"; 442 "] [filenames...]\n";
434 443
435extern int 444extern int ls_main(int argc, char **argv)
436ls_main(int argc, char * * argv)
437{ 445{
438 int argi=1, i; 446 int argi = 1, i;
439 447
440 /* process options */ 448 /* process options */
441 while (argi < argc && argv[argi][0] == '-') { 449 while (argi < argc && argv[argi][0] == '-') {
442 const char *p = &argv[argi][1]; 450 const char *p = &argv[argi][1];
443 451
444 if (!*p) goto print_usage_message; /* "-" by itself not allowed */ 452 if (!*p)
453 goto print_usage_message; /* "-" by itself not allowed */
445 if (*p == '-') { 454 if (*p == '-') {
446 if (!p[1]) { /* "--" forces end of options */ 455 if (!p[1]) { /* "--" forces end of options */
447 argi++; 456 argi++;
448 break; 457 break;
449 } 458 }
450 /* it's a long option name - we don't support them */ 459 /* it's a long option name - we don't support them */
451 goto print_usage_message; 460 goto print_usage_message;
452 } 461 }
453 462
454 while (*p) 463 while (*p)
455 switch (*p++) { 464 switch (*p++) {
456 case 'l': display_fmt = FMT_LONG; break; 465 case 'l':
457 case '1': display_fmt = FMT_SINGLE; break; 466 display_fmt = FMT_LONG;
458 case 'x': display_fmt = FMT_ROWS; break; 467 break;
459 case 'C': display_fmt = FMT_COLUMNS; break; 468 case '1':
469 display_fmt = FMT_SINGLE;
470 break;
471 case 'x':
472 display_fmt = FMT_ROWS;
473 break;
474 case 'C':
475 display_fmt = FMT_COLUMNS;
476 break;
460#ifdef BB_FEATURE_LS_FILETYPES 477#ifdef BB_FEATURE_LS_FILETYPES
461 case 'p': opts |= DISP_FTYPE; break; 478 case 'p':
462 case 'F': opts |= DISP_FTYPE|DISP_EXEC; break; 479 opts |= DISP_FTYPE;
480 break;
481 case 'F':
482 opts |= DISP_FTYPE | DISP_EXEC;
483 break;
463#endif 484#endif
464 case 'A': opts |= DISP_HIDDEN; break; 485 case 'A':
465 case 'a': opts |= DISP_HIDDEN|DISP_DOT; break; 486 opts |= DISP_HIDDEN;
466 case 'n': opts |= DISP_NUMERIC; break; 487 break;
467 case 'd': opts |= DIR_NOLIST; break; 488 case 'a':
489 opts |= DISP_HIDDEN | DISP_DOT;
490 break;
491 case 'n':
492 opts |= DISP_NUMERIC;
493 break;
494 case 'd':
495 opts |= DIR_NOLIST;
496 break;
468#ifdef FEATURE_RECURSIVE 497#ifdef FEATURE_RECURSIVE
469 case 'R': opts |= DIR_RECURSE; break; 498 case 'R':
499 opts |= DIR_RECURSE;
500 break;
470#endif 501#endif
471#ifdef BB_FEATURE_LS_TIMESTAMPS 502#ifdef BB_FEATURE_LS_TIMESTAMPS
472 case 'u': time_fmt = TIME_ACCESS; break; 503 case 'u':
473 case 'c': time_fmt = TIME_CHANGE; break; 504 time_fmt = TIME_ACCESS;
474 case 'e': opts |= DISP_FULLTIME; break; 505 break;
506 case 'c':
507 time_fmt = TIME_CHANGE;
508 break;
509 case 'e':
510 opts |= DISP_FULLTIME;
511 break;
475#endif 512#endif
476 default: goto print_usage_message; 513 default:
514 goto print_usage_message;
477 } 515 }
478 516
479 argi++; 517 argi++;
480 } 518 }
481 519
@@ -483,29 +521,30 @@ ls_main(int argc, char * * argv)
483 if (display_fmt == FMT_AUTO) 521 if (display_fmt == FMT_AUTO)
484 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE; 522 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE;
485 if (argi < argc - 1) 523 if (argi < argc - 1)
486 opts |= DISP_DIRNAME; /* 2 or more items? label directories */ 524 opts |= DISP_DIRNAME; /* 2 or more items? label directories */
487#ifdef BB_FEATURE_AUTOWIDTH 525#ifdef BB_FEATURE_AUTOWIDTH
488 /* could add a -w option and/or TIOCGWINSZ call */ 526 /* could add a -w option and/or TIOCGWINSZ call */
489 if (terminal_width < 1) terminal_width = TERMINAL_WIDTH; 527 if (terminal_width < 1)
490 528 terminal_width = TERMINAL_WIDTH;
529
491 for (i = argi; i < argc; i++) { 530 for (i = argi; i < argc; i++) {
492 int len = strlen(argv[i]); 531 int len = strlen(argv[i]);
532
493 if (column_width < len) 533 if (column_width < len)
494 column_width = len; 534 column_width = len;
495 } 535 }
496#endif 536#endif
497 537
498 /* process files specified, or current directory if none */ 538 /* process files specified, or current directory if none */
499 i=0; 539 i = 0;
500 if (argi == argc) 540 if (argi == argc)
501 i = list_item("."); 541 i = list_item(".");
502 while (argi < argc) 542 while (argi < argc)
503 i |= list_item(argv[argi++]); 543 i |= list_item(argv[argi++]);
504 newline(); 544 newline();
505 exit( i); 545 exit(i);
506 546
507print_usage_message: 547 print_usage_message:
508 usage (ls_usage); 548 usage(ls_usage);
509 exit( FALSE); 549 exit(FALSE);
510} 550}
511
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 8e3f51bfb..70fdbdfb5 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkdir implementation for busybox 3 * Mini mkdir implementation for busybox
3 * 4 *
@@ -28,14 +29,15 @@
28 29
29#include <stdio.h> 30#include <stdio.h>
30#include <errno.h> 31#include <errno.h>
31#include <sys/param.h> /* for PATH_MAX */ 32#include <sys/param.h> /* for PATH_MAX */
32 33
33static const char mkdir_usage[] = 34static const char mkdir_usage[] =
34"mkdir [OPTION] DIRECTORY...\n\n" 35 "mkdir [OPTION] DIRECTORY...\n\n"
35"Create the DIRECTORY(ies), if they do not already exist\n\n" 36 "Create the DIRECTORY(ies), if they do not already exist\n\n"
36"Options:\n" 37 "Options:\n"
37"\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" 38
38"\t-p\tno error if existing, make parent directories as needed\n"; 39 "\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n"
40 "\t-p\tno error if existing, make parent directories as needed\n";
39 41
40 42
41static int parentFlag = FALSE; 43static int parentFlag = FALSE;
@@ -44,71 +46,70 @@ static mode_t mode = 0777;
44 46
45extern int mkdir_main(int argc, char **argv) 47extern int mkdir_main(int argc, char **argv)
46{ 48{
47 int i = FALSE; 49 int i = FALSE;
48 argc--;
49 argv++;
50 50
51 /* Parse any options */
52 while (argc > 0 && **argv == '-') {
53 while (i == FALSE && *++(*argv)) {
54 switch (**argv) {
55 case 'm':
56 if (--argc == 0)
57 usage( mkdir_usage);
58 /* Find the specified modes */
59 mode = 0;
60 if (parse_mode(*(++argv), &mode) == FALSE ) {
61 fprintf(stderr, "Unknown mode: %s\n", *argv);
62 exit FALSE;
63 }
64 /* Set the umask for this process so it doesn't
65 * screw up whatever the user just entered. */
66 umask(0);
67 i = TRUE;
68 break;
69 case 'p':
70 parentFlag = TRUE;
71 break;
72 default:
73 usage( mkdir_usage);
74 }
75 }
76 argc--; 51 argc--;
77 argv++; 52 argv++;
78 }
79
80 if (argc < 1) {
81 usage( mkdir_usage);
82 }
83 53
84 while (argc > 0) { 54 /* Parse any options */
85 int status; 55 while (argc > 0 && **argv == '-') {
86 struct stat statBuf; 56 while (i == FALSE && *++(*argv)) {
87 char buf[PATH_MAX + 1]; 57 switch (**argv) {
88 if (strlen(*argv) > PATH_MAX - 1) { 58 case 'm':
89 fprintf(stderr, name_too_long, "mkdir"); 59 if (--argc == 0)
90 exit FALSE; 60 usage(mkdir_usage);
91 } 61 /* Find the specified modes */
92 strcpy (buf, *argv); 62 mode = 0;
93 status = stat(buf, &statBuf); 63 if (parse_mode(*(++argv), &mode) == FALSE) {
94 if (parentFlag == FALSE && status != -1 && errno != ENOENT) { 64 fprintf(stderr, "Unknown mode: %s\n", *argv);
95 fprintf(stderr, "%s: File exists\n", buf); 65 exit FALSE;
96 exit FALSE; 66 }
97 } 67 /* Set the umask for this process so it doesn't
98 if (parentFlag == TRUE) { 68 * screw up whatever the user just entered. */
99 strcat( buf, "/"); 69 umask(0);
100 createPath(buf, mode); 70 i = TRUE;
71 break;
72 case 'p':
73 parentFlag = TRUE;
74 break;
75 default:
76 usage(mkdir_usage);
77 }
78 }
79 argc--;
80 argv++;
101 } 81 }
102 else { 82
103 if (mkdir (buf, mode) != 0 && parentFlag == FALSE) { 83 if (argc < 1) {
104 perror(buf); 84 usage(mkdir_usage);
105 exit FALSE;
106 }
107 } 85 }
108 argc--;
109 argv++;
110 }
111 exit TRUE;
112}
113 86
87 while (argc > 0) {
88 int status;
89 struct stat statBuf;
90 char buf[PATH_MAX + 1];
114 91
92 if (strlen(*argv) > PATH_MAX - 1) {
93 fprintf(stderr, name_too_long, "mkdir");
94 exit FALSE;
95 }
96 strcpy(buf, *argv);
97 status = stat(buf, &statBuf);
98 if (parentFlag == FALSE && status != -1 && errno != ENOENT) {
99 fprintf(stderr, "%s: File exists\n", buf);
100 exit FALSE;
101 }
102 if (parentFlag == TRUE) {
103 strcat(buf, "/");
104 createPath(buf, mode);
105 } else {
106 if (mkdir(buf, mode) != 0 && parentFlag == FALSE) {
107 perror(buf);
108 exit FALSE;
109 }
110 }
111 argc--;
112 argv++;
113 }
114 exit TRUE;
115}
diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c
index 676592ac7..c74402d4c 100644
--- a/coreutils/mkfifo.c
+++ b/coreutils/mkfifo.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkfifo implementation for busybox 3 * Mini mkfifo implementation for busybox
3 * 4 *
@@ -26,36 +27,43 @@
26#include <errno.h> 27#include <errno.h>
27 28
28static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n" 29static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n"
29"Create the named fifo\n\n" 30 "Create the named fifo\n\n"
30"Options:\n" 31
31"\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n"; 32 "Options:\n"
33 "\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n";
32 34
33extern int mkfifo_main(int argc, char **argv) 35extern int mkfifo_main(int argc, char **argv)
34{ 36{
35 char *thisarg; 37 char *thisarg;
36 mode_t mode = 0666; 38 mode_t mode = 0666;
37 argc--; 39
38 argv++; 40 argc--;
41 argv++;
39 42
40 /* Parse any options */ 43 /* Parse any options */
41 while (argc > 1) { 44 while (argc > 1) {
42 if (**argv != '-') usage(mkfifo_usage); 45 if (**argv != '-')
43 thisarg = *argv; thisarg++; 46 usage(mkfifo_usage);
44 switch (*thisarg) { 47 thisarg = *argv;
45 case 'm': 48 thisarg++;
46 argc--; argv++; 49 switch (*thisarg) {
47 parse_mode(*argv, &mode); 50 case 'm':
48 break; 51 argc--;
49 default: 52 argv++;
50 usage (mkfifo_usage); 53 parse_mode(*argv, &mode);
51 } 54 break;
52 argc--; argv++; 55 default:
53 } 56 usage(mkfifo_usage);
54 if (argc < 1) usage (mkfifo_usage); 57 }
55 if (mkfifo(*argv, mode) < 0) { 58 argc--;
56 perror("mkfifo"); 59 argv++;
57 exit(255); 60 }
58 } else { 61 if (argc < 1)
59 exit(TRUE); 62 usage(mkfifo_usage);
60 } 63 if (mkfifo(*argv, mode) < 0) {
64 perror("mkfifo");
65 exit(255);
66 } else {
67 exit(TRUE);
68 }
61} 69}
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
index 5822cd3ad..b11a81f2a 100644
--- a/coreutils/mknod.c
+++ b/coreutils/mknod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mknod implementation for busybox 3 * Mini mknod implementation for busybox
3 * 4 *
@@ -28,22 +29,22 @@
28#include <unistd.h> 29#include <unistd.h>
29 30
30static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n" 31static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n"
31"Make block or character special files.\n\n" 32 "Make block or character special files.\n\n"
32"TYPEs include:\n" 33 "TYPEs include:\n"
33"\tb:\tMake a block (buffered) device.\n" 34 "\tb:\tMake a block (buffered) device.\n"
34"\tc or u:\tMake a character (un-buffered) device.\n"
35"\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
36 35
37int 36 "\tc or u:\tMake a character (un-buffered) device.\n"
38mknod_main(int argc, char** argv) 37 "\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
38
39int mknod_main(int argc, char **argv)
39{ 40{
40 mode_t mode = 0; 41 mode_t mode = 0;
41 dev_t dev = 0; 42 dev_t dev = 0;
42 43
43 if ( argc != 5 || **(argv+1) == '-' ) { 44 if (argc != 5 || **(argv + 1) == '-') {
44 usage (mknod_usage); 45 usage(mknod_usage);
45 } 46 }
46 switch(argv[2][0]) { 47 switch (argv[2][0]) {
47 case 'c': 48 case 'c':
48 case 'u': 49 case 'u':
49 mode = S_IFCHR; 50 mode = S_IFCHR;
@@ -55,21 +56,21 @@ mknod_main(int argc, char** argv)
55 mode = S_IFIFO; 56 mode = S_IFIFO;
56 break; 57 break;
57 default: 58 default:
58 usage (mknod_usage); 59 usage(mknod_usage);
59 } 60 }
60 61
61 if ( mode == S_IFCHR || mode == S_IFBLK ) { 62 if (mode == S_IFCHR || mode == S_IFBLK) {
62 dev = (atoi(argv[3]) << 8) | atoi(argv[4]); 63 dev = (atoi(argv[3]) << 8) | atoi(argv[4]);
63 if ( argc != 5 ) { 64 if (argc != 5) {
64 usage (mknod_usage); 65 usage(mknod_usage);
65 } 66 }
66 } 67 }
67 68
68 mode |= 0666; 69 mode |= 0666;
69 70
70 if ( mknod(argv[1], mode, dev) != 0 ) { 71 if (mknod(argv[1], mode, dev) != 0) {
71 perror(argv[1]); 72 perror(argv[1]);
72 return( FALSE); 73 return (FALSE);
73 } 74 }
74 return( TRUE); 75 return (TRUE);
75} 76}
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 5fd5ea303..41ab2e442 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* printf - format and print data 2/* printf - format and print data
2 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. 3 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3 4
@@ -42,7 +43,7 @@
42 to convert all of the given arguments. 43 to convert all of the given arguments.
43 44
44 David MacKenzie <djm@gnu.ai.mit.edu> */ 45 David MacKenzie <djm@gnu.ai.mit.edu> */
45 46
46 47
47// 19990508 Busy Boxed! Dave Cinege 48// 19990508 Busy Boxed! Dave Cinege
48 49
@@ -84,11 +85,11 @@
84#if !defined(S_ISSOCK) && defined(S_IFSOCK) 85#if !defined(S_ISSOCK) && defined(S_IFSOCK)
85# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 86# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
86#endif 87#endif
87#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ 88#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
88# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) 89# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
89# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) 90# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
90#endif 91#endif
91#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ 92#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
92# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) 93# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
93#endif 94#endif
94 95
@@ -121,407 +122,358 @@
121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') 122#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
122#define octtobin(c) ((c) - '0') 123#define octtobin(c) ((c) - '0')
123 124
124static double xstrtod __P ((char *s)); 125static double xstrtod __P((char *s));
125static int print_esc __P ((char *escstart)); 126static int print_esc __P((char *escstart));
126static int print_formatted __P ((char *format, int argc, char **argv)); 127static int print_formatted __P((char *format, int argc, char **argv));
127static long xstrtol __P ((char *s)); 128static long xstrtol __P((char *s));
128static unsigned long xstrtoul __P ((char *s)); 129static unsigned long xstrtoul __P((char *s));
129static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument)); 130static void print_direc
130static void print_esc_char __P ((int c)); 131__P(
131static void print_esc_string __P ((char *str)); 132
132static void verify __P ((char *s, char *end)); 133 (char *start, size_t length, int field_width, int precision,
134 char *argument));
135static void print_esc_char __P((int c));
136static void print_esc_string __P((char *str));
137static void verify __P((char *s, char *end));
133 138
134/* The value to return to the calling program. */ 139/* The value to return to the calling program. */
135static int exit_status; 140static int exit_status;
136 141
137static const char printf_usage[] = "printf format [argument...]\n"; 142static const char printf_usage[] = "printf format [argument...]\n";
138 143
139int 144int printf_main(int argc, char **argv)
140printf_main(int argc, char** argv)
141{ 145{
142 char *format; 146 char *format;
143 int args_used; 147 int args_used;
144 148
145 exit_status = 0; 149 exit_status = 0;
146 if ( argc <= 1 || **(argv+1) == '-' ) { 150 if (argc <= 1 || **(argv + 1) == '-') {
147 usage (printf_usage); 151 usage(printf_usage);
148 } 152 }
149 153
150 format = argv[1]; 154 format = argv[1];
151 argc -= 2; 155 argc -= 2;
152 argv += 2; 156 argv += 2;
153 157
154 do 158 do {
155 { 159 args_used = print_formatted(format, argc, argv);
156 args_used = print_formatted (format, argc, argv); 160 argc -= args_used;
157 argc -= args_used; 161 argv += args_used;
158 argv += args_used; 162 }
159 } 163 while (args_used > 0 && argc > 0);
160 while (args_used > 0 && argc > 0);
161 164
162/* 165/*
163 if (argc > 0) 166 if (argc > 0)
164 fprintf(stderr, "excess args ignored"); 167 fprintf(stderr, "excess args ignored");
165*/ 168*/
166 169
167 exit (exit_status); 170 exit(exit_status);
168} 171}
169 172
170/* Print the text in FORMAT, using ARGV (with ARGC elements) for 173/* Print the text in FORMAT, using ARGV (with ARGC elements) for
171 arguments to any `%' directives. 174 arguments to any `%' directives.
172 Return the number of elements of ARGV used. */ 175 Return the number of elements of ARGV used. */
173 176
174static int 177static int print_formatted(char *format, int argc, char **argv)
175print_formatted (char *format, int argc, char **argv)
176{ 178{
177 int save_argc = argc; /* Preserve original value. */ 179 int save_argc = argc; /* Preserve original value. */
178 char *f; /* Pointer into `format'. */ 180 char *f; /* Pointer into `format'. */
179 char *direc_start; /* Start of % directive. */ 181 char *direc_start; /* Start of % directive. */
180 size_t direc_length; /* Length of % directive. */ 182 size_t direc_length; /* Length of % directive. */
181 int field_width; /* Arg to first '*', or -1 if none. */ 183 int field_width; /* Arg to first '*', or -1 if none. */
182 int precision; /* Arg to second '*', or -1 if none. */ 184 int precision; /* Arg to second '*', or -1 if none. */
183 185
184 for (f = format; *f; ++f) 186 for (f = format; *f; ++f) {
185 { 187 switch (*f) {
186 switch (*f) 188 case '%':
187 { 189 direc_start = f++;
188 case '%': 190 direc_length = 1;
189 direc_start = f++; 191 field_width = precision = -1;
190 direc_length = 1; 192 if (*f == '%') {
191 field_width = precision = -1; 193 putchar('%');
192 if (*f == '%') 194 break;
193 { 195 }
194 putchar ('%'); 196 if (*f == 'b') {
195 break; 197 if (argc > 0) {
196 } 198 print_esc_string(*argv);
197 if (*f == 'b') 199 ++argv;
198 { 200 --argc;
199 if (argc > 0) 201 }
200 { 202 break;
201 print_esc_string (*argv); 203 }
202 ++argv; 204 if (strchr("-+ #", *f)) {
203 --argc; 205 ++f;
204 } 206 ++direc_length;
205 break; 207 }
206 } 208 if (*f == '*') {
207 if (strchr ("-+ #", *f)) 209 ++f;
208 { 210 ++direc_length;
209 ++f; 211 if (argc > 0) {
210 ++direc_length; 212 field_width = xstrtoul(*argv);
211 } 213 ++argv;
212 if (*f == '*') 214 --argc;
213 { 215 } else
214 ++f; 216 field_width = 0;
215 ++direc_length; 217 } else
216 if (argc > 0) 218 while (ISDIGIT(*f)) {
217 { 219 ++f;
218 field_width = xstrtoul (*argv); 220 ++direc_length;
219 ++argv; 221 }
220 --argc; 222 if (*f == '.') {
223 ++f;
224 ++direc_length;
225 if (*f == '*') {
226 ++f;
227 ++direc_length;
228 if (argc > 0) {
229 precision = xstrtoul(*argv);
230 ++argv;
231 --argc;
232 } else
233 precision = 0;
234 } else
235 while (ISDIGIT(*f)) {
236 ++f;
237 ++direc_length;
238 }
239 }
240 if (*f == 'l' || *f == 'L' || *f == 'h') {
241 ++f;
242 ++direc_length;
243 }
244 /*
245 if (!strchr ("diouxXfeEgGcs", *f))
246 fprintf(stderr, "%%%c: invalid directive", *f);
247 */
248 ++direc_length;
249 if (argc > 0) {
250 print_direc(direc_start, direc_length, field_width,
251 precision, *argv);
252 ++argv;
253 --argc;
254 } else
255 print_direc(direc_start, direc_length, field_width,
256 precision, "");
257 break;
258
259 case '\\':
260 f += print_esc(f);
261 break;
262
263 default:
264 putchar(*f);
221 } 265 }
222 else
223 field_width = 0;
224 }
225 else
226 while (ISDIGIT (*f))
227 {
228 ++f;
229 ++direc_length;
230 }
231 if (*f == '.')
232 {
233 ++f;
234 ++direc_length;
235 if (*f == '*')
236 {
237 ++f;
238 ++direc_length;
239 if (argc > 0)
240 {
241 precision = xstrtoul (*argv);
242 ++argv;
243 --argc;
244 }
245 else
246 precision = 0;
247 }
248 else
249 while (ISDIGIT (*f))
250 {
251 ++f;
252 ++direc_length;
253 }
254 }
255 if (*f == 'l' || *f == 'L' || *f == 'h')
256 {
257 ++f;
258 ++direc_length;
259 }
260 /*
261 if (!strchr ("diouxXfeEgGcs", *f))
262 fprintf(stderr, "%%%c: invalid directive", *f);
263 */
264 ++direc_length;
265 if (argc > 0)
266 {
267 print_direc (direc_start, direc_length, field_width,
268 precision, *argv);
269 ++argv;
270 --argc;
271 }
272 else
273 print_direc (direc_start, direc_length, field_width,
274 precision, "");
275 break;
276
277 case '\\':
278 f += print_esc (f);
279 break;
280
281 default:
282 putchar (*f);
283 } 266 }
284 }
285 267
286 return save_argc - argc; 268 return save_argc - argc;
287} 269}
288 270
289/* Print a \ escape sequence starting at ESCSTART. 271/* Print a \ escape sequence starting at ESCSTART.
290 Return the number of characters in the escape sequence 272 Return the number of characters in the escape sequence
291 besides the backslash. */ 273 besides the backslash. */
292 274
293static int 275static int print_esc(char *escstart)
294print_esc (char *escstart)
295{ 276{
296 register char *p = escstart + 1; 277 register char *p = escstart + 1;
297 int esc_value = 0; /* Value of \nnn escape. */ 278 int esc_value = 0; /* Value of \nnn escape. */
298 int esc_length; /* Length of \nnn escape. */ 279 int esc_length; /* Length of \nnn escape. */
299 280
300 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */ 281 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
301 if (*p == 'x') 282 if (*p == 'x') {
302 { 283 for (esc_length = 0, ++p;
303 for (esc_length = 0, ++p; 284 esc_length < 3 && ISXDIGIT(*p); ++esc_length, ++p)
304 esc_length < 3 && ISXDIGIT (*p); 285 esc_value = esc_value * 16 + hextobin(*p);
305 ++esc_length, ++p)
306 esc_value = esc_value * 16 + hextobin (*p);
307/* if (esc_length == 0) 286/* if (esc_length == 0)
308 fprintf(stderr, "missing hex in esc"); 287 fprintf(stderr, "missing hex in esc");
309*/ 288*/
310 putchar (esc_value); 289 putchar(esc_value);
311 } 290 } else if (*p == '0') {
312 else if (*p == '0') 291 for (esc_length = 0, ++p;
313 { 292 esc_length < 3 && isodigit(*p); ++esc_length, ++p)
314 for (esc_length = 0, ++p; 293 esc_value = esc_value * 8 + octtobin(*p);
315 esc_length < 3 && isodigit (*p); 294 putchar(esc_value);
316 ++esc_length, ++p) 295 } else if (strchr("\"\\abcfnrtv", *p))
317 esc_value = esc_value * 8 + octtobin (*p); 296 print_esc_char(*p++);
318 putchar (esc_value);
319 }
320 else if (strchr ("\"\\abcfnrtv", *p))
321 print_esc_char (*p++);
322/* else 297/* else
323 fprintf(stderr, "\\%c: invalid esc", *p); 298 fprintf(stderr, "\\%c: invalid esc", *p);
324*/ 299*/
325 return p - escstart - 1; 300 return p - escstart - 1;
326} 301}
327 302
328/* Output a single-character \ escape. */ 303/* Output a single-character \ escape. */
329 304
330static void 305static void print_esc_char(int c)
331print_esc_char (int c)
332{ 306{
333 switch (c) 307 switch (c) {
334 { 308 case 'a': /* Alert. */
335 case 'a': /* Alert. */ 309 putchar(7);
336 putchar (7); 310 break;
337 break; 311 case 'b': /* Backspace. */
338 case 'b': /* Backspace. */ 312 putchar(8);
339 putchar (8); 313 break;
340 break; 314 case 'c': /* Cancel the rest of the output. */
341 case 'c': /* Cancel the rest of the output. */ 315 exit(0);
342 exit (0); 316 break;
343 break; 317 case 'f': /* Form feed. */
344 case 'f': /* Form feed. */ 318 putchar(12);
345 putchar (12); 319 break;
346 break; 320 case 'n': /* New line. */
347 case 'n': /* New line. */ 321 putchar(10);
348 putchar (10); 322 break;
349 break; 323 case 'r': /* Carriage return. */
350 case 'r': /* Carriage return. */ 324 putchar(13);
351 putchar (13); 325 break;
352 break; 326 case 't': /* Horizontal tab. */
353 case 't': /* Horizontal tab. */ 327 putchar(9);
354 putchar (9); 328 break;
355 break; 329 case 'v': /* Vertical tab. */
356 case 'v': /* Vertical tab. */ 330 putchar(11);
357 putchar (11); 331 break;
358 break; 332 default:
359 default: 333 putchar(c);
360 putchar (c); 334 break;
361 break; 335 }
362 }
363} 336}
364 337
365/* Print string STR, evaluating \ escapes. */ 338/* Print string STR, evaluating \ escapes. */
366 339
367static void 340static void print_esc_string(char *str)
368print_esc_string (char *str)
369{ 341{
370 for (; *str; str++) 342 for (; *str; str++)
371 if (*str == '\\') 343 if (*str == '\\')
372 str += print_esc (str); 344 str += print_esc(str);
373 else 345 else
374 putchar (*str); 346 putchar(*str);
375} 347}
376 348
377static void 349static void
378print_direc (char *start, size_t length, int field_width, int precision, char *argument) 350print_direc(char *start, size_t length, int field_width, int precision,
351 char *argument)
379{ 352{
380 char *p; /* Null-terminated copy of % directive. */ 353 char *p; /* Null-terminated copy of % directive. */
381 354
382 p = xmalloc ((unsigned) (length + 1)); 355 p = xmalloc((unsigned) (length + 1));
383 strncpy (p, start, length); 356 strncpy(p, start, length);
384 p[length] = 0; 357 p[length] = 0;
385 358
386 switch (p[length - 1]) 359 switch (p[length - 1]) {
387 { 360 case 'd':
388 case 'd': 361 case 'i':
389 case 'i': 362 if (field_width < 0) {
390 if (field_width < 0) 363 if (precision < 0)
391 { 364 printf(p, xstrtol(argument));
392 if (precision < 0) 365 else
393 printf (p, xstrtol (argument)); 366 printf(p, precision, xstrtol(argument));
394 else 367 } else {
395 printf (p, precision, xstrtol (argument)); 368 if (precision < 0)
396 } 369 printf(p, field_width, xstrtol(argument));
397 else 370 else
398 { 371 printf(p, field_width, precision, xstrtol(argument));
399 if (precision < 0) 372 }
400 printf (p, field_width, xstrtol (argument)); 373 break;
401 else 374
402 printf (p, field_width, precision, xstrtol (argument)); 375 case 'o':
403 } 376 case 'u':
404 break; 377 case 'x':
405 378 case 'X':
406 case 'o': 379 if (field_width < 0) {
407 case 'u': 380 if (precision < 0)
408 case 'x': 381 printf(p, xstrtoul(argument));
409 case 'X': 382 else
410 if (field_width < 0) 383 printf(p, precision, xstrtoul(argument));
411 { 384 } else {
412 if (precision < 0) 385 if (precision < 0)
413 printf (p, xstrtoul (argument)); 386 printf(p, field_width, xstrtoul(argument));
414 else 387 else
415 printf (p, precision, xstrtoul (argument)); 388 printf(p, field_width, precision, xstrtoul(argument));
416 } 389 }
417 else 390 break;
418 { 391
419 if (precision < 0) 392 case 'f':
420 printf (p, field_width, xstrtoul (argument)); 393 case 'e':
421 else 394 case 'E':
422 printf (p, field_width, precision, xstrtoul (argument)); 395 case 'g':
423 } 396 case 'G':
424 break; 397 if (field_width < 0) {
425 398 if (precision < 0)
426 case 'f': 399 printf(p, xstrtod(argument));
427 case 'e': 400 else
428 case 'E': 401 printf(p, precision, xstrtod(argument));
429 case 'g': 402 } else {
430 case 'G': 403 if (precision < 0)
431 if (field_width < 0) 404 printf(p, field_width, xstrtod(argument));
432 { 405 else
433 if (precision < 0) 406 printf(p, field_width, precision, xstrtod(argument));
434 printf (p, xstrtod (argument)); 407 }
435 else 408 break;
436 printf (p, precision, xstrtod (argument)); 409
437 } 410 case 'c':
438 else 411 printf(p, *argument);
439 { 412 break;
440 if (precision < 0) 413
441 printf (p, field_width, xstrtod (argument)); 414 case 's':
442 else 415 if (field_width < 0) {
443 printf (p, field_width, precision, xstrtod (argument)); 416 if (precision < 0)
444 } 417 printf(p, argument);
445 break; 418 else
446 419 printf(p, precision, argument);
447 case 'c': 420 } else {
448 printf (p, *argument); 421 if (precision < 0)
449 break; 422 printf(p, field_width, argument);
450 423 else
451 case 's': 424 printf(p, field_width, precision, argument);
452 if (field_width < 0) 425 }
453 { 426 break;
454 if (precision < 0)
455 printf (p, argument);
456 else
457 printf (p, precision, argument);
458 }
459 else
460 {
461 if (precision < 0)
462 printf (p, field_width, argument);
463 else
464 printf (p, field_width, precision, argument);
465 } 427 }
466 break;
467 }
468 428
469 free (p); 429 free(p);
470} 430}
471 431
472static unsigned long 432static unsigned long xstrtoul(char *s)
473xstrtoul (char *s)
474{ 433{
475 char *end; 434 char *end;
476 unsigned long val; 435 unsigned long val;
477 436
478 errno = 0; 437 errno = 0;
479 val = strtoul (s, &end, 0); 438 val = strtoul(s, &end, 0);
480 verify (s, end); 439 verify(s, end);
481 return val; 440 return val;
482} 441}
483 442
484static long 443static long xstrtol(char *s)
485xstrtol (char *s)
486{ 444{
487 char *end; 445 char *end;
488 long val; 446 long val;
489 447
490 errno = 0; 448 errno = 0;
491 val = strtol (s, &end, 0); 449 val = strtol(s, &end, 0);
492 verify (s, end); 450 verify(s, end);
493 return val; 451 return val;
494} 452}
495 453
496static double 454static double xstrtod(char *s)
497xstrtod (char *s)
498{ 455{
499 char *end; 456 char *end;
500 double val; 457 double val;
501 458
502 errno = 0; 459 errno = 0;
503 val = strtod (s, &end); 460 val = strtod(s, &end);
504 verify (s, end); 461 verify(s, end);
505 return val; 462 return val;
506} 463}
507 464
508static void 465static void verify(char *s, char *end)
509verify (char *s, char *end)
510{ 466{
511 if (errno) 467 if (errno) {
512 { 468 fprintf(stderr, "%s", s);
513 fprintf(stderr, "%s", s); 469 exit_status = 1;
514 exit_status = 1; 470 } else if (*end) {
515 } 471 /*
516 else if (*end) 472 if (s == end)
517 { 473 fprintf(stderr, "%s: expected numeric", s);
518 /* 474 else
519 if (s == end) 475 fprintf(stderr, "%s: not completely converted", s);
520 fprintf(stderr, "%s: expected numeric", s); 476 */
521 else 477 exit_status = 1;
522 fprintf(stderr, "%s: not completely converted", s); 478 }
523 */
524 exit_status = 1;
525 }
526} 479}
527
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
index bacabd77a..00163178b 100644
--- a/coreutils/pwd.c
+++ b/coreutils/pwd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini pwd implementation for busybox 3 * Mini pwd implementation for busybox
3 * 4 *
@@ -25,16 +26,15 @@
25#include <dirent.h> 26#include <dirent.h>
26#include <sys/param.h> 27#include <sys/param.h>
27 28
28extern int 29extern int pwd_main(int argc, char **argv)
29pwd_main(int argc, char * * argv)
30{ 30{
31 char buf[PATH_MAX + 1]; 31 char buf[PATH_MAX + 1];
32 32
33 if ( getcwd(buf, sizeof(buf)) == NULL ) { 33 if (getcwd(buf, sizeof(buf)) == NULL) {
34 perror("get working directory"); 34 perror("get working directory");
35 exit( FALSE); 35 exit(FALSE);
36 } 36 }
37 37
38 printf("%s\n", buf); 38 printf("%s\n", buf);
39 exit( TRUE); 39 exit(TRUE);
40} 40}
diff --git a/coreutils/rm.c b/coreutils/rm.c
index ee434fb39..41afedaf9 100644
--- a/coreutils/rm.c
+++ b/coreutils/rm.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rm implementation for busybox 3 * Mini rm implementation for busybox
3 * 4 *
@@ -28,11 +29,12 @@
28#include <dirent.h> 29#include <dirent.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char* rm_usage = "rm [OPTION]... FILE...\n\n" 32static const char *rm_usage = "rm [OPTION]... FILE...\n\n"
32"Remove (unlink) the FILE(s).\n\n" 33 "Remove (unlink) the FILE(s).\n\n"
33"Options:\n" 34 "Options:\n"
34"\t-f\t\tremove existing destinations, never prompt\n" 35
35"\t-r or -R\tremove the contents of directories recursively\n"; 36 "\t-f\t\tremove existing destinations, never prompt\n"
37 "\t-r or -R\tremove the contents of directories recursively\n";
36 38
37 39
38static int recursiveFlag = FALSE; 40static int recursiveFlag = FALSE;
@@ -40,63 +42,63 @@ static int forceFlag = FALSE;
40static const char *srcName; 42static const char *srcName;
41 43
42 44
43static int fileAction(const char *fileName, struct stat* statbuf) 45static int fileAction(const char *fileName, struct stat *statbuf)
44{ 46{
45 if (unlink( fileName) < 0 ) { 47 if (unlink(fileName) < 0) {
46 perror( fileName); 48 perror(fileName);
47 return ( FALSE); 49 return (FALSE);
48 } 50 }
49 return ( TRUE); 51 return (TRUE);
50} 52}
51 53
52static int dirAction(const char *fileName, struct stat* statbuf) 54static int dirAction(const char *fileName, struct stat *statbuf)
53{ 55{
54 if (rmdir( fileName) < 0 ) { 56 if (rmdir(fileName) < 0) {
55 perror( fileName); 57 perror(fileName);
56 return ( FALSE); 58 return (FALSE);
57 } 59 }
58 return ( TRUE); 60 return (TRUE);
59} 61}
60 62
61extern int rm_main(int argc, char **argv) 63extern int rm_main(int argc, char **argv)
62{ 64{
63 struct stat statbuf; 65 struct stat statbuf;
64 66
65 if (argc < 2) { 67 if (argc < 2) {
66 usage( rm_usage); 68 usage(rm_usage);
67 } 69 }
68 argc--;
69 argv++;
70
71 /* Parse any options */
72 while (**argv == '-') {
73 while (*++(*argv))
74 switch (**argv) {
75 case 'R':
76 case 'r':
77 recursiveFlag = TRUE;
78 break;
79 case 'f':
80 forceFlag = TRUE;
81 break;
82 default:
83 usage( rm_usage);
84 }
85 argc--; 70 argc--;
86 argv++; 71 argv++;
87 }
88 72
89 while (argc-- > 0) { 73 /* Parse any options */
90 srcName = *(argv++); 74 while (**argv == '-') {
91 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0 && errno == ENOENT) { 75 while (*++(*argv))
92 /* do not reports errors for non-existent files if -f, just skip them */ 76 switch (**argv) {
77 case 'R':
78 case 'r':
79 recursiveFlag = TRUE;
80 break;
81 case 'f':
82 forceFlag = TRUE;
83 break;
84 default:
85 usage(rm_usage);
86 }
87 argc--;
88 argv++;
93 } 89 }
94 else { 90
95 if (recursiveAction( srcName, recursiveFlag, FALSE, 91 while (argc-- > 0) {
96 TRUE, fileAction, dirAction) == FALSE) { 92 srcName = *(argv++);
97 exit( FALSE); 93 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0
98 } 94 && errno == ENOENT) {
95 /* do not reports errors for non-existent files if -f, just skip them */
96 } else {
97 if (recursiveAction(srcName, recursiveFlag, FALSE,
98 TRUE, fileAction, dirAction) == FALSE) {
99 exit(FALSE);
100 }
101 }
99 } 102 }
100 } 103 exit(TRUE);
101 exit( TRUE);
102} 104}
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
index 013fef1a4..f49569749 100644
--- a/coreutils/rmdir.c
+++ b/coreutils/rmdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rmdir implementation for busybox 3 * Mini rmdir implementation for busybox
3 * 4 *
@@ -28,15 +29,16 @@
28 29
29extern int rmdir_main(int argc, char **argv) 30extern int rmdir_main(int argc, char **argv)
30{ 31{
31 if ( argc==1 || **(argv+1) == '-' ) { 32 if (argc == 1 || **(argv + 1) == '-') {
32 usage( "rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n"); 33 usage
33 } 34 ("rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n");
35 }
34 36
35 while (--argc > 0) { 37 while (--argc > 0) {
36 if ( rmdir(*(++argv)) == -1 ) { 38 if (rmdir(*(++argv)) == -1) {
37 fprintf(stderr, "%s: %s\n", *argv, strerror(errno)); 39 fprintf(stderr, "%s: %s\n", *argv, strerror(errno));
38 exit(FALSE); 40 exit(FALSE);
41 }
39 } 42 }
40 } 43 exit(TRUE);
41 exit(TRUE);
42} 44}
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index bfbb78f61..9687b8446 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sleep implementation for busybox 3 * Mini sleep implementation for busybox
3 * 4 *
@@ -23,19 +24,17 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26const char sleep_usage[] = "sleep N\n\n" 27const char sleep_usage[] = "sleep N\n\n" "Pause for N seconds.\n";
27"Pause for N seconds.\n";
28 28
29extern int 29extern int sleep_main(int argc, char **argv)
30sleep_main(int argc, char * * argv)
31{ 30{
32 if ( (argc < 2) || (**(argv+1) == '-') ) { 31 if ((argc < 2) || (**(argv + 1) == '-')) {
33 usage( sleep_usage ); 32 usage(sleep_usage);
34 } 33 }
35 34
36 if ( sleep(atoi(*(++argv))) != 0 ) { 35 if (sleep(atoi(*(++argv))) != 0) {
37 perror( "sleep"); 36 perror("sleep");
38 exit (FALSE); 37 exit(FALSE);
39 } else 38 } else
40 exit (TRUE); 39 exit(TRUE);
41} 40}
diff --git a/coreutils/sort.c b/coreutils/sort.c
index d529ce722..609c5e08c 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sort implementation for busybox 3 * Mini sort implementation for busybox
3 * 4 *
@@ -28,29 +29,27 @@
28#include <stdio.h> 29#include <stdio.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char sort_usage[] = 32static const char sort_usage[] = "sort [OPTION]... [FILE]...\n\n";
32"sort [OPTION]... [FILE]...\n\n"
33;
34 33
35/* typedefs _______________________________________________________________ */ 34/* typedefs _______________________________________________________________ */
36 35
37/* line node */ 36/* line node */
38typedef struct Line { 37typedef struct Line {
39 char *data; /* line data */ 38 char *data; /* line data */
40 struct Line *next; /* pointer to next line node */ 39 struct Line *next; /* pointer to next line node */
41} Line; 40} Line;
42 41
43/* singly-linked list of lines */ 42/* singly-linked list of lines */
44typedef struct { 43typedef struct {
45 int len; /* number of Lines */ 44 int len; /* number of Lines */
46 Line **sorted; /* array fed to qsort */ 45 Line **sorted; /* array fed to qsort */
47 46
48 Line *head; /* head of List */ 47 Line *head; /* head of List */
49 Line *current; /* current Line */ 48 Line *current; /* current Line */
50} List; 49} List;
51 50
52/* comparison function */ 51/* comparison function */
53typedef int (Compare)(const void *, const void *); 52typedef int (Compare) (const void *, const void *);
54 53
55 54
56/* methods ________________________________________________________________ */ 55/* methods ________________________________________________________________ */
@@ -58,175 +57,176 @@ typedef int (Compare)(const void *, const void *);
58static const int max = 1024; 57static const int max = 1024;
59 58
60/* mallocate Line */ 59/* mallocate Line */
61static Line * 60static Line *line_alloc()
62line_alloc()
63{ 61{
64 Line *self; 62 Line *self;
65 self = malloc(1 * sizeof(Line)); 63
66 return self; 64 self = malloc(1 * sizeof(Line));
65 return self;
67} 66}
68 67
69/* Initialize Line with string */ 68/* Initialize Line with string */
70static Line * 69static Line *line_init(Line * self, const char *string)
71line_init(Line *self, const char *string)
72{ 70{
73 self->data = malloc((strlen(string) + 1) * sizeof(char)); 71 self->data = malloc((strlen(string) + 1) * sizeof(char));
74 if (self->data == NULL) { return NULL; } 72
75 strcpy(self->data, string); 73 if (self->data == NULL) {
76 self->next = NULL; 74 return NULL;
77 return self; 75 }
76 strcpy(self->data, string);
77 self->next = NULL;
78 return self;
78} 79}
79 80
80/* Construct Line from FILE* */ 81/* Construct Line from FILE* */
81static Line * 82static Line *line_newFromFile(FILE * src)
82line_newFromFile(FILE *src)
83{ 83{
84 char buffer[max]; 84 char buffer[max];
85 Line *self; 85 Line *self;
86 86
87 if (fgets(buffer, max, src)) { 87 if (fgets(buffer, max, src)) {
88 self = line_alloc(); 88 self = line_alloc();
89 if (self == NULL) { return NULL; } 89 if (self == NULL) {
90 line_init(self, buffer); 90 return NULL;
91 return self; 91 }
92 } 92 line_init(self, buffer);
93 return NULL; 93 return self;
94 }
95 return NULL;
94} 96}
95 97
96/* Line destructor */ 98/* Line destructor */
97static Line * 99static Line *line_release(Line * self)
98line_release(Line *self)
99{ 100{
100 if (self->data) { 101 if (self->data) {
101 free(self->data); 102 free(self->data);
102 free(self); 103 free(self);
103 } 104 }
104 return self; 105 return self;
105} 106}
106 107
107 108
108/* Comparison */ 109/* Comparison */
109 110
110/* ascii order */ 111/* ascii order */
111static int 112static int compare_ascii(const void *a, const void *b)
112compare_ascii(const void *a, const void *b)
113{ 113{
114 Line **doh; 114 Line **doh;
115 Line *x, *y; 115 Line *x, *y;
116 116
117 doh = (Line **) a; 117 doh = (Line **) a;
118 x = *doh; 118 x = *doh;
119 doh = (Line **) b; 119 doh = (Line **) b;
120 y = *doh; 120 y = *doh;
121 121
122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); 122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data);
123 return strcmp(x->data, y->data); 123 return strcmp(x->data, y->data);
124} 124}
125 125
126/* numeric order */ 126/* numeric order */
127static int 127static int compare_numeric(const void *a, const void *b)
128compare_numeric(const void *a, const void *b)
129{ 128{
130 Line **doh; 129 Line **doh;
131 Line *x, *y; 130 Line *x, *y;
132 int xint, yint; 131 int xint, yint;
133 132
134 doh = (Line **) a; 133 doh = (Line **) a;
135 x = *doh; 134 x = *doh;
136 doh = (Line **) b; 135 doh = (Line **) b;
137 y = *doh; 136 y = *doh;
138 137
139 xint = strtoul(x->data, NULL, 10); 138 xint = strtoul(x->data, NULL, 10);
140 yint = strtoul(y->data, NULL, 10); 139 yint = strtoul(y->data, NULL, 10);
141 140
142 return (xint - yint); 141 return (xint - yint);
143} 142}
144 143
145 144
146/* List */ 145/* List */
147 146
148/* */ 147/* */
149static List * 148static List *list_init(List * self)
150list_init(List *self)
151{ 149{
152 self->len = 0; 150 self->len = 0;
153 self->sorted = NULL; 151 self->sorted = NULL;
154 self->head = NULL; 152 self->head = NULL;
155 self->current = NULL; 153 self->current = NULL;
156 return self; 154 return self;
157} 155}
158 156
159/* for simplicity, the List gains ownership of the line */ 157/* for simplicity, the List gains ownership of the line */
160static List * 158static List *list_insert(List * self, Line * line)
161list_insert(List *self, Line *line)
162{ 159{
163 if (line == NULL) { return NULL; } 160 if (line == NULL) {
164 161 return NULL;
165 /* first insertion */ 162 }
166 if (self->head == NULL) { 163
167 self->head = line; 164 /* first insertion */
168 self->current = line; 165 if (self->head == NULL) {
169 166 self->head = line;
170 /* all subsequent insertions */ 167 self->current = line;
171 } else { 168
172 self->current->next = line; 169 /* all subsequent insertions */
173 self->current = line; 170 } else {
174 } 171 self->current->next = line;
175 self->len++; 172 self->current = line;
176 return self; 173 }
174 self->len++;
175 return self;
177} 176}
178 177
179/* order the list according to compare() */ 178/* order the list according to compare() */
180static List * 179static List *list_sort(List * self, Compare * compare)
181list_sort(List *self, Compare *compare)
182{ 180{
183 int i; 181 int i;
184 Line *line; 182 Line *line;
185 183
186 /* mallocate array of Line*s */ 184 /* mallocate array of Line*s */
187 self->sorted = (Line **) malloc(self->len * sizeof(Line*)); 185 self->sorted = (Line **) malloc(self->len * sizeof(Line *));
188 if (self->sorted == NULL) { return NULL; } 186 if (self->sorted == NULL) {
189 187 return NULL;
190 /* fill array w/ List's contents */ 188 }
191 i = 0; 189
192 line = self->head; 190 /* fill array w/ List's contents */
193 while (line) { 191 i = 0;
194 self->sorted[i++] = line; 192 line = self->head;
195 line = line->next; 193 while (line) {
196 } 194 self->sorted[i++] = line;
197 195 line = line->next;
198 /* apply qsort */ 196 }
199 qsort(self->sorted, self->len, sizeof(Line*), compare); 197
200 return self; 198 /* apply qsort */
199 qsort(self->sorted, self->len, sizeof(Line *), compare);
200 return self;
201} 201}
202 202
203/* precondition: list must be sorted */ 203/* precondition: list must be sorted */
204static List * 204static List *list_writeToFile(List * self, FILE * dst)
205list_writeToFile(List *self, FILE* dst)
206{ 205{
207 int i; 206 int i;
208 Line **line = self->sorted; 207 Line **line = self->sorted;
209 208
210 if (self->sorted == NULL) { return NULL; } 209 if (self->sorted == NULL) {
211 for (i = 0; i < self->len; i++) { 210 return NULL;
212 fprintf(dst, "%s", line[i]->data); 211 }
213 } 212 for (i = 0; i < self->len; i++) {
214 return self; 213 fprintf(dst, "%s", line[i]->data);
214 }
215 return self;
215} 216}
216 217
217/* deallocate */ 218/* deallocate */
218static void 219static void list_release(List * self)
219list_release(List *self)
220{ 220{
221 Line *i; 221 Line *i;
222 Line *die; 222 Line *die;
223 223
224 i = self->head; 224 i = self->head;
225 while (i) { 225 while (i) {
226 die = i; 226 die = i;
227 i = die->next; 227 i = die->next;
228 line_release(die); 228 line_release(die);
229 } 229 }
230} 230}
231 231
232 232
@@ -237,76 +237,77 @@ list_release(List *self)
237 * and finally print it 237 * and finally print it
238 */ 238 */
239 239
240int 240int sort_main(int argc, char **argv)
241sort_main(int argc, char **argv)
242{ 241{
243 int i; 242 int i;
244 char opt; 243 char opt;
245 List list; 244 List list;
246 Line *l; 245 Line *l;
247 Compare *compare; 246 Compare *compare;
248 247
249 /* init */ 248 /* init */
250 compare = compare_ascii; 249 compare = compare_ascii;
251 list_init(&list); 250 list_init(&list);
252 251
253 /* parse argv[] */ 252 /* parse argv[] */
254 for (i = 1; i < argc; i++) { 253 for (i = 1; i < argc; i++) {
255 if (argv[i][0] == '-') { 254 if (argv[i][0] == '-') {
256 opt = argv[i][1]; 255 opt = argv[i][1];
257 switch (opt) { 256 switch (opt) {
258 case 'g': 257 case 'g':
259 /* what's the diff between -g && -n? */ 258 /* what's the diff between -g && -n? */
260 compare = compare_numeric; 259 compare = compare_numeric;
261 break; 260 break;
262 case 'h': 261 case 'h':
263 usage(sort_usage); 262 usage(sort_usage);
264 break; 263 break;
265 case 'n': 264 case 'n':
266 /* what's the diff between -g && -n? */ 265 /* what's the diff between -g && -n? */
267 compare = compare_numeric; 266 compare = compare_numeric;
268 break; 267 break;
269 case 'r': 268 case 'r':
270 /* reverse */ 269 /* reverse */
271 break; 270 break;
272 default: 271 default:
273 fprintf(stderr, "sort: invalid option -- %c\n", opt); 272 fprintf(stderr, "sort: invalid option -- %c\n", opt);
274 usage(sort_usage); 273 usage(sort_usage);
275 } 274 }
276 } else { 275 } else {
277 break; 276 break;
277 }
278 } 278 }
279 }
280 279
281 /* this could be factored better */ 280 /* this could be factored better */
282 281
283 /* work w/ stdin */ 282 /* work w/ stdin */
284 if (i >= argc) { 283 if (i >= argc) {
285 while ( (l = line_newFromFile(stdin))) { 284 while ((l = line_newFromFile(stdin))) {
286 list_insert(&list, l); 285 list_insert(&list, l);
287 } 286 }
288 list_sort(&list, compare); 287 list_sort(&list, compare);
289 list_writeToFile(&list, stdout); 288 list_writeToFile(&list, stdout);
290 list_release(&list); 289 list_release(&list);
291 290
292 /* work w/ what's left in argv[] */ 291 /* work w/ what's left in argv[] */
293 } else { 292 } else {
294 FILE *src; 293 FILE *src;
295 294
296 for ( ; i < argc; i++) { 295 for (; i < argc; i++) {
297 src = fopen(argv[i], "r"); 296 src = fopen(argv[i], "r");
298 if (src == NULL) { break; } 297 if (src == NULL) {
299 while ( (l = line_newFromFile(src))) { 298 break;
300 list_insert(&list, l); 299 }
301 } 300 while ((l = line_newFromFile(src))) {
302 fclose(src); 301 list_insert(&list, l);
302 }
303 fclose(src);
304 }
305 list_sort(&list, compare);
306 list_writeToFile(&list, stdout);
307 list_release(&list);
303 } 308 }
304 list_sort(&list, compare);
305 list_writeToFile(&list, stdout);
306 list_release(&list);
307 }
308 309
309 exit(0); 310 exit(0);
310} 311}
311 312
312/* $Id: sort.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 313/* $Id: sort.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/sync.c b/coreutils/sync.c
index 145ed1eda..f8160c8dc 100644
--- a/coreutils/sync.c
+++ b/coreutils/sync.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sync implementation for busybox 3 * Mini sync implementation for busybox
3 * 4 *
@@ -23,12 +24,10 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26extern int 27extern int sync_main(int argc, char **argv)
27sync_main(int argc, char * * argv)
28{ 28{
29 if ( argc>1 && **(argv+1) == '-' ) { 29 if (argc > 1 && **(argv + 1) == '-') {
30 usage( "sync\n\nWrite all buffered filesystem blocks to disk.\n"); 30 usage("sync\n\nWrite all buffered filesystem blocks to disk.\n");
31 } 31 }
32 exit( sync()); 32 exit(sync());
33} 33}
34
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 0ab8f11b0..31705afa2 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2/* This file contains _two_ implementations of tail. One is 3/* This file contains _two_ implementations of tail. One is
3 * a bit more full featured, but costs 6k. The other (i.e. the 4 * a bit more full featured, but costs 6k. The other (i.e. the
@@ -68,22 +69,23 @@ static int forever;
68static int print_headers; 69static int print_headers;
69 70
70const char tail_usage[] = 71const char tail_usage[] =
71 "tail [OPTION] [FILE]...\n\n" 72 "tail [OPTION] [FILE]...\n\n"
72 "Print last 10 lines of each FILE to standard output.\n" 73 "Print last 10 lines of each FILE to standard output.\n"
73 "With more than one FILE, precede each with a header giving the\n" 74 "With more than one FILE, precede each with a header giving the\n"
74 "file name. With no FILE, or when FILE is -, read standard input.\n\n" 75 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
75 "Options:\n" 76 "Options:\n"
76 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n" 77 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
77 "\t-f\t\tOutput data as the file grows. This version\n" 78
78 "\t\t\tof 'tail -f' supports only one file at a time.\n"; 79 "\t-f\t\tOutput data as the file grows. This version\n"
80 "\t\t\tof 'tail -f' supports only one file at a time.\n";
79 81
80 82
81static void write_header(const char *filename) 83static void write_header(const char *filename)
82{ 84{
83 static int first_file = 1; 85 static int first_file = 1;
84 86
85 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename); 87 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
86 first_file = 0; 88 first_file = 0;
87} 89}
88 90
89/* Print the last N_LINES lines from the end of file FD. 91/* Print the last N_LINES lines from the end of file FD.
@@ -97,57 +99,57 @@ static void write_header(const char *filename)
97static int 99static int
98file_lines(const char *filename, int fd, long int n_lines, off_t pos) 100file_lines(const char *filename, int fd, long int n_lines, off_t pos)
99{ 101{
100 char buffer[BUFSIZ]; 102 char buffer[BUFSIZ];
101 int bytes_read; 103 int bytes_read;
102 int i; /* Index into `buffer' for scanning. */ 104 int i; /* Index into `buffer' for scanning. */
103
104 if (n_lines == 0)
105 return 0;
106 105
107 /* Set `bytes_read' to the size of the last, probably partial, buffer; 106 if (n_lines == 0)
108 0 < `bytes_read' <= `BUFSIZ'. */
109 bytes_read = pos % BUFSIZ;
110 if (bytes_read == 0)
111 bytes_read = BUFSIZ;
112 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
113 reads will be on block boundaries, which might increase efficiency. */
114 pos -= bytes_read;
115 lseek(fd, pos, SEEK_SET);
116 bytes_read = fullRead(fd, buffer, bytes_read);
117 if (bytes_read == -1)
118 error("read error");
119
120 /* Count the incomplete line on files that don't end with a newline. */
121 if (bytes_read && buffer[bytes_read - 1] != '\n')
122 --n_lines;
123
124 do {
125 /* Scan backward, counting the newlines in this bufferfull. */
126 for (i = bytes_read - 1; i >= 0; i--) {
127 /* Have we counted the requested number of newlines yet? */
128 if (buffer[i] == '\n' && n_lines-- == 0) {
129 /* If this newline wasn't the last character in the buffer,
130 print the text after it. */
131 if (i != bytes_read - 1)
132 XWRITE(STDOUT_FILENO, &buffer[i + 1],
133 bytes_read - (i + 1));
134 return 0; 107 return 0;
135 } 108
136 } 109 /* Set `bytes_read' to the size of the last, probably partial, buffer;
137 /* Not enough newlines in that bufferfull. */ 110 0 < `bytes_read' <= `BUFSIZ'. */
138 if (pos == 0) { 111 bytes_read = pos % BUFSIZ;
139 /* Not enough lines in the file; print the entire file. */ 112 if (bytes_read == 0)
140 lseek(fd, (off_t) 0, SEEK_SET); 113 bytes_read = BUFSIZ;
141 return 0; 114 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
142 } 115 reads will be on block boundaries, which might increase efficiency. */
143 pos -= BUFSIZ; 116 pos -= bytes_read;
144 lseek(fd, pos, SEEK_SET); 117 lseek(fd, pos, SEEK_SET);
145 } 118 bytes_read = fullRead(fd, buffer, bytes_read);
146 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0); 119 if (bytes_read == -1)
147 if (bytes_read == -1) 120 error("read error");
148 error("read error"); 121
122 /* Count the incomplete line on files that don't end with a newline. */
123 if (bytes_read && buffer[bytes_read - 1] != '\n')
124 --n_lines;
125
126 do {
127 /* Scan backward, counting the newlines in this bufferfull. */
128 for (i = bytes_read - 1; i >= 0; i--) {
129 /* Have we counted the requested number of newlines yet? */
130 if (buffer[i] == '\n' && n_lines-- == 0) {
131 /* If this newline wasn't the last character in the buffer,
132 print the text after it. */
133 if (i != bytes_read - 1)
134 XWRITE(STDOUT_FILENO, &buffer[i + 1],
135 bytes_read - (i + 1));
136 return 0;
137 }
138 }
139 /* Not enough newlines in that bufferfull. */
140 if (pos == 0) {
141 /* Not enough lines in the file; print the entire file. */
142 lseek(fd, (off_t) 0, SEEK_SET);
143 return 0;
144 }
145 pos -= BUFSIZ;
146 lseek(fd, pos, SEEK_SET);
147 }
148 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
149 if (bytes_read == -1)
150 error("read error");
149 151
150 return 0; 152 return 0;
151} 153}
152 154
153/* Print the last N_LINES lines from the end of the standard input, 155/* Print the last N_LINES lines from the end of the standard input,
@@ -157,100 +159,100 @@ file_lines(const char *filename, int fd, long int n_lines, off_t pos)
157 159
158static int pipe_lines(const char *filename, int fd, long int n_lines) 160static int pipe_lines(const char *filename, int fd, long int n_lines)
159{ 161{
160 struct linebuffer { 162 struct linebuffer {
161 int nbytes, nlines; 163 int nbytes, nlines;
162 char buffer[BUFSIZ]; 164 char buffer[BUFSIZ];
163 struct linebuffer *next; 165 struct linebuffer *next;
164 }; 166 };
165 typedef struct linebuffer LBUFFER; 167 typedef struct linebuffer LBUFFER;
166 LBUFFER *first, *last, *tmp; 168 LBUFFER *first, *last, *tmp;
167 int i; /* Index into buffers. */ 169 int i; /* Index into buffers. */
168 int total_lines = 0; /* Total number of newlines in all buffers. */ 170 int total_lines = 0; /* Total number of newlines in all buffers. */
169 int errors = 0; 171 int errors = 0;
170 172
171 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 173 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
172 first->nbytes = first->nlines = 0; 174 first->nbytes = first->nlines = 0;
173 first->next = NULL; 175 first->next = NULL;
174 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 176 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
175 177
176 /* Input is always read into a fresh buffer. */ 178 /* Input is always read into a fresh buffer. */
177 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) { 179 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
178 tmp->nlines = 0; 180 tmp->nlines = 0;
179 tmp->next = NULL; 181 tmp->next = NULL;
180 182
181 /* Count the number of newlines just read. */ 183 /* Count the number of newlines just read. */
182 for (i = 0; i < tmp->nbytes; i++) 184 for (i = 0; i < tmp->nbytes; i++)
183 if (tmp->buffer[i] == '\n') 185 if (tmp->buffer[i] == '\n')
184 ++tmp->nlines; 186 ++tmp->nlines;
185 total_lines += tmp->nlines; 187 total_lines += tmp->nlines;
186 188
187 /* If there is enough room in the last buffer read, just append the new 189 /* If there is enough room in the last buffer read, just append the new
188 one to it. This is because when reading from a pipe, `nbytes' can 190 one to it. This is because when reading from a pipe, `nbytes' can
189 often be very small. */ 191 often be very small. */
190 if (tmp->nbytes + last->nbytes < BUFSIZ) { 192 if (tmp->nbytes + last->nbytes < BUFSIZ) {
191 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 193 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
192 last->nbytes += tmp->nbytes; 194 last->nbytes += tmp->nbytes;
193 last->nlines += tmp->nlines; 195 last->nlines += tmp->nlines;
194 } else { 196 } else {
195 /* If there's not enough room, link the new buffer onto the end of 197 /* If there's not enough room, link the new buffer onto the end of
196 the list, then either free up the oldest buffer for the next 198 the list, then either free up the oldest buffer for the next
197 read if that would leave enough lines, or else malloc a new one. 199 read if that would leave enough lines, or else malloc a new one.
198 Some compaction mechanism is possible but probably not 200 Some compaction mechanism is possible but probably not
199 worthwhile. */ 201 worthwhile. */
200 last = last->next = tmp; 202 last = last->next = tmp;
201 if (total_lines - first->nlines > n_lines) { 203 if (total_lines - first->nlines > n_lines) {
202 tmp = first; 204 tmp = first;
203 total_lines -= first->nlines; 205 total_lines -= first->nlines;
204 first = first->next; 206 first = first->next;
205 } else 207 } else
206 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 208 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
209 }
207 } 210 }
208 } 211 if (tmp->nbytes == -1)
209 if (tmp->nbytes == -1) 212 error("read error");
210 error("read error"); 213
211 214 free((char *) tmp);
212 free((char *) tmp); 215
213 216 /* This prevents a core dump when the pipe contains no newlines. */
214 /* This prevents a core dump when the pipe contains no newlines. */ 217 if (n_lines == 0)
215 if (n_lines == 0) 218 goto free_lbuffers;
216 goto free_lbuffers; 219
217 220 /* Count the incomplete line on files that don't end with a newline. */
218 /* Count the incomplete line on files that don't end with a newline. */ 221 if (last->buffer[last->nbytes - 1] != '\n') {
219 if (last->buffer[last->nbytes - 1] != '\n') { 222 ++last->nlines;
220 ++last->nlines; 223 ++total_lines;
221 ++total_lines; 224 }
222 } 225
223 226 /* Run through the list, printing lines. First, skip over unneeded
224 /* Run through the list, printing lines. First, skip over unneeded 227 buffers. */
225 buffers. */ 228 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
226 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next) 229 total_lines -= tmp->nlines;
227 total_lines -= tmp->nlines; 230
228 231 /* Find the correct beginning, then print the rest of the file. */
229 /* Find the correct beginning, then print the rest of the file. */ 232 if (total_lines > n_lines) {
230 if (total_lines > n_lines) { 233 char *cp;
231 char *cp; 234
232 235 /* Skip `total_lines' - `n_lines' newlines. We made sure that
233 /* Skip `total_lines' - `n_lines' newlines. We made sure that 236 `total_lines' - `n_lines' <= `tmp->nlines'. */
234 `total_lines' - `n_lines' <= `tmp->nlines'. */ 237 cp = tmp->buffer;
235 cp = tmp->buffer; 238 for (i = total_lines - n_lines; i; --i)
236 for (i = total_lines - n_lines; i; --i) 239 while (*cp++ != '\n')
237 while (*cp++ != '\n') 240 /* Do nothing. */ ;
238 /* Do nothing. */ ; 241 i = cp - tmp->buffer;
239 i = cp - tmp->buffer; 242 } else
240 } else 243 i = 0;
241 i = 0; 244 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
242 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i); 245
243 246 for (tmp = tmp->next; tmp; tmp = tmp->next)
244 for (tmp = tmp->next; tmp; tmp = tmp->next) 247 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
245 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
246 248
247 free_lbuffers: 249 free_lbuffers:
248 while (first) { 250 while (first) {
249 tmp = first->next; 251 tmp = first->next;
250 free((char *) first); 252 free((char *) first);
251 first = tmp; 253 first = tmp;
252 } 254 }
253 return errors; 255 return errors;
254} 256}
255 257
256/* Display file FILENAME from the current position in FD to the end. 258/* Display file FILENAME from the current position in FD to the end.
@@ -259,25 +261,25 @@ static int pipe_lines(const char *filename, int fd, long int n_lines)
259 261
260static long dump_remainder(const char *filename, int fd) 262static long dump_remainder(const char *filename, int fd)
261{ 263{
262 char buffer[BUFSIZ]; 264 char buffer[BUFSIZ];
263 int bytes_read; 265 int bytes_read;
264 long total; 266 long total;
265 267
266 total = 0; 268 total = 0;
267 output: 269 output:
268 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) { 270 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
269 XWRITE(STDOUT_FILENO, buffer, bytes_read); 271 XWRITE(STDOUT_FILENO, buffer, bytes_read);
270 total += bytes_read; 272 total += bytes_read;
271 } 273 }
272 if (bytes_read == -1) 274 if (bytes_read == -1)
273 error("read error"); 275 error("read error");
274 if (forever) { 276 if (forever) {
275 fflush(stdout); 277 fflush(stdout);
276 sleep(1); 278 sleep(1);
277 goto output; 279 goto output;
278 } 280 }
279 281
280 return total; 282 return total;
281} 283}
282 284
283/* Output the last N_LINES lines of file FILENAME open for reading in FD. 285/* Output the last N_LINES lines of file FILENAME open for reading in FD.
@@ -285,31 +287,31 @@ static long dump_remainder(const char *filename, int fd)
285 287
286static int tail_lines(const char *filename, int fd, long int n_lines) 288static int tail_lines(const char *filename, int fd, long int n_lines)
287{ 289{
288 struct stat stats; 290 struct stat stats;
289 off_t length; 291 off_t length;
290 292
291 if (print_headers) 293 if (print_headers)
292 write_header(filename); 294 write_header(filename);
293 295
294 if (fstat(fd, &stats)) 296 if (fstat(fd, &stats))
295 error("fstat error"); 297 error("fstat error");
296 298
297 /* Use file_lines only if FD refers to a regular file with 299 /* Use file_lines only if FD refers to a regular file with
298 its file pointer positioned at beginning of file. */ 300 its file pointer positioned at beginning of file. */
299 /* FIXME: adding the lseek conjunct is a kludge. 301 /* FIXME: adding the lseek conjunct is a kludge.
300 Once there's a reasonable test suite, fix the true culprit: 302 Once there's a reasonable test suite, fix the true culprit:
301 file_lines. file_lines shouldn't presume that the input 303 file_lines. file_lines shouldn't presume that the input
302 file pointer is initially positioned to beginning of file. */ 304 file pointer is initially positioned to beginning of file. */
303 if (S_ISREG(stats.st_mode) 305 if (S_ISREG(stats.st_mode)
304 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) { 306 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
305 length = lseek(fd, (off_t) 0, SEEK_END); 307 length = lseek(fd, (off_t) 0, SEEK_END);
306 if (length != 0 && file_lines(filename, fd, n_lines, length)) 308 if (length != 0 && file_lines(filename, fd, n_lines, length))
307 return 1; 309 return 1;
308 dump_remainder(filename, fd); 310 dump_remainder(filename, fd);
309 } else 311 } else
310 return pipe_lines(filename, fd, n_lines); 312 return pipe_lines(filename, fd, n_lines);
311 313
312 return 0; 314 return 0;
313} 315}
314 316
315/* Display the last N_UNITS lines of file FILENAME. 317/* Display the last N_UNITS lines of file FILENAME.
@@ -318,78 +320,78 @@ static int tail_lines(const char *filename, int fd, long int n_lines)
318 320
319static int tail_file(const char *filename, off_t n_units) 321static int tail_file(const char *filename, off_t n_units)
320{ 322{
321 int fd, errors; 323 int fd, errors;
322 324
323 if (!strcmp(filename, "-")) { 325 if (!strcmp(filename, "-")) {
324 filename = "standard input"; 326 filename = "standard input";
325 errors = tail_lines(filename, 0, (long) n_units); 327 errors = tail_lines(filename, 0, (long) n_units);
326 } else { 328 } else {
327 /* Not standard input. */ 329 /* Not standard input. */
328 fd = open(filename, O_RDONLY); 330 fd = open(filename, O_RDONLY);
329 if (fd == -1) 331 if (fd == -1)
330 error("open error"); 332 error("open error");
331 333
332 errors = tail_lines(filename, fd, (long) n_units); 334 errors = tail_lines(filename, fd, (long) n_units);
333 close(fd); 335 close(fd);
334 } 336 }
335 337
336 return errors; 338 return errors;
337} 339}
338 340
339extern int tail_main(int argc, char **argv) 341extern int tail_main(int argc, char **argv)
340{ 342{
341 int exit_status = 0; 343 int exit_status = 0;
342 int n_units = DEFAULT_N_LINES; 344 int n_units = DEFAULT_N_LINES;
343 int n_tmp, i; 345 int n_tmp, i;
344 char opt; 346 char opt;
345 347
346 forever = print_headers = 0; 348 forever = print_headers = 0;
347 349
348 /* parse argv[] */ 350 /* parse argv[] */
349 for (i = 1; i < argc; i++) { 351 for (i = 1; i < argc; i++) {
350 if (argv[i][0] == '-') { 352 if (argv[i][0] == '-') {
351 opt = argv[i][1]; 353 opt = argv[i][1];
352 switch (opt) { 354 switch (opt) {
353 case 'f': 355 case 'f':
354 forever = 1; 356 forever = 1;
355 break; 357 break;
356 case 'n': 358 case 'n':
357 n_tmp = 0; 359 n_tmp = 0;
358 if (++i < argc) 360 if (++i < argc)
359 n_tmp = atoi(argv[i]); 361 n_tmp = atoi(argv[i]);
360 if (n_tmp < 1) 362 if (n_tmp < 1)
361 usage(tail_usage); 363 usage(tail_usage);
362 n_units = n_tmp; 364 n_units = n_tmp;
363 break; 365 break;
364 case '-': 366 case '-':
365 case 'h': 367 case 'h':
366 usage(tail_usage); 368 usage(tail_usage);
367 default: 369 default:
368 fprintf(stderr, "tail: invalid option -- %c\n", opt); 370 fprintf(stderr, "tail: invalid option -- %c\n", opt);
369 usage(tail_usage); 371 usage(tail_usage);
370 } 372 }
371 } else { 373 } else {
372 break; 374 break;
375 }
373 } 376 }
374 }
375 377
376 if (i + 1 < argc) { 378 if (i + 1 < argc) {
377 if (forever) { 379 if (forever) {
378 fprintf(stderr, 380 fprintf(stderr,
379 "tail: option -f is invalid with multiple files\n"); 381 "tail: option -f is invalid with multiple files\n");
380 usage(tail_usage); 382 usage(tail_usage);
383 }
384 print_headers = 1;
381 } 385 }
382 print_headers = 1;
383 }
384 386
385 if (i >= argc) { 387 if (i >= argc) {
386 exit_status |= tail_file("-", n_units); 388 exit_status |= tail_file("-", n_units);
387 } else { 389 } else {
388 for (; i < argc; i++) 390 for (; i < argc; i++)
389 exit_status |= tail_file(argv[i], n_units); 391 exit_status |= tail_file(argv[i], n_units);
390 } 392 }
391 393
392 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 394 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
393} 395}
394 396
395 397
@@ -441,15 +443,15 @@ extern int tail_main(int argc, char **argv)
441#define NDEBUG 1 443#define NDEBUG 1
442 444
443 445
444static void detailed_error(int i, int errnum, char* fmt, ...) 446static void detailed_error(int i, int errnum, char *fmt, ...)
445{ 447{
446 va_list arguments; 448 va_list arguments;
447 449
448 va_start(arguments, fmt); 450 va_start(arguments, fmt);
449 vfprintf(stderr, fmt, arguments); 451 vfprintf(stderr, fmt, arguments);
450 fprintf(stderr, "\n%s\n", strerror( errnum)); 452 fprintf(stderr, "\n%s\n", strerror(errnum));
451 va_end(arguments); 453 va_end(arguments);
452 exit(i); 454 exit(i);
453} 455}
454 456
455 457
@@ -494,9 +496,8 @@ static int from_start;
494static int print_headers; 496static int print_headers;
495 497
496/* When to print the filename banners. */ 498/* When to print the filename banners. */
497enum header_mode 499enum header_mode {
498{ 500 multiple_files, always, never
499 multiple_files, always, never
500}; 501};
501 502
502/* The name this program was run with. */ 503/* The name this program was run with. */
@@ -506,8 +507,7 @@ char *program_name;
506static int have_read_stdin; 507static int have_read_stdin;
507 508
508 509
509static const char tail_usage[] = 510static const char tail_usage[] = "tail [OPTION]... [FILE]...\n\
510"tail [OPTION]... [FILE]...\n\
511\n\ 511\n\
512Print last 10 lines of each FILE to standard output.\n\ 512Print last 10 lines of each FILE to standard output.\n\
513With more than one FILE, precede each with a header giving the file name.\n\ 513With more than one FILE, precede each with a header giving the file name.\n\
@@ -524,15 +524,13 @@ If the first character of N (bytes or lines) is a `+', output begins with \n\
524the Nth item from the start of each file, otherwise, print the last N items\n\ 524the Nth item from the start of each file, otherwise, print the last N items\n\
525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; 525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
526 526
527static void 527static void write_header(const char *filename, const char *comment)
528write_header (const char *filename, const char *comment)
529{ 528{
530 static int first_file = 1; 529 static int first_file = 1;
531 530
532 printf ("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename, 531 printf("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename,
533 (comment ? ": " : ""), 532 (comment ? ": " : ""), (comment ? comment : ""));
534 (comment ? comment : "")); 533 first_file = 0;
535 first_file = 0;
536} 534}
537 535
538/* Print the last N_LINES lines from the end of file FD. 536/* Print the last N_LINES lines from the end of file FD.
@@ -544,67 +542,62 @@ write_header (const char *filename, const char *comment)
544 Return 0 if successful, 1 if an error occurred. */ 542 Return 0 if successful, 1 if an error occurred. */
545 543
546static int 544static int
547file_lines (const char *filename, int fd, long int n_lines, off_t pos) 545file_lines(const char *filename, int fd, long int n_lines, off_t pos)
548{ 546{
549 char buffer[BUFSIZ]; 547 char buffer[BUFSIZ];
550 int bytes_read; 548 int bytes_read;
551 int i; /* Index into `buffer' for scanning. */ 549 int i; /* Index into `buffer' for scanning. */
552 550
553 if (n_lines == 0) 551 if (n_lines == 0)
554 return 0; 552 return 0;
555 553
556 /* Set `bytes_read' to the size of the last, probably partial, buffer; 554 /* Set `bytes_read' to the size of the last, probably partial, buffer;
557 0 < `bytes_read' <= `BUFSIZ'. */ 555 0 < `bytes_read' <= `BUFSIZ'. */
558 bytes_read = pos % BUFSIZ; 556 bytes_read = pos % BUFSIZ;
559 if (bytes_read == 0) 557 if (bytes_read == 0)
560 bytes_read = BUFSIZ; 558 bytes_read = BUFSIZ;
561 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all 559 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
562 reads will be on block boundaries, which might increase efficiency. */ 560 reads will be on block boundaries, which might increase efficiency. */
563 pos -= bytes_read; 561 pos -= bytes_read;
564 lseek (fd, pos, SEEK_SET); 562 lseek(fd, pos, SEEK_SET);
565 bytes_read = fullRead (fd, buffer, bytes_read); 563 bytes_read = fullRead(fd, buffer, bytes_read);
566 if (bytes_read == -1) 564 if (bytes_read == -1) {
567 { 565 detailed_error(0, errno, "%s", filename);
568 detailed_error (0, errno, "%s", filename); 566 return 1;
569 return 1; 567 }
570 } 568
571 569 /* Count the incomplete line on files that don't end with a newline. */
572 /* Count the incomplete line on files that don't end with a newline. */ 570 if (bytes_read && buffer[bytes_read - 1] != '\n')
573 if (bytes_read && buffer[bytes_read - 1] != '\n') 571 --n_lines;
574 --n_lines; 572
575 573 do {
576 do 574 /* Scan backward, counting the newlines in this bufferfull. */
577 { 575 for (i = bytes_read - 1; i >= 0; i--) {
578 /* Scan backward, counting the newlines in this bufferfull. */ 576 /* Have we counted the requested number of newlines yet? */
579 for (i = bytes_read - 1; i >= 0; i--) 577 if (buffer[i] == '\n' && n_lines-- == 0) {
580 { 578 /* If this newline wasn't the last character in the buffer,
581 /* Have we counted the requested number of newlines yet? */ 579 print the text after it. */
582 if (buffer[i] == '\n' && n_lines-- == 0) 580 if (i != bytes_read - 1)
583 { 581 XWRITE(STDOUT_FILENO, &buffer[i + 1],
584 /* If this newline wasn't the last character in the buffer, 582 bytes_read - (i + 1));
585 print the text after it. */ 583 return 0;
586 if (i != bytes_read - 1) 584 }
587 XWRITE (STDOUT_FILENO, &buffer[i + 1], bytes_read - (i + 1)); 585 }
588 return 0; 586 /* Not enough newlines in that bufferfull. */
589 } 587 if (pos == 0) {
588 /* Not enough lines in the file; print the entire file. */
589 lseek(fd, (off_t) 0, SEEK_SET);
590 return 0;
591 }
592 pos -= BUFSIZ;
593 lseek(fd, pos, SEEK_SET);
590 } 594 }
591 /* Not enough newlines in that bufferfull. */ 595 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
592 if (pos == 0) 596 if (bytes_read == -1) {
593 { 597 detailed_error(0, errno, "%s", filename);
594 /* Not enough lines in the file; print the entire file. */ 598 return 1;
595 lseek (fd, (off_t) 0, SEEK_SET);
596 return 0;
597 } 599 }
598 pos -= BUFSIZ; 600 return 0;
599 lseek (fd, pos, SEEK_SET);
600 }
601 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
602 if (bytes_read == -1)
603 {
604 detailed_error (0, errno, "%s", filename);
605 return 1;
606 }
607 return 0;
608} 601}
609 602
610/* Print the last N_LINES lines from the end of the standard input, 603/* Print the last N_LINES lines from the end of the standard input,
@@ -612,301 +605,264 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
612 Buffer the text as a linked list of LBUFFERs, adding them as needed. 605 Buffer the text as a linked list of LBUFFERs, adding them as needed.
613 Return 0 if successful, 1 if an error occured. */ 606 Return 0 if successful, 1 if an error occured. */
614 607
615static int 608static int pipe_lines(const char *filename, int fd, long int n_lines)
616pipe_lines (const char *filename, int fd, long int n_lines)
617{ 609{
618 struct linebuffer 610 struct linebuffer {
619 { 611 int nbytes, nlines;
620 int nbytes, nlines; 612 char buffer[BUFSIZ];
621 char buffer[BUFSIZ]; 613 struct linebuffer *next;
622 struct linebuffer *next; 614 };
623 }; 615 typedef struct linebuffer LBUFFER;
624 typedef struct linebuffer LBUFFER; 616 LBUFFER *first, *last, *tmp;
625 LBUFFER *first, *last, *tmp; 617 int i; /* Index into buffers. */
626 int i; /* Index into buffers. */ 618 int total_lines = 0; /* Total number of newlines in all buffers. */
627 int total_lines = 0; /* Total number of newlines in all buffers. */ 619 int errors = 0;
628 int errors = 0; 620
629 621 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
630 first = last = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 622 first->nbytes = first->nlines = 0;
631 first->nbytes = first->nlines = 0; 623 first->next = NULL;
632 first->next = NULL; 624 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
633 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 625
634 626 /* Input is always read into a fresh buffer. */
635 /* Input is always read into a fresh buffer. */ 627 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
636 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 628 tmp->nlines = 0;
637 { 629 tmp->next = NULL;
638 tmp->nlines = 0; 630
639 tmp->next = NULL; 631 /* Count the number of newlines just read. */
640 632 for (i = 0; i < tmp->nbytes; i++)
641 /* Count the number of newlines just read. */ 633 if (tmp->buffer[i] == '\n')
642 for (i = 0; i < tmp->nbytes; i++) 634 ++tmp->nlines;
643 if (tmp->buffer[i] == '\n') 635 total_lines += tmp->nlines;
644 ++tmp->nlines; 636
645 total_lines += tmp->nlines; 637 /* If there is enough room in the last buffer read, just append the new
646 638 one to it. This is because when reading from a pipe, `nbytes' can
647 /* If there is enough room in the last buffer read, just append the new 639 often be very small. */
648 one to it. This is because when reading from a pipe, `nbytes' can 640 if (tmp->nbytes + last->nbytes < BUFSIZ) {
649 often be very small. */ 641 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
650 if (tmp->nbytes + last->nbytes < BUFSIZ) 642 last->nbytes += tmp->nbytes;
651 { 643 last->nlines += tmp->nlines;
652 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 644 } else {
653 last->nbytes += tmp->nbytes; 645 /* If there's not enough room, link the new buffer onto the end of
654 last->nlines += tmp->nlines; 646 the list, then either free up the oldest buffer for the next
647 read if that would leave enough lines, or else malloc a new one.
648 Some compaction mechanism is possible but probably not
649 worthwhile. */
650 last = last->next = tmp;
651 if (total_lines - first->nlines > n_lines) {
652 tmp = first;
653 total_lines -= first->nlines;
654 first = first->next;
655 } else
656 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
657 }
658 }
659 if (tmp->nbytes == -1) {
660 detailed_error(0, errno, "%s", filename);
661 errors = 1;
662 free((char *) tmp);
663 goto free_lbuffers;
655 } 664 }
656 else 665
657 { 666 free((char *) tmp);
658 /* If there's not enough room, link the new buffer onto the end of 667
659 the list, then either free up the oldest buffer for the next 668 /* This prevents a core dump when the pipe contains no newlines. */
660 read if that would leave enough lines, or else malloc a new one. 669 if (n_lines == 0)
661 Some compaction mechanism is possible but probably not 670 goto free_lbuffers;
662 worthwhile. */ 671
663 last = last->next = tmp; 672 /* Count the incomplete line on files that don't end with a newline. */
664 if (total_lines - first->nlines > n_lines) 673 if (last->buffer[last->nbytes - 1] != '\n') {
665 { 674 ++last->nlines;
666 tmp = first; 675 ++total_lines;
667 total_lines -= first->nlines; 676 }
668 first = first->next; 677
669 } 678 /* Run through the list, printing lines. First, skip over unneeded
670 else 679 buffers. */
671 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 680 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
681 total_lines -= tmp->nlines;
682
683 /* Find the correct beginning, then print the rest of the file. */
684 if (total_lines > n_lines) {
685 char *cp;
686
687 /* Skip `total_lines' - `n_lines' newlines. We made sure that
688 `total_lines' - `n_lines' <= `tmp->nlines'. */
689 cp = tmp->buffer;
690 for (i = total_lines - n_lines; i; --i)
691 while (*cp++ != '\n')
692 /* Do nothing. */ ;
693 i = cp - tmp->buffer;
694 } else
695 i = 0;
696 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
697
698 for (tmp = tmp->next; tmp; tmp = tmp->next)
699 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
700
701 free_lbuffers:
702 while (first) {
703 tmp = first->next;
704 free((char *) first);
705 first = tmp;
672 } 706 }
673 } 707 return errors;
674 if (tmp->nbytes == -1)
675 {
676 detailed_error (0, errno, "%s", filename);
677 errors = 1;
678 free ((char *) tmp);
679 goto free_lbuffers;
680 }
681
682 free ((char *) tmp);
683
684 /* This prevents a core dump when the pipe contains no newlines. */
685 if (n_lines == 0)
686 goto free_lbuffers;
687
688 /* Count the incomplete line on files that don't end with a newline. */
689 if (last->buffer[last->nbytes - 1] != '\n')
690 {
691 ++last->nlines;
692 ++total_lines;
693 }
694
695 /* Run through the list, printing lines. First, skip over unneeded
696 buffers. */
697 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
698 total_lines -= tmp->nlines;
699
700 /* Find the correct beginning, then print the rest of the file. */
701 if (total_lines > n_lines)
702 {
703 char *cp;
704
705 /* Skip `total_lines' - `n_lines' newlines. We made sure that
706 `total_lines' - `n_lines' <= `tmp->nlines'. */
707 cp = tmp->buffer;
708 for (i = total_lines - n_lines; i; --i)
709 while (*cp++ != '\n')
710 /* Do nothing. */ ;
711 i = cp - tmp->buffer;
712 }
713 else
714 i = 0;
715 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
716
717 for (tmp = tmp->next; tmp; tmp = tmp->next)
718 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
719
720free_lbuffers:
721 while (first)
722 {
723 tmp = first->next;
724 free ((char *) first);
725 first = tmp;
726 }
727 return errors;
728} 708}
729 709
730/* Print the last N_BYTES characters from the end of pipe FD. 710/* Print the last N_BYTES characters from the end of pipe FD.
731 This is a stripped down version of pipe_lines. 711 This is a stripped down version of pipe_lines.
732 Return 0 if successful, 1 if an error occurred. */ 712 Return 0 if successful, 1 if an error occurred. */
733 713
734static int 714static int pipe_bytes(const char *filename, int fd, off_t n_bytes)
735pipe_bytes (const char *filename, int fd, off_t n_bytes)
736{ 715{
737 struct charbuffer 716 struct charbuffer {
738 { 717 int nbytes;
739 int nbytes; 718 char buffer[BUFSIZ];
740 char buffer[BUFSIZ]; 719 struct charbuffer *next;
741 struct charbuffer *next; 720 };
742 }; 721 typedef struct charbuffer CBUFFER;
743 typedef struct charbuffer CBUFFER; 722 CBUFFER *first, *last, *tmp;
744 CBUFFER *first, *last, *tmp; 723 int i; /* Index into buffers. */
745 int i; /* Index into buffers. */ 724 int total_bytes = 0; /* Total characters in all buffers. */
746 int total_bytes = 0; /* Total characters in all buffers. */ 725 int errors = 0;
747 int errors = 0; 726
748 727 first = last = (CBUFFER *) xmalloc(sizeof(CBUFFER));
749 first = last = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 728 first->nbytes = 0;
750 first->nbytes = 0; 729 first->next = NULL;
751 first->next = NULL; 730 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
752 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 731
753 732 /* Input is always read into a fresh buffer. */
754 /* Input is always read into a fresh buffer. */ 733 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
755 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 734 tmp->next = NULL;
756 { 735
757 tmp->next = NULL; 736 total_bytes += tmp->nbytes;
758 737 /* If there is enough room in the last buffer read, just append the new
759 total_bytes += tmp->nbytes; 738 one to it. This is because when reading from a pipe, `nbytes' can
760 /* If there is enough room in the last buffer read, just append the new 739 often be very small. */
761 one to it. This is because when reading from a pipe, `nbytes' can 740 if (tmp->nbytes + last->nbytes < BUFSIZ) {
762 often be very small. */ 741 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
763 if (tmp->nbytes + last->nbytes < BUFSIZ) 742 last->nbytes += tmp->nbytes;
764 { 743 } else {
765 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 744 /* If there's not enough room, link the new buffer onto the end of
766 last->nbytes += tmp->nbytes; 745 the list, then either free up the oldest buffer for the next
746 read if that would leave enough characters, or else malloc a new
747 one. Some compaction mechanism is possible but probably not
748 worthwhile. */
749 last = last->next = tmp;
750 if (total_bytes - first->nbytes > n_bytes) {
751 tmp = first;
752 total_bytes -= first->nbytes;
753 first = first->next;
754 } else {
755 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
756 }
757 }
767 } 758 }
768 else 759 if (tmp->nbytes == -1) {
769 { 760 detailed_error(0, errno, "%s", filename);
770 /* If there's not enough room, link the new buffer onto the end of 761 errors = 1;
771 the list, then either free up the oldest buffer for the next 762 free((char *) tmp);
772 read if that would leave enough characters, or else malloc a new 763 goto free_cbuffers;
773 one. Some compaction mechanism is possible but probably not 764 }
774 worthwhile. */ 765
775 last = last->next = tmp; 766 free((char *) tmp);
776 if (total_bytes - first->nbytes > n_bytes) 767
777 { 768 /* Run through the list, printing characters. First, skip over unneeded
778 tmp = first; 769 buffers. */
779 total_bytes -= first->nbytes; 770 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
780 first = first->next; 771 total_bytes -= tmp->nbytes;
781 } 772
782 else 773 /* Find the correct beginning, then print the rest of the file.
783 { 774 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
784 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 775 if (total_bytes > n_bytes)
785 } 776 i = total_bytes - n_bytes;
777 else
778 i = 0;
779 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
780
781 for (tmp = tmp->next; tmp; tmp = tmp->next)
782 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
783
784 free_cbuffers:
785 while (first) {
786 tmp = first->next;
787 free((char *) first);
788 first = tmp;
786 } 789 }
787 } 790 return errors;
788 if (tmp->nbytes == -1)
789 {
790 detailed_error (0, errno, "%s", filename);
791 errors = 1;
792 free ((char *) tmp);
793 goto free_cbuffers;
794 }
795
796 free ((char *) tmp);
797
798 /* Run through the list, printing characters. First, skip over unneeded
799 buffers. */
800 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
801 total_bytes -= tmp->nbytes;
802
803 /* Find the correct beginning, then print the rest of the file.
804 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
805 if (total_bytes > n_bytes)
806 i = total_bytes - n_bytes;
807 else
808 i = 0;
809 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
810
811 for (tmp = tmp->next; tmp; tmp = tmp->next)
812 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
813
814free_cbuffers:
815 while (first)
816 {
817 tmp = first->next;
818 free ((char *) first);
819 first = tmp;
820 }
821 return errors;
822} 791}
823 792
824/* Skip N_BYTES characters from the start of pipe FD, and print 793/* Skip N_BYTES characters from the start of pipe FD, and print
825 any extra characters that were read beyond that. 794 any extra characters that were read beyond that.
826 Return 1 on error, 0 if ok. */ 795 Return 1 on error, 0 if ok. */
827 796
828static int 797static int start_bytes(const char *filename, int fd, off_t n_bytes)
829start_bytes (const char *filename, int fd, off_t n_bytes)
830{ 798{
831 char buffer[BUFSIZ]; 799 char buffer[BUFSIZ];
832 int bytes_read = 0; 800 int bytes_read = 0;
833 801
834 while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 802 while (n_bytes > 0 && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0)
835 n_bytes -= bytes_read; 803 n_bytes -= bytes_read;
836 if (bytes_read == -1) 804 if (bytes_read == -1) {
837 { 805 detailed_error(0, errno, "%s", filename);
838 detailed_error (0, errno, "%s", filename); 806 return 1;
839 return 1; 807 } else if (n_bytes < 0)
840 } 808 XWRITE(STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
841 else if (n_bytes < 0) 809 return 0;
842 XWRITE (STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
843 return 0;
844} 810}
845 811
846/* Skip N_LINES lines at the start of file or pipe FD, and print 812/* Skip N_LINES lines at the start of file or pipe FD, and print
847 any extra characters that were read beyond that. 813 any extra characters that were read beyond that.
848 Return 1 on error, 0 if ok. */ 814 Return 1 on error, 0 if ok. */
849 815
850static int 816static int start_lines(const char *filename, int fd, long int n_lines)
851start_lines (const char *filename, int fd, long int n_lines)
852{ 817{
853 char buffer[BUFSIZ]; 818 char buffer[BUFSIZ];
854 int bytes_read = 0; 819 int bytes_read = 0;
855 int bytes_to_skip = 0; 820 int bytes_to_skip = 0;
856 821
857 while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 822 while (n_lines && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
858 { 823 bytes_to_skip = 0;
859 bytes_to_skip = 0; 824 while (bytes_to_skip < bytes_read)
860 while (bytes_to_skip < bytes_read) 825 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0)
861 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0) 826 break;
862 break; 827 }
863 } 828 if (bytes_read == -1) {
864 if (bytes_read == -1) 829 detailed_error(0, errno, "%s", filename);
865 { 830 return 1;
866 detailed_error (0, errno, "%s", filename); 831 } else if (bytes_to_skip < bytes_read) {
867 return 1; 832 XWRITE(STDOUT_FILENO, &buffer[bytes_to_skip],
868 } 833 bytes_read - bytes_to_skip);
869 else if (bytes_to_skip < bytes_read) 834 }
870 { 835 return 0;
871 XWRITE (STDOUT_FILENO, &buffer[bytes_to_skip],
872 bytes_read - bytes_to_skip);
873 }
874 return 0;
875} 836}
876 837
877/* Display file FILENAME from the current position in FD to the end. 838/* Display file FILENAME from the current position in FD to the end.
878 If `forever' is nonzero, keep reading from the end of the file 839 If `forever' is nonzero, keep reading from the end of the file
879 until killed. Return the number of bytes read from the file. */ 840 until killed. Return the number of bytes read from the file. */
880 841
881static long 842static long dump_remainder(const char *filename, int fd)
882dump_remainder (const char *filename, int fd)
883{ 843{
884 char buffer[BUFSIZ]; 844 char buffer[BUFSIZ];
885 int bytes_read; 845 int bytes_read;
886 long total; 846 long total;
887 847
888 total = 0; 848 total = 0;
889output: 849 output:
890 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 850 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
891 { 851 XWRITE(STDOUT_FILENO, buffer, bytes_read);
892 XWRITE (STDOUT_FILENO, buffer, bytes_read); 852 total += bytes_read;
893 total += bytes_read; 853 }
894 } 854 if (bytes_read == -1)
895 if (bytes_read == -1) 855 detailed_error(EXIT_FAILURE, errno, "%s", filename);
896 detailed_error (EXIT_FAILURE, errno, "%s", filename); 856 if (forever) {
897 if (forever) 857 fflush(stdout);
898 { 858 sleep(1);
899 fflush (stdout); 859 goto output;
900 sleep (1); 860 } else {
901 goto output; 861 if (forever_multiple)
902 } 862 fflush(stdout);
903 else 863 }
904 { 864
905 if (forever_multiple) 865 return total;
906 fflush (stdout);
907 }
908
909 return total;
910} 866}
911 867
912/* Tail NFILES (>1) files forever until killed. The file names are in 868/* Tail NFILES (>1) files forever until killed. The file names are in
@@ -916,186 +872,161 @@ output:
916 none of them have changed size in one iteration, we sleep for a 872 none of them have changed size in one iteration, we sleep for a
917 second and try again. We do this until the user interrupts us. */ 873 second and try again. We do this until the user interrupts us. */
918 874
919static void 875static void tail_forever(char **names, int nfiles)
920tail_forever (char **names, int nfiles)
921{ 876{
922 int last; 877 int last;
923 878
924 last = -1; 879 last = -1;
925 880
926 while (1) 881 while (1) {
927 { 882 int i;
928 int i; 883 int changed;
929 int changed; 884
930 885 changed = 0;
931 changed = 0; 886 for (i = 0; i < nfiles; i++) {
932 for (i = 0; i < nfiles; i++) 887 struct stat stats;
933 { 888
934 struct stat stats; 889 if (file_descs[i] < 0)
935 890 continue;
936 if (file_descs[i] < 0) 891 if (fstat(file_descs[i], &stats) < 0) {
937 continue; 892 detailed_error(0, errno, "%s", names[i]);
938 if (fstat (file_descs[i], &stats) < 0) 893 file_descs[i] = -1;
939 { 894 continue;
940 detailed_error (0, errno, "%s", names[i]); 895 }
941 file_descs[i] = -1; 896 if (stats.st_size == file_sizes[i])
942 continue; 897 continue;
943 } 898
944 if (stats.st_size == file_sizes[i]) 899 /* This file has changed size. Print out what we can, and
945 continue; 900 then keep looping. */
946 901
947 /* This file has changed size. Print out what we can, and 902 changed = 1;
948 then keep looping. */ 903
949 904 if (stats.st_size < file_sizes[i]) {
950 changed = 1; 905 write_header(names[i], "file truncated");
951 906 last = i;
952 if (stats.st_size < file_sizes[i]) 907 lseek(file_descs[i], stats.st_size, SEEK_SET);
953 { 908 file_sizes[i] = stats.st_size;
954 write_header (names[i], "file truncated"); 909 continue;
955 last = i; 910 }
956 lseek (file_descs[i], stats.st_size, SEEK_SET); 911
957 file_sizes[i] = stats.st_size; 912 if (i != last) {
958 continue; 913 if (print_headers)
959 } 914 write_header(names[i], NULL);
960 915 last = i;
961 if (i != last) 916 }
962 { 917 file_sizes[i] += dump_remainder(names[i], file_descs[i]);
963 if (print_headers) 918 }
964 write_header (names[i], NULL);
965 last = i;
966 }
967 file_sizes[i] += dump_remainder (names[i], file_descs[i]);
968 }
969 919
970 /* If none of the files changed size, sleep. */ 920 /* If none of the files changed size, sleep. */
971 if (! changed) 921 if (!changed)
972 sleep (1); 922 sleep(1);
973 } 923 }
974} 924}
975 925
976/* Output the last N_BYTES bytes of file FILENAME open for reading in FD. 926/* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
977 Return 0 if successful, 1 if an error occurred. */ 927 Return 0 if successful, 1 if an error occurred. */
978 928
979static int 929static int tail_bytes(const char *filename, int fd, off_t n_bytes)
980tail_bytes (const char *filename, int fd, off_t n_bytes)
981{ 930{
982 struct stat stats; 931 struct stat stats;
983 932
984 /* FIXME: resolve this like in dd.c. */ 933 /* FIXME: resolve this like in dd.c. */
985 /* Use fstat instead of checking for errno == ESPIPE because 934 /* Use fstat instead of checking for errno == ESPIPE because
986 lseek doesn't work on some special files but doesn't return an 935 lseek doesn't work on some special files but doesn't return an
987 error, either. */ 936 error, either. */
988 if (fstat (fd, &stats)) 937 if (fstat(fd, &stats)) {
989 { 938 detailed_error(0, errno, "%s", filename);
990 detailed_error (0, errno, "%s", filename); 939 return 1;
991 return 1; 940 }
992 } 941
993 942 if (from_start) {
994 if (from_start) 943 if (S_ISREG(stats.st_mode))
995 { 944 lseek(fd, n_bytes, SEEK_CUR);
996 if (S_ISREG (stats.st_mode)) 945 else if (start_bytes(filename, fd, n_bytes))
997 lseek (fd, n_bytes, SEEK_CUR); 946 return 1;
998 else if (start_bytes (filename, fd, n_bytes)) 947 dump_remainder(filename, fd);
999 return 1; 948 } else {
1000 dump_remainder (filename, fd); 949 if (S_ISREG(stats.st_mode)) {
1001 } 950 off_t current_pos, end_pos;
1002 else 951 size_t bytes_remaining;
1003 { 952
1004 if (S_ISREG (stats.st_mode)) 953 if ((current_pos = lseek(fd, (off_t) 0, SEEK_CUR)) != -1
1005 { 954 && (end_pos = lseek(fd, (off_t) 0, SEEK_END)) != -1) {
1006 off_t current_pos, end_pos; 955 off_t diff;
1007 size_t bytes_remaining; 956
1008 957 /* Be careful here. The current position may actually be
1009 if ((current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1 958 beyond the end of the file. */
1010 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1) 959 bytes_remaining = (diff =
1011 { 960 end_pos - current_pos) < 0 ? 0 : diff;
1012 off_t diff; 961 } else {
1013 /* Be careful here. The current position may actually be 962 detailed_error(0, errno, "%s", filename);
1014 beyond the end of the file. */ 963 return 1;
1015 bytes_remaining = (diff = end_pos - current_pos) < 0 ? 0 : diff; 964 }
1016 } 965
1017 else 966 if (bytes_remaining <= n_bytes) {
1018 { 967 /* From the current position to end of file, there are no
1019 detailed_error (0, errno, "%s", filename); 968 more bytes than have been requested. So reposition the
1020 return 1; 969 file pointer to the incoming current position and print
1021 } 970 everything after that. */
1022 971 lseek(fd, current_pos, SEEK_SET);
1023 if (bytes_remaining <= n_bytes) 972 } else {
1024 { 973 /* There are more bytes remaining than were requested.
1025 /* From the current position to end of file, there are no 974 Back up. */
1026 more bytes than have been requested. So reposition the 975 lseek(fd, -n_bytes, SEEK_END);
1027 file pointer to the incoming current position and print 976 }
1028 everything after that. */ 977 dump_remainder(filename, fd);
1029 lseek (fd, current_pos, SEEK_SET); 978 } else
1030 } 979 return pipe_bytes(filename, fd, n_bytes);
1031 else
1032 {
1033 /* There are more bytes remaining than were requested.
1034 Back up. */
1035 lseek (fd, -n_bytes, SEEK_END);
1036 }
1037 dump_remainder (filename, fd);
1038 } 980 }
1039 else 981 return 0;
1040 return pipe_bytes (filename, fd, n_bytes);
1041 }
1042 return 0;
1043} 982}
1044 983
1045/* Output the last N_LINES lines of file FILENAME open for reading in FD. 984/* Output the last N_LINES lines of file FILENAME open for reading in FD.
1046 Return 0 if successful, 1 if an error occurred. */ 985 Return 0 if successful, 1 if an error occurred. */
1047 986
1048static int 987static int tail_lines(const char *filename, int fd, long int n_lines)
1049tail_lines (const char *filename, int fd, long int n_lines)
1050{ 988{
1051 struct stat stats; 989 struct stat stats;
1052 off_t length; 990 off_t length;
1053 991
1054 if (fstat (fd, &stats)) 992 if (fstat(fd, &stats)) {
1055 { 993 detailed_error(0, errno, "%s", filename);
1056 detailed_error (0, errno, "%s", filename); 994 return 1;
1057 return 1; 995 }
1058 } 996
1059 997 if (from_start) {
1060 if (from_start) 998 if (start_lines(filename, fd, n_lines))
1061 { 999 return 1;
1062 if (start_lines (filename, fd, n_lines)) 1000 dump_remainder(filename, fd);
1063 return 1; 1001 } else {
1064 dump_remainder (filename, fd); 1002 /* Use file_lines only if FD refers to a regular file with
1065 } 1003 its file pointer positioned at beginning of file. */
1066 else 1004 /* FIXME: adding the lseek conjunct is a kludge.
1067 { 1005 Once there's a reasonable test suite, fix the true culprit:
1068 /* Use file_lines only if FD refers to a regular file with 1006 file_lines. file_lines shouldn't presume that the input
1069 its file pointer positioned at beginning of file. */ 1007 file pointer is initially positioned to beginning of file. */
1070 /* FIXME: adding the lseek conjunct is a kludge. 1008 if (S_ISREG(stats.st_mode)
1071 Once there's a reasonable test suite, fix the true culprit: 1009 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
1072 file_lines. file_lines shouldn't presume that the input 1010 length = lseek(fd, (off_t) 0, SEEK_END);
1073 file pointer is initially positioned to beginning of file. */ 1011 if (length != 0 && file_lines(filename, fd, n_lines, length))
1074 if (S_ISREG (stats.st_mode) 1012 return 1;
1075 && lseek (fd, (off_t) 0, SEEK_CUR) == (off_t) 0) 1013 dump_remainder(filename, fd);
1076 { 1014 } else
1077 length = lseek (fd, (off_t) 0, SEEK_END); 1015 return pipe_lines(filename, fd, n_lines);
1078 if (length != 0 && file_lines (filename, fd, n_lines, length))
1079 return 1;
1080 dump_remainder (filename, fd);
1081 } 1016 }
1082 else 1017 return 0;
1083 return pipe_lines (filename, fd, n_lines);
1084 }
1085 return 0;
1086} 1018}
1087 1019
1088/* Display the last N_UNITS units of file FILENAME, open for reading 1020/* Display the last N_UNITS units of file FILENAME, open for reading
1089 in FD. 1021 in FD.
1090 Return 0 if successful, 1 if an error occurred. */ 1022 Return 0 if successful, 1 if an error occurred. */
1091 1023
1092static int 1024static int tail(const char *filename, int fd, off_t n_units)
1093tail (const char *filename, int fd, off_t n_units)
1094{ 1025{
1095 if (count_lines) 1026 if (count_lines)
1096 return tail_lines (filename, fd, (long) n_units); 1027 return tail_lines(filename, fd, (long) n_units);
1097 else 1028 else
1098 return tail_bytes (filename, fd, n_units); 1029 return tail_bytes(filename, fd, n_units);
1099} 1030}
1100 1031
1101/* Display the last N_UNITS units of file FILENAME. 1032/* Display the last N_UNITS units of file FILENAME.
@@ -1103,207 +1034,183 @@ tail (const char *filename, int fd, off_t n_units)
1103 FILENUM is this file's index in the list of files the user gave. 1034 FILENUM is this file's index in the list of files the user gave.
1104 Return 0 if successful, 1 if an error occurred. */ 1035 Return 0 if successful, 1 if an error occurred. */
1105 1036
1106static int 1037static int tail_file(const char *filename, off_t n_units, int filenum)
1107tail_file (const char *filename, off_t n_units, int filenum)
1108{ 1038{
1109 int fd, errors; 1039 int fd, errors;
1110 struct stat stats; 1040 struct stat stats;
1111 1041
1112 if (!strcmp (filename, "-")) 1042 if (!strcmp(filename, "-")) {
1113 { 1043 have_read_stdin = 1;
1114 have_read_stdin = 1; 1044 filename = "standard input";
1115 filename = "standard input"; 1045 if (print_headers)
1116 if (print_headers) 1046 write_header(filename, NULL);
1117 write_header (filename, NULL); 1047 errors = tail(filename, 0, n_units);
1118 errors = tail (filename, 0, n_units); 1048 if (forever_multiple) {
1119 if (forever_multiple) 1049 if (fstat(0, &stats) < 0) {
1120 { 1050 detailed_error(0, errno, "standard input");
1121 if (fstat (0, &stats) < 0) 1051 errors = 1;
1122 { 1052 } else if (!S_ISREG(stats.st_mode)) {
1123 detailed_error (0, errno, "standard input"); 1053 detailed_error(0, 0,
1124 errors = 1; 1054 "standard input: cannot follow end of non-regular file");
1125 } 1055 errors = 1;
1126 else if (!S_ISREG (stats.st_mode)) 1056 }
1127 { 1057 if (errors)
1128 detailed_error (0, 0, 1058 file_descs[filenum] = -1;
1129 "standard input: cannot follow end of non-regular file"); 1059 else {
1130 errors = 1; 1060 file_descs[filenum] = 0;
1131 } 1061 file_sizes[filenum] = stats.st_size;
1132 if (errors) 1062 }
1133 file_descs[filenum] = -1;
1134 else
1135 {
1136 file_descs[filenum] = 0;
1137 file_sizes[filenum] = stats.st_size;
1138 }
1139 }
1140 }
1141 else
1142 {
1143 /* Not standard input. */
1144 fd = open (filename, O_RDONLY);
1145 if (fd == -1)
1146 {
1147 if (forever_multiple)
1148 file_descs[filenum] = -1;
1149 detailed_error (0, errno, "%s", filename);
1150 errors = 1;
1151 }
1152 else
1153 {
1154 if (print_headers)
1155 write_header (filename, NULL);
1156 errors = tail (filename, fd, n_units);
1157 if (forever_multiple)
1158 {
1159 if (fstat (fd, &stats) < 0)
1160 {
1161 detailed_error (0, errno, "%s", filename);
1162 errors = 1;
1163 }
1164 else if (!S_ISREG (stats.st_mode))
1165 {
1166 detailed_error (0, 0, "%s: cannot follow end of non-regular file",
1167 filename);
1168 errors = 1;
1169 }
1170 if (errors)
1171 {
1172 close (fd);
1173 file_descs[filenum] = -1;
1174 }
1175 else
1176 {
1177 file_descs[filenum] = fd;
1178 file_sizes[filenum] = stats.st_size;
1179 } 1063 }
1180 } 1064 } else {
1181 else 1065 /* Not standard input. */
1182 { 1066 fd = open(filename, O_RDONLY);
1183 if (close (fd)) 1067 if (fd == -1) {
1184 { 1068 if (forever_multiple)
1185 detailed_error (0, errno, "%s", filename); 1069 file_descs[filenum] = -1;
1186 errors = 1; 1070 detailed_error(0, errno, "%s", filename);
1071 errors = 1;
1072 } else {
1073 if (print_headers)
1074 write_header(filename, NULL);
1075 errors = tail(filename, fd, n_units);
1076 if (forever_multiple) {
1077 if (fstat(fd, &stats) < 0) {
1078 detailed_error(0, errno, "%s", filename);
1079 errors = 1;
1080 } else if (!S_ISREG(stats.st_mode)) {
1081 detailed_error(0, 0,
1082 "%s: cannot follow end of non-regular file",
1083 filename);
1084 errors = 1;
1085 }
1086 if (errors) {
1087 close(fd);
1088 file_descs[filenum] = -1;
1089 } else {
1090 file_descs[filenum] = fd;
1091 file_sizes[filenum] = stats.st_size;
1092 }
1093 } else {
1094 if (close(fd)) {
1095 detailed_error(0, errno, "%s", filename);
1096 errors = 1;
1097 }
1098 }
1187 } 1099 }
1188 }
1189 } 1100 }
1190 }
1191 1101
1192 return errors; 1102 return errors;
1193} 1103}
1194 1104
1195extern int 1105extern int tail_main(int argc, char **argv)
1196tail_main (int argc, char **argv)
1197{ 1106{
1198 int stopit = 0; 1107 int stopit = 0;
1199 enum header_mode header_mode = multiple_files; 1108 enum header_mode header_mode = multiple_files;
1200 int exit_status = 0; 1109 int exit_status = 0;
1201 /* If from_start, the number of items to skip before printing; otherwise, 1110
1202 the number of items at the end of the file to print. Initially, -1 1111 /* If from_start, the number of items to skip before printing; otherwise,
1203 means the value has not been set. */ 1112 the number of items at the end of the file to print. Initially, -1
1204 off_t n_units = -1; 1113 means the value has not been set. */
1205 int n_files; 1114 off_t n_units = -1;
1206 char **file; 1115 int n_files;
1207 1116 char **file;
1208 program_name = argv[0]; 1117
1209 have_read_stdin = 0; 1118 program_name = argv[0];
1210 count_lines = 1; 1119 have_read_stdin = 0;
1211 forever = forever_multiple = from_start = print_headers = 0; 1120 count_lines = 1;
1212 1121 forever = forever_multiple = from_start = print_headers = 0;
1213 /* Parse any options */ 1122
1214 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 1123 /* Parse any options */
1215 while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { 1124 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
1216 if (**argv == '+') { 1125 while (--argc > 0 && (**(++argv) == '-' || **argv == '+')) {
1217 from_start = 1; 1126 if (**argv == '+') {
1127 from_start = 1;
1128 }
1129 stopit = 0;
1130 while (stopit == 0 && *(++(*argv))) {
1131 switch (**argv) {
1132 case 'c':
1133 count_lines = 0;
1134
1135 if (--argc < 1) {
1136 usage(tail_usage);
1137 }
1138 n_units = getNum(*(++argv));
1139 stopit = 1;
1140 break;
1141
1142 case 'f':
1143 forever = 1;
1144 break;
1145
1146 case 'n':
1147 count_lines = 1;
1148
1149 if (--argc < 1) {
1150 usage(tail_usage);
1151 }
1152 n_units = atol(*(++argv));
1153 stopit = 1;
1154 break;
1155
1156 case 'q':
1157 header_mode = never;
1158 break;
1159
1160 case 'v':
1161 header_mode = always;
1162 break;
1163
1164 default:
1165 usage(tail_usage);
1166 }
1167 }
1168 }
1169
1170
1171 if (n_units == -1)
1172 n_units = DEFAULT_N_LINES;
1173
1174 /* To start printing with item N_UNITS from the start of the file, skip
1175 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix
1176 compatibility it's treated the same as `tail +1'. */
1177 if (from_start) {
1178 if (n_units)
1179 --n_units;
1218 } 1180 }
1219 stopit = 0; 1181
1220 while (stopit == 0 && *(++(*argv))) { 1182 n_files = argc;
1221 switch (**argv) { 1183 file = argv;
1222 case 'c': 1184
1223 count_lines = 0; 1185 if (n_files > 1 && forever) {
1224 1186 forever_multiple = 1;
1225 if (--argc < 1) { 1187 forever = 0;
1226 usage(tail_usage); 1188 file_descs = (int *) xmalloc(n_files * sizeof(int));
1227 } 1189
1228 n_units = getNum(*(++argv)); 1190 file_sizes = (off_t *) xmalloc(n_files * sizeof(off_t));
1229 stopit = 1;
1230 break;
1231
1232 case 'f':
1233 forever = 1;
1234 break;
1235
1236 case 'n':
1237 count_lines = 1;
1238
1239 if (--argc < 1) {
1240 usage(tail_usage);
1241 }
1242 n_units = atol(*(++argv));
1243 stopit = 1;
1244 break;
1245
1246 case 'q':
1247 header_mode = never;
1248 break;
1249
1250 case 'v':
1251 header_mode = always;
1252 break;
1253
1254 default:
1255 usage (tail_usage);
1256 }
1257 } 1191 }
1258 } 1192
1259 1193 if (header_mode == always
1260 1194 || (header_mode == multiple_files && n_files > 1))
1261 if (n_units == -1) 1195 print_headers = 1;
1262 n_units = DEFAULT_N_LINES; 1196
1263 1197 if (n_files == 0) {
1264 /* To start printing with item N_UNITS from the start of the file, skip 1198 exit_status |= tail_file("-", n_units, 0);
1265 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix 1199 } else {
1266 compatibility it's treated the same as `tail +1'. */ 1200 int i;
1267 if (from_start) 1201
1268 { 1202 for (i = 0; i < n_files; i++)
1269 if (n_units) 1203 exit_status |= tail_file(file[i], n_units, i);
1270 --n_units; 1204
1271 } 1205 if (forever_multiple)
1272 1206 tail_forever(file, n_files);
1273 n_files = argc; 1207 }
1274 file = argv; 1208
1275 1209 if (have_read_stdin && close(0) < 0)
1276 if (n_files > 1 && forever) 1210 detailed_error(EXIT_FAILURE, errno, "-");
1277 { 1211 if (fclose(stdout) == EOF)
1278 forever_multiple = 1; 1212 detailed_error(EXIT_FAILURE, errno, "write error");
1279 forever = 0; 1213 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1280 file_descs = (int *) xmalloc (n_files * sizeof (int));
1281 file_sizes = (off_t *) xmalloc (n_files * sizeof (off_t));
1282 }
1283
1284 if (header_mode == always
1285 || (header_mode == multiple_files && n_files > 1))
1286 print_headers = 1;
1287
1288 if (n_files == 0)
1289 {
1290 exit_status |= tail_file ("-", n_units, 0);
1291 }
1292 else
1293 {
1294 int i;
1295 for (i = 0; i < n_files; i++)
1296 exit_status |= tail_file (file[i], n_units, i);
1297
1298 if (forever_multiple)
1299 tail_forever (file, n_files);
1300 }
1301
1302 if (have_read_stdin && close (0) < 0)
1303 detailed_error (EXIT_FAILURE, errno, "-");
1304 if (fclose (stdout) == EOF)
1305 detailed_error (EXIT_FAILURE, errno, "write error");
1306 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1307} 1214}
1308 1215
1309 1216
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 4c5c691c6..2f746f96d 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tee implementation for busybox 3 * Mini tee implementation for busybox
3 * 4 *
@@ -25,102 +26,100 @@
25#include <stdio.h> 26#include <stdio.h>
26 27
27static const char tee_usage[] = 28static const char tee_usage[] =
28 "tee [OPTION]... [FILE]...\n\n" 29 "tee [OPTION]... [FILE]...\n\n"
29 "Copy standard input to each FILE, and also to standard output.\n\n" 30 "Copy standard input to each FILE, and also to standard output.\n\n"
30 "Options:\n" 31 "Options:\n" "\t-a\tappend to the given FILEs, do not overwrite\n"
31 "\t-a\tappend to the given FILEs, do not overwrite\n"
32#if 0 32#if 0
33 "\t-i\tignore interrupt signals\n" 33 "\t-i\tignore interrupt signals\n"
34#endif 34#endif
35 ; 35;
36 36
37 37
38/* FileList _______________________________________________________________ */ 38/* FileList _______________________________________________________________ */
39 39
40#define FL_MAX 1024 40#define FL_MAX 1024
41static FILE *FileList[FL_MAX]; 41static FILE *FileList[FL_MAX];
42static int FL_end; 42static int FL_end;
43
44typedef void (FL_Function) (FILE * file, char c);
43 45
44typedef void (FL_Function)(FILE *file, char c);
45
46 46
47/* apply a function to everything in FileList */ 47/* apply a function to everything in FileList */
48static void 48static void FL_apply(FL_Function * f, char c)
49FL_apply(FL_Function *f, char c)
50{ 49{
51 int i; 50 int i;
52 for (i = 0; i <= FL_end; i++) { 51
53 f(FileList[i], c); 52 for (i = 0; i <= FL_end; i++) {
54 } 53 f(FileList[i], c);
54 }
55} 55}
56 56
57/* FL_Function for writing to files*/ 57/* FL_Function for writing to files*/
58static void 58static void tee_fwrite(FILE * file, char c)
59tee_fwrite(FILE *file, char c)
60{ 59{
61 fputc(c, file); 60 fputc(c, file);
62} 61}
63 62
64/* FL_Function for closing files */ 63/* FL_Function for closing files */
65static void 64static void tee_fclose(FILE * file, char c)
66tee_fclose(FILE *file, char c)
67{ 65{
68 fclose(file); 66 fclose(file);
69} 67}
70 68
71/* ________________________________________________________________________ */ 69/* ________________________________________________________________________ */
72 70
73/* BusyBoxed tee(1) */ 71/* BusyBoxed tee(1) */
74int 72int tee_main(int argc, char **argv)
75tee_main(int argc, char **argv)
76{ 73{
77 int i; 74 int i;
78 char c; 75 char c;
79 char opt; 76 char opt;
80 char opt_fopen[2] = "w"; 77 char opt_fopen[2] = "w";
81 FILE *file; 78 FILE *file;
82 79
83 /* parse argv[] */ 80 /* parse argv[] */
84 for (i = 1; i < argc; i++) { 81 for (i = 1; i < argc; i++) {
85 if (argv[i][0] == '-') { 82 if (argv[i][0] == '-') {
86 opt = argv[i][1]; 83 opt = argv[i][1];
87 switch (opt) { 84 switch (opt) {
88 case 'a': 85 case 'a':
89 opt_fopen[0] = 'a'; 86 opt_fopen[0] = 'a';
90 break; 87 break;
91#if 0 88#if 0
92 case 'i': 89 case 'i':
93 fprintf(stderr, "ignore interrupt not implemented\n"); 90 fprintf(stderr, "ignore interrupt not implemented\n");
94 break; 91 break;
95#endif 92#endif
96 default: 93 default:
97 usage(tee_usage); 94 usage(tee_usage);
98 } 95 }
99 } else { 96 } else {
100 break; 97 break;
98 }
101 } 99 }
102 } 100
103 101 /* init FILE pointers */
104 /* init FILE pointers */ 102 FL_end = 0;
105 FL_end = 0; 103 FileList[0] = stdout;
106 FileList[0] = stdout; 104 for (; i < argc; i++) {
107 for ( ; i < argc; i++) { 105 /* add a file to FileList */
108 /* add a file to FileList */ 106 file = fopen(argv[i], opt_fopen);
109 file = fopen(argv[i], opt_fopen); 107 if (!file) {
110 if (!file) { continue; } 108 continue;
111 if (FL_end < FL_MAX) { 109 }
112 FileList[++FL_end] = file; 110 if (FL_end < FL_MAX) {
111 FileList[++FL_end] = file;
112 }
113 } 113 }
114 }
115 114
116 /* read and redirect */ 115 /* read and redirect */
117 while ((c = (char) getchar()) && (!feof(stdin))) { 116 while ((c = (char) getchar()) && (!feof(stdin))) {
118 FL_apply(tee_fwrite, c); 117 FL_apply(tee_fwrite, c);
119 } 118 }
120 119
121 /* clean up */ 120 /* clean up */
122 FL_apply(tee_fclose, 0); 121 FL_apply(tee_fclose, 0);
123 exit(0); 122 exit(0);
124} 123}
125 124
126/* $Id: tee.c,v 1.5 2000/02/07 05:29:42 erik Exp $ */ 125/* $Id: tee.c,v 1.6 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/touch.c b/coreutils/touch.c
index d2d3e9484..a0f21acdd 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini touch implementation for busybox 3 * Mini touch implementation for busybox
3 * 4 *
@@ -31,56 +32,50 @@
31 32
32 33
33static const char touch_usage[] = "touch [-c] file [file ...]\n\n" 34static const char touch_usage[] = "touch [-c] file [file ...]\n\n"
34"Update the last-modified date on the given file[s].\n";
35 35
36 "Update the last-modified date on the given file[s].\n";
36 37
37 38
38extern int
39touch_main(int argc, char **argv)
40{
41 int fd;
42 int create=TRUE;
43 39
44 if (argc < 2) { 40extern int touch_main(int argc, char **argv)
45 usage( touch_usage); 41{
46 } 42 int fd;
47 argc--; 43 int create = TRUE;
48 argv++;
49 44
50 /* Parse options */ 45 if (argc < 2) {
51 while (**argv == '-') { 46 usage(touch_usage);
52 while (*++(*argv)) switch (**argv) {
53 case 'c':
54 create = FALSE;
55 break;
56 default:
57 usage( touch_usage);
58 exit( FALSE);
59 } 47 }
60 argc--; 48 argc--;
61 argv++; 49 argv++;
62 }
63 50
64 fd = open (*argv, (create==FALSE)? O_RDWR : O_RDWR | O_CREAT, 0644); 51 /* Parse options */
65 if (fd < 0 ) { 52 while (**argv == '-') {
66 if (create==FALSE && errno == ENOENT) 53 while (*++(*argv))
67 exit( TRUE); 54 switch (**argv) {
68 else { 55 case 'c':
69 perror("touch"); 56 create = FALSE;
70 exit( FALSE); 57 break;
58 default:
59 usage(touch_usage);
60 exit(FALSE);
61 }
62 argc--;
63 argv++;
71 } 64 }
72 }
73 close( fd);
74 if (utime (*argv, NULL)) {
75 perror("touch");
76 exit( FALSE);
77 }
78 else
79 exit( TRUE);
80}
81
82
83
84
85
86 65
66 fd = open(*argv, (create == FALSE) ? O_RDWR : O_RDWR | O_CREAT, 0644);
67 if (fd < 0) {
68 if (create == FALSE && errno == ENOENT)
69 exit(TRUE);
70 else {
71 perror("touch");
72 exit(FALSE);
73 }
74 }
75 close(fd);
76 if (utime(*argv, NULL)) {
77 perror("touch");
78 exit(FALSE);
79 } else
80 exit(TRUE);
81}
diff --git a/coreutils/tty.c b/coreutils/tty.c
index 83abaffb5..8ac1c1fcd 100644
--- a/coreutils/tty.c
+++ b/coreutils/tty.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tty implementation for busybox 3 * Mini tty implementation for busybox
3 * 4 *
@@ -24,19 +25,23 @@
24#include <sys/types.h> 25#include <sys/types.h>
25 26
26static const char tty_usage[] = "tty\n\n" 27static const char tty_usage[] = "tty\n\n"
27"Print the file name of the terminal connected to standard input.\n" 28 "Print the file name of the terminal connected to standard input.\n"
28"\t-s\tprint nothing, only return an exit status\n";
29 29
30extern int tty_main(int argc, char **argv) { 30 "\t-s\tprint nothing, only return an exit status\n";
31
32extern int tty_main(int argc, char **argv)
33{
31 char *tty; 34 char *tty;
32 35
33 if (argc > 1) { 36 if (argc > 1) {
34 if (argv[1][0] != '-' || argv[1][1] != 's') usage (tty_usage); 37 if (argv[1][0] != '-' || argv[1][1] != 's')
35 } 38 usage(tty_usage);
36 else { 39 } else {
37 tty = ttyname (0); 40 tty = ttyname(0);
38 if (tty) puts (tty); 41 if (tty)
39 else puts ("not a tty"); 42 puts(tty);
43 else
44 puts("not a tty");
40 } 45 }
41 exit (isatty (0) ? TRUE : FALSE); 46 exit(isatty(0) ? TRUE : FALSE);
42} 47}
diff --git a/coreutils/uname.c b/coreutils/uname.c
index 9083edb04..9a1cb808a 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* uname -- print system information 2/* uname -- print system information
2 Copyright (C) 1989-1999 Free Software Foundation, Inc. 3 Copyright (C) 1989-1999 Free Software Foundation, Inc.
3 4
@@ -41,16 +42,17 @@
41 42
42 43
43static const char uname_usage[] = 44static const char uname_usage[] =
44 "uname [OPTION]...\n\n" 45 "uname [OPTION]...\n\n"
45 "Print certain system information. With no OPTION, same as -s.\n\n" 46 "Print certain system information. With no OPTION, same as -s.\n\n"
46 "Options:\n" 47 "Options:\n"
47 "\t-a\tprint all information\n" 48 "\t-a\tprint all information\n"
48 "\t-m\tthe machine (hardware) type\n" 49 "\t-m\tthe machine (hardware) type\n"
49 "\t-n\tprint the machine's network node hostname\n" 50 "\t-n\tprint the machine's network node hostname\n"
50 "\t-r\tprint the operating system release\n" 51 "\t-r\tprint the operating system release\n"
51 "\t-s\tprint the operating system name\n" 52 "\t-s\tprint the operating system name\n"
52 "\t-p\tprint the host processor type\n" 53
53 "\t-v\tprint the operating system version\n"; 54 "\t-p\tprint the host processor type\n"
55 "\t-v\tprint the operating system version\n";
54 56
55 57
56static void print_element(unsigned int mask, char *element); 58static void print_element(unsigned int mask, char *element);
@@ -80,77 +82,78 @@ static unsigned char toprint;
80 82
81int uname_main(int argc, char **argv) 83int uname_main(int argc, char **argv)
82{ 84{
83 struct utsname name; 85 struct utsname name;
84 char processor[256]; 86 char processor[256];
87
85#if defined(__sparc__) && defined(__linux__) 88#if defined(__sparc__) && defined(__linux__)
86 char *fake_sparc = getenv("FAKE_SPARC"); 89 char *fake_sparc = getenv("FAKE_SPARC");
87#endif 90#endif
88 91
89 toprint = 0; 92 toprint = 0;
90 93
91 /* Parse any options */ 94 /* Parse any options */
92 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 95 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
93 while (--argc > 0 && **(++argv) == '-') { 96 while (--argc > 0 && **(++argv) == '-') {
94 while (*(++(*argv))) { 97 while (*(++(*argv))) {
95 switch (**argv) { 98 switch (**argv) {
96 case 's': 99 case 's':
97 toprint |= PRINT_SYSNAME; 100 toprint |= PRINT_SYSNAME;
98 break; 101 break;
99 case 'n': 102 case 'n':
100 toprint |= PRINT_NODENAME; 103 toprint |= PRINT_NODENAME;
101 break; 104 break;
102 case 'r': 105 case 'r':
103 toprint |= PRINT_RELEASE; 106 toprint |= PRINT_RELEASE;
104 break; 107 break;
105 case 'v': 108 case 'v':
106 toprint |= PRINT_VERSION; 109 toprint |= PRINT_VERSION;
107 break; 110 break;
108 case 'm': 111 case 'm':
109 toprint |= PRINT_MACHINE; 112 toprint |= PRINT_MACHINE;
110 break; 113 break;
111 case 'p': 114 case 'p':
112 toprint |= PRINT_PROCESSOR; 115 toprint |= PRINT_PROCESSOR;
113 break; 116 break;
114 case 'a': 117 case 'a':
115 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE | 118 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE |
116 PRINT_PROCESSOR | PRINT_VERSION | 119 PRINT_PROCESSOR | PRINT_VERSION |
117 PRINT_MACHINE); 120 PRINT_MACHINE);
118 break; 121 break;
119 default: 122 default:
120 usage(uname_usage); 123 usage(uname_usage);
121 } 124 }
125 }
122 } 126 }
123 }
124 127
125 if (toprint == 0) 128 if (toprint == 0)
126 toprint = PRINT_SYSNAME; 129 toprint = PRINT_SYSNAME;
127 130
128 if (uname(&name) == -1) 131 if (uname(&name) == -1)
129 perror("cannot get system name"); 132 perror("cannot get system name");
130 133
131#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE) 134#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE)
132 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1) 135 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1)
133 perror("cannot get processor type"); 136 perror("cannot get processor type");
134} 137}
135 138
136#else 139#else
137 strcpy(processor, "unknown"); 140 strcpy(processor, "unknown");
138#endif 141#endif
139 142
140#if defined(__sparc__) && defined(__linux__) 143#if defined(__sparc__) && defined(__linux__)
141 if (fake_sparc != NULL 144 if (fake_sparc != NULL
142 && (fake_sparc[0] == 'y' 145 && (fake_sparc[0] == 'y'
143 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc"); 146 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc");
144#endif 147#endif
145 148
146 print_element(PRINT_SYSNAME, name.sysname); 149 print_element(PRINT_SYSNAME, name.sysname);
147 print_element(PRINT_NODENAME, name.nodename); 150 print_element(PRINT_NODENAME, name.nodename);
148 print_element(PRINT_RELEASE, name.release); 151 print_element(PRINT_RELEASE, name.release);
149 print_element(PRINT_VERSION, name.version); 152 print_element(PRINT_VERSION, name.version);
150 print_element(PRINT_MACHINE, name.machine); 153 print_element(PRINT_MACHINE, name.machine);
151 print_element(PRINT_PROCESSOR, processor); 154 print_element(PRINT_PROCESSOR, processor);
152 155
153 exit(TRUE); 156 exit(TRUE);
154} 157}
155 158
156/* If the name element set in MASK is selected for printing in `toprint', 159/* If the name element set in MASK is selected for printing in `toprint',
@@ -159,8 +162,8 @@ int uname_main(int argc, char **argv)
159 162
160static void print_element(unsigned int mask, char *element) 163static void print_element(unsigned int mask, char *element)
161{ 164{
162 if (toprint & mask) { 165 if (toprint & mask) {
163 toprint &= ~mask; 166 toprint &= ~mask;
164 printf("%s%c", element, toprint ? ' ' : '\n'); 167 printf("%s%c", element, toprint ? ' ' : '\n');
165 } 168 }
166} 169}
diff --git a/coreutils/uniq.c b/coreutils/uniq.c
index 965d290c2..1e41eaacd 100644
--- a/coreutils/uniq.c
+++ b/coreutils/uniq.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini uniq implementation for busybox 3 * Mini uniq implementation for busybox
3 * 4 *
@@ -27,119 +28,116 @@
27#include <errno.h> 28#include <errno.h>
28 29
29static const char uniq_usage[] = 30static const char uniq_usage[] =
30"uniq [OPTION]... [INPUT [OUTPUT]]\n" 31 "uniq [OPTION]... [INPUT [OUTPUT]]\n"
31"Discard all but one of successive identical lines from INPUT (or\n" 32 "Discard all but one of successive identical lines from INPUT (or\n"
32"standard input), writing to OUTPUT (or standard output).\n" 33 "standard input), writing to OUTPUT (or standard output).\n"
33"\n" 34 "\n"
34"\t-h\tdisplay this help and exit\n" 35 "\t-h\tdisplay this help and exit\n"
35"\n" 36
36"A field is a run of whitespace, then non-whitespace characters.\n" 37 "\n"
37"Fields are skipped before chars.\n" 38 "A field is a run of whitespace, then non-whitespace characters.\n"
38; 39 "Fields are skipped before chars.\n";
39 40
40/* max chars in line */ 41/* max chars in line */
41#define UNIQ_MAX 4096 42#define UNIQ_MAX 4096
42 43
43typedef void (Print)(FILE *, const char *); 44typedef void (Print) (FILE *, const char *);
44 45
45typedef int (Decide)(const char *, const char *); 46typedef int (Decide) (const char *, const char *);
46 47
47/* container for two lines to be compared */ 48/* container for two lines to be compared */
48typedef struct { 49typedef struct {
49 char *a; 50 char *a;
50 char *b; 51 char *b;
51 int recurrence; 52 int recurrence;
52 FILE *in; 53 FILE *in;
53 FILE *out; 54 FILE *out;
54 void *func; 55 void *func;
55} Subject; 56} Subject;
56 57
57/* set up all the variables of a uniq operation */ 58/* set up all the variables of a uniq operation */
58static Subject * 59static Subject *subject_init(Subject * self, FILE * in, FILE * out,
59subject_init(Subject *self, FILE *in, FILE *out, void *func) 60 void *func)
60{ 61{
61 self->a = NULL; 62 self->a = NULL;
62 self->b = NULL; 63 self->b = NULL;
63 self->in = in; 64 self->in = in;
64 self->out = out; 65 self->out = out;
65 self->func = func; 66 self->func = func;
66 self->recurrence = 0; 67 self->recurrence = 0;
67 return self; 68 return self;
68} 69}
69 70
70/* point a and b to the appropriate lines; 71/* point a and b to the appropriate lines;
71 * count the recurrences (if any) of a string; 72 * count the recurrences (if any) of a string;
72 */ 73 */
73static Subject * 74static Subject *subject_next(Subject * self)
74subject_next(Subject *self)
75{ 75{
76 /* tmp line holders */ 76 /* tmp line holders */
77 static char line[2][UNIQ_MAX]; 77 static char line[2][UNIQ_MAX];
78 static int alternator = 0; 78 static int alternator = 0;
79 79
80 if (fgets(line[alternator], UNIQ_MAX, self->in)) { 80 if (fgets(line[alternator], UNIQ_MAX, self->in)) {
81 self->a = self->b; 81 self->a = self->b;
82 self->b = line[alternator]; 82 self->b = line[alternator];
83 alternator ^= 1; 83 alternator ^= 1;
84 return self; 84 return self;
85 } 85 }
86 86
87 return NULL; 87 return NULL;
88} 88}
89 89
90static Subject * 90static Subject *subject_last(Subject * self)
91subject_last(Subject *self)
92{ 91{
93 self->a = self->b; 92 self->a = self->b;
94 self->b = NULL; 93 self->b = NULL;
95 return self; 94 return self;
96} 95}
97 96
98static Subject * 97static Subject *subject_study(Subject * self)
99subject_study(Subject *self)
100{ 98{
101 if (self->a == NULL) { 99 if (self->a == NULL) {
102 return self; 100 return self;
103 } 101 }
104 if (self->b == NULL) { 102 if (self->b == NULL) {
105 fprintf(self->out, "%s", self->a); 103 fprintf(self->out, "%s", self->a);
104 return self;
105 }
106 if (strcmp(self->a, self->b) == 0) {
107 self->recurrence++;
108 } else {
109 fprintf(self->out, "%s", self->a);
110 self->recurrence = 0;
111 }
106 return self; 112 return self;
107 }
108 if (strcmp(self->a, self->b) == 0) {
109 self->recurrence++;
110 } else {
111 fprintf(self->out, "%s", self->a);
112 self->recurrence = 0;
113 }
114 return self;
115} 113}
116 114
117static int 115static int
118set_file_pointers(int schema, FILE **in, FILE **out, char **argv) 116set_file_pointers(int schema, FILE ** in, FILE ** out, char **argv)
119{ 117{
120 switch (schema) { 118 switch (schema) {
121 case 0: 119 case 0:
122 *in = stdin; 120 *in = stdin;
123 *out = stdout; 121 *out = stdout;
124 break; 122 break;
125 case 1: 123 case 1:
126 *in = fopen(argv[0], "r"); 124 *in = fopen(argv[0], "r");
127 *out = stdout; 125 *out = stdout;
128 break; 126 break;
129 case 2: 127 case 2:
130 *in = fopen(argv[0], "r"); 128 *in = fopen(argv[0], "r");
131 *out = fopen(argv[1], "w"); 129 *out = fopen(argv[1], "w");
132 break; 130 break;
133 } 131 }
134 if (*in == NULL) { 132 if (*in == NULL) {
135 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno)); 133 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno));
136 return errno; 134 return errno;
137 } 135 }
138 if (*out == NULL) { 136 if (*out == NULL) {
139 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno)); 137 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno));
140 return errno; 138 return errno;
141 } 139 }
142 return 0; 140 return 0;
143} 141}
144 142
145 143
@@ -152,45 +150,44 @@ set_file_pointers(int schema, FILE **in, FILE **out, char **argv)
152/* it seems like GNU/uniq only takes one or two files as an option */ 150/* it seems like GNU/uniq only takes one or two files as an option */
153 151
154/* ________________________________________________________________________ */ 152/* ________________________________________________________________________ */
155int 153int uniq_main(int argc, char **argv)
156uniq_main(int argc, char **argv)
157{ 154{
158 int i; 155 int i;
159 char opt; 156 char opt;
160 FILE *in, *out; 157 FILE *in, *out;
161 Subject s; 158 Subject s;
162 159
163 /* parse argv[] */ 160 /* parse argv[] */
164 for (i = 1; i < argc; i++) { 161 for (i = 1; i < argc; i++) {
165 if (argv[i][0] == '-') { 162 if (argv[i][0] == '-') {
166 opt = argv[i][1]; 163 opt = argv[i][1];
167 switch (opt) { 164 switch (opt) {
168 case '-': 165 case '-':
169 case 'h': 166 case 'h':
170 usage(uniq_usage); 167 usage(uniq_usage);
171 default: 168 default:
172 usage(uniq_usage); 169 usage(uniq_usage);
173 } 170 }
174 } else { 171 } else {
175 break; 172 break;
173 }
176 } 174 }
177 }
178 175
179 /* 0 src: stdin; dst: stdout */ 176 /* 0 src: stdin; dst: stdout */
180 /* 1 src: file; dst: stdout */ 177 /* 1 src: file; dst: stdout */
181 /* 2 src: file; dst: file */ 178 /* 2 src: file; dst: file */
182 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) { 179 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) {
183 exit(1); 180 exit(1);
184 } 181 }
185 182
186 subject_init(&s, in, out, NULL); 183 subject_init(&s, in, out, NULL);
187 while (subject_next(&s)) { 184 while (subject_next(&s)) {
185 subject_study(&s);
186 }
187 subject_last(&s);
188 subject_study(&s); 188 subject_study(&s);
189 }
190 subject_last(&s);
191 subject_study(&s);
192 189
193 exit(0); 190 exit(0);
194} 191}
195 192
196/* $Id: uniq.c,v 1.6 2000/02/07 05:29:42 erik Exp $ */ 193/* $Id: uniq.c,v 1.7 2000/02/08 19:58:47 erik Exp $ */
diff --git a/coreutils/wc.c b/coreutils/wc.c
index e69f0d899..8004e6294 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini wc implementation for busybox 3 * Mini wc implementation for busybox
3 * 4 *
@@ -23,78 +24,82 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n" 26static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n"
26"Print line, word, and byte counts for each FILE, and a total line if\n" 27 "Print line, word, and byte counts for each FILE, and a total line if\n"
27"more than one FILE is specified. With no FILE, read standard input.\n" 28 "more than one FILE is specified. With no FILE, read standard input.\n"
28"\t-c\tprint the byte counts\n" 29 "\t-c\tprint the byte counts\n"
29"\t-l\tprint the newline counts\n" 30 "\t-l\tprint the newline counts\n"
30"\t-L\tprint the length of the longest line\n" 31
31"\t-w\tprint the word counts\n"; 32 "\t-L\tprint the length of the longest line\n"
33 "\t-w\tprint the word counts\n";
32 34
33static int total_lines, total_words, total_chars, max_length; 35static int total_lines, total_words, total_chars, max_length;
34static int print_lines, print_words, print_chars, print_length; 36static int print_lines, print_words, print_chars, print_length;
35 37
36void print_counts (int lines, int words, int chars, int length, 38void print_counts(int lines, int words, int chars, int length,
37 const char *name) { 39 const char *name)
40{
38 char const *space = ""; 41 char const *space = "";
42
39 if (print_lines) { 43 if (print_lines) {
40 printf ("%7d", lines); 44 printf("%7d", lines);
41 space = " "; 45 space = " ";
42 } 46 }
43 if (print_words) { 47 if (print_words) {
44 printf ("%s%7d", space, words); 48 printf("%s%7d", space, words);
45 space = " "; 49 space = " ";
46 } 50 }
47 if (print_chars) { 51 if (print_chars) {
48 printf ("%s%7d", space, chars); 52 printf("%s%7d", space, chars);
49 space = " "; 53 space = " ";
50 } 54 }
51 if (print_length) 55 if (print_length)
52 printf ("%s%7d", space, length); 56 printf("%s%7d", space, length);
53 if (*name) 57 if (*name)
54 printf (" %s", name); 58 printf(" %s", name);
55 putchar ('\n'); 59 putchar('\n');
56} 60}
57 61
58static void wc_file(FILE *file, const char *name) 62static void wc_file(FILE * file, const char *name)
59{ 63{
60 int lines, words, chars, length; 64 int lines, words, chars, length;
61 int in_word = 0, linepos = 0; 65 int in_word = 0, linepos = 0;
62 int c; 66 int c;
67
63 lines = words = chars = length = 0; 68 lines = words = chars = length = 0;
64 while ((c = getc(file)) != EOF) { 69 while ((c = getc(file)) != EOF) {
65 chars++; 70 chars++;
66 switch (c) { 71 switch (c) {
67 case '\n': 72 case '\n':
68 lines++; 73 lines++;
69 case '\r': 74 case '\r':
70 case '\f': 75 case '\f':
71 if (linepos > length) 76 if (linepos > length)
72 length = linepos; 77 length = linepos;
73 linepos = 0; 78 linepos = 0;
74 goto word_separator; 79 goto word_separator;
75 case '\t': 80 case '\t':
76 linepos += 8 - (linepos % 8); 81 linepos += 8 - (linepos % 8);
77 goto word_separator; 82 goto word_separator;
78 case ' ': 83 case ' ':
79 linepos++; 84 linepos++;
80 case '\v': 85 case '\v':
81 word_separator: 86 word_separator:
82 if (in_word) { 87 if (in_word) {
83 in_word = 0; 88 in_word = 0;
84 words++; 89 words++;
85 } 90 }
86 break; 91 break;
87 default: 92 default:
88 linepos++; 93 linepos++;
89 in_word = 1; 94 in_word = 1;
90 break; 95 break;
91 } 96 }
92 } 97 }
93 if (linepos > length) 98 if (linepos > length)
94 length = linepos; 99 length = linepos;
95 if (in_word) 100 if (in_word)
96 words++; 101 words++;
97 print_counts (lines, words, chars, length, name); 102 print_counts(lines, words, chars, length, name);
98 total_lines += lines; 103 total_lines += lines;
99 total_words += words; 104 total_words += words;
100 total_chars += chars; 105 total_chars += chars;
@@ -104,28 +109,30 @@ static void wc_file(FILE *file, const char *name)
104 fflush(stdout); 109 fflush(stdout);
105} 110}
106 111
107int wc_main(int argc, char **argv) { 112int wc_main(int argc, char **argv)
113{
108 FILE *file; 114 FILE *file;
115
109 total_lines = total_words = total_chars = max_length = 0; 116 total_lines = total_words = total_chars = max_length = 0;
110 print_lines = print_words = print_chars = print_length = 0; 117 print_lines = print_words = print_chars = print_length = 0;
111 118
112 while (--argc && **(++argv) == '-') { 119 while (--argc && **(++argv) == '-') {
113 while (*++(*argv)) 120 while (*++(*argv))
114 switch (**argv) { 121 switch (**argv) {
115 case 'c': 122 case 'c':
116 print_chars = 1; 123 print_chars = 1;
117 break; 124 break;
118 case 'l': 125 case 'l':
119 print_lines = 1; 126 print_lines = 1;
120 break; 127 break;
121 case 'L': 128 case 'L':
122 print_length = 1; 129 print_length = 1;
123 break; 130 break;
124 case 'w': 131 case 'w':
125 print_words = 1; 132 print_words = 1;
126 break; 133 break;
127 default: 134 default:
128 usage (wc_usage); 135 usage(wc_usage);
129 } 136 }
130 } 137 }
131 138
@@ -135,16 +142,14 @@ int wc_main(int argc, char **argv) {
135 if (argc == 0) { 142 if (argc == 0) {
136 wc_file(stdin, ""); 143 wc_file(stdin, "");
137 exit(TRUE); 144 exit(TRUE);
138 } 145 } else if (argc == 1) {
139 else if (argc == 1) {
140 file = fopen(*argv, "r"); 146 file = fopen(*argv, "r");
141 if (file == NULL) { 147 if (file == NULL) {
142 perror(*argv); 148 perror(*argv);
143 exit(FALSE); 149 exit(FALSE);
144 } 150 }
145 wc_file(file, *argv); 151 wc_file(file, *argv);
146 } 152 } else {
147 else {
148 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) { 153 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) {
149 file = fopen(*argv, "r"); 154 file = fopen(*argv, "r");
150 if (file == NULL) { 155 if (file == NULL) {
@@ -154,8 +159,8 @@ int wc_main(int argc, char **argv) {
154 wc_file(file, *argv); 159 wc_file(file, *argv);
155 argv++; 160 argv++;
156 } 161 }
157 print_counts (total_lines, total_words, total_chars, 162 print_counts(total_lines, total_words, total_chars,
158 max_length, "total"); 163 max_length, "total");
159 } 164 }
160 exit(TRUE); 165 exit(TRUE);
161} 166}
diff --git a/coreutils/whoami.c b/coreutils/whoami.c
index 7fd5d01b2..3677c2fbc 100644
--- a/coreutils/whoami.c
+++ b/coreutils/whoami.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini whoami implementation for busybox 3 * Mini whoami implementation for busybox
3 * 4 *
@@ -24,21 +25,25 @@
24#include <pwd.h> 25#include <pwd.h>
25 26
26static const char whoami_usage[] = "whoami\n\n" 27static const char whoami_usage[] = "whoami\n\n"
27"Print the user name associated with the current effective user id.\n" 28 "Print the user name associated with the current effective user id.\n"
28"Same as id -un.\n";
29 29
30extern int whoami_main(int argc, char **argv) { 30 "Same as id -un.\n";
31
32extern int whoami_main(int argc, char **argv)
33{
31 struct passwd *pw; 34 struct passwd *pw;
32 uid_t uid; 35 uid_t uid;
33 36
34 if (argc > 1) usage (whoami_usage); 37 if (argc > 1)
38 usage(whoami_usage);
35 39
36 uid = geteuid (); 40 uid = geteuid();
37 pw = getpwuid (uid); 41 pw = getpwuid(uid);
38 if (pw) { 42 if (pw) {
39 puts (pw->pw_name); 43 puts(pw->pw_name);
40 exit (TRUE); 44 exit(TRUE);
41 } 45 }
42 fprintf (stderr, "%s: cannot find username for UID %u\n", argv[0], (unsigned) uid); 46 fprintf(stderr, "%s: cannot find username for UID %u\n", argv[0],
43 exit (FALSE); 47 (unsigned) uid);
48 exit(FALSE);
44} 49}
diff --git a/coreutils/yes.c b/coreutils/yes.c
index 96d6257d0..ac67845ac 100644
--- a/coreutils/yes.c
+++ b/coreutils/yes.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini yes implementation for busybox 3 * Mini yes implementation for busybox
3 * 4 *
@@ -22,19 +23,22 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int yes_main(int argc, char **argv) { 26extern int yes_main(int argc, char **argv)
27{
26 int i; 28 int i;
29
27 if (argc == 1) 30 if (argc == 1)
28 while (1) 31 while (1)
29 if (puts ("y") == EOF) { 32 if (puts("y") == EOF) {
30 perror ("yes"); 33 perror("yes");
31 exit(FALSE); 34 exit(FALSE);
32 } 35 }
33 36
34 while (1) 37 while (1)
35 for (i = 1; i < argc; i++) 38 for (i = 1; i < argc; i++)
36 if (fputs (argv[i], stdout) == EOF || putchar (i == argc - 1 ? '\n' : ' ') == EOF) { 39 if (fputs(argv[i], stdout) == EOF
37 perror ("yes"); 40 || putchar(i == argc - 1 ? '\n' : ' ') == EOF) {
41 perror("yes");
38 exit(FALSE); 42 exit(FALSE);
39 } 43 }
40 exit(TRUE); 44 exit(TRUE);
diff --git a/cp_mv.c b/cp_mv.c
index 2ba8662b9..33adf8f55 100644
--- a/cp_mv.c
+++ b/cp_mv.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini `cp' and `mv' implementation for BusyBox. 3 * Mini `cp' and `mv' implementation for BusyBox.
3 * 4 *
@@ -39,217 +40,205 @@
39 40
40#define is_cp 0 41#define is_cp 0
41#define is_mv 1 42#define is_mv 1
42static const char *dz; /* dollar zero, .bss */ 43static const char *dz; /* dollar zero, .bss */
43static int dz_i; /* index, .bss */ 44static int dz_i; /* index, .bss */
44static const char *cp_mv_usage[] = /* .rodata */ 45static const char *cp_mv_usage[] = /* .rodata */
45{ 46{
46 "cp [OPTION]... SOURCE DEST\n" 47 "cp [OPTION]... SOURCE DEST\n"
47 " or: cp [OPTION]... SOURCE... DIRECTORY\n\n" 48 " or: cp [OPTION]... SOURCE... DIRECTORY\n\n"
48 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" 49 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n"
49 "\n" 50 "\n"
50 "\t-a\tsame as -dpR\n" 51 "\t-a\tsame as -dpR\n"
51 "\t-d\tpreserve links\n" 52 "\t-d\tpreserve links\n"
52 "\t-p\tpreserve file attributes if possible\n" 53 "\t-p\tpreserve file attributes if possible\n"
53 "\t-R\tcopy directories recursively\n" 54 "\t-R\tcopy directories recursively\n",
54 , 55 "mv SOURCE DEST\n"
55 "mv SOURCE DEST\n" 56 " or: mv SOURCE... DIRECTORY\n\n"
56 " or: mv SOURCE... DIRECTORY\n\n" 57 "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n"
57 "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n" 58 "Warning!! This is not GNU `mv'. It does not preserve hard links.\n"
58 "Warning!! This is not GNU `mv'. It does not preserve hard links.\n"
59}; 59};
60 60
61extern int cp_mv_main(int argc, char **argv) 61extern int cp_mv_main(int argc, char **argv)
62{ 62{
63 __label__ name_too_long__exit; 63 __label__ name_too_long__exit;
64 __label__ exit_false; 64 __label__ exit_false;
65 65
66 int recursiveFlag; 66 int recursiveFlag;
67 int followLinks; 67 int followLinks;
68 int preserveFlag; 68 int preserveFlag;
69
70 const char *baseSrcName;
71 int srcDirFlag;
72
73 char baseDestName[PATH_MAX + 1];
74 size_t baseDestLen;
75 int destDirFlag;
76
77 void fill_baseDest_buf(char *_buf, size_t * _buflen) {
78 const char *srcBasename;
79 if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) {
80 srcBasename = baseSrcName;
81 if (_buf[*_buflen - 1] != '/') {
82 if (++(*_buflen) > PATH_MAX)
83 goto name_too_long__exit;
84 strcat(_buf, "/");
85 }
86 }
87 if (*_buflen + strlen(srcBasename) > PATH_MAX)
88 goto name_too_long__exit;
89 strcat(_buf, srcBasename);
90 return;
91 }
69 92
70 const char *baseSrcName; 93 int fileAction(const char *fileName, struct stat *statbuf) {
71 int srcDirFlag; 94 __label__ return_false;
95 char destName[PATH_MAX + 1];
96 size_t destLen;
97 const char *srcBasename;
98
99 strcpy(destName, baseDestName);
100 destLen = strlen(destName);
101
102 if (srcDirFlag == TRUE) {
103 if (recursiveFlag == FALSE) {
104 fprintf(stderr, omitting_directory, "cp", baseSrcName);
105 return TRUE;
106 }
107 srcBasename = (strstr(fileName, baseSrcName)
108 + strlen(baseSrcName));
109
110 if (destLen + strlen(srcBasename) > PATH_MAX) {
111 fprintf(stderr, name_too_long, "cp");
112 goto return_false;
113 }
114 strcat(destName, srcBasename);
115 } else if (destDirFlag == TRUE) {
116 fill_baseDest_buf(&destName[0], &destLen);
117 } else {
118 srcBasename = baseSrcName;
119 }
120 return copyFile(fileName, destName, preserveFlag, followLinks);
72 121
73 char baseDestName[PATH_MAX + 1]; 122 return_false:
74 size_t baseDestLen; 123 return FALSE;
75 int destDirFlag; 124 }
76 125
77 void fill_baseDest_buf(char *_buf, size_t *_buflen) 126 int rmfileAction(const char *fileName, struct stat *statbuf) {
78 { 127 if (unlink(fileName) < 0) {
79 const char *srcBasename; 128 perror(fileName);
80 if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) 129 return FALSE;
81 {
82 srcBasename = baseSrcName;
83 if (_buf[*_buflen - 1] != '/')
84 {
85 if (++(*_buflen) > PATH_MAX)
86 goto name_too_long__exit;
87 strcat(_buf, "/");
88 } 130 }
89 } 131 return TRUE;
90 if (*_buflen + strlen(srcBasename) > PATH_MAX)
91 goto name_too_long__exit;
92 strcat(_buf, srcBasename);
93 return;
94 } 132 }
95 133
96 int fileAction(const char *fileName, struct stat *statbuf) 134 int rmdirAction(const char *fileName, struct stat *statbuf) {
97 { 135 if (rmdir(fileName) < 0) {
98 __label__ return_false; 136 perror(fileName);
99 char destName[PATH_MAX + 1]; 137 return FALSE;
100 size_t destLen;
101 const char *srcBasename;
102
103 strcpy(destName, baseDestName);
104 destLen = strlen(destName);
105
106 if (srcDirFlag == TRUE)
107 {
108 if (recursiveFlag == FALSE)
109 {
110 fprintf(stderr, omitting_directory, "cp", baseSrcName);
111 return TRUE;
112 }
113 srcBasename = (strstr(fileName, baseSrcName)
114 + strlen(baseSrcName));
115 if (destLen + strlen(srcBasename) > PATH_MAX)
116 {
117 fprintf(stderr, name_too_long, "cp");
118 goto return_false;
119 } 138 }
120 strcat(destName, srcBasename); 139 return TRUE;
121 }
122 else if (destDirFlag == TRUE)
123 {
124 fill_baseDest_buf(&destName[0], &destLen);
125 }
126 else
127 {
128 srcBasename = baseSrcName;
129 }
130 return copyFile(fileName, destName, preserveFlag, followLinks);
131
132 return_false:
133 return FALSE;
134 } 140 }
135 141
136 int rmfileAction(const char *fileName, struct stat* statbuf) 142 if ((dz = strrchr(*argv, '/')) == NULL)
137 { 143 dz = *argv;
138 if (unlink(fileName) < 0 ) { 144 else
139 perror(fileName); 145 dz++;
140 return FALSE; 146 if (*dz == 'c' && *(dz + 1) == 'p')
141 } 147 dz_i = is_cp;
142 return TRUE; 148 else
143 } 149 dz_i = is_mv;
144 150 if (argc < 3)
145 int rmdirAction(const char *fileName, struct stat* statbuf) 151 usage(cp_mv_usage[dz_i]);
146 { 152 argc--;
147 if (rmdir(fileName) < 0 ) { 153 argv++;
148 perror(fileName); 154
149 return FALSE; 155 if (dz_i == is_cp) {
150 } 156 recursiveFlag = preserveFlag = FALSE;
151 return TRUE; 157 followLinks = TRUE;
152 } 158 while (**argv == '-') {
153 159 while (*++(*argv)) {
154 if ((dz = strrchr(*argv, '/')) == NULL) dz = *argv; else dz++; 160 switch (**argv) {
155 if (*dz == 'c' && *(dz + 1) == 'p') dz_i = is_cp; else dz_i = is_mv; 161 case 'a':
156 if (argc < 3) usage(cp_mv_usage[dz_i]); 162 followLinks = FALSE;
157 argc--; 163 preserveFlag = TRUE;
158 argv++; 164 recursiveFlag = TRUE;
159 165 break;
160 if (dz_i == is_cp) 166 case 'd':
161 { 167 followLinks = FALSE;
162 recursiveFlag = preserveFlag = FALSE; 168 break;
163 followLinks = TRUE; 169 case 'p':
164 while (**argv == '-') 170 preserveFlag = TRUE;
165 { 171 break;
166 while (*++(*argv)) 172 case 'R':
167 { 173 recursiveFlag = TRUE;
168 switch (**argv) 174 break;
169 { 175 default:
170 case 'a': 176 usage(cp_mv_usage[is_cp]);
171 followLinks = FALSE; 177 }
172 preserveFlag = TRUE; 178 }
173 recursiveFlag = TRUE; 179 argc--;
174 break; 180 argv++;
175 case 'd':
176 followLinks = FALSE;
177 break;
178 case 'p':
179 preserveFlag = TRUE;
180 break;
181 case 'R':
182 recursiveFlag = TRUE;
183 break;
184 default:
185 usage(cp_mv_usage[is_cp]);
186 } 181 }
187 } 182 } else { /* (dz_i == is_mv) */
188 argc--;
189 argv++;
190 }
191 }
192 else /* (dz_i == is_mv) */
193 {
194 recursiveFlag = preserveFlag = TRUE;
195 followLinks = FALSE;
196 }
197 183
198 if (strlen(argv[argc - 1]) > PATH_MAX) 184 recursiveFlag = preserveFlag = TRUE;
199 { 185 followLinks = FALSE;
200 fprintf(stderr, name_too_long, "cp"); 186 }
201 goto exit_false;
202 }
203 strcpy(baseDestName, argv[argc - 1]);
204 baseDestLen = strlen(baseDestName);
205 if (baseDestLen == 0) goto exit_false;
206 187
207 destDirFlag = isDirectory(baseDestName, TRUE); 188 if (strlen(argv[argc - 1]) > PATH_MAX) {
208 if ((argc > 3) && destDirFlag == FALSE) 189 fprintf(stderr, name_too_long, "cp");
209 { 190 goto exit_false;
210 fprintf(stderr, not_a_directory, "cp", baseDestName); 191 }
211 goto exit_false; 192 strcpy(baseDestName, argv[argc - 1]);
212 } 193 baseDestLen = strlen(baseDestName);
194 if (baseDestLen == 0)
195 goto exit_false;
196
197 destDirFlag = isDirectory(baseDestName, TRUE);
198 if ((argc > 3) && destDirFlag == FALSE) {
199 fprintf(stderr, not_a_directory, "cp", baseDestName);
200 goto exit_false;
201 }
213 202
214 while (argc-- > 1) 203 while (argc-- > 1) {
215 { 204 size_t srcLen;
216 size_t srcLen; 205 int flags_memo;
217 int flags_memo;
218 206
219 baseSrcName = *(argv++); 207 baseSrcName = *(argv++);
220 208
221 if ((srcLen = strlen(baseSrcName)) > PATH_MAX) 209 if ((srcLen = strlen(baseSrcName)) > PATH_MAX)
222 goto name_too_long__exit; 210 goto name_too_long__exit;
223 211
224 if (srcLen == 0) continue; 212 if (srcLen == 0)
213 continue;
225 214
226 srcDirFlag = isDirectory(baseSrcName, followLinks); 215 srcDirFlag = isDirectory(baseSrcName, followLinks);
227 216
228 if ((flags_memo = (recursiveFlag == TRUE && 217 if ((flags_memo = (recursiveFlag == TRUE &&
229 srcDirFlag == TRUE && destDirFlag == TRUE))) 218 srcDirFlag == TRUE && destDirFlag == TRUE))) {
230 { 219 fill_baseDest_buf(&baseDestName[0], &baseDestLen);
231 fill_baseDest_buf(&baseDestName[0], &baseDestLen); 220 }
221 if (recursiveAction(baseSrcName,
222 recursiveFlag, followLinks, FALSE,
223 fileAction, fileAction) == FALSE)
224 goto exit_false;
225
226 if (dz_i == is_mv &&
227 recursiveAction(baseSrcName,
228 recursiveFlag, followLinks, TRUE,
229 rmfileAction, rmdirAction) == FALSE)
230 goto exit_false;
231
232 if (flags_memo)
233 *(baseDestName + baseDestLen) = '\0';
232 } 234 }
233 if (recursiveAction(baseSrcName,
234 recursiveFlag, followLinks, FALSE,
235 fileAction, fileAction)
236 == FALSE) goto exit_false;
237
238 if (dz_i == is_mv &&
239 recursiveAction(baseSrcName,
240 recursiveFlag, followLinks, TRUE,
241 rmfileAction, rmdirAction)
242 == FALSE) goto exit_false;
243 235
244 if (flags_memo) *(baseDestName + baseDestLen) = '\0'; 236 exit TRUE;
245 }
246 237
247 exit TRUE; 238 name_too_long__exit:
248 239 fprintf(stderr, name_too_long, "cp");
249 name_too_long__exit: 240 exit_false:
250 fprintf(stderr, name_too_long, "cp"); 241 exit FALSE;
251 exit_false:
252 exit FALSE;
253} 242}
254 243
255// Local Variables: 244// Local Variables:
diff --git a/date.c b/date.c
index a3528921d..b4c3e7153 100644
--- a/date.c
+++ b/date.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini date implementation for busybox 3 * Mini date implementation for busybox
3 * 4 *
@@ -38,12 +39,13 @@
38 an RFC 822 complient date output for shell scripting 39 an RFC 822 complient date output for shell scripting
39 mail commands */ 40 mail commands */
40 41
41static const char date_usage[] = "date [OPTION]... [+FORMAT]\n" 42static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
42" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n" 43 " or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n\n"
43"Display the current time in the given FORMAT, or set the system date.\n" 44 "Display the current time in the given FORMAT, or set the system date.\n"
44"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" 45 "\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n"
45"\t-s\t\tset time described by STRING\n" 46 "\t-s\t\tset time described by STRING\n"
46"\t-u\t\tprint or set Coordinated Universal Time\n"; 47
48 "\t-u\t\tprint or set Coordinated Universal Time\n";
47 49
48 50
49/* Input parsing code is always bulky - used heavy duty libc stuff as 51/* Input parsing code is always bulky - used heavy duty libc stuff as
@@ -51,240 +53,233 @@ static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
51 53
52/* Default input handling to save suprising some people */ 54/* Default input handling to save suprising some people */
53 55
54struct tm * 56struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
55date_conv_time(struct tm *tm_time, const char *t_string) { 57{
56 int nr; 58 int nr;
57 59
58 nr = sscanf(t_string, "%2d%2d%2d%2d%d", 60 nr = sscanf(t_string, "%2d%2d%2d%2d%d",
59 &(tm_time->tm_mon), 61 &(tm_time->tm_mon),
60 &(tm_time->tm_mday), 62 &(tm_time->tm_mday),
61 &(tm_time->tm_hour), 63 &(tm_time->tm_hour),
62 &(tm_time->tm_min), 64 &(tm_time->tm_min), &(tm_time->tm_year));
63 &(tm_time->tm_year)); 65
64 66 if (nr < 4 || nr > 5) {
65 if(nr < 4 || nr > 5) { 67 fprintf(stderr, invalid_date, "date", t_string);
66 fprintf(stderr, invalid_date, "date", t_string); 68 exit(FALSE);
67 exit( FALSE); 69 }
68 } 70
69 71 /* correct for century - minor Y2K problem here? */
70 /* correct for century - minor Y2K problem here? */ 72 if (tm_time->tm_year >= 1900)
71 if(tm_time->tm_year >= 1900) 73 tm_time->tm_year -= 1900;
72 tm_time->tm_year -= 1900; 74 /* adjust date */
73 /* adjust date */ 75 tm_time->tm_mon -= 1;
74 tm_time->tm_mon -= 1; 76
75 77 return (tm_time);
76 return(tm_time);
77 78
78} 79}
79 80
80 81
81/* The new stuff for LRP */ 82/* The new stuff for LRP */
82 83
83struct tm * 84struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
84date_conv_ftime(struct tm *tm_time, const char *t_string) { 85{
85 struct tm itm_time, jtm_time, ktm_time, \ 86 struct tm itm_time, jtm_time, ktm_time, ltm_time, mtm_time, ntm_time;
86 ltm_time, mtm_time, ntm_time; 87
87 88 itm_time = *tm_time;
88 itm_time = *tm_time; 89 jtm_time = *tm_time;
89 jtm_time = *tm_time; 90 ktm_time = *tm_time;
90 ktm_time = *tm_time; 91 ltm_time = *tm_time;
91 ltm_time = *tm_time; 92 mtm_time = *tm_time;
92 mtm_time = *tm_time; 93 ntm_time = *tm_time;
93 ntm_time = *tm_time; 94
94 95 /* Parse input and assign appropriately to tm_time */
95 /* Parse input and assign appropriately to tm_time */ 96
96 97 if (sscanf(t_string, "%d:%d:%d",
97 if(sscanf(t_string, "%d:%d:%d", 98 &itm_time.tm_hour, &itm_time.tm_min, &itm_time.tm_sec) == 3) {
98 &itm_time.tm_hour, 99
99 &itm_time.tm_min, 100 *tm_time = itm_time;
100 &itm_time.tm_sec) == 3 ) { 101 return (tm_time);
101 102
102 *tm_time = itm_time; 103 } else if (sscanf(t_string, "%d:%d",
103 return(tm_time); 104 &jtm_time.tm_hour, &jtm_time.tm_min) == 2) {
104 105
105 } else if (sscanf(t_string, "%d:%d", 106 *tm_time = jtm_time;
106 &jtm_time.tm_hour, 107 return (tm_time);
107 &jtm_time.tm_min) == 2) { 108
108 109 } else if (sscanf(t_string, "%d.%d-%d:%d:%d",
109 *tm_time = jtm_time; 110 &ktm_time.tm_mon,
110 return(tm_time); 111 &ktm_time.tm_mday,
111 112 &ktm_time.tm_hour,
112 } else if (sscanf(t_string, "%d.%d-%d:%d:%d", 113 &ktm_time.tm_min, &ktm_time.tm_sec) == 5) {
113 &ktm_time.tm_mon, 114
114 &ktm_time.tm_mday, 115 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
115 &ktm_time.tm_hour, 116 *tm_time = ktm_time;
116 &ktm_time.tm_min, 117 return (tm_time);
117 &ktm_time.tm_sec) == 5) { 118
118 119 } else if (sscanf(t_string, "%d.%d-%d:%d",
119 ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 120 &ltm_time.tm_mon,
120 *tm_time = ktm_time; 121 &ltm_time.tm_mday,
121 return(tm_time); 122 &ltm_time.tm_hour, &ltm_time.tm_min) == 4) {
122 123
123 } else if (sscanf(t_string, "%d.%d-%d:%d", 124 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
124 &ltm_time.tm_mon, 125 *tm_time = ltm_time;
125 &ltm_time.tm_mday, 126 return (tm_time);
126 &ltm_time.tm_hour, 127
127 &ltm_time.tm_min) == 4) { 128 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d",
128 129 &mtm_time.tm_year,
129 ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 130 &mtm_time.tm_mon,
130 *tm_time = ltm_time; 131 &mtm_time.tm_mday,
131 return(tm_time); 132 &mtm_time.tm_hour,
132 133 &mtm_time.tm_min, &mtm_time.tm_sec) == 6) {
133 } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d", 134
134 &mtm_time.tm_year, 135 mtm_time.tm_year -= 1900; /* Adjust years */
135 &mtm_time.tm_mon, 136 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
136 &mtm_time.tm_mday, 137 *tm_time = mtm_time;
137 &mtm_time.tm_hour, 138 return (tm_time);
138 &mtm_time.tm_min, 139
139 &mtm_time.tm_sec) == 6) { 140 } else if (sscanf(t_string, "%d.%d.%d-%d:%d",
140 141 &ntm_time.tm_year,
141 mtm_time.tm_year -= 1900; /* Adjust years */ 142 &ntm_time.tm_mon,
142 mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 143 &ntm_time.tm_mday,
143 *tm_time = mtm_time; 144 &ntm_time.tm_hour, &ntm_time.tm_min) == 5) {
144 return(tm_time); 145 ntm_time.tm_year -= 1900; /* Adjust years */
145 146 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
146 } else if (sscanf(t_string, "%d.%d.%d-%d:%d", 147 *tm_time = ntm_time;
147 &ntm_time.tm_year, 148 return (tm_time);
148 &ntm_time.tm_mon, 149
149 &ntm_time.tm_mday, 150 }
150 &ntm_time.tm_hour, 151
151 &ntm_time.tm_min) == 5) { 152 fprintf(stderr, invalid_date, "date", t_string);
152 ntm_time.tm_year -= 1900; /* Adjust years */ 153
153 ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ 154 exit(FALSE);
154 *tm_time = ntm_time;
155 return(tm_time);
156
157 }
158
159 fprintf(stderr, invalid_date, "date", t_string);
160
161 exit( FALSE);
162 155
163} 156}
164 157
165 158
166int 159int date_main(int argc, char **argv)
167date_main(int argc, char * * argv)
168{ 160{
169 char *date_str = NULL; 161 char *date_str = NULL;
170 char *date_fmt = NULL; 162 char *date_fmt = NULL;
171 char *t_buff; 163 char *t_buff;
172 int i; 164 int i;
173 int set_time = 0; 165 int set_time = 0;
174 int rfc822 = 0; 166 int rfc822 = 0;
175 int utc = 0; 167 int utc = 0;
176 int use_arg = 0; 168 int use_arg = 0;
177 time_t tm; 169 time_t tm;
178 struct tm tm_time; 170 struct tm tm_time;
179 171
180 /* Interpret command line args */ 172 /* Interpret command line args */
181 i = --argc; 173 i = --argc;
182 argv++; 174 argv++;
183 while (i > 0 && **argv) { 175 while (i > 0 && **argv) {
184 if (**argv == '-') { 176 if (**argv == '-') {
185 while (i>0 && *++(*argv)) switch (**argv) { 177 while (i > 0 && *++(*argv))
186 case 'R': 178 switch (**argv) {
187 rfc822 = 1; 179 case 'R':
188 break; 180 rfc822 = 1;
189 case 's': 181 break;
190 set_time = 1; 182 case 's':
191 if(date_str != NULL) usage ( date_usage); 183 set_time = 1;
192 date_str = optarg; 184 if (date_str != NULL)
193 break; 185 usage(date_usage);
194 case 'u': 186 date_str = optarg;
195 utc = 1; 187 break;
196 if (putenv ("TZ=UTC0") != 0) { 188 case 'u':
197 fprintf(stderr, memory_exhausted, "date"); 189 utc = 1;
198 exit( FALSE); 190 if (putenv("TZ=UTC0") != 0) {
191 fprintf(stderr, memory_exhausted, "date");
192 exit(FALSE);
193 }
194 /* Look ma, no break. Don't fix it either. */
195 case 'd':
196 use_arg = 1;
197 if (date_str != NULL)
198 usage(date_usage);
199 date_str = optarg;
200 break;
201 case '-':
202 usage(date_usage);
203 }
204 } else {
205 if ((date_fmt == NULL) && (strcmp(*argv, "+") == 0))
206 date_fmt = *argv;
207 else if (date_str == NULL) {
208 set_time = 1;
209 date_str = *argv;
210 } else {
211 usage(date_usage);
212 }
199 } 213 }
200 /* Look ma, no break. Don't fix it either. */ 214 i--;
201 case 'd': 215 argv++;
202 use_arg = 1;
203 if(date_str != NULL) usage ( date_usage);
204 date_str = optarg;
205 break;
206 case '-':
207 usage ( date_usage);
208 }
209 } else {
210 if ( (date_fmt == NULL) && (strcmp(*argv, "+")==0) )
211 date_fmt=*argv;
212 else if (date_str == NULL) {
213 set_time = 1;
214 date_str=*argv;
215 } else {
216 usage ( date_usage);
217 }
218 } 216 }
219 i--; 217
220 argv++; 218
221 } 219 /* Now we have parsed all the information except the date format
222 220 which depends on whether the clock is being set or read */
223 221
224 /* Now we have parsed all the information except the date format 222 time(&tm);
225 which depends on whether the clock is being set or read */ 223 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
226 224 /* Zero out fields - take her back to midnight! */
227 time(&tm); 225 if (date_str != NULL) {
228 memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); 226 tm_time.tm_sec = 0;
229 /* Zero out fields - take her back to midnight!*/ 227 tm_time.tm_min = 0;
230 if(date_str != NULL) { 228 tm_time.tm_hour = 0;
231 tm_time.tm_sec = 0; 229 }
232 tm_time.tm_min = 0; 230
233 tm_time.tm_hour = 0; 231 /* Process any date input to UNIX time since 1 Jan 1970 */
234 } 232 if (date_str != NULL) {
235 233
236 /* Process any date input to UNIX time since 1 Jan 1970 */ 234 if (strchr(date_str, ':') != NULL) {
237 if(date_str != NULL) { 235 date_conv_ftime(&tm_time, date_str);
238 236 } else {
239 if(strchr(date_str, ':') != NULL) { 237 date_conv_time(&tm_time, date_str);
240 date_conv_ftime(&tm_time, date_str); 238 }
241 } else { 239
242 date_conv_time(&tm_time, date_str); 240 /* Correct any day of week and day of year etc fields */
243 } 241 tm = mktime(&tm_time);
244 242 if (tm < 0) {
245 /* Correct any day of week and day of year etc fields */ 243 fprintf(stderr, invalid_date, "date", date_str);
246 tm = mktime(&tm_time); 244 exit(FALSE);
247 if (tm < 0 ) { 245 }
248 fprintf(stderr, invalid_date, "date", date_str); 246
249 exit( FALSE); 247 /* if setting time, set it */
250 } 248 if (set_time) {
251 249 if (stime(&tm) < 0) {
252 /* if setting time, set it */ 250 fprintf(stderr, "date: can't set date.\n");
253 if(set_time) { 251 exit(FALSE);
254 if( stime(&tm) < 0) { 252 }
255 fprintf(stderr, "date: can't set date.\n"); 253 }
256 exit( FALSE); 254 }
257 } 255
258 } 256 /* Display output */
259 } 257
260 258 /* Deal with format string */
261 /* Display output */ 259 if (date_fmt == NULL) {
262 260 date_fmt = (rfc822
263 /* Deal with format string */ 261 ? (utc
264 if(date_fmt == NULL) { 262 ? "%a, %_d %b %Y %H:%M:%S GMT"
265 date_fmt = (rfc822 263 : "%a, %_d %b %Y %H:%M:%S %z")
266 ? (utc 264 : "%a %b %e %H:%M:%S %Z %Y");
267 ? "%a, %_d %b %Y %H:%M:%S GMT" 265
268 : "%a, %_d %b %Y %H:%M:%S %z") 266 } else if (*date_fmt == '\0') {
269 : "%a %b %e %H:%M:%S %Z %Y"); 267 /* Imitate what GNU 'date' does with NO format string! */
270 268 printf("\n");
271 } else if ( *date_fmt == '\0' ) { 269 exit(TRUE);
272 /* Imitate what GNU 'date' does with NO format string! */ 270 }
273 printf ("\n"); 271
274 exit( TRUE); 272 /* Handle special conversions */
275 } 273
276 274 if (strncmp(date_fmt, "%f", 2) == 0) {
277 /* Handle special conversions */ 275 date_fmt = "%Y.%m.%d-%H:%M:%S";
278 276 }
279 if( strncmp( date_fmt, "%f", 2) == 0 ) { 277
280 date_fmt = "%Y.%m.%d-%H:%M:%S"; 278 /* Print OUTPUT (after ALL that!) */
281 } 279 t_buff = malloc(201);
282 280 strftime(t_buff, 200, date_fmt, &tm_time);
283 /* Print OUTPUT (after ALL that!) */ 281 printf("%s\n", t_buff);
284 t_buff = malloc(201); 282
285 strftime(t_buff, 200, date_fmt, &tm_time); 283 exit(TRUE);
286 printf("%s\n", t_buff);
287
288 exit( TRUE);
289 284
290} 285}
diff --git a/dd.c b/dd.c
index 3e1024a60..0d5b3e8ab 100644
--- a/dd.c
+++ b/dd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini dd implementation for busybox 3 * Mini dd implementation for busybox
3 * 4 *
@@ -40,164 +41,159 @@ typedef unsigned long long int uintmax_t;
40#endif 41#endif
41 42
42static const char dd_usage[] = 43static const char dd_usage[] =
43"dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n" 44 "dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n]\n\n"
44"Copy a file, converting and formatting according to options\n\n" 45 "Copy a file, converting and formatting according to options\n\n"
45"\tif=FILE\tread from FILE instead of stdin\n" 46 "\tif=FILE\tread from FILE instead of stdin\n"
46"\tof=FILE\twrite to FILE instead of stdout\n" 47 "\tof=FILE\twrite to FILE instead of stdout\n"
47"\tbs=n\tread and write n bytes at a time\n" 48 "\tbs=n\tread and write n bytes at a time\n"
48"\tcount=n\tcopy only n input blocks\n" 49 "\tcount=n\tcopy only n input blocks\n"
49"\tskip=n\tskip n input blocks\n" 50 "\tskip=n\tskip n input blocks\n"
50"\tseek=n\tskip n output blocks\n" 51 "\tseek=n\tskip n output blocks\n"
51"\n"
52"Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
53 52
53 "\n"
54 "Numbers may be suffixed by w (x2), k (x1024), b (x512), or M (x1024^2)\n";
54 55
55 56
56extern int dd_main (int argc, char **argv) 57
58extern int dd_main(int argc, char **argv)
57{ 59{
58 const char *inFile = NULL; 60 const char *inFile = NULL;
59 const char *outFile = NULL; 61 const char *outFile = NULL;
60 char *cp; 62 char *cp;
61 int inFd; 63 int inFd;
62 int outFd; 64 int outFd;
63 int inCc = 0; 65 int inCc = 0;
64 int outCc; 66 int outCc;
65 long blockSize = 512; 67 long blockSize = 512;
66 uintmax_t skipBlocks = 0; 68 uintmax_t skipBlocks = 0;
67 uintmax_t seekBlocks = 0; 69 uintmax_t seekBlocks = 0;
68 uintmax_t count = (uintmax_t)-1; 70 uintmax_t count = (uintmax_t) - 1;
69 uintmax_t intotal; 71 uintmax_t intotal;
70 uintmax_t outTotal; 72 uintmax_t outTotal;
71 unsigned char *buf; 73 unsigned char *buf;
72 74
73 argc--; 75 argc--;
74 argv++; 76 argv++;
75
76 /* Parse any options */
77 while (argc) {
78 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
79 inFile=((strchr(*argv, '='))+1);
80 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
81 outFile=((strchr(*argv, '='))+1);
82 else if (strncmp("count", *argv, 5) == 0) {
83 count = getNum ((strchr(*argv, '='))+1);
84 if (count <= 0) {
85 fprintf (stderr, "Bad count value %s\n", *argv);
86 goto usage;
87 }
88 }
89 else if (strncmp(*argv, "bs", 2) == 0) {
90 blockSize = getNum ((strchr(*argv, '='))+1);
91 if (blockSize <= 0) {
92 fprintf (stderr, "Bad block size value %s\n", *argv);
93 goto usage;
94 }
95 }
96 else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum ((strchr(*argv, '='))+1);
98 if (skipBlocks <= 0) {
99 fprintf (stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102 77
78 /* Parse any options */
79 while (argc) {
80 if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
81 inFile = ((strchr(*argv, '=')) + 1);
82 else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
83 outFile = ((strchr(*argv, '=')) + 1);
84 else if (strncmp("count", *argv, 5) == 0) {
85 count = getNum((strchr(*argv, '=')) + 1);
86 if (count <= 0) {
87 fprintf(stderr, "Bad count value %s\n", *argv);
88 goto usage;
89 }
90 } else if (strncmp(*argv, "bs", 2) == 0) {
91 blockSize = getNum((strchr(*argv, '=')) + 1);
92 if (blockSize <= 0) {
93 fprintf(stderr, "Bad block size value %s\n", *argv);
94 goto usage;
95 }
96 } else if (strncmp(*argv, "skip", 4) == 0) {
97 skipBlocks = getNum((strchr(*argv, '=')) + 1);
98 if (skipBlocks <= 0) {
99 fprintf(stderr, "Bad skip value %s\n", *argv);
100 goto usage;
101 }
102
103 } else if (strncmp(*argv, "seek", 4) == 0) {
104 seekBlocks = getNum((strchr(*argv, '=')) + 1);
105 if (seekBlocks <= 0) {
106 fprintf(stderr, "Bad seek value %s\n", *argv);
107 goto usage;
108 }
109
110 } else {
111 goto usage;
112 }
113 argc--;
114 argv++;
103 } 115 }
104 else if (strncmp(*argv, "seek", 4) == 0) {
105 seekBlocks = getNum ((strchr(*argv, '='))+1);
106 if (seekBlocks <= 0) {
107 fprintf (stderr, "Bad seek value %s\n", *argv);
108 goto usage;
109 }
110 116
117 buf = malloc(blockSize);
118 if (buf == NULL) {
119 fprintf(stderr, "Cannot allocate buffer\n");
120 exit(FALSE);
111 } 121 }
112 else { 122
113 goto usage; 123 intotal = 0;
124 outTotal = 0;
125
126 if (inFile == NULL)
127 inFd = fileno(stdin);
128 else
129 inFd = open(inFile, 0);
130
131 if (inFd < 0) {
132 perror(inFile);
133 free(buf);
134 exit(FALSE);
114 } 135 }
115 argc--; 136
116 argv++; 137 if (outFile == NULL)
117 } 138 outFd = fileno(stdout);
118 139 else
119 buf = malloc (blockSize); 140 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
120 if (buf == NULL) { 141
121 fprintf (stderr, "Cannot allocate buffer\n"); 142 if (outFd < 0) {
122 exit( FALSE); 143 perror(outFile);
123 } 144 close(inFd);
124 145 free(buf);
125 intotal = 0; 146 exit(FALSE);
126 outTotal = 0;
127
128 if (inFile == NULL)
129 inFd = fileno(stdin);
130 else
131 inFd = open (inFile, 0);
132
133 if (inFd < 0) {
134 perror (inFile);
135 free (buf);
136 exit( FALSE);
137 }
138
139 if (outFile == NULL)
140 outFd = fileno(stdout);
141 else
142 outFd = open(outFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
143
144 if (outFd < 0) {
145 perror (outFile);
146 close (inFd);
147 free (buf);
148 exit( FALSE);
149 }
150
151 lseek(inFd, skipBlocks*blockSize, SEEK_SET);
152 lseek(outFd, seekBlocks*blockSize, SEEK_SET);
153 //
154 //TODO: Convert to using fullRead & fullWrite
155 // from utility.c
156 // -Erik
157 while (outTotal < count * blockSize) {
158 inCc = read (inFd, buf, blockSize);
159 if (inCc < 0) {
160 perror (inFile);
161 goto cleanup;
162 } else if (inCc == 0) {
163 goto cleanup;
164 } 147 }
165 intotal += inCc; 148
166 cp = buf; 149 lseek(inFd, skipBlocks * blockSize, SEEK_SET);
167 150 lseek(outFd, seekBlocks * blockSize, SEEK_SET);
168 while (intotal > outTotal) { 151 //
169 if (outTotal + inCc > count * blockSize) 152 //TODO: Convert to using fullRead & fullWrite
170 inCc = count * blockSize - outTotal; 153 // from utility.c
171 outCc = write (outFd, cp, inCc); 154 // -Erik
172 if (outCc < 0) { 155 while (outTotal < count * blockSize) {
173 perror (outFile); 156 inCc = read(inFd, buf, blockSize);
174 goto cleanup; 157 if (inCc < 0) {
175 } else if (outCc == 0) { 158 perror(inFile);
176 goto cleanup; 159 goto cleanup;
177 } 160 } else if (inCc == 0) {
178 161 goto cleanup;
179 inCc -= outCc; 162 }
180 cp += outCc; 163 intotal += inCc;
181 outTotal += outCc; 164 cp = buf;
165
166 while (intotal > outTotal) {
167 if (outTotal + inCc > count * blockSize)
168 inCc = count * blockSize - outTotal;
169 outCc = write(outFd, cp, inCc);
170 if (outCc < 0) {
171 perror(outFile);
172 goto cleanup;
173 } else if (outCc == 0) {
174 goto cleanup;
175 }
176
177 inCc -= outCc;
178 cp += outCc;
179 outTotal += outCc;
180 }
182 } 181 }
183 }
184 182
185 if (inCc < 0) 183 if (inCc < 0)
186 perror (inFile); 184 perror(inFile);
187 185
188 cleanup: 186 cleanup:
189 close (inFd); 187 close(inFd);
190 close (outFd); 188 close(outFd);
191 free (buf); 189 free(buf);
192 190
193 printf ("%ld+%d records in\n", (long)(intotal / blockSize), 191 printf("%ld+%d records in\n", (long) (intotal / blockSize),
194 (intotal % blockSize) != 0); 192 (intotal % blockSize) != 0);
195 printf ("%ld+%d records out\n", (long)(outTotal / blockSize), 193 printf("%ld+%d records out\n", (long) (outTotal / blockSize),
196 (outTotal % blockSize) != 0); 194 (outTotal % blockSize) != 0);
197 exit( TRUE); 195 exit(TRUE);
198 usage: 196 usage:
199 197
200 usage( dd_usage); 198 usage(dd_usage);
201} 199}
202
203
diff --git a/deallocvt.c b/deallocvt.c
index 1e13ff69c..141062edc 100644
--- a/deallocvt.c
+++ b/deallocvt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s) 3 * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s)
3 * Renamed deallocvt. 4 * Renamed deallocvt.
@@ -13,38 +14,39 @@
13extern int getfd(void); 14extern int getfd(void);
14char *progname; 15char *progname;
15 16
16int 17int deallocvt_main(int argc, char *argv[])
17deallocvt_main(int argc, char *argv[]) { 18{
18 int fd, num, i; 19 int fd, num, i;
19 20
20 if ( ( argc != 2) || (**(argv+1) == '-' ) ) { 21 if ((argc != 2) || (**(argv + 1) == '-')) {
21 usage ("deallocvt N\n\nDeallocate unused virtual terminal /dev/ttyN\n"); 22 usage
22 } 23 ("deallocvt N\n\nDeallocate unused virtual terminal /dev/ttyN\n");
24 }
23 25
24 progname = argv[0]; 26 progname = argv[0];
25 27
26 fd = get_console_fd("/dev/console"); 28 fd = get_console_fd("/dev/console");
27 29
28 if (argc == 1) { 30 if (argc == 1) {
29 /* deallocate all unused consoles */ 31 /* deallocate all unused consoles */
30 if (ioctl(fd,VT_DISALLOCATE,0)) { 32 if (ioctl(fd, VT_DISALLOCATE, 0)) {
31 perror("VT_DISALLOCATE"); 33 perror("VT_DISALLOCATE");
32 exit(1); 34 exit(1);
33 } 35 }
34 } else 36 } else
35 for (i = 1; i < argc; i++) { 37 for (i = 1; i < argc; i++) {
36 num = atoi(argv[i]); 38 num = atoi(argv[i]);
37 if (num == 0) 39 if (num == 0)
38 fprintf(stderr, "%s: 0: illegal VT number\n", progname); 40 fprintf(stderr, "%s: 0: illegal VT number\n", progname);
39 else if (num == 1) 41 else if (num == 1)
40 fprintf(stderr, "%s: VT 1 cannot be deallocated\n", progname); 42 fprintf(stderr, "%s: VT 1 cannot be deallocated\n",
41 else 43 progname);
42 if (ioctl(fd,VT_DISALLOCATE,num)) { 44 else if (ioctl(fd, VT_DISALLOCATE, num)) {
43 perror("VT_DISALLOCATE"); 45 perror("VT_DISALLOCATE");
44 fprintf(stderr, "%s: could not deallocate console %d\n", 46 fprintf(stderr, "%s: could not deallocate console %d\n",
45 progname, num); 47 progname, num);
46 exit(1); 48 exit(1);
47 } 49 }
48 } 50 }
49 exit(0); 51 exit(0);
50} 52}
diff --git a/df.c b/df.c
index 24c94a246..43d5d26e7 100644
--- a/df.c
+++ b/df.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini df implementation for busybox 3 * Mini df implementation for busybox
3 * 4 *
@@ -29,81 +30,81 @@
29#include <fstab.h> 30#include <fstab.h>
30 31
31static const char df_usage[] = "df [filesystem ...]\n" 32static const char df_usage[] = "df [filesystem ...]\n"
32 "\n" "\tPrint the filesystem space used and space available.\n";
33 33
34extern const char mtab_file[]; /* Defined in utility.c */ 34 "\n" "\tPrint the filesystem space used and space available.\n";
35
36extern const char mtab_file[]; /* Defined in utility.c */
35 37
36static int df(char *device, const char *mountPoint) 38static int df(char *device, const char *mountPoint)
37{ 39{
38 struct statfs s; 40 struct statfs s;
39 long blocks_used; 41 long blocks_used;
40 long blocks_percent_used; 42 long blocks_percent_used;
41 struct fstab* fstabItem; 43 struct fstab *fstabItem;
42
43 if (statfs(mountPoint, &s) != 0) {
44 perror(mountPoint);
45 return FALSE;
46 }
47 44
48 if (s.f_blocks > 0) { 45 if (statfs(mountPoint, &s) != 0) {
49 blocks_used = s.f_blocks - s.f_bfree; 46 perror(mountPoint);
50 blocks_percent_used = (long) 47 return FALSE;
51 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
52 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
53 if (strcmp (device, "/dev/root") == 0) {
54 fstabItem = getfsfile ("/");
55 if (fstabItem != NULL)
56 device = fstabItem->fs_spec;
57 } 48 }
58 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
59 device,
60 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
61 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
62 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
63 blocks_percent_used, mountPoint);
64 49
65 } 50 if (s.f_blocks > 0) {
51 blocks_used = s.f_blocks - s.f_bfree;
52 blocks_percent_used = (long)
53 (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
54 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
55 if (strcmp(device, "/dev/root") == 0) {
56 fstabItem = getfsfile("/");
57 if (fstabItem != NULL)
58 device = fstabItem->fs_spec;
59 }
60 printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
61 device,
62 (long) (s.f_blocks * (s.f_bsize / 1024.0)),
63 (long) ((s.f_blocks - s.f_bfree) * (s.f_bsize / 1024.0)),
64 (long) (s.f_bavail * (s.f_bsize / 1024.0)),
65 blocks_percent_used, mountPoint);
66
67 }
66 68
67 return TRUE; 69 return TRUE;
68} 70}
69 71
70extern int df_main(int argc, char **argv) 72extern int df_main(int argc, char **argv)
71{ 73{
72 printf("%-20s %-14s %s %s %s %s\n", "Filesystem", 74 printf("%-20s %-14s %s %s %s %s\n", "Filesystem",
73 "1k-blocks", "Used", "Available", "Use%", "Mounted on"); 75 "1k-blocks", "Used", "Available", "Use%", "Mounted on");
74 76
75 if (argc > 1) { 77 if (argc > 1) {
76 struct mntent *mountEntry; 78 struct mntent *mountEntry;
77 int status; 79 int status;
78 80
79 while (argc > 1) { 81 while (argc > 1) {
80 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 82 if ((mountEntry = findMountPoint(argv[1], mtab_file)) == 0) {
81 0) { 83 fprintf(stderr, "%s: can't find mount point.\n", argv[1]);
82 fprintf(stderr, "%s: can't find mount point.\n", argv[1]); 84 exit(FALSE);
83 exit( FALSE); 85 }
84 } 86 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
85 status = df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 87 if (status != 0)
86 if (status != 0) 88 exit(status);
87 exit( status); 89 argc--;
88 argc--; 90 argv++;
89 argv++; 91 }
90 } 92 exit(TRUE);
91 exit( TRUE); 93 } else {
92 } else { 94 FILE *mountTable;
93 FILE *mountTable; 95 struct mntent *mountEntry;
94 struct mntent *mountEntry;
95 96
96 mountTable = setmntent(mtab_file, "r"); 97 mountTable = setmntent(mtab_file, "r");
97 if (mountTable == 0) { 98 if (mountTable == 0) {
98 perror(mtab_file); 99 perror(mtab_file);
99 exit(FALSE); 100 exit(FALSE);
100 } 101 }
101 102
102 while ((mountEntry = getmntent(mountTable))) { 103 while ((mountEntry = getmntent(mountTable))) {
103 df(mountEntry->mnt_fsname, mountEntry->mnt_dir); 104 df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
105 }
106 endmntent(mountTable);
104 } 107 }
105 endmntent(mountTable);
106 }
107 108
108 exit( TRUE); 109 exit(TRUE);
109} 110}
diff --git a/dmesg.c b/dmesg.c
index e38fd5555..bbed8221a 100644
--- a/dmesg.c
+++ b/dmesg.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* dmesg.c -- Print out the contents of the kernel ring buffer 2/* dmesg.c -- Print out the contents of the kernel ring buffer
2 * Created: Sat Oct 9 16:19:47 1993 3 * Created: Sat Oct 9 16:19:47 1993
3 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu 4 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu
@@ -24,8 +25,8 @@
24 25
25#ifndef __alpha__ 26#ifndef __alpha__
26# define __NR_klogctl __NR_syslog 27# define __NR_klogctl __NR_syslog
27 static inline _syscall3(int, klogctl, int, type, char *, b, int, len); 28static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
28#else /* __alpha__ */ 29#else /* __alpha__ */
29#define klogctl syslog 30#define klogctl syslog
30#endif 31#endif
31 32
@@ -35,90 +36,91 @@
35 36
36static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n"; 37static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n";
37 38
38int dmesg_main( int argc, char** argv ) 39int dmesg_main(int argc, char **argv)
39{ 40{
40 char *buf; 41 char *buf;
41 int bufsize=8196; 42 int bufsize = 8196;
42 int i; 43 int i;
43 int n; 44 int n;
44 int level = 0; 45 int level = 0;
45 int lastc; 46 int lastc;
46 int cmd = 3; 47 int cmd = 3;
47 int stopDoingThat; 48 int stopDoingThat;
48 49
49 argc--; 50 argc--;
50 argv++; 51 argv++;
51 52
52 /* Parse any options */ 53 /* Parse any options */
53 while (argc && **argv == '-') { 54 while (argc && **argv == '-') {
54 stopDoingThat = FALSE; 55 stopDoingThat = FALSE;
55 while (stopDoingThat == FALSE && *++(*argv)) { 56 while (stopDoingThat == FALSE && *++(*argv)) {
56 switch (**argv) { 57 switch (**argv) {
57 case 'c': 58 case 'c':
58 cmd = 4; 59 cmd = 4;
59 break; 60 break;
60 case 'n': 61 case 'n':
61 cmd = 8; 62 cmd = 8;
62 if (--argc == 0) 63 if (--argc == 0)
63 goto end; 64 goto end;
64 level = atoi (*(++argv)); 65 level = atoi(*(++argv));
65 if (--argc > 0) 66 if (--argc > 0)
66 ++argv; 67 ++argv;
67 stopDoingThat = TRUE; 68 stopDoingThat = TRUE;
68 break; 69 break;
69 case 's': 70 case 's':
70 if (--argc == 0) 71 if (--argc == 0)
71 goto end; 72 goto end;
72 bufsize = atoi (*(++argv)); 73 bufsize = atoi(*(++argv));
73 if (--argc > 0) 74 if (--argc > 0)
74 ++argv; 75 ++argv;
75 stopDoingThat = TRUE; 76 stopDoingThat = TRUE;
76 break; 77 break;
77 default: 78 default:
79 goto end;
80 }
81 }
82 }
83
84 if (argc > 1) {
78 goto end; 85 goto end;
79 }
80 } 86 }
81 }
82
83 if (argc > 1) {
84 goto end;
85 }
86 87
87 if (cmd == 8) { 88 if (cmd == 8) {
88 n = klogctl( cmd, NULL, level ); 89 n = klogctl(cmd, NULL, level);
89 if (n < 0) { 90 if (n < 0) {
90 goto klogctl_error; 91 goto klogctl_error;
91 } 92 }
92 exit( TRUE ); 93 exit(TRUE);
93 } 94 }
94 95
95 if (bufsize < 4096) bufsize = 4096; 96 if (bufsize < 4096)
96 buf = (char*)malloc(bufsize); 97 bufsize = 4096;
97 n = klogctl( cmd, buf, bufsize ); 98 buf = (char *) malloc(bufsize);
98 if (n < 0) { 99 n = klogctl(cmd, buf, bufsize);
99 goto klogctl_error; 100 if (n < 0) {
100 } 101 goto klogctl_error;
102 }
101 103
102 lastc = '\n'; 104 lastc = '\n';
103 for (i = 0; i < n; i++) { 105 for (i = 0; i < n; i++) {
104 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 106 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
105 i++; 107 i++;
106 while (buf[i] >= '0' && buf[i] <= '9') 108 while (buf[i] >= '0' && buf[i] <= '9')
107 i++; 109 i++;
108 if (buf[i] == '>') 110 if (buf[i] == '>')
109 i++; 111 i++;
110 } 112 }
111 lastc = buf[i]; 113 lastc = buf[i];
112 putchar( lastc ); 114 putchar(lastc);
113 } 115 }
114 if (lastc != '\n') 116 if (lastc != '\n')
115 putchar( '\n' ); 117 putchar('\n');
116 exit( TRUE); 118 exit(TRUE);
117end: 119 end:
118 usage( dmesg_usage); 120 usage(dmesg_usage);
119 exit (FALSE); 121 exit(FALSE);
120klogctl_error: 122 klogctl_error:
121 perror( "klogctl" ); 123 perror("klogctl");
122 exit( FALSE ); 124 exit(FALSE);
123 125
124} 126}
diff --git a/du.c b/du.c
index e2cf3f7c0..7151e3a9c 100644
--- a/du.c
+++ b/du.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini du implementation for busybox 3 * Mini du implementation for busybox
3 * 4 *
@@ -31,119 +32,121 @@
31#include <dirent.h> 32#include <dirent.h>
32#include <stdio.h> 33#include <stdio.h>
33#include <errno.h> 34#include <errno.h>
34#include <sys/param.h> /* for PATH_MAX */ 35#include <sys/param.h> /* for PATH_MAX */
35 36
36typedef void (Display)(long, char *); 37typedef void (Display) (long, char *);
37 38
38static const char du_usage[] = 39static const char du_usage[] =
39"du [OPTION]... [FILE]...\n\n"
40"\t-s\tdisplay only a total for each argument\n"
41;
42 40
43static int du_depth = 0; 41 "du [OPTION]... [FILE]...\n\n"
42 "\t-s\tdisplay only a total for each argument\n";
44 43
45static Display *print; 44static int du_depth = 0;
46 45
47static void 46static Display *print;
48print_normal(long size, char *filename) 47
48static void print_normal(long size, char *filename)
49{ 49{
50 fprintf(stdout, "%-7ld %s\n", size, filename); 50 fprintf(stdout, "%-7ld %s\n", size, filename);
51} 51}
52 52
53static void 53static void print_summary(long size, char *filename)
54print_summary(long size, char *filename)
55{ 54{
56 if (du_depth == 1) { 55 if (du_depth == 1) {
57 print_normal(size, filename); 56 print_normal(size, filename);
58 } 57 }
59} 58}
60 59
61 60
62/* tiny recursive du */ 61/* tiny recursive du */
63static long 62static long du(char *filename)
64du(char *filename)
65{ 63{
66 struct stat statbuf; 64 struct stat statbuf;
67 long sum; 65 long sum;
68 66
69 if ((lstat(filename, &statbuf)) != 0) { 67 if ((lstat(filename, &statbuf)) != 0) {
70 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno)); 68 fprintf(stdout, "du: %s: %s\n", filename, strerror(errno));
71 return 0; 69 return 0;
72 }
73
74 du_depth++;
75 sum = statbuf.st_blocks;
76
77 if (S_ISDIR(statbuf.st_mode)) {
78 DIR *dir;
79 struct dirent *entry;
80
81 dir = opendir(filename);
82 if (!dir) { return 0; }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ( (strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0))
89 { continue; }
90
91 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
92 fprintf(stderr, name_too_long, "du");
93 return 0;
94 }
95 sprintf(newfile, "%s/%s", filename, name);
96
97 sum += du(newfile);
98 } 70 }
99 closedir(dir); 71
100 print(sum, filename); 72 du_depth++;
101 } 73 sum = statbuf.st_blocks;
102 du_depth--; 74
103 return sum; 75 if (S_ISDIR(statbuf.st_mode)) {
76 DIR *dir;
77 struct dirent *entry;
78
79 dir = opendir(filename);
80 if (!dir) {
81 return 0;
82 }
83 while ((entry = readdir(dir))) {
84 char newfile[PATH_MAX + 1];
85 char *name = entry->d_name;
86
87 if ((strcmp(name, "..") == 0)
88 || (strcmp(name, ".") == 0)) {
89 continue;
90 }
91
92 if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
93 fprintf(stderr, name_too_long, "du");
94 return 0;
95 }
96 sprintf(newfile, "%s/%s", filename, name);
97
98 sum += du(newfile);
99 }
100 closedir(dir);
101 print(sum, filename);
102 }
103 du_depth--;
104 return sum;
104} 105}
105 106
106int 107int du_main(int argc, char **argv)
107du_main(int argc, char **argv)
108{ 108{
109 int i; 109 int i;
110 char opt; 110 char opt;
111 111
112 /* default behaviour */ 112 /* default behaviour */
113 print = print_normal; 113 print = print_normal;
114 114
115 /* parse argv[] */ 115 /* parse argv[] */
116 for (i = 1; i < argc; i++) { 116 for (i = 1; i < argc; i++) {
117 if (argv[i][0] == '-') { 117 if (argv[i][0] == '-') {
118 opt = argv[i][1]; 118 opt = argv[i][1];
119 switch (opt) { 119 switch (opt) {
120 case 's': 120 case 's':
121 print = print_summary; 121 print = print_summary;
122 break; 122 break;
123 case 'h': 123 case 'h':
124 usage(du_usage); 124 usage(du_usage);
125 break; 125 break;
126 default: 126 default:
127 fprintf(stderr, "du: invalid option -- %c\n", opt); 127 fprintf(stderr, "du: invalid option -- %c\n", opt);
128 usage(du_usage); 128 usage(du_usage);
129 } 129 }
130 } else { 130 } else {
131 break; 131 break;
132 }
132 } 133 }
133 }
134 134
135 /* go through remaining args (if any) */ 135 /* go through remaining args (if any) */
136 if (i >= argc) { 136 if (i >= argc) {
137 du("."); 137 du(".");
138 } else { 138 } else {
139 long sum; 139 long sum;
140 for ( ; i < argc; i++) { 140
141 sum = du(argv[i]); 141 for (; i < argc; i++) {
142 if ((sum) && (isDirectory(argv[i], FALSE))) { print_normal(sum, argv[i]); } 142 sum = du(argv[i]);
143 if ((sum) && (isDirectory(argv[i], FALSE))) {
144 print_normal(sum, argv[i]);
145 }
146 }
143 } 147 }
144 }
145 148
146 exit(0); 149 exit(0);
147} 150}
148 151
149/* $Id: du.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 152/* $Id: du.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/dutmp.c b/dutmp.c
index a9e879daf..45eab8ae7 100644
--- a/dutmp.c
+++ b/dutmp.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> 3 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
3 * 4 *
@@ -15,37 +16,38 @@
15#include <utmp.h> 16#include <utmp.h>
16 17
17static const char dutmp_usage[] = "dutmp\n" 18static const char dutmp_usage[] = "dutmp\n"
18 "\n" 19 "\n"
19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20 "\tdutmp /var/run/utmp\n";
21 20
22extern int dutmp_main (int argc, char **argv) 21 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
22 "\tdutmp /var/run/utmp\n";
23
24extern int dutmp_main(int argc, char **argv)
23{ 25{
24 26
25 FILE *f = stdin; 27 FILE *f = stdin;
26 struct utmp ut; 28 struct utmp ut;
27 29
28 if ((argc < 2) || (**(argv + 1) == '-')) { 30 if ((argc < 2) || (**(argv + 1) == '-')) {
29 usage( dutmp_usage); 31 usage(dutmp_usage);
30 } 32 }
31 33
32 if ( **(++argv) == 0 ) { 34 if (**(++argv) == 0) {
33 f = fopen (*(++argv), "r"); 35 f = fopen(*(++argv), "r");
34 if (f < 0 ) { 36 if (f < 0) {
35 perror (*argv); 37 perror(*argv);
36 exit (FALSE); 38 exit(FALSE);
37 } 39 }
38 } 40 }
39 41
40 while (fread (&ut, 1, sizeof (struct utmp), f)) { 42 while (fread(&ut, 1, sizeof(struct utmp), f)) {
41 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n", 43 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
42 printf ("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n", 44 printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
43 ut.ut_type, ut.ut_pid, ut.ut_line, 45 ut.ut_type, ut.ut_pid, ut.ut_line,
44 ut.ut_id, ut.ut_user, ut.ut_host, 46 ut.ut_id, ut.ut_user, ut.ut_host,
45 ut.ut_exit.e_termination, ut.ut_exit.e_exit, 47 ut.ut_exit.e_termination, ut.ut_exit.e_exit,
46 ut.ut_session, 48 ut.ut_session,
47 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr); 49 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr);
48 } 50 }
49 51
50 exit (TRUE); 52 exit(TRUE);
51} 53}
diff --git a/editors/sed.c b/editors/sed.c
index 25777243d..3a7737e2f 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sed implementation for busybox 3 * Mini sed implementation for busybox
3 * 4 *
@@ -37,27 +38,27 @@
37#include <ctype.h> 38#include <ctype.h>
38 39
39static const char sed_usage[] = 40static const char sed_usage[] =
40 "sed [-n] -e script [file...]\n\n" 41 "sed [-n] -e script [file...]\n\n"
41 "Allowed sed scripts come in the following form:\n" 42 "Allowed sed scripts come in the following form:\n"
42 "\t'ADDR [!] COMMAND'\n\n" 43 "\t'ADDR [!] COMMAND'\n\n"
43 "\twhere address ADDR can be:\n" 44 "\twhere address ADDR can be:\n"
44 "\t NUMBER Match specified line number\n" 45 "\t NUMBER Match specified line number\n"
45 "\t $ Match last line\n" 46 "\t $ Match last line\n"
46 "\t /REGEXP/ Match specified regexp\n" 47 "\t /REGEXP/ Match specified regexp\n"
47 "\t (! inverts the meaning of the match)\n\n" 48 "\t (! inverts the meaning of the match)\n\n"
48 "\tand COMMAND can be:\n" 49 "\tand COMMAND can be:\n"
49 "\t s/regexp/replacement/[igp]\n" 50 "\t s/regexp/replacement/[igp]\n"
50 "\t which attempt to match regexp against the pattern space\n" 51 "\t which attempt to match regexp against the pattern space\n"
51 "\t and if successful replaces the matched portion with replacement.\n\n" 52 "\t and if successful replaces the matched portion with replacement.\n\n"
52 "\t aTEXT\n" 53 "\t aTEXT\n"
53 "\t which appends TEXT after the pattern space\n" 54 "\t which appends TEXT after the pattern space\n"
54 "Options:\n" 55 "Options:\n"
55 "-e\tadd the script to the commands to be executed\n" 56 "-e\tadd the script to the commands to be executed\n"
56 "-n\tsuppress automatic printing of pattern space\n\n" 57 "-n\tsuppress automatic printing of pattern space\n\n"
57#if defined BB_REGEXP 58#if defined BB_REGEXP
58 "This version of sed matches full regular expresions.\n"; 59 "This version of sed matches full regular expresions.\n";
59#else 60#else
60 "This version of sed matches strings (not full regular expresions).\n"; 61 "This version of sed matches strings (not full regular expresions).\n";
61#endif 62#endif
62 63
63/* Flags & variables */ 64/* Flags & variables */
@@ -76,276 +77,277 @@ static int negated = 0;
76 77
77static inline int at_last(FILE * fp) 78static inline int at_last(FILE * fp)
78{ 79{
79 int res = 0; 80 int res = 0;
80 81
81 if (feof(fp)) 82 if (feof(fp))
82 return 1; 83 return 1;
83 else { 84 else {
84 char ch; 85 char ch;
85 if ((ch = fgetc(fp)) == EOF) 86
86 res++; 87 if ((ch = fgetc(fp)) == EOF)
87 ungetc(ch, fp); 88 res++;
88 } 89 ungetc(ch, fp);
89 return res; 90 }
91 return res;
90} 92}
91 93
92static void do_sed_repl(FILE * fp, char *needle, char *newNeedle, 94static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
93 int ignoreCase, int printFlag, int quietFlag) 95 int ignoreCase, int printFlag, int quietFlag)
94{ 96{
95 int foundOne = FALSE; 97 int foundOne = FALSE;
96 char haystack[BUFSIZE]; 98 char haystack[BUFSIZE];
97 int line = 1, doit; 99 int line = 1, doit;
98 100
99 while (fgets(haystack, BUFSIZE - 1, fp)) { 101 while (fgets(haystack, BUFSIZE - 1, fp)) {
100 doit = 0; 102 doit = 0;
101 if (addr_pattern) { 103 if (addr_pattern) {
102 doit = !find_match(haystack, addr_pattern, FALSE); 104 doit = !find_match(haystack, addr_pattern, FALSE);
103 } else if (addr_line == NO_LINE) 105 } else if (addr_line == NO_LINE)
104 doit = 1; 106 doit = 1;
105 else if (addr_line == LAST_LINE) { 107 else if (addr_line == LAST_LINE) {
106 if (at_last(fp)) 108 if (at_last(fp))
107 doit = 1; 109 doit = 1;
108 } else { 110 } else {
109 if (line == addr_line) 111 if (line == addr_line)
110 doit = 1; 112 doit = 1;
111 } 113 }
112 if (negated) 114 if (negated)
113 doit = 1 - doit; 115 doit = 1 - doit;
114 if (doit) { 116 if (doit) {
115 foundOne = 117 foundOne =
116 replace_match(haystack, needle, newNeedle, ignoreCase); 118 replace_match(haystack, needle, newNeedle, ignoreCase);
117 119
118 if (foundOne == TRUE && printFlag == TRUE) { 120 if (foundOne == TRUE && printFlag == TRUE) {
119 fprintf(stdout, haystack); 121 fprintf(stdout, haystack);
120 } 122 }
121 } 123 }
122 124
123 if (quietFlag == FALSE) { 125 if (quietFlag == FALSE) {
124 fprintf(stdout, haystack); 126 fprintf(stdout, haystack);
125 } 127 }
126 128
127 line++; 129 line++;
128 } 130 }
129} 131}
130 132
131static void do_sed_append(FILE * fp, char *appendline, int quietFlag) 133static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
132{ 134{
133 char buffer[BUFSIZE]; 135 char buffer[BUFSIZE];
134 int line = 1, doit; 136 int line = 1, doit;
135 137
136 while (fgets(buffer, BUFSIZE - 1, fp)) { 138 while (fgets(buffer, BUFSIZE - 1, fp)) {
137 doit = 0; 139 doit = 0;
138 if (addr_pattern) { 140 if (addr_pattern) {
139 doit = !find_match(buffer, addr_pattern, FALSE); 141 doit = !find_match(buffer, addr_pattern, FALSE);
140 } else if (addr_line == NO_LINE) 142 } else if (addr_line == NO_LINE)
141 doit = 1; 143 doit = 1;
142 else if (addr_line == LAST_LINE) { 144 else if (addr_line == LAST_LINE) {
143 if (at_last(fp)) 145 if (at_last(fp))
144 doit = 1; 146 doit = 1;
145 } else { 147 } else {
146 if (line == addr_line) 148 if (line == addr_line)
147 doit = 1; 149 doit = 1;
148 } 150 }
149 if (negated) 151 if (negated)
150 doit = 1 - doit; 152 doit = 1 - doit;
151 if (quietFlag == FALSE) { 153 if (quietFlag == FALSE) {
152 fprintf(stdout, buffer); 154 fprintf(stdout, buffer);
153 } 155 }
154 if (doit) { 156 if (doit) {
155 fputs(appendline, stdout); 157 fputs(appendline, stdout);
156 fputc('\n', stdout); 158 fputc('\n', stdout);
157 } 159 }
158 160
159 line++; 161 line++;
160 } 162 }
161} 163}
162 164
163extern int sed_main(int argc, char **argv) 165extern int sed_main(int argc, char **argv)
164{ 166{
165 FILE *fp; 167 FILE *fp;
166 char *needle = NULL, *newNeedle = NULL; 168 char *needle = NULL, *newNeedle = NULL;
167 char *name; 169 char *name;
168 char *cp; 170 char *cp;
169 int ignoreCase = FALSE; 171 int ignoreCase = FALSE;
170 int printFlag = FALSE; 172 int printFlag = FALSE;
171 int quietFlag = FALSE; 173 int quietFlag = FALSE;
172 int stopNow; 174 int stopNow;
173 char *line_s = NULL, saved; 175 char *line_s = NULL, saved;
174 char *appendline = NULL; 176 char *appendline = NULL;
175 char *pos; 177 char *pos;
176 sed_function sed_f = f_none; 178 sed_function sed_f = f_none;
177
178 argc--;
179 argv++;
180 if (argc < 1) {
181 usage(sed_usage);
182 }
183
184 if (**argv == '-') {
185 argc--;
186 cp = *argv++;
187 stopNow = FALSE;
188
189 while (*++cp && stopNow == FALSE) {
190 switch (*cp) {
191 case 'n':
192 quietFlag = TRUE;
193 break;
194 case 'e':
195 if (*(cp + 1) == 0 && --argc < 0) {
196 usage(sed_usage);
197 }
198 if (*++cp != 's')
199 cp = *argv++;
200
201 /* Read address if present */
202 SKIPSPACES(cp);
203 if (*cp == '$') {
204 addr_line = LAST_LINE;
205 cp++;
206 } else {
207 if (isdigit(*cp)) { /* LINE ADDRESS */
208 line_s = cp;
209 while (isdigit(*cp))
210 cp++;
211 if (cp > line_s) {
212 /* numeric line */
213 saved = *cp;
214 *cp = '\0';
215 addr_line = atoi(line_s);
216 *cp = saved;
217 }
218 } else if (*cp == '/') { /* PATTERN ADDRESS */
219 pos = addr_pattern = cp + 1;
220 pos = strchr(pos, '/');
221 if (!pos)
222 usage(sed_usage);
223 *pos = '\0';
224 cp = pos + 1;
225 }
226 }
227
228 SKIPSPACES(cp);
229 if (*cp == '!') {
230 negated++;
231 cp++;
232 }
233 179
234 /* Read command */ 180 argc--;
181 argv++;
182 if (argc < 1) {
183 usage(sed_usage);
184 }
235 185
236 SKIPSPACES(cp); 186 if (**argv == '-') {
237 switch (*cp) { 187 argc--;
238 case 's': /* REPLACE */ 188 cp = *argv++;
239 if (strlen(cp) <= 3 || *(cp + 1) != '/') 189 stopNow = FALSE;
240 break;
241 sed_f = f_replace;
242 190
243 pos = needle = cp + 2; 191 while (*++cp && stopNow == FALSE) {
192 switch (*cp) {
193 case 'n':
194 quietFlag = TRUE;
195 break;
196 case 'e':
197 if (*(cp + 1) == 0 && --argc < 0) {
198 usage(sed_usage);
199 }
200 if (*++cp != 's')
201 cp = *argv++;
202
203 /* Read address if present */
204 SKIPSPACES(cp);
205 if (*cp == '$') {
206 addr_line = LAST_LINE;
207 cp++;
208 } else {
209 if (isdigit(*cp)) { /* LINE ADDRESS */
210 line_s = cp;
211 while (isdigit(*cp))
212 cp++;
213 if (cp > line_s) {
214 /* numeric line */
215 saved = *cp;
216 *cp = '\0';
217 addr_line = atoi(line_s);
218 *cp = saved;
219 }
220 } else if (*cp == '/') { /* PATTERN ADDRESS */
221 pos = addr_pattern = cp + 1;
222 pos = strchr(pos, '/');
223 if (!pos)
224 usage(sed_usage);
225 *pos = '\0';
226 cp = pos + 1;
227 }
228 }
229
230 SKIPSPACES(cp);
231 if (*cp == '!') {
232 negated++;
233 cp++;
234 }
235
236 /* Read command */
237
238 SKIPSPACES(cp);
239 switch (*cp) {
240 case 's': /* REPLACE */
241 if (strlen(cp) <= 3 || *(cp + 1) != '/')
242 break;
243 sed_f = f_replace;
244
245 pos = needle = cp + 2;
246
247 for (;;) {
248 pos = strchr(pos, '/');
249 if (pos == NULL) {
250 usage(sed_usage);
251 }
252 if (*(pos - 1) == '\\') {
253 pos++;
254 continue;
255 }
256 break;
257 }
258 *pos = 0;
259 newNeedle = ++pos;
260 for (;;) {
261 pos = strchr(pos, '/');
262 if (pos == NULL) {
263 usage(sed_usage);
264 }
265 if (*(pos - 1) == '\\') {
266 pos++;
267 continue;
268 }
269 break;
270 }
271 *pos = 0;
272 if (pos + 2 != 0) {
273 while (*++pos) {
274 switch (*pos) {
275 case 'i':
276 ignoreCase = TRUE;
277 break;
278 case 'p':
279 printFlag = TRUE;
280 break;
281 case 'g':
282 break;
283 default:
284 usage(sed_usage);
285 }
286 }
287 }
288 cp = pos;
289 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
290 break;
291
292 case 'a': /* APPEND */
293 if (strlen(cp) < 2)
294 break;
295 sed_f = f_append;
296 appendline = ++cp;
297 /* fprintf(stderr, "append '%s'\n", appendline); */
298 break;
299 }
300
301 stopNow = TRUE;
302 break;
244 303
245 for (;;) { 304 default:
246 pos = strchr(pos, '/'); 305 usage(sed_usage);
247 if (pos == NULL) {
248 usage(sed_usage);
249 }
250 if (*(pos - 1) == '\\') {
251 pos++;
252 continue;
253 } 306 }
307 }
308 }
309
310 if (argc == 0) {
311 switch (sed_f) {
312 case f_none:
254 break; 313 break;
255 } 314 case f_replace:
256 *pos = 0; 315 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
257 newNeedle = ++pos; 316 quietFlag);
258 for (;;) {
259 pos = strchr(pos, '/');
260 if (pos == NULL) {
261 usage(sed_usage);
262 }
263 if (*(pos - 1) == '\\') {
264 pos++;
265 continue;
266 }
267 break; 317 break;
268 } 318 case f_append:
269 *pos = 0; 319 do_sed_append(stdin, appendline, quietFlag);
270 if (pos + 2 != 0) { 320 break;
271 while (*++pos) { 321 }
272 switch (*pos) { 322 } else {
273 case 'i': 323 while (argc-- > 0) {
274 ignoreCase = TRUE; 324 name = *argv++;
325
326 fp = fopen(name, "r");
327 if (fp == NULL) {
328 perror(name);
329 continue;
330 }
331
332 switch (sed_f) {
333 case f_none:
275 break; 334 break;
276 case 'p': 335 case f_replace:
277 printFlag = TRUE; 336 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
337 quietFlag);
278 break; 338 break;
279 case 'g': 339 case f_append:
340 do_sed_append(fp, appendline, quietFlag);
280 break; 341 break;
281 default:
282 usage(sed_usage);
283 }
284 } 342 }
285 }
286 cp = pos;
287 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
288 break;
289 343
290 case 'a': /* APPEND */ 344 if (ferror(fp))
291 if (strlen(cp) < 2) 345 perror(name);
292 break;
293 sed_f = f_append;
294 appendline = ++cp;
295 /* fprintf(stderr, "append '%s'\n", appendline); */
296 break;
297 }
298 346
299 stopNow = TRUE; 347 fclose(fp);
300 break; 348 }
301
302 default:
303 usage(sed_usage);
304 }
305 }
306 }
307
308 if (argc == 0) {
309 switch (sed_f) {
310 case f_none:
311 break;
312 case f_replace:
313 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
314 quietFlag);
315 break;
316 case f_append:
317 do_sed_append(stdin, appendline, quietFlag);
318 break;
319 }
320 } else {
321 while (argc-- > 0) {
322 name = *argv++;
323
324 fp = fopen(name, "r");
325 if (fp == NULL) {
326 perror(name);
327 continue;
328 }
329
330 switch (sed_f) {
331 case f_none:
332 break;
333 case f_replace:
334 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
335 quietFlag);
336 break;
337 case f_append:
338 do_sed_append(fp, appendline, quietFlag);
339 break;
340 }
341
342 if (ferror(fp))
343 perror(name);
344
345 fclose(fp);
346 } 349 }
347 } 350 exit(TRUE);
348 exit(TRUE);
349} 351}
350 352
351 353
diff --git a/fbset.c b/fbset.c
index c29145e51..a75e431db 100644
--- a/fbset.c
+++ b/fbset.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini fbset implementation for busybox 3 * Mini fbset implementation for busybox
3 * 4 *
@@ -48,7 +49,7 @@
48#define OPT_READMODE (1 << 2) 49#define OPT_READMODE (1 << 2)
49 50
50#define CMD_HELP 0 51#define CMD_HELP 0
51#define CMD_FB 1 52#define CMD_FB 1
52#define CMD_DB 2 53#define CMD_DB 2
53#define CMD_GEOMETRY 3 54#define CMD_GEOMETRY 3
54#define CMD_TIMING 4 55#define CMD_TIMING 4
@@ -87,213 +88,242 @@
87static unsigned int g_options = 0; 88static unsigned int g_options = 0;
88 89
89struct cmdoptions_t { 90struct cmdoptions_t {
90 char *name; 91 char *name;
91 unsigned char param_count; 92 unsigned char param_count;
92 unsigned char code; 93 unsigned char code;
93} g_cmdoptions[] = { 94} g_cmdoptions[] = {
94 { "-h", 0, CMD_HELP }, 95 {
95 { "-fb", 1, CMD_FB }, 96 "-h", 0, CMD_HELP}, {
96 { "-db", 1, CMD_DB }, 97 "-fb", 1, CMD_FB}, {
97 { "-a", 0, CMD_ALL }, 98 "-db", 1, CMD_DB}, {
98 { "-i", 0, CMD_INFO }, 99 "-a", 0, CMD_ALL}, {
99 { "-g", 5, CMD_GEOMETRY }, 100 "-i", 0, CMD_INFO}, {
100 { "-t", 7, CMD_TIMING }, 101 "-g", 5, CMD_GEOMETRY}, {
101 { "-accel", 1, CMD_ACCEL }, 102 "-t", 7, CMD_TIMING}, {
102 { "-hsync", 1, CMD_HSYNC }, 103 "-accel", 1, CMD_ACCEL}, {
103 { "-vsync", 1, CMD_VSYNC }, 104 "-hsync", 1, CMD_HSYNC}, {
104 { "-laced", 1, CMD_LACED }, 105 "-vsync", 1, CMD_VSYNC}, {
105 { "-double", 1, CMD_DOUBLE }, 106 "-laced", 1, CMD_LACED}, {
106 107 "-double", 1, CMD_DOUBLE},
107#ifdef BB_FBSET_FANCY 108#ifdef BB_FBSET_FANCY
108 { "--help", 0, CMD_HELP }, 109 {
109 { "-all", 0, CMD_ALL }, 110 "--help", 0, CMD_HELP}, {
110 { "-xres", 1, CMD_XRES }, 111 "-all", 0, CMD_ALL}, {
111 { "-yres", 1, CMD_YRES }, 112 "-xres", 1, CMD_XRES}, {
112 { "-vxres", 1, CMD_VXRES }, 113 "-yres", 1, CMD_YRES}, {
113 { "-vyres", 1, CMD_VYRES }, 114 "-vxres", 1, CMD_VXRES}, {
114 { "-depth", 1, CMD_DEPTH }, 115 "-vyres", 1, CMD_VYRES}, {
115 { "-match", 0, CMD_MATCH }, 116 "-depth", 1, CMD_DEPTH}, {
116 { "--geometry", 5, CMD_GEOMETRY }, 117 "-match", 0, CMD_MATCH}, {
117 118 "--geometry", 5, CMD_GEOMETRY}, {
118 { "-pixclock", 1, CMD_PIXCLOCK }, 119 "-pixclock", 1, CMD_PIXCLOCK}, {
119 { "-left", 1, CMD_LEFT }, 120 "-left", 1, CMD_LEFT}, {
120 { "-right", 1, CMD_RIGHT }, 121 "-right", 1, CMD_RIGHT}, {
121 { "-upper", 1, CMD_UPPER }, 122 "-upper", 1, CMD_UPPER}, {
122 { "-lower", 1, CMD_LOWER }, 123 "-lower", 1, CMD_LOWER}, {
123 { "-hslen", 1, CMD_HSLEN }, 124 "-hslen", 1, CMD_HSLEN}, {
124 { "-vslen", 1, CMD_VSLEN }, 125 "-vslen", 1, CMD_VSLEN}, {
125 { "--timings", 7, CMD_TIMING }, 126 "--timings", 7, CMD_TIMING}, {
126 127 "-csync", 1, CMD_CSYNC}, {
127 { "-csync", 1, CMD_CSYNC }, 128 "-gsync", 1, CMD_GSYNC}, {
128 { "-gsync", 1, CMD_GSYNC }, 129 "-extsync", 1, CMD_EXTSYNC}, {
129 { "-extsync", 1, CMD_EXTSYNC }, 130 "-bcast", 1, CMD_BCAST}, {
130 { "-bcast", 1, CMD_BCAST }, 131 "-rgba", 1, CMD_RGBA}, {
131 { "-rgba", 1, CMD_RGBA }, 132 "-step", 1, CMD_STEP}, {
132 { "-step", 1, CMD_STEP }, 133 "-move", 1, CMD_MOVE},
133 { "-move", 1, CMD_MOVE },
134#endif 134#endif
135 { 0, 0, 0 } 135 {
136 0, 0, 0}
136}; 137};
137 138
138static int readmode(struct fb_var_screeninfo *base, const char *fn, 139static int readmode(struct fb_var_screeninfo *base, const char *fn,
139 const char *mode) 140 const char *mode)
140{ 141{
141#ifdef BB_FBSET_READMODE 142#ifdef BB_FBSET_READMODE
142 FILE *f; 143 FILE *f;
143 char buf[256]; 144 char buf[256];
144 char *p = buf; 145 char *p = buf;
145 146
146 if ((f = fopen(fn, "r")) == NULL) PERROR("readmode(fopen)"); 147 if ((f = fopen(fn, "r")) == NULL)
147 while (!feof(f)) { 148 PERROR("readmode(fopen)");
148 fgets(buf, sizeof(buf), f); 149 while (!feof(f)) {
149 if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { 150 fgets(buf, sizeof(buf), f);
150 p += 5; 151 if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) {
151 if ((p = strstr(buf, mode))) { 152 p += 5;
152 p += strlen(mode); 153 if ((p = strstr(buf, mode))) {
153 if (!isspace(*p) && (*p != 0) && (*p != '"') && (*p != '\r') 154 p += strlen(mode);
154 && (*p != '\n')) continue; /* almost, but not quite */ 155 if (!isspace(*p) && (*p != 0) && (*p != '"')
155 while (!feof(f)) { 156 && (*p != '\r') && (*p != '\n'))
156 fgets(buf, sizeof(buf), f); 157 continue; /* almost, but not quite */
157 if (!strstr(buf, "endmode")) return 1; 158 while (!feof(f)) {
159 fgets(buf, sizeof(buf), f);
160 if (!strstr(buf, "endmode"))
161 return 1;
162 }
163 }
158 } 164 }
159 }
160 } 165 }
161 }
162#else 166#else
163 fprintf(stderr, "W: mode reading was disabled on this copy of fbset; ignoring request\n"); 167 fprintf(stderr,
168 "W: mode reading was disabled on this copy of fbset; ignoring request\n");
164#endif 169#endif
165 return 0; 170 return 0;
166} 171}
167 172
168static void setmode(struct fb_var_screeninfo *base, 173static void setmode(struct fb_var_screeninfo *base,
169 struct fb_var_screeninfo *set) 174 struct fb_var_screeninfo *set)
170{ 175{
171 if ((int)set->xres > 0) base->xres = set->xres; 176 if ((int) set->xres > 0)
172 if ((int)set->yres > 0) base->yres = set->yres; 177 base->xres = set->xres;
173 if ((int)set->xres_virtual > 0) base->xres_virtual = set->xres_virtual; 178 if ((int) set->yres > 0)
174 if ((int)set->yres_virtual > 0) base->yres_virtual = set->yres_virtual; 179 base->yres = set->yres;
175 if ((int)set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel; 180 if ((int) set->xres_virtual > 0)
181 base->xres_virtual = set->xres_virtual;
182 if ((int) set->yres_virtual > 0)
183 base->yres_virtual = set->yres_virtual;
184 if ((int) set->bits_per_pixel > 0)
185 base->bits_per_pixel = set->bits_per_pixel;
176} 186}
177 187
178static void showmode(struct fb_var_screeninfo *v) 188static void showmode(struct fb_var_screeninfo *v)
179{ 189{
180 double drate = 0, hrate = 0, vrate = 0; 190 double drate = 0, hrate = 0, vrate = 0;
181 if (v->pixclock) { 191
182 drate = 1e12 / v->pixclock; 192 if (v->pixclock) {
183 hrate = drate / (v->left_margin+v->xres+v->right_margin+v->hsync_len); 193 drate = 1e12 / v->pixclock;
184 vrate = hrate / (v->upper_margin+v->yres+v->lower_margin+v->vsync_len); 194 hrate =
185 } 195 drate / (v->left_margin + v->xres + v->right_margin +
186 printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int)(vrate+0.5)); 196 v->hsync_len);
197 vrate =
198 hrate / (v->upper_margin + v->yres + v->lower_margin +
199 v->vsync_len);
200 }
201 printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5));
187#ifdef BB_FBSET_FANCY 202#ifdef BB_FBSET_FANCY
188 printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate/1e6, hrate/1e3, 203 printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6,
189 vrate); 204 hrate / 1e3, vrate);
190#endif 205#endif
191 printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, 206 printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres,
192 v->xres_virtual, v->yres_virtual, v->bits_per_pixel); 207 v->xres_virtual, v->yres_virtual, v->bits_per_pixel);
193#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 208#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
194 printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, 209 printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin,
195 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, 210 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len,
196 v->vsync_len); 211 v->vsync_len);
197 printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); 212 printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false"));
198#else 213#else
199 printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock, v->left_margin, 214 printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock,
200 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, 215 v->left_margin, v->right_margin, v->upper_margin,
201 v->vsync_len); 216 v->lower_margin, v->hsync_len, v->vsync_len);
202#endif 217#endif
203 printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, v->red.offset, 218 printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length,
204 v->green.length, v->green.offset, v->blue.length, v->blue.offset, 219 v->red.offset, v->green.length, v->green.offset, v->blue.length,
205 v->transp.length, v->transp.offset); 220 v->blue.offset, v->transp.length, v->transp.offset);
206 printf("endmode\n"); 221 printf("endmode\n");
207} 222}
208 223
209static void fbset_usage(void) 224static void fbset_usage(void)
210{ 225{
211 int i; 226 int i;
227
212#ifndef STANDALONE 228#ifndef STANDALONE
213 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 229 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
230 BB_VER, BB_BT);
214#endif 231#endif
215 fprintf(stderr, "Usage: fbset [options] [mode]\n"); 232 fprintf(stderr, "Usage: fbset [options] [mode]\n");
216 fprintf(stderr, "\tThe following options are recognized:\n"); 233 fprintf(stderr, "\tThe following options are recognized:\n");
217 for (i = 0; g_cmdoptions[i].name; i++) 234 for (i = 0; g_cmdoptions[i].name; i++)
218 fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name); 235 fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name);
219 exit(-1); 236 exit(-1);
220} 237}
221 238
222#ifdef STANDALONE 239#ifdef STANDALONE
223int main(int argc, char **argv) 240int main(int argc, char **argv)
224#else 241#else
225extern int fbset_main(int argc, char **argv) 242extern int fbset_main(int argc, char **argv)
226#endif 243#endif
227{ 244{
228 struct fb_var_screeninfo var, varset; 245 struct fb_var_screeninfo var, varset;
229 int fh, i; 246 int fh, i;
230 char *fbdev = DEFAULTFBDEV; 247 char *fbdev = DEFAULTFBDEV;
231 char *modefile = DEFAULTFBMODE; 248 char *modefile = DEFAULTFBMODE;
232 char *thisarg, *mode = NULL; 249 char *thisarg, *mode = NULL;
250
251 memset(&varset, 0xFF, sizeof(varset));
233 252
234 memset(&varset, 0xFF, sizeof(varset)); 253 /* parse cmd args.... why do they have to make things so difficult? */
235 254 argv++;
236 /* parse cmd args.... why do they have to make things so difficult? */ 255 argc--;
237 argv++; argc--; 256 for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
238 for (; argc > 0 && (thisarg = *argv); argc--, argv++) { 257 for (i = 0; g_cmdoptions[i].name; i++) {
239 for (i = 0; g_cmdoptions[i].name; i++) { 258 if (!strcmp(thisarg, g_cmdoptions[i].name)) {
240 if (!strcmp(thisarg, g_cmdoptions[i].name)) { 259 if (argc - 1 < g_cmdoptions[i].param_count)
241 if (argc - 1 < g_cmdoptions[i].param_count) fbset_usage(); 260 fbset_usage();
242 switch (g_cmdoptions[i].code) { 261 switch (g_cmdoptions[i].code) {
243 case CMD_HELP: fbset_usage(); 262 case CMD_HELP:
244 case CMD_FB: fbdev = argv[1]; break; 263 fbset_usage();
245 case CMD_DB: modefile = argv[1]; break; 264 case CMD_FB:
246 case CMD_GEOMETRY: 265 fbdev = argv[1];
247 varset.xres = strtoul(argv[1],0,0); 266 break;
248 varset.yres = strtoul(argv[2],0,0); 267 case CMD_DB:
249 varset.xres_virtual = strtoul(argv[3],0,0); 268 modefile = argv[1];
250 varset.yres_virtual = strtoul(argv[4],0,0); 269 break;
251 varset.bits_per_pixel = strtoul(argv[5],0,0); 270 case CMD_GEOMETRY:
252 break; 271 varset.xres = strtoul(argv[1], 0, 0);
253 case CMD_TIMING: 272 varset.yres = strtoul(argv[2], 0, 0);
254 varset.pixclock = strtoul(argv[1],0,0); 273 varset.xres_virtual = strtoul(argv[3], 0, 0);
255 varset.left_margin = strtoul(argv[2],0,0); 274 varset.yres_virtual = strtoul(argv[4], 0, 0);
256 varset.right_margin = strtoul(argv[3],0,0); 275 varset.bits_per_pixel = strtoul(argv[5], 0, 0);
257 varset.upper_margin = strtoul(argv[4],0,0); 276 break;
258 varset.lower_margin = strtoul(argv[5],0,0); 277 case CMD_TIMING:
259 varset.hsync_len = strtoul(argv[6],0,0); 278 varset.pixclock = strtoul(argv[1], 0, 0);
260 varset.vsync_len = strtoul(argv[7],0,0); 279 varset.left_margin = strtoul(argv[2], 0, 0);
261 break; 280 varset.right_margin = strtoul(argv[3], 0, 0);
281 varset.upper_margin = strtoul(argv[4], 0, 0);
282 varset.lower_margin = strtoul(argv[5], 0, 0);
283 varset.hsync_len = strtoul(argv[6], 0, 0);
284 varset.vsync_len = strtoul(argv[7], 0, 0);
285 break;
262#ifdef BB_FBSET_FANCY 286#ifdef BB_FBSET_FANCY
263 case CMD_XRES: varset.xres = strtoul(argv[1],0,0); break; 287 case CMD_XRES:
264 case CMD_YRES: varset.yres = strtoul(argv[1],0,0); break; 288 varset.xres = strtoul(argv[1], 0, 0);
289 break;
290 case CMD_YRES:
291 varset.yres = strtoul(argv[1], 0, 0);
292 break;
265#endif 293#endif
294 }
295 argc -= g_cmdoptions[i].param_count;
296 argv += g_cmdoptions[i].param_count;
297 break;
298 }
299 }
300 if (!g_cmdoptions[i].name) {
301 if (argc == 1) {
302 mode = *argv;
303 g_options |= OPT_READMODE;
304 } else {
305 fbset_usage();
306 }
266 } 307 }
267 argc -= g_cmdoptions[i].param_count;
268 argv += g_cmdoptions[i].param_count;
269 break;
270 }
271 }
272 if (!g_cmdoptions[i].name) {
273 if (argc == 1) {
274 mode = *argv;
275 g_options |= OPT_READMODE;
276 } else {
277 fbset_usage();
278 }
279 } 308 }
280 }
281 309
282 if ((fh = open(fbdev, O_RDONLY)) < 0) PERROR("fbset(open)"); 310 if ((fh = open(fbdev, O_RDONLY)) < 0)
283 if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); 311 PERROR("fbset(open)");
284 if (g_options & OPT_READMODE) { 312 if (ioctl(fh, FBIOGET_VSCREENINFO, &var))
285 if (!readmode(&var, modefile, mode)) { 313 PERROR("fbset(ioctl)");
286 fprintf(stderr, "Unknown video mode `%s'\n", mode); 314 if (g_options & OPT_READMODE) {
287 exit(1); 315 if (!readmode(&var, modefile, mode)) {
316 fprintf(stderr, "Unknown video mode `%s'\n", mode);
317 exit(1);
318 }
288 } 319 }
289 }
290 320
291 setmode(&var, &varset); 321 setmode(&var, &varset);
292 if (g_options & OPT_CHANGE) 322 if (g_options & OPT_CHANGE)
293 if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); 323 if (ioctl(fh, FBIOPUT_VSCREENINFO, &var))
294 showmode(&var); 324 PERROR("fbset(ioctl)");
295 close(fh); 325 showmode(&var);
296 326 close(fh);
297 return(TRUE);
298}
299 327
328 return (TRUE);
329}
diff --git a/fdflush.c b/fdflush.c
index a244e8def..0b154c8a6 100644
--- a/fdflush.c
+++ b/fdflush.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini fdflush implementation for busybox 3 * Mini fdflush implementation for busybox
3 * 4 *
@@ -29,24 +30,25 @@
29 30
30extern int fdflush_main(int argc, char **argv) 31extern int fdflush_main(int argc, char **argv)
31{ 32{
32 int value; 33 int value;
33 int fd; 34 int fd;
34 if ( argc <= 1 || **(argv++) == '-' ) {
35 usage( "fdflush device\n");
36 }
37 35
38 fd = open(*argv, 0); 36 if (argc <= 1 || **(argv++) == '-') {
39 if ( fd < 0 ) { 37 usage("fdflush device\n");
40 perror(*argv); 38 }
41 exit(FALSE);
42 }
43 39
44 value = ioctl(fd, FDFLUSH, 0); 40 fd = open(*argv, 0);
45 close(fd); 41 if (fd < 0) {
42 perror(*argv);
43 exit(FALSE);
44 }
46 45
47 if ( value ) { 46 value = ioctl(fd, FDFLUSH, 0);
48 perror(*argv); 47 close(fd);
49 exit(FALSE); 48
50 } 49 if (value) {
51 exit (TRUE); 50 perror(*argv);
51 exit(FALSE);
52 }
53 exit(TRUE);
52} 54}
diff --git a/find.c b/find.c
index 50872b7f1..6346d454f 100644
--- a/find.c
+++ b/find.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini find implementation for busybox 3 * Mini find implementation for busybox
3 * 4 *
@@ -28,92 +29,95 @@
28#include <dirent.h> 29#include <dirent.h>
29 30
30 31
31static char* pattern=NULL; 32static char *pattern = NULL;
32static char* directory="."; 33static char *directory = ".";
33static int dereferenceFlag=FALSE; 34static int dereferenceFlag = FALSE;
34 35
35static const char find_usage[] = "find [PATH...] [EXPRESSION]\n\n" 36static const char find_usage[] = "find [PATH...] [EXPRESSION]\n\n"
36"Search for files in a directory hierarchy. The default PATH is\n" 37 "Search for files in a directory hierarchy. The default PATH is\n"
37"the current directory; default EXPRESSION is '-print'\n\n" 38 "the current directory; default EXPRESSION is '-print'\n\n"
38"\nEXPRESSION may consist of:\n" 39 "\nEXPRESSION may consist of:\n"
39"\t-follow\n\t\tDereference symbolic links.\n" 40 "\t-follow\n\t\tDereference symbolic links.\n"
40"\t-name PATTERN\n\t\tFile name (with leading directories removed) matches PATTERN.\n" 41 "\t-name PATTERN\n\t\tFile name (with leading directories removed) matches PATTERN.\n"
41"\t-print\n\t\tprint the full file name followed by a newline to stdout.\n\n" 42 "\t-print\n\t\tprint the full file name followed by a newline to stdout.\n\n"
42#if defined BB_REGEXP 43#if defined BB_REGEXP
43"This version of find matches full regular expresions.\n"; 44 "This version of find matches full regular expresions.\n";
44#else 45#else
45"This version of find matches strings (not regular expresions).\n"; 46 "This version of find matches strings (not regular expresions).\n";
46#endif 47#endif
47 48
48 49
49 50
50static int fileAction(const char *fileName, struct stat* statbuf) 51static int fileAction(const char *fileName, struct stat *statbuf)
51{ 52{
52 if (pattern==NULL) 53 if (pattern == NULL)
53 fprintf(stdout, "%s\n", fileName); 54 fprintf(stdout, "%s\n", fileName);
54 else { 55 else {
55 char* tmp = strrchr( fileName, '/'); 56 char *tmp = strrchr(fileName, '/');
56 if (tmp == NULL) 57
57 tmp = (char*)fileName; 58 if (tmp == NULL)
58 else 59 tmp = (char *) fileName;
59 tmp++; 60 else
60 if (check_wildcard_match(tmp, pattern) == TRUE) 61 tmp++;
61 fprintf(stdout, "%s\n", fileName); 62 if (check_wildcard_match(tmp, pattern) == TRUE)
62 } 63 fprintf(stdout, "%s\n", fileName);
63 return( TRUE); 64 }
65 return (TRUE);
64} 66}
65 67
66int find_main(int argc, char **argv) 68int find_main(int argc, char **argv)
67{ 69{
68 /* peel off the "find" */ 70 /* peel off the "find" */
69 argc--;
70 argv++;
71
72 if ( argc > 0 && **argv != '-') {
73 directory = *argv;
74 argc--; 71 argc--;
75 argv++; 72 argv++;
76 }
77 73
78 /* Parse any options */ 74 if (argc > 0 && **argv != '-') {
79 while (argc > 0 && **argv == '-') { 75 directory = *argv;
80 int stopit=FALSE; 76 argc--;
81 while (*++(*argv) && stopit==FALSE) switch (**argv) { 77 argv++;
82 case 'f':
83 if (strcmp(*argv, "follow")==0) {
84 argc--;
85 argv++;
86 dereferenceFlag=TRUE;
87 }
88 break;
89 case 'n':
90 if (strcmp(*argv, "name")==0) {
91 if (argc-- > 1) {
92 pattern = *(++argv);
93 stopit = TRUE;
94 } else {
95 usage (find_usage);
96 }
97 }
98 break;
99 case '-':
100 /* Ignore all long options */
101 break;
102 default:
103 usage (find_usage);
104 } 78 }
105 if (argc-- > 1)
106 argv++;
107 if (**argv != '-')
108 break;
109 else
110 break;
111 }
112 79
113 if (recursiveAction(directory, TRUE, FALSE, FALSE, 80 /* Parse any options */
114 fileAction, fileAction) == FALSE) { 81 while (argc > 0 && **argv == '-') {
115 exit( FALSE); 82 int stopit = FALSE;
116 } 83
84 while (*++(*argv) && stopit == FALSE)
85 switch (**argv) {
86 case 'f':
87 if (strcmp(*argv, "follow") == 0) {
88 argc--;
89 argv++;
90 dereferenceFlag = TRUE;
91 }
92 break;
93 case 'n':
94 if (strcmp(*argv, "name") == 0) {
95 if (argc-- > 1) {
96 pattern = *(++argv);
97 stopit = TRUE;
98 } else {
99 usage(find_usage);
100 }
101 }
102 break;
103 case '-':
104 /* Ignore all long options */
105 break;
106 default:
107 usage(find_usage);
108 }
109 if (argc-- > 1)
110 argv++;
111 if (**argv != '-')
112 break;
113 else
114 break;
115 }
116
117 if (recursiveAction(directory, TRUE, FALSE, FALSE,
118 fileAction, fileAction) == FALSE) {
119 exit(FALSE);
120 }
117 121
118 exit(TRUE); 122 exit(TRUE);
119} 123}
diff --git a/findutils/find.c b/findutils/find.c
index 50872b7f1..6346d454f 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini find implementation for busybox 3 * Mini find implementation for busybox
3 * 4 *
@@ -28,92 +29,95 @@
28#include <dirent.h> 29#include <dirent.h>
29 30
30 31
31static char* pattern=NULL; 32static char *pattern = NULL;
32static char* directory="."; 33static char *directory = ".";
33static int dereferenceFlag=FALSE; 34static int dereferenceFlag = FALSE;
34 35
35static const char find_usage[] = "find [PATH...] [EXPRESSION]\n\n" 36static const char find_usage[] = "find [PATH...] [EXPRESSION]\n\n"
36"Search for files in a directory hierarchy. The default PATH is\n" 37 "Search for files in a directory hierarchy. The default PATH is\n"
37"the current directory; default EXPRESSION is '-print'\n\n" 38 "the current directory; default EXPRESSION is '-print'\n\n"
38"\nEXPRESSION may consist of:\n" 39 "\nEXPRESSION may consist of:\n"
39"\t-follow\n\t\tDereference symbolic links.\n" 40 "\t-follow\n\t\tDereference symbolic links.\n"
40"\t-name PATTERN\n\t\tFile name (with leading directories removed) matches PATTERN.\n" 41 "\t-name PATTERN\n\t\tFile name (with leading directories removed) matches PATTERN.\n"
41"\t-print\n\t\tprint the full file name followed by a newline to stdout.\n\n" 42 "\t-print\n\t\tprint the full file name followed by a newline to stdout.\n\n"
42#if defined BB_REGEXP 43#if defined BB_REGEXP
43"This version of find matches full regular expresions.\n"; 44 "This version of find matches full regular expresions.\n";
44#else 45#else
45"This version of find matches strings (not regular expresions).\n"; 46 "This version of find matches strings (not regular expresions).\n";
46#endif 47#endif
47 48
48 49
49 50
50static int fileAction(const char *fileName, struct stat* statbuf) 51static int fileAction(const char *fileName, struct stat *statbuf)
51{ 52{
52 if (pattern==NULL) 53 if (pattern == NULL)
53 fprintf(stdout, "%s\n", fileName); 54 fprintf(stdout, "%s\n", fileName);
54 else { 55 else {
55 char* tmp = strrchr( fileName, '/'); 56 char *tmp = strrchr(fileName, '/');
56 if (tmp == NULL) 57
57 tmp = (char*)fileName; 58 if (tmp == NULL)
58 else 59 tmp = (char *) fileName;
59 tmp++; 60 else
60 if (check_wildcard_match(tmp, pattern) == TRUE) 61 tmp++;
61 fprintf(stdout, "%s\n", fileName); 62 if (check_wildcard_match(tmp, pattern) == TRUE)
62 } 63 fprintf(stdout, "%s\n", fileName);
63 return( TRUE); 64 }
65 return (TRUE);
64} 66}
65 67
66int find_main(int argc, char **argv) 68int find_main(int argc, char **argv)
67{ 69{
68 /* peel off the "find" */ 70 /* peel off the "find" */
69 argc--;
70 argv++;
71
72 if ( argc > 0 && **argv != '-') {
73 directory = *argv;
74 argc--; 71 argc--;
75 argv++; 72 argv++;
76 }
77 73
78 /* Parse any options */ 74 if (argc > 0 && **argv != '-') {
79 while (argc > 0 && **argv == '-') { 75 directory = *argv;
80 int stopit=FALSE; 76 argc--;
81 while (*++(*argv) && stopit==FALSE) switch (**argv) { 77 argv++;
82 case 'f':
83 if (strcmp(*argv, "follow")==0) {
84 argc--;
85 argv++;
86 dereferenceFlag=TRUE;
87 }
88 break;
89 case 'n':
90 if (strcmp(*argv, "name")==0) {
91 if (argc-- > 1) {
92 pattern = *(++argv);
93 stopit = TRUE;
94 } else {
95 usage (find_usage);
96 }
97 }
98 break;
99 case '-':
100 /* Ignore all long options */
101 break;
102 default:
103 usage (find_usage);
104 } 78 }
105 if (argc-- > 1)
106 argv++;
107 if (**argv != '-')
108 break;
109 else
110 break;
111 }
112 79
113 if (recursiveAction(directory, TRUE, FALSE, FALSE, 80 /* Parse any options */
114 fileAction, fileAction) == FALSE) { 81 while (argc > 0 && **argv == '-') {
115 exit( FALSE); 82 int stopit = FALSE;
116 } 83
84 while (*++(*argv) && stopit == FALSE)
85 switch (**argv) {
86 case 'f':
87 if (strcmp(*argv, "follow") == 0) {
88 argc--;
89 argv++;
90 dereferenceFlag = TRUE;
91 }
92 break;
93 case 'n':
94 if (strcmp(*argv, "name") == 0) {
95 if (argc-- > 1) {
96 pattern = *(++argv);
97 stopit = TRUE;
98 } else {
99 usage(find_usage);
100 }
101 }
102 break;
103 case '-':
104 /* Ignore all long options */
105 break;
106 default:
107 usage(find_usage);
108 }
109 if (argc-- > 1)
110 argv++;
111 if (**argv != '-')
112 break;
113 else
114 break;
115 }
116
117 if (recursiveAction(directory, TRUE, FALSE, FALSE,
118 fileAction, fileAction) == FALSE) {
119 exit(FALSE);
120 }
117 121
118 exit(TRUE); 122 exit(TRUE);
119} 123}
diff --git a/findutils/grep.c b/findutils/grep.c
index 287d9f80d..d8d2f1837 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini grep implementation for busybox 3 * Mini grep implementation for busybox
3 * 4 *
@@ -40,126 +41,125 @@
40#include <ctype.h> 41#include <ctype.h>
41 42
42static const char grep_usage[] = 43static const char grep_usage[] =
43"grep [OPTIONS]... PATTERN [FILE]...\n\n" 44 "grep [OPTIONS]... PATTERN [FILE]...\n\n"
44"Search for PATTERN in each FILE or standard input.\n\n" 45 "Search for PATTERN in each FILE or standard input.\n\n"
45"OPTIONS:\n" 46 "OPTIONS:\n"
46"\t-h\tsuppress the prefixing filename on output\n" 47 "\t-h\tsuppress the prefixing filename on output\n"
47"\t-i\tignore case distinctions\n" 48 "\t-i\tignore case distinctions\n"
48"\t-n\tprint line number with output lines\n" 49 "\t-n\tprint line number with output lines\n"
49"\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n\n" 50 "\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n\n"
50#if defined BB_REGEXP 51#if defined BB_REGEXP
51"This version of grep matches full regular expresions.\n"; 52 "This version of grep matches full regular expresions.\n";
52#else 53#else
53"This version of grep matches strings (not regular expresions).\n"; 54 "This version of grep matches strings (not regular expresions).\n";
54#endif 55#endif
55 56
56static int match = FALSE, beQuiet = FALSE; 57static int match = FALSE, beQuiet = FALSE;
57 58
58static void do_grep(FILE *fp, char* needle, char *fileName, int tellName, int ignoreCase, int tellLine) 59static void do_grep(FILE * fp, char *needle, char *fileName, int tellName,
60 int ignoreCase, int tellLine)
59{ 61{
60 char *cp; 62 char *cp;
61 long line = 0; 63 long line = 0;
62 char haystack[BUF_SIZE]; 64 char haystack[BUF_SIZE];
63 65
64 while (fgets (haystack, sizeof (haystack), fp)) { 66 while (fgets(haystack, sizeof(haystack), fp)) {
65 line++; 67 line++;
66 cp = &haystack[strlen (haystack) - 1]; 68 cp = &haystack[strlen(haystack) - 1];
67 69
68 if (*cp != '\n') 70 if (*cp != '\n')
69 fprintf (stderr, "%s: Line too long\n", fileName); 71 fprintf(stderr, "%s: Line too long\n", fileName);
70 72
71 if (find_match(haystack, needle, ignoreCase) == TRUE) { 73 if (find_match(haystack, needle, ignoreCase) == TRUE) {
72 if (tellName==TRUE) 74 if (tellName == TRUE)
73 printf ("%s:", fileName); 75 printf("%s:", fileName);
74 76
75 if (tellLine==TRUE) 77 if (tellLine == TRUE)
76 printf ("%ld:", line); 78 printf("%ld:", line);
77 79
78 if (beQuiet==FALSE) 80 if (beQuiet == FALSE)
79 fputs (haystack, stdout); 81 fputs(haystack, stdout);
80 82
81 match = TRUE; 83 match = TRUE;
84 }
82 } 85 }
83 }
84} 86}
85 87
86 88
87extern int grep_main (int argc, char **argv) 89extern int grep_main(int argc, char **argv)
88{ 90{
89 FILE *fp; 91 FILE *fp;
90 char *cp; 92 char *cp;
91 char *needle; 93 char *needle;
92 char *fileName; 94 char *fileName;
93 int tellName=TRUE; 95 int tellName = TRUE;
94 int ignoreCase=TRUE; 96 int ignoreCase = TRUE;
95 int tellLine=FALSE; 97 int tellLine = FALSE;
96 98
97 99
98 ignoreCase = FALSE; 100 ignoreCase = FALSE;
99 tellLine = FALSE; 101 tellLine = FALSE;
100 102
101 argc--;
102 argv++;
103 if (argc < 1) {
104 usage(grep_usage);
105 }
106
107 if (**argv == '-') {
108 argc--; 103 argc--;
109 cp = *argv++; 104 argv++;
105 if (argc < 1) {
106 usage(grep_usage);
107 }
110 108
111 while (*++cp) 109 if (**argv == '-') {
112 switch (*cp) { 110 argc--;
113 case 'i': 111 cp = *argv++;
114 ignoreCase = TRUE;
115 break;
116 112
117 case 'h': 113 while (*++cp)
118 tellName = FALSE; 114 switch (*cp) {
119 break; 115 case 'i':
116 ignoreCase = TRUE;
117 break;
120 118
121 case 'n': 119 case 'h':
122 tellLine = TRUE; 120 tellName = FALSE;
123 break; 121 break;
124 122
125 case 'q': 123 case 'n':
126 beQuiet = TRUE; 124 tellLine = TRUE;
127 break; 125 break;
128 126
129 default: 127 case 'q':
130 usage(grep_usage); 128 beQuiet = TRUE;
131 } 129 break;
132 } 130
133 131 default:
134 needle = *argv++; 132 usage(grep_usage);
135 argc--; 133 }
136
137 if (argc==0) {
138 do_grep( stdin, needle, "stdin", FALSE, ignoreCase, tellLine);
139 } else {
140 /* Never print the filename for just one file */
141 if (argc==1)
142 tellName=FALSE;
143 while (argc-- > 0) {
144 fileName = *argv++;
145
146 fp = fopen (fileName, "r");
147 if (fp == NULL) {
148 perror (fileName);
149 continue;
150 }
151
152 do_grep( fp, needle, fileName, tellName, ignoreCase, tellLine);
153
154 if (ferror (fp))
155 perror (fileName);
156 fclose (fp);
157 } 134 }
158 }
159 exit(match);
160}
161 135
136 needle = *argv++;
137 argc--;
162 138
163/* END CODE */ 139 if (argc == 0) {
140 do_grep(stdin, needle, "stdin", FALSE, ignoreCase, tellLine);
141 } else {
142 /* Never print the filename for just one file */
143 if (argc == 1)
144 tellName = FALSE;
145 while (argc-- > 0) {
146 fileName = *argv++;
147
148 fp = fopen(fileName, "r");
149 if (fp == NULL) {
150 perror(fileName);
151 continue;
152 }
153
154 do_grep(fp, needle, fileName, tellName, ignoreCase, tellLine);
155
156 if (ferror(fp))
157 perror(fileName);
158 fclose(fp);
159 }
160 }
161 exit(match);
162}
164 163
165 164
165/* END CODE */
diff --git a/free.c b/free.c
index 36d357522..b07135430 100644
--- a/free.c
+++ b/free.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini free implementation for busybox 3 * Mini free implementation for busybox
3 * 4 *
@@ -30,6 +31,7 @@
30 31
31extern int free_main(int argc, char **argv) 32extern int free_main(int argc, char **argv)
32{ 33{
33 char* cmd[] = { "cat", "/proc/meminfo", "\0" }; 34 char *cmd[] = { "cat", "/proc/meminfo", "\0" };
34 exit(cat_main( 3, cmd)); 35
36 exit(cat_main(3, cmd));
35} 37}
diff --git a/fsck_minix.c b/fsck_minix.c
index 09111c5dc..084c76d36 100644
--- a/fsck_minix.c
+++ b/fsck_minix.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * fsck.c - a file system consistency checker for Linux. 3 * fsck.c - a file system consistency checker for Linux.
3 * 4 *
@@ -96,7 +97,7 @@
96#include <termios.h> 97#include <termios.h>
97#include <mntent.h> 98#include <mntent.h>
98#include <sys/stat.h> 99#include <sys/stat.h>
99#include <sys/param.h> /* for PATH_MAX */ 100#include <sys/param.h> /* for PATH_MAX */
100 101
101#include <linux/fs.h> 102#include <linux/fs.h>
102#include <linux/minix_fs.h> 103#include <linux/minix_fs.h>
@@ -124,17 +125,17 @@
124 125
125#define BITS_PER_BLOCK (BLOCK_SIZE<<3) 126#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
126 127
127static char * program_name = "fsck.minix"; 128static char *program_name = "fsck.minix";
128static char * program_version = "1.2 - 11/11/96"; 129static char *program_version = "1.2 - 11/11/96";
129static char * device_name = NULL; 130static char *device_name = NULL;
130static int IN; 131static int IN;
131static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0, 132static int repair = 0, automatic = 0, verbose = 0, list = 0, show =
132 force=0; 133 0, warn_mode = 0, force = 0;
133static int directory=0, regular=0, blockdev=0, chardev=0, links=0, 134static int directory = 0, regular = 0, blockdev = 0, chardev = 0, links =
134 symlinks=0, total=0; 135 0, symlinks = 0, total = 0;
135 136
136static int changed = 0; /* flags if the filesystem has been changed */ 137static int changed = 0; /* flags if the filesystem has been changed */
137static int errors_uncorrected = 0; /* flag if some error was not corrected */ 138static int errors_uncorrected = 0; /* flag if some error was not corrected */
138static int dirsize = 16; 139static int dirsize = 16;
139static int namelen = 14; 140static int namelen = 14;
140static int version2 = 0; 141static int version2 = 0;
@@ -146,10 +147,12 @@ static int termios_set = 0;
146static int name_depth = 0; 147static int name_depth = 0;
147static char name_list[MAX_DEPTH][PATH_MAX + 1]; 148static char name_list[MAX_DEPTH][PATH_MAX + 1];
148 149
149static char * inode_buffer = NULL; 150static char *inode_buffer = NULL;
151
150#define Inode (((struct minix_inode *) inode_buffer)-1) 152#define Inode (((struct minix_inode *) inode_buffer)-1)
151#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 153#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
152static char super_block_buffer[BLOCK_SIZE]; 154static char super_block_buffer[BLOCK_SIZE];
155
153#define Super (*(struct minix_super_block *)super_block_buffer) 156#define Super (*(struct minix_super_block *)super_block_buffer)
154#define INODES ((unsigned long)Super.s_ninodes) 157#define INODES ((unsigned long)Super.s_ninodes)
155#ifdef HAVE_MINIX2 158#ifdef HAVE_MINIX2
@@ -168,8 +171,8 @@ static char super_block_buffer[BLOCK_SIZE];
168static char *inode_map; 171static char *inode_map;
169static char *zone_map; 172static char *zone_map;
170 173
171static unsigned char * inode_count = NULL; 174static unsigned char *inode_count = NULL;
172static unsigned char * zone_count = NULL; 175static unsigned char *zone_count = NULL;
173 176
174static void recursive_check(unsigned int ino); 177static void recursive_check(unsigned int ino);
175static void recursive_check2(unsigned int ino); 178static void recursive_check2(unsigned int ino);
@@ -191,22 +194,27 @@ static void leave(int status)
191 exit(status); 194 exit(status);
192} 195}
193 196
194static void show_usage(void) { 197static void show_usage(void)
195 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 198{
199 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
200 BB_VER, BB_BT);
196 fprintf(stderr, "Usage: %s [-larvsmf] /dev/name\n\n", program_name); 201 fprintf(stderr, "Usage: %s [-larvsmf] /dev/name\n\n", program_name);
197 fprintf(stderr, "Performs a consistency check for MINIX filesystems.\n\n"); 202 fprintf(stderr,
203 "Performs a consistency check for MINIX filesystems.\n\n");
198 fprintf(stderr, "OPTIONS:\n"); 204 fprintf(stderr, "OPTIONS:\n");
199 fprintf(stderr, "\t-l\tLists all filenames\n"); 205 fprintf(stderr, "\t-l\tLists all filenames\n");
200 fprintf(stderr, "\t-r\tPerform interactive repairs\n"); 206 fprintf(stderr, "\t-r\tPerform interactive repairs\n");
201 fprintf(stderr, "\t-a\tPerform automatic repairs\n"); 207 fprintf(stderr, "\t-a\tPerform automatic repairs\n");
202 fprintf(stderr, "\t-v\tverbose\n"); 208 fprintf(stderr, "\t-v\tverbose\n");
203 fprintf(stderr, "\t-s\tOutputs super-block information\n"); 209 fprintf(stderr, "\t-s\tOutputs super-block information\n");
204 fprintf(stderr, "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n"); 210 fprintf(stderr,
211 "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n");
205 fprintf(stderr, "\t-f\tForce file system check.\n\n"); 212 fprintf(stderr, "\t-f\tForce file system check.\n\n");
206 leave(16); 213 leave(16);
207} 214}
208 215
209static void die(const char *str) { 216static void die(const char *str)
217{
210 fprintf(stderr, "%s: %s\n", program_name, str); 218 fprintf(stderr, "%s: %s\n", program_name, str);
211 leave(8); 219 leave(8);
212} 220}
@@ -217,15 +225,15 @@ static void die(const char *str) {
217 */ 225 */
218static void print_current_name(void) 226static void print_current_name(void)
219{ 227{
220 int i=0; 228 int i = 0;
221 229
222 while (i<name_depth) 230 while (i < name_depth)
223 printf("/%.*s",namelen,name_list[i++]); 231 printf("/%.*s", namelen, name_list[i++]);
224 if (i == 0) 232 if (i == 0)
225 printf ("/"); 233 printf("/");
226} 234}
227 235
228static int ask(const char * string, int def) 236static int ask(const char *string, int def)
229{ 237{
230 int c; 238 int c;
231 239
@@ -237,18 +245,18 @@ static int ask(const char * string, int def)
237 if (automatic) { 245 if (automatic) {
238 printf("\n"); 246 printf("\n");
239 if (!def) 247 if (!def)
240 errors_uncorrected = 1; 248 errors_uncorrected = 1;
241 return def; 249 return def;
242 } 250 }
243 printf(def?"%s (y/n)? ":"%s (n/y)? ",string); 251 printf(def ? "%s (y/n)? " : "%s (n/y)? ", string);
244 for (;;) { 252 for (;;) {
245 fflush(stdout); 253 fflush(stdout);
246 if ((c=getchar())==EOF) { 254 if ((c = getchar()) == EOF) {
247 if (!def) 255 if (!def)
248 errors_uncorrected = 1; 256 errors_uncorrected = 1;
249 return def; 257 return def;
250 } 258 }
251 c=toupper(c); 259 c = toupper(c);
252 if (c == 'Y') { 260 if (c == 'Y') {
253 def = 1; 261 def = 1;
254 break; 262 break;
@@ -263,7 +271,7 @@ static int ask(const char * string, int def)
263 else { 271 else {
264 printf("n\n"); 272 printf("n\n");
265 errors_uncorrected = 1; 273 errors_uncorrected = 1;
266 } 274 }
267 return def; 275 return def;
268} 276}
269 277
@@ -274,17 +282,17 @@ static int ask(const char * string, int def)
274 */ 282 */
275static void check_mount(void) 283static void check_mount(void)
276{ 284{
277 FILE * f; 285 FILE *f;
278 struct mntent * mnt; 286 struct mntent *mnt;
279 int cont; 287 int cont;
280 int fd; 288 int fd;
281 289
282 if ((f = setmntent (MOUNTED, "r")) == NULL) 290 if ((f = setmntent(MOUNTED, "r")) == NULL)
283 return; 291 return;
284 while ((mnt = getmntent (f)) != NULL) 292 while ((mnt = getmntent(f)) != NULL)
285 if (strcmp (device_name, mnt->mnt_fsname) == 0) 293 if (strcmp(device_name, mnt->mnt_fsname) == 0)
286 break; 294 break;
287 endmntent (f); 295 endmntent(f);
288 if (!mnt) 296 if (!mnt)
289 return; 297 return;
290 298
@@ -298,15 +306,15 @@ static void check_mount(void)
298 return; 306 return;
299 else 307 else
300 close(fd); 308 close(fd);
301 309
302 printf ("%s is mounted. ", device_name); 310 printf("%s is mounted. ", device_name);
303 if (isatty(0) && isatty(1)) 311 if (isatty(0) && isatty(1))
304 cont = ask("Do you really want to continue", 0); 312 cont = ask("Do you really want to continue", 0);
305 else 313 else
306 cont = 0; 314 cont = 0;
307 if (!cont) { 315 if (!cont) {
308 printf ("check aborted.\n"); 316 printf("check aborted.\n");
309 exit (0); 317 exit(0);
310 } 318 }
311 return; 319 return;
312} 320}
@@ -317,7 +325,7 @@ static void check_mount(void)
317 * if an error was corrected, and returns the zone (0 for no zone 325 * if an error was corrected, and returns the zone (0 for no zone
318 * or a bad zone-number). 326 * or a bad zone-number).
319 */ 327 */
320static int check_zone_nr(unsigned short * nr, int * corrected) 328static int check_zone_nr(unsigned short *nr, int *corrected)
321{ 329{
322 if (!*nr) 330 if (!*nr)
323 return 0; 331 return 0;
@@ -329,7 +337,7 @@ static int check_zone_nr(unsigned short * nr, int * corrected)
329 return *nr; 337 return *nr;
330 print_current_name(); 338 print_current_name();
331 printf("'."); 339 printf("'.");
332 if (ask("Remove block",1)) { 340 if (ask("Remove block", 1)) {
333 *nr = 0; 341 *nr = 0;
334 *corrected = 1; 342 *corrected = 1;
335 } 343 }
@@ -337,19 +345,19 @@ static int check_zone_nr(unsigned short * nr, int * corrected)
337} 345}
338 346
339#ifdef HAVE_MINIX2 347#ifdef HAVE_MINIX2
340static int check_zone_nr2 (unsigned int *nr, int *corrected) 348static int check_zone_nr2(unsigned int *nr, int *corrected)
341{ 349{
342 if (!*nr) 350 if (!*nr)
343 return 0; 351 return 0;
344 if (*nr < FIRSTZONE) 352 if (*nr < FIRSTZONE)
345 printf ("Zone nr < FIRSTZONE in file `"); 353 printf("Zone nr < FIRSTZONE in file `");
346 else if (*nr >= ZONES) 354 else if (*nr >= ZONES)
347 printf ("Zone nr >= ZONES in file `"); 355 printf("Zone nr >= ZONES in file `");
348 else 356 else
349 return *nr; 357 return *nr;
350 print_current_name (); 358 print_current_name();
351 printf ("'."); 359 printf("'.");
352 if (ask ("Remove block", 1)) { 360 if (ask("Remove block", 1)) {
353 *nr = 0; 361 *nr = 0;
354 *corrected = 1; 362 *corrected = 1;
355 } 363 }
@@ -360,23 +368,23 @@ static int check_zone_nr2 (unsigned int *nr, int *corrected)
360/* 368/*
361 * read-block reads block nr into the buffer at addr. 369 * read-block reads block nr into the buffer at addr.
362 */ 370 */
363static void read_block(unsigned int nr, char * addr) 371static void read_block(unsigned int nr, char *addr)
364{ 372{
365 if (!nr) { 373 if (!nr) {
366 memset(addr,0,BLOCK_SIZE); 374 memset(addr, 0, BLOCK_SIZE);
367 return; 375 return;
368 } 376 }
369 if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) { 377 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) {
370 printf("Read error: unable to seek to block in file '"); 378 printf("Read error: unable to seek to block in file '");
371 print_current_name(); 379 print_current_name();
372 printf("'\n"); 380 printf("'\n");
373 memset(addr,0,BLOCK_SIZE); 381 memset(addr, 0, BLOCK_SIZE);
374 errors_uncorrected = 1; 382 errors_uncorrected = 1;
375 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { 383 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
376 printf("Read error: bad block in file '"); 384 printf("Read error: bad block in file '");
377 print_current_name(); 385 print_current_name();
378 printf("'\n"); 386 printf("'\n");
379 memset(addr,0,BLOCK_SIZE); 387 memset(addr, 0, BLOCK_SIZE);
380 errors_uncorrected = 1; 388 errors_uncorrected = 1;
381 } 389 }
382} 390}
@@ -384,17 +392,17 @@ static void read_block(unsigned int nr, char * addr)
384/* 392/*
385 * write_block writes block nr to disk. 393 * write_block writes block nr to disk.
386 */ 394 */
387static void write_block(unsigned int nr, char * addr) 395static void write_block(unsigned int nr, char *addr)
388{ 396{
389 if (!nr) 397 if (!nr)
390 return; 398 return;
391 if (nr < FIRSTZONE || nr >= ZONES) { 399 if (nr < FIRSTZONE || nr >= ZONES) {
392 printf("Internal error: trying to write bad block\n" 400 printf("Internal error: trying to write bad block\n"
393 "Write request ignored\n"); 401 "Write request ignored\n");
394 errors_uncorrected = 1; 402 errors_uncorrected = 1;
395 return; 403 return;
396 } 404 }
397 if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) 405 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET))
398 die("seek failed in write_block"); 406 die("seek failed in write_block");
399 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { 407 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
400 printf("Write error: bad block in file '"); 408 printf("Write error: bad block in file '");
@@ -409,16 +417,16 @@ static void write_block(unsigned int nr, char * addr)
409 * It sets 'changed' if the inode has needed changing, and re-writes 417 * It sets 'changed' if the inode has needed changing, and re-writes
410 * any indirect blocks with errors. 418 * any indirect blocks with errors.
411 */ 419 */
412static int map_block(struct minix_inode * inode, unsigned int blknr) 420static int map_block(struct minix_inode *inode, unsigned int blknr)
413{ 421{
414 unsigned short ind[BLOCK_SIZE>>1]; 422 unsigned short ind[BLOCK_SIZE >> 1];
415 unsigned short dind[BLOCK_SIZE>>1]; 423 unsigned short dind[BLOCK_SIZE >> 1];
416 int blk_chg, block, result; 424 int blk_chg, block, result;
417 425
418 if (blknr<7) 426 if (blknr < 7)
419 return check_zone_nr(inode->i_zone + blknr, &changed); 427 return check_zone_nr(inode->i_zone + blknr, &changed);
420 blknr -= 7; 428 blknr -= 7;
421 if (blknr<512) { 429 if (blknr < 512) {
422 block = check_zone_nr(inode->i_zone + 7, &changed); 430 block = check_zone_nr(inode->i_zone + 7, &changed);
423 read_block(block, (char *) ind); 431 read_block(block, (char *) ind);
424 blk_chg = 0; 432 blk_chg = 0;
@@ -431,73 +439,73 @@ static int map_block(struct minix_inode * inode, unsigned int blknr)
431 block = check_zone_nr(inode->i_zone + 8, &changed); 439 block = check_zone_nr(inode->i_zone + 8, &changed);
432 read_block(block, (char *) dind); 440 read_block(block, (char *) dind);
433 blk_chg = 0; 441 blk_chg = 0;
434 result = check_zone_nr(dind + (blknr/512), &blk_chg); 442 result = check_zone_nr(dind + (blknr / 512), &blk_chg);
435 if (blk_chg) 443 if (blk_chg)
436 write_block(block, (char *) dind); 444 write_block(block, (char *) dind);
437 block = result; 445 block = result;
438 read_block(block, (char *) ind); 446 read_block(block, (char *) ind);
439 blk_chg = 0; 447 blk_chg = 0;
440 result = check_zone_nr(ind + (blknr%512), &blk_chg); 448 result = check_zone_nr(ind + (blknr % 512), &blk_chg);
441 if (blk_chg) 449 if (blk_chg)
442 write_block(block, (char *) ind); 450 write_block(block, (char *) ind);
443 return result; 451 return result;
444} 452}
445 453
446#ifdef HAVE_MINIX2 454#ifdef HAVE_MINIX2
447static int map_block2 (struct minix2_inode *inode, unsigned int blknr) 455static int map_block2(struct minix2_inode *inode, unsigned int blknr)
448{ 456{
449 unsigned int ind[BLOCK_SIZE >> 2]; 457 unsigned int ind[BLOCK_SIZE >> 2];
450 unsigned int dind[BLOCK_SIZE >> 2]; 458 unsigned int dind[BLOCK_SIZE >> 2];
451 unsigned int tind[BLOCK_SIZE >> 2]; 459 unsigned int tind[BLOCK_SIZE >> 2];
452 int blk_chg, block, result; 460 int blk_chg, block, result;
453 461
454 if (blknr < 7) 462 if (blknr < 7)
455 return check_zone_nr2 (inode->i_zone + blknr, &changed); 463 return check_zone_nr2(inode->i_zone + blknr, &changed);
456 blknr -= 7; 464 blknr -= 7;
457 if (blknr < 256) { 465 if (blknr < 256) {
458 block = check_zone_nr2 (inode->i_zone + 7, &changed); 466 block = check_zone_nr2(inode->i_zone + 7, &changed);
459 read_block (block, (char *) ind); 467 read_block(block, (char *) ind);
460 blk_chg = 0; 468 blk_chg = 0;
461 result = check_zone_nr2 (blknr + ind, &blk_chg); 469 result = check_zone_nr2(blknr + ind, &blk_chg);
462 if (blk_chg) 470 if (blk_chg)
463 write_block (block, (char *) ind); 471 write_block(block, (char *) ind);
464 return result; 472 return result;
465 } 473 }
466 blknr -= 256; 474 blknr -= 256;
467 if (blknr >= 256 * 256) { 475 if (blknr >= 256 * 256) {
468 block = check_zone_nr2 (inode->i_zone + 8, &changed); 476 block = check_zone_nr2(inode->i_zone + 8, &changed);
469 read_block (block, (char *) dind); 477 read_block(block, (char *) dind);
470 blk_chg = 0; 478 blk_chg = 0;
471 result = check_zone_nr2 (dind + blknr / 256, &blk_chg); 479 result = check_zone_nr2(dind + blknr / 256, &blk_chg);
472 if (blk_chg) 480 if (blk_chg)
473 write_block (block, (char *) dind); 481 write_block(block, (char *) dind);
474 block = result; 482 block = result;
475 read_block (block, (char *) ind); 483 read_block(block, (char *) ind);
476 blk_chg = 0; 484 blk_chg = 0;
477 result = check_zone_nr2 (ind + blknr % 256, &blk_chg); 485 result = check_zone_nr2(ind + blknr % 256, &blk_chg);
478 if (blk_chg) 486 if (blk_chg)
479 write_block (block, (char *) ind); 487 write_block(block, (char *) ind);
480 return result; 488 return result;
481 } 489 }
482 blknr -= 256 * 256; 490 blknr -= 256 * 256;
483 block = check_zone_nr2 (inode->i_zone + 9, &changed); 491 block = check_zone_nr2(inode->i_zone + 9, &changed);
484 read_block (block, (char *) tind); 492 read_block(block, (char *) tind);
485 blk_chg = 0; 493 blk_chg = 0;
486 result = check_zone_nr2 (tind + blknr / (256 * 256), &blk_chg); 494 result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg);
487 if (blk_chg) 495 if (blk_chg)
488 write_block (block, (char *) tind); 496 write_block(block, (char *) tind);
489 block = result; 497 block = result;
490 read_block (block, (char *) dind); 498 read_block(block, (char *) dind);
491 blk_chg = 0; 499 blk_chg = 0;
492 result = check_zone_nr2 (dind + (blknr / 256) % 256, &blk_chg); 500 result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg);
493 if (blk_chg) 501 if (blk_chg)
494 write_block (block, (char *) dind); 502 write_block(block, (char *) dind);
495 block = result; 503 block = result;
496 read_block (block, (char *) ind); 504 read_block(block, (char *) ind);
497 blk_chg = 0; 505 blk_chg = 0;
498 result = check_zone_nr2 (ind + blknr % 256, &blk_chg); 506 result = check_zone_nr2(ind + blknr % 256, &blk_chg);
499 if (blk_chg) 507 if (blk_chg)
500 write_block (block, (char *) ind); 508 write_block(block, (char *) ind);
501 return result; 509 return result;
502} 510}
503#endif 511#endif
@@ -510,11 +518,11 @@ static void write_super_block(void)
510 * unconditionally set if we get this far. 518 * unconditionally set if we get this far.
511 */ 519 */
512 Super.s_state |= MINIX_VALID_FS; 520 Super.s_state |= MINIX_VALID_FS;
513 if ( errors_uncorrected ) 521 if (errors_uncorrected)
514 Super.s_state |= MINIX_ERROR_FS; 522 Super.s_state |= MINIX_ERROR_FS;
515 else 523 else
516 Super.s_state &= ~MINIX_ERROR_FS; 524 Super.s_state &= ~MINIX_ERROR_FS;
517 525
518 if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) 526 if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
519 die("seek failed in write_super_block"); 527 die("seek failed in write_super_block");
520 if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) 528 if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
@@ -527,15 +535,15 @@ static void write_tables(void)
527{ 535{
528 write_super_block(); 536 write_super_block();
529 537
530 if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE)) 538 if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE))
531 die("Unable to write inode map"); 539 die("Unable to write inode map");
532 if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE)) 540 if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE))
533 die("Unable to write zone map"); 541 die("Unable to write zone map");
534 if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE)) 542 if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE))
535 die("Unable to write inodes"); 543 die("Unable to write inodes");
536} 544}
537 545
538static void get_dirsize (void) 546static void get_dirsize(void)
539{ 547{
540 int block; 548 int block;
541 char blk[BLOCK_SIZE]; 549 char blk[BLOCK_SIZE];
@@ -547,9 +555,9 @@ static void get_dirsize (void)
547 else 555 else
548#endif 556#endif
549 block = Inode[ROOT_INO].i_zone[0]; 557 block = Inode[ROOT_INO].i_zone[0];
550 read_block (block, blk); 558 read_block(block, blk);
551 for (size = 16; size < BLOCK_SIZE; size <<= 1) { 559 for (size = 16; size < BLOCK_SIZE; size <<= 1) {
552 if (strcmp (blk + size + 2, "..") == 0) { 560 if (strcmp(blk + size + 2, "..") == 0) {
553 dirsize = size; 561 dirsize = size;
554 namelen = size - 2; 562 namelen = size - 2;
555 return; 563 return;
@@ -600,8 +608,8 @@ static void read_tables(void)
600 zone_map = malloc(ZMAPS * BLOCK_SIZE); 608 zone_map = malloc(ZMAPS * BLOCK_SIZE);
601 if (!inode_map) 609 if (!inode_map)
602 die("Unable to allocate buffer for zone map"); 610 die("Unable to allocate buffer for zone map");
603 memset(inode_map,0,sizeof(inode_map)); 611 memset(inode_map, 0, sizeof(inode_map));
604 memset(zone_map,0,sizeof(zone_map)); 612 memset(zone_map, 0, sizeof(zone_map));
605 inode_buffer = malloc(INODE_BUFFER_SIZE); 613 inode_buffer = malloc(INODE_BUFFER_SIZE);
606 if (!inode_buffer) 614 if (!inode_buffer)
607 die("Unable to allocate buffer for inodes"); 615 die("Unable to allocate buffer for inodes");
@@ -611,31 +619,31 @@ static void read_tables(void)
611 zone_count = malloc(ZONES); 619 zone_count = malloc(ZONES);
612 if (!zone_count) 620 if (!zone_count)
613 die("Unable to allocate buffer for zone count"); 621 die("Unable to allocate buffer for zone count");
614 if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE)) 622 if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE))
615 die("Unable to read inode map"); 623 die("Unable to read inode map");
616 if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE)) 624 if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE))
617 die("Unable to read zone map"); 625 die("Unable to read zone map");
618 if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE)) 626 if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE))
619 die("Unable to read inodes"); 627 die("Unable to read inodes");
620 if (NORM_FIRSTZONE != FIRSTZONE) { 628 if (NORM_FIRSTZONE != FIRSTZONE) {
621 printf("Warning: Firstzone != Norm_firstzone\n"); 629 printf("Warning: Firstzone != Norm_firstzone\n");
622 errors_uncorrected = 1; 630 errors_uncorrected = 1;
623 } 631 }
624 get_dirsize (); 632 get_dirsize();
625 if (show) { 633 if (show) {
626 printf("%ld inodes\n",INODES); 634 printf("%ld inodes\n", INODES);
627 printf("%ld blocks\n",ZONES); 635 printf("%ld blocks\n", ZONES);
628 printf("Firstdatazone=%ld (%ld)\n",FIRSTZONE,NORM_FIRSTZONE); 636 printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE);
629 printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); 637 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
630 printf("Maxsize=%ld\n",MAXSIZE); 638 printf("Maxsize=%ld\n", MAXSIZE);
631 printf("Filesystem state=%d\n", Super.s_state); 639 printf("Filesystem state=%d\n", Super.s_state);
632 printf("namelen=%d\n\n",namelen); 640 printf("namelen=%d\n\n", namelen);
633 } 641 }
634} 642}
635 643
636struct minix_inode * get_inode(unsigned int nr) 644struct minix_inode *get_inode(unsigned int nr)
637{ 645{
638 struct minix_inode * inode; 646 struct minix_inode *inode;
639 647
640 if (!nr || nr > INODES) 648 if (!nr || nr > INODES)
641 return NULL; 649 return NULL;
@@ -643,15 +651,14 @@ struct minix_inode * get_inode(unsigned int nr)
643 inode = Inode + nr; 651 inode = Inode + nr;
644 if (!inode_count[nr]) { 652 if (!inode_count[nr]) {
645 if (!inode_in_use(nr)) { 653 if (!inode_in_use(nr)) {
646 printf("Inode %d marked not used, but used for file '", 654 printf("Inode %d marked not used, but used for file '", nr);
647 nr);
648 print_current_name(); 655 print_current_name();
649 printf("'\n"); 656 printf("'\n");
650 if (repair) { 657 if (repair) {
651 if (ask("Mark in use",1)) 658 if (ask("Mark in use", 1))
652 mark_inode(nr); 659 mark_inode(nr);
653 } else { 660 } else {
654 errors_uncorrected = 1; 661 errors_uncorrected = 1;
655 } 662 }
656 } 663 }
657 if (S_ISDIR(inode->i_mode)) 664 if (S_ISDIR(inode->i_mode))
@@ -664,14 +671,12 @@ struct minix_inode * get_inode(unsigned int nr)
664 blockdev++; 671 blockdev++;
665 else if (S_ISLNK(inode->i_mode)) 672 else if (S_ISLNK(inode->i_mode))
666 symlinks++; 673 symlinks++;
667 else if (S_ISSOCK(inode->i_mode)) 674 else if (S_ISSOCK(inode->i_mode));
668 ; 675 else if (S_ISFIFO(inode->i_mode));
669 else if (S_ISFIFO(inode->i_mode))
670 ;
671 else { 676 else {
672 print_current_name(); 677 print_current_name();
673 printf(" has mode %05o\n",inode->i_mode); 678 printf(" has mode %05o\n", inode->i_mode);
674 } 679 }
675 680
676 } else 681 } else
677 links++; 682 links++;
@@ -684,8 +689,7 @@ struct minix_inode * get_inode(unsigned int nr)
684} 689}
685 690
686#ifdef HAVE_MINIX2 691#ifdef HAVE_MINIX2
687struct minix2_inode * 692struct minix2_inode *get_inode2(unsigned int nr)
688get_inode2 (unsigned int nr)
689{ 693{
690 struct minix2_inode *inode; 694 struct minix2_inode *inode;
691 695
@@ -694,37 +698,37 @@ get_inode2 (unsigned int nr)
694 total++; 698 total++;
695 inode = Inode2 + nr; 699 inode = Inode2 + nr;
696 if (!inode_count[nr]) { 700 if (!inode_count[nr]) {
697 if (!inode_in_use (nr)) { 701 if (!inode_in_use(nr)) {
698 printf ("Inode %d marked not used, but used for file '", nr); 702 printf("Inode %d marked not used, but used for file '", nr);
699 print_current_name (); 703 print_current_name();
700 printf ("'\n"); 704 printf("'\n");
701 if (repair) { 705 if (repair) {
702 if (ask ("Mark in use", 1)) 706 if (ask("Mark in use", 1))
703 mark_inode (nr); 707 mark_inode(nr);
704 else 708 else
705 errors_uncorrected = 1; 709 errors_uncorrected = 1;
706 } 710 }
707 } 711 }
708 if (S_ISDIR (inode->i_mode)) 712 if (S_ISDIR(inode->i_mode))
709 directory++; 713 directory++;
710 else if (S_ISREG (inode->i_mode)) 714 else if (S_ISREG(inode->i_mode))
711 regular++; 715 regular++;
712 else if (S_ISCHR (inode->i_mode)) 716 else if (S_ISCHR(inode->i_mode))
713 chardev++; 717 chardev++;
714 else if (S_ISBLK (inode->i_mode)) 718 else if (S_ISBLK(inode->i_mode))
715 blockdev++; 719 blockdev++;
716 else if (S_ISLNK (inode->i_mode)) 720 else if (S_ISLNK(inode->i_mode))
717 symlinks++; 721 symlinks++;
718 else if (S_ISSOCK (inode->i_mode)); 722 else if (S_ISSOCK(inode->i_mode));
719 else if (S_ISFIFO (inode->i_mode)); 723 else if (S_ISFIFO(inode->i_mode));
720 else { 724 else {
721 print_current_name (); 725 print_current_name();
722 printf (" has mode %05o\n", inode->i_mode); 726 printf(" has mode %05o\n", inode->i_mode);
723 } 727 }
724 } else 728 } else
725 links++; 729 links++;
726 if (!++inode_count[nr]) { 730 if (!++inode_count[nr]) {
727 printf ("Warning: inode count too big.\n"); 731 printf("Warning: inode count too big.\n");
728 inode_count[nr]--; 732 inode_count[nr]--;
729 errors_uncorrected = 1; 733 errors_uncorrected = 1;
730 } 734 }
@@ -734,23 +738,23 @@ get_inode2 (unsigned int nr)
734 738
735static void check_root(void) 739static void check_root(void)
736{ 740{
737 struct minix_inode * inode = Inode + ROOT_INO; 741 struct minix_inode *inode = Inode + ROOT_INO;
738 742
739 if (!inode || !S_ISDIR(inode->i_mode)) 743 if (!inode || !S_ISDIR(inode->i_mode))
740 die("root inode isn't a directory"); 744 die("root inode isn't a directory");
741} 745}
742 746
743#ifdef HAVE_MINIX2 747#ifdef HAVE_MINIX2
744static void check_root2 (void) 748static void check_root2(void)
745{ 749{
746 struct minix2_inode *inode = Inode2 + ROOT_INO; 750 struct minix2_inode *inode = Inode2 + ROOT_INO;
747 751
748 if (!inode || !S_ISDIR (inode->i_mode)) 752 if (!inode || !S_ISDIR(inode->i_mode))
749 die ("root inode isn't a directory"); 753 die("root inode isn't a directory");
750} 754}
751#endif 755#endif
752 756
753static int add_zone(unsigned short * znr, int * corrected) 757static int add_zone(unsigned short *znr, int *corrected)
754{ 758{
755 int result; 759 int result;
756 int block; 760 int block;
@@ -763,7 +767,7 @@ static int add_zone(unsigned short * znr, int * corrected)
763 printf("Block has been used before. Now in file `"); 767 printf("Block has been used before. Now in file `");
764 print_current_name(); 768 print_current_name();
765 printf("'."); 769 printf("'.");
766 if (ask("Clear",1)) { 770 if (ask("Clear", 1)) {
767 *znr = 0; 771 *znr = 0;
768 block = 0; 772 block = 0;
769 *corrected = 1; 773 *corrected = 1;
@@ -772,10 +776,10 @@ static int add_zone(unsigned short * znr, int * corrected)
772 if (!block) 776 if (!block)
773 return 0; 777 return 0;
774 if (!zone_in_use(block)) { 778 if (!zone_in_use(block)) {
775 printf("Block %d in file `",block); 779 printf("Block %d in file `", block);
776 print_current_name(); 780 print_current_name();
777 printf("' is marked not in use."); 781 printf("' is marked not in use.");
778 if (ask("Correct",1)) 782 if (ask("Correct", 1))
779 mark_zone(block); 783 mark_zone(block);
780 } 784 }
781 if (!++zone_count[block]) 785 if (!++zone_count[block])
@@ -784,20 +788,20 @@ static int add_zone(unsigned short * znr, int * corrected)
784} 788}
785 789
786#ifdef HAVE_MINIX2 790#ifdef HAVE_MINIX2
787static int add_zone2 (unsigned int *znr, int *corrected) 791static int add_zone2(unsigned int *znr, int *corrected)
788{ 792{
789 int result; 793 int result;
790 int block; 794 int block;
791 795
792 result = 0; 796 result = 0;
793 block = check_zone_nr2 (znr, corrected); 797 block = check_zone_nr2(znr, corrected);
794 if (!block) 798 if (!block)
795 return 0; 799 return 0;
796 if (zone_count[block]) { 800 if (zone_count[block]) {
797 printf ("Block has been used before. Now in file `"); 801 printf("Block has been used before. Now in file `");
798 print_current_name (); 802 print_current_name();
799 printf ("'."); 803 printf("'.");
800 if (ask ("Clear", 1)) { 804 if (ask("Clear", 1)) {
801 *znr = 0; 805 *znr = 0;
802 block = 0; 806 block = 0;
803 *corrected = 1; 807 *corrected = 1;
@@ -805,12 +809,12 @@ static int add_zone2 (unsigned int *znr, int *corrected)
805 } 809 }
806 if (!block) 810 if (!block)
807 return 0; 811 return 0;
808 if (!zone_in_use (block)) { 812 if (!zone_in_use(block)) {
809 printf ("Block %d in file `", block); 813 printf("Block %d in file `", block);
810 print_current_name (); 814 print_current_name();
811 printf ("' is marked not in use."); 815 printf("' is marked not in use.");
812 if (ask ("Correct", 1)) 816 if (ask("Correct", 1))
813 mark_zone (block); 817 mark_zone(block);
814 } 818 }
815 if (!++zone_count[block]) 819 if (!++zone_count[block])
816 zone_count[block]--; 820 zone_count[block]--;
@@ -818,182 +822,179 @@ static int add_zone2 (unsigned int *znr, int *corrected)
818} 822}
819#endif 823#endif
820 824
821static void add_zone_ind(unsigned short * znr, int * corrected) 825static void add_zone_ind(unsigned short *znr, int *corrected)
822{ 826{
823 static char blk[BLOCK_SIZE]; 827 static char blk[BLOCK_SIZE];
824 int i, chg_blk=0; 828 int i, chg_blk = 0;
825 int block; 829 int block;
826 830
827 block = add_zone(znr, corrected); 831 block = add_zone(znr, corrected);
828 if (!block) 832 if (!block)
829 return; 833 return;
830 read_block(block, blk); 834 read_block(block, blk);
831 for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) 835 for (i = 0; i < (BLOCK_SIZE >> 1); i++)
832 add_zone(i + (unsigned short *) blk, &chg_blk); 836 add_zone(i + (unsigned short *) blk, &chg_blk);
833 if (chg_blk) 837 if (chg_blk)
834 write_block(block, blk); 838 write_block(block, blk);
835} 839}
836 840
837#ifdef HAVE_MINIX2 841#ifdef HAVE_MINIX2
838static void 842static void add_zone_ind2(unsigned int *znr, int *corrected)
839add_zone_ind2 (unsigned int *znr, int *corrected)
840{ 843{
841 static char blk[BLOCK_SIZE]; 844 static char blk[BLOCK_SIZE];
842 int i, chg_blk = 0; 845 int i, chg_blk = 0;
843 int block; 846 int block;
844 847
845 block = add_zone2 (znr, corrected); 848 block = add_zone2(znr, corrected);
846 if (!block) 849 if (!block)
847 return; 850 return;
848 read_block (block, blk); 851 read_block(block, blk);
849 for (i = 0; i < BLOCK_SIZE >> 2; i++) 852 for (i = 0; i < BLOCK_SIZE >> 2; i++)
850 add_zone2 (i + (unsigned int *) blk, &chg_blk); 853 add_zone2(i + (unsigned int *) blk, &chg_blk);
851 if (chg_blk) 854 if (chg_blk)
852 write_block (block, blk); 855 write_block(block, blk);
853} 856}
854#endif 857#endif
855 858
856static void add_zone_dind(unsigned short * znr, int * corrected) 859static void add_zone_dind(unsigned short *znr, int *corrected)
857{ 860{
858 static char blk[BLOCK_SIZE]; 861 static char blk[BLOCK_SIZE];
859 int i, blk_chg=0; 862 int i, blk_chg = 0;
860 int block; 863 int block;
861 864
862 block = add_zone(znr, corrected); 865 block = add_zone(znr, corrected);
863 if (!block) 866 if (!block)
864 return; 867 return;
865 read_block(block, blk); 868 read_block(block, blk);
866 for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) 869 for (i = 0; i < (BLOCK_SIZE >> 1); i++)
867 add_zone_ind(i + (unsigned short *) blk, &blk_chg); 870 add_zone_ind(i + (unsigned short *) blk, &blk_chg);
868 if (blk_chg) 871 if (blk_chg)
869 write_block(block, blk); 872 write_block(block, blk);
870} 873}
871 874
872#ifdef HAVE_MINIX2 875#ifdef HAVE_MINIX2
873static void 876static void add_zone_dind2(unsigned int *znr, int *corrected)
874add_zone_dind2 (unsigned int *znr, int *corrected)
875{ 877{
876 static char blk[BLOCK_SIZE]; 878 static char blk[BLOCK_SIZE];
877 int i, blk_chg = 0; 879 int i, blk_chg = 0;
878 int block; 880 int block;
879 881
880 block = add_zone2 (znr, corrected); 882 block = add_zone2(znr, corrected);
881 if (!block) 883 if (!block)
882 return; 884 return;
883 read_block (block, blk); 885 read_block(block, blk);
884 for (i = 0; i < BLOCK_SIZE >> 2; i++) 886 for (i = 0; i < BLOCK_SIZE >> 2; i++)
885 add_zone_ind2 (i + (unsigned int *) blk, &blk_chg); 887 add_zone_ind2(i + (unsigned int *) blk, &blk_chg);
886 if (blk_chg) 888 if (blk_chg)
887 write_block (block, blk); 889 write_block(block, blk);
888} 890}
889 891
890static void 892static void add_zone_tind2(unsigned int *znr, int *corrected)
891add_zone_tind2 (unsigned int *znr, int *corrected)
892{ 893{
893 static char blk[BLOCK_SIZE]; 894 static char blk[BLOCK_SIZE];
894 int i, blk_chg = 0; 895 int i, blk_chg = 0;
895 int block; 896 int block;
896 897
897 block = add_zone2 (znr, corrected); 898 block = add_zone2(znr, corrected);
898 if (!block) 899 if (!block)
899 return; 900 return;
900 read_block (block, blk); 901 read_block(block, blk);
901 for (i = 0; i < BLOCK_SIZE >> 2; i++) 902 for (i = 0; i < BLOCK_SIZE >> 2; i++)
902 add_zone_dind2 (i + (unsigned int *) blk, &blk_chg); 903 add_zone_dind2(i + (unsigned int *) blk, &blk_chg);
903 if (blk_chg) 904 if (blk_chg)
904 write_block (block, blk); 905 write_block(block, blk);
905} 906}
906#endif 907#endif
907 908
908static void check_zones(unsigned int i) 909static void check_zones(unsigned int i)
909{ 910{
910 struct minix_inode * inode; 911 struct minix_inode *inode;
911 912
912 if (!i || i > INODES) 913 if (!i || i > INODES)
913 return; 914 return;
914 if (inode_count[i] > 1) /* have we counted this file already? */ 915 if (inode_count[i] > 1) /* have we counted this file already? */
915 return; 916 return;
916 inode = Inode + i; 917 inode = Inode + i;
917 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && 918 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
918 !S_ISLNK(inode->i_mode)) 919 !S_ISLNK(inode->i_mode)) return;
919 return; 920 for (i = 0; i < 7; i++)
920 for (i=0 ; i<7 ; i++)
921 add_zone(i + inode->i_zone, &changed); 921 add_zone(i + inode->i_zone, &changed);
922 add_zone_ind(7 + inode->i_zone, &changed); 922 add_zone_ind(7 + inode->i_zone, &changed);
923 add_zone_dind(8 + inode->i_zone, &changed); 923 add_zone_dind(8 + inode->i_zone, &changed);
924} 924}
925 925
926#ifdef HAVE_MINIX2 926#ifdef HAVE_MINIX2
927static void 927static void check_zones2(unsigned int i)
928check_zones2 (unsigned int i)
929{ 928{
930 struct minix2_inode *inode; 929 struct minix2_inode *inode;
931 930
932 if (!i || i > INODES) 931 if (!i || i > INODES)
933 return; 932 return;
934 if (inode_count[i] > 1) /* have we counted this file already? */ 933 if (inode_count[i] > 1) /* have we counted this file already? */
935 return; 934 return;
936 inode = Inode2 + i; 935 inode = Inode2 + i;
937 if (!S_ISDIR (inode->i_mode) && !S_ISREG (inode->i_mode) 936 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode)
938 && !S_ISLNK (inode->i_mode)) 937 && !S_ISLNK(inode->i_mode))
939 return; 938 return;
940 for (i = 0; i < 7; i++) 939 for (i = 0; i < 7; i++)
941 add_zone2 (i + inode->i_zone, &changed); 940 add_zone2(i + inode->i_zone, &changed);
942 add_zone_ind2 (7 + inode->i_zone, &changed); 941 add_zone_ind2(7 + inode->i_zone, &changed);
943 add_zone_dind2 (8 + inode->i_zone, &changed); 942 add_zone_dind2(8 + inode->i_zone, &changed);
944 add_zone_tind2 (9 + inode->i_zone, &changed); 943 add_zone_tind2(9 + inode->i_zone, &changed);
945} 944}
946#endif 945#endif
947 946
948static void check_file(struct minix_inode * dir, unsigned int offset) 947static void check_file(struct minix_inode *dir, unsigned int offset)
949{ 948{
950 static char blk[BLOCK_SIZE]; 949 static char blk[BLOCK_SIZE];
951 struct minix_inode * inode; 950 struct minix_inode *inode;
952 int ino; 951 int ino;
953 char * name; 952 char *name;
954 int block; 953 int block;
955 954
956 block = map_block(dir,offset/BLOCK_SIZE); 955 block = map_block(dir, offset / BLOCK_SIZE);
957 read_block(block, blk); 956 read_block(block, blk);
958 name = blk + (offset % BLOCK_SIZE) + 2; 957 name = blk + (offset % BLOCK_SIZE) + 2;
959 ino = * (unsigned short *) (name-2); 958 ino = *(unsigned short *) (name - 2);
960 if (ino > INODES) { 959 if (ino > INODES) {
961 print_current_name(); 960 print_current_name();
962 printf(" contains a bad inode number for file '"); 961 printf(" contains a bad inode number for file '");
963 printf("%.*s'.",namelen,name); 962 printf("%.*s'.", namelen, name);
964 if (ask(" Remove",1)) { 963 if (ask(" Remove", 1)) {
965 *(unsigned short *)(name-2) = 0; 964 *(unsigned short *) (name - 2) = 0;
966 write_block(block, blk); 965 write_block(block, blk);
967 } 966 }
968 ino = 0; 967 ino = 0;
969 } 968 }
970 if (name_depth < MAX_DEPTH) 969 if (name_depth < MAX_DEPTH)
971 strncpy (name_list[name_depth], name, namelen); 970 strncpy(name_list[name_depth], name, namelen);
972 name_depth++; 971 name_depth++;
973 inode = get_inode(ino); 972 inode = get_inode(ino);
974 name_depth--; 973 name_depth--;
975 if (!offset) { 974 if (!offset) {
976 if (!inode || strcmp(".",name)) { 975 if (!inode || strcmp(".", name)) {
977 print_current_name(); 976 print_current_name();
978 printf(": bad directory: '.' isn't first\n"); 977 printf(": bad directory: '.' isn't first\n");
979 errors_uncorrected = 1; 978 errors_uncorrected = 1;
980 } else return; 979 } else
980 return;
981 } 981 }
982 if (offset == dirsize) { 982 if (offset == dirsize) {
983 if (!inode || strcmp("..",name)) { 983 if (!inode || strcmp("..", name)) {
984 print_current_name(); 984 print_current_name();
985 printf(": bad directory: '..' isn't second\n"); 985 printf(": bad directory: '..' isn't second\n");
986 errors_uncorrected = 1; 986 errors_uncorrected = 1;
987 } else return; 987 } else
988 return;
988 } 989 }
989 if (!inode) 990 if (!inode)
990 return; 991 return;
991 if (name_depth < MAX_DEPTH) 992 if (name_depth < MAX_DEPTH)
992 strncpy(name_list[name_depth],name,namelen); 993 strncpy(name_list[name_depth], name, namelen);
993 name_depth++; 994 name_depth++;
994 if (list) { 995 if (list) {
995 if (verbose) 996 if (verbose)
996 printf("%6d %07o %3d ",ino,inode->i_mode,inode->i_nlinks); 997 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
997 print_current_name(); 998 print_current_name();
998 if (S_ISDIR(inode->i_mode)) 999 if (S_ISDIR(inode->i_mode))
999 printf(":\n"); 1000 printf(":\n");
@@ -1008,8 +1009,7 @@ static void check_file(struct minix_inode * dir, unsigned int offset)
1008} 1009}
1009 1010
1010#ifdef HAVE_MINIX2 1011#ifdef HAVE_MINIX2
1011static void 1012static void check_file2(struct minix2_inode *dir, unsigned int offset)
1012check_file2 (struct minix2_inode *dir, unsigned int offset)
1013{ 1013{
1014 static char blk[BLOCK_SIZE]; 1014 static char blk[BLOCK_SIZE];
1015 struct minix2_inode *inode; 1015 struct minix2_inode *inode;
@@ -1017,37 +1017,37 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1017 char *name; 1017 char *name;
1018 int block; 1018 int block;
1019 1019
1020 block = map_block2 (dir, offset / BLOCK_SIZE); 1020 block = map_block2(dir, offset / BLOCK_SIZE);
1021 read_block (block, blk); 1021 read_block(block, blk);
1022 name = blk + (offset % BLOCK_SIZE) + 2; 1022 name = blk + (offset % BLOCK_SIZE) + 2;
1023 ino = *(unsigned short *) (name - 2); 1023 ino = *(unsigned short *) (name - 2);
1024 if (ino > INODES) { 1024 if (ino > INODES) {
1025 print_current_name (); 1025 print_current_name();
1026 printf (" contains a bad inode number for file '"); 1026 printf(" contains a bad inode number for file '");
1027 printf ("%.*s'.", namelen, name); 1027 printf("%.*s'.", namelen, name);
1028 if (ask (" Remove", 1)) { 1028 if (ask(" Remove", 1)) {
1029 *(unsigned short *) (name - 2) = 0; 1029 *(unsigned short *) (name - 2) = 0;
1030 write_block (block, blk); 1030 write_block(block, blk);
1031 } 1031 }
1032 ino = 0; 1032 ino = 0;
1033 } 1033 }
1034 if (name_depth < MAX_DEPTH) 1034 if (name_depth < MAX_DEPTH)
1035 strncpy (name_list[name_depth], name, namelen); 1035 strncpy(name_list[name_depth], name, namelen);
1036 name_depth++; 1036 name_depth++;
1037 inode = get_inode2 (ino); 1037 inode = get_inode2(ino);
1038 name_depth--; 1038 name_depth--;
1039 if (!offset) { 1039 if (!offset) {
1040 if (!inode || strcmp (".", name)) { 1040 if (!inode || strcmp(".", name)) {
1041 print_current_name (); 1041 print_current_name();
1042 printf (": bad directory: '.' isn't first\n"); 1042 printf(": bad directory: '.' isn't first\n");
1043 errors_uncorrected = 1; 1043 errors_uncorrected = 1;
1044 } else 1044 } else
1045 return; 1045 return;
1046 } 1046 }
1047 if (offset == dirsize) { 1047 if (offset == dirsize) {
1048 if (!inode || strcmp ("..", name)) { 1048 if (!inode || strcmp("..", name)) {
1049 print_current_name (); 1049 print_current_name();
1050 printf (": bad directory: '..' isn't second\n"); 1050 printf(": bad directory: '..' isn't second\n");
1051 errors_uncorrected = 1; 1051 errors_uncorrected = 1;
1052 } else 1052 } else
1053 return; 1053 return;
@@ -1057,16 +1057,16 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1057 name_depth++; 1057 name_depth++;
1058 if (list) { 1058 if (list) {
1059 if (verbose) 1059 if (verbose)
1060 printf ("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); 1060 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
1061 print_current_name (); 1061 print_current_name();
1062 if (S_ISDIR (inode->i_mode)) 1062 if (S_ISDIR(inode->i_mode))
1063 printf (":\n"); 1063 printf(":\n");
1064 else 1064 else
1065 printf ("\n"); 1065 printf("\n");
1066 } 1066 }
1067 check_zones2 (ino); 1067 check_zones2(ino);
1068 if (inode && S_ISDIR (inode->i_mode)) 1068 if (inode && S_ISDIR(inode->i_mode))
1069 recursive_check2 (ino); 1069 recursive_check2(ino);
1070 name_depth--; 1070 name_depth--;
1071 return; 1071 return;
1072} 1072}
@@ -1074,7 +1074,7 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1074 1074
1075static void recursive_check(unsigned int ino) 1075static void recursive_check(unsigned int ino)
1076{ 1076{
1077 struct minix_inode * dir; 1077 struct minix_inode *dir;
1078 unsigned int offset; 1078 unsigned int offset;
1079 1079
1080 dir = Inode + ino; 1080 dir = Inode + ino;
@@ -1085,27 +1085,26 @@ static void recursive_check(unsigned int ino)
1085 printf(": bad directory: size<32"); 1085 printf(": bad directory: size<32");
1086 errors_uncorrected = 1; 1086 errors_uncorrected = 1;
1087 } 1087 }
1088 for (offset = 0 ; offset < dir->i_size ; offset += dirsize) 1088 for (offset = 0; offset < dir->i_size; offset += dirsize)
1089 check_file(dir,offset); 1089 check_file(dir, offset);
1090} 1090}
1091 1091
1092#ifdef HAVE_MINIX2 1092#ifdef HAVE_MINIX2
1093static void 1093static void recursive_check2(unsigned int ino)
1094recursive_check2 (unsigned int ino)
1095{ 1094{
1096 struct minix2_inode *dir; 1095 struct minix2_inode *dir;
1097 unsigned int offset; 1096 unsigned int offset;
1098 1097
1099 dir = Inode2 + ino; 1098 dir = Inode2 + ino;
1100 if (!S_ISDIR (dir->i_mode)) 1099 if (!S_ISDIR(dir->i_mode))
1101 die ("internal error"); 1100 die("internal error");
1102 if (dir->i_size < 2 * dirsize) { 1101 if (dir->i_size < 2 * dirsize) {
1103 print_current_name (); 1102 print_current_name();
1104 printf (": bad directory: size < 32"); 1103 printf(": bad directory: size < 32");
1105 errors_uncorrected = 1; 1104 errors_uncorrected = 1;
1106 } 1105 }
1107 for (offset = 0; offset < dir->i_size; offset += dirsize) 1106 for (offset = 0; offset < dir->i_size; offset += dirsize)
1108 check_file2 (dir, offset); 1107 check_file2(dir, offset);
1109} 1108}
1110#endif 1109#endif
1111 1110
@@ -1113,7 +1112,7 @@ static int bad_zone(int i)
1113{ 1112{
1114 char buffer[1024]; 1113 char buffer[1024];
1115 1114
1116 if (BLOCK_SIZE*i != lseek(IN, BLOCK_SIZE*i, SEEK_SET)) 1115 if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET))
1117 die("seek failed in bad_zone"); 1116 die("seek failed in bad_zone");
1118 return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); 1117 return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
1119} 1118}
@@ -1122,10 +1121,10 @@ static void check_counts(void)
1122{ 1121{
1123 int i; 1122 int i;
1124 1123
1125 for (i=1 ; i <= INODES ; i++) { 1124 for (i = 1; i <= INODES; i++) {
1126 if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) { 1125 if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) {
1127 printf("Inode %d mode not cleared.",i); 1126 printf("Inode %d mode not cleared.", i);
1128 if (ask("Clear",1)) { 1127 if (ask("Clear", 1)) {
1129 Inode[i].i_mode = 0; 1128 Inode[i].i_mode = 0;
1130 changed = 1; 1129 changed = 1;
1131 } 1130 }
@@ -1133,117 +1132,115 @@ static void check_counts(void)
1133 if (!inode_count[i]) { 1132 if (!inode_count[i]) {
1134 if (!inode_in_use(i)) 1133 if (!inode_in_use(i))
1135 continue; 1134 continue;
1136 printf("Inode %d not used, marked used in the bitmap.",i); 1135 printf("Inode %d not used, marked used in the bitmap.", i);
1137 if (ask("Clear",1)) 1136 if (ask("Clear", 1))
1138 unmark_inode(i); 1137 unmark_inode(i);
1139 continue; 1138 continue;
1140 } 1139 }
1141 if (!inode_in_use(i)) { 1140 if (!inode_in_use(i)) {
1142 printf("Inode %d used, marked unused in the bitmap.", i); 1141 printf("Inode %d used, marked unused in the bitmap.", i);
1143 if (ask("Set",1)) 1142 if (ask("Set", 1))
1144 mark_inode(i); 1143 mark_inode(i);
1145 } 1144 }
1146 if (Inode[i].i_nlinks != inode_count[i]) { 1145 if (Inode[i].i_nlinks != inode_count[i]) {
1147 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", 1146 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.",
1148 i,Inode[i].i_mode,Inode[i].i_nlinks,inode_count[i]); 1147 i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]);
1149 if (ask("Set i_nlinks to count",1)) { 1148 if (ask("Set i_nlinks to count", 1)) {
1150 Inode[i].i_nlinks=inode_count[i]; 1149 Inode[i].i_nlinks = inode_count[i];
1151 changed=1; 1150 changed = 1;
1152 } 1151 }
1153 } 1152 }
1154 } 1153 }
1155 for (i=FIRSTZONE ; i < ZONES ; i++) { 1154 for (i = FIRSTZONE; i < ZONES; i++) {
1156 if (zone_in_use(i) == zone_count[i]) 1155 if (zone_in_use(i) == zone_count[i])
1157 continue; 1156 continue;
1158 if (!zone_count[i]) { 1157 if (!zone_count[i]) {
1159 if (bad_zone(i)) 1158 if (bad_zone(i))
1160 continue; 1159 continue;
1161 printf("Zone %d: marked in use, no file uses it.",i); 1160 printf("Zone %d: marked in use, no file uses it.", i);
1162 if (ask("Unmark",1)) 1161 if (ask("Unmark", 1))
1163 unmark_zone(i); 1162 unmark_zone(i);
1164 continue; 1163 continue;
1165 } 1164 }
1166 printf("Zone %d: %sin use, counted=%d\n", 1165 printf("Zone %d: %sin use, counted=%d\n",
1167 i,zone_in_use(i)?"":"not ",zone_count[i]); 1166 i, zone_in_use(i) ? "" : "not ", zone_count[i]);
1168 } 1167 }
1169} 1168}
1170 1169
1171#ifdef HAVE_MINIX2 1170#ifdef HAVE_MINIX2
1172static void 1171static void check_counts2(void)
1173check_counts2 (void)
1174{ 1172{
1175 int i; 1173 int i;
1176 1174
1177 for (i = 1; i <= INODES; i++) { 1175 for (i = 1; i <= INODES; i++) {
1178 if (!inode_in_use (i) && Inode2[i].i_mode && warn_mode) { 1176 if (!inode_in_use(i) && Inode2[i].i_mode && warn_mode) {
1179 printf ("Inode %d mode not cleared.", i); 1177 printf("Inode %d mode not cleared.", i);
1180 if (ask ("Clear", 1)) { 1178 if (ask("Clear", 1)) {
1181 Inode2[i].i_mode = 0; 1179 Inode2[i].i_mode = 0;
1182 changed = 1; 1180 changed = 1;
1183 } 1181 }
1184 } 1182 }
1185 if (!inode_count[i]) { 1183 if (!inode_count[i]) {
1186 if (!inode_in_use (i)) 1184 if (!inode_in_use(i))
1187 continue; 1185 continue;
1188 printf ("Inode %d not used, marked used in the bitmap.", i); 1186 printf("Inode %d not used, marked used in the bitmap.", i);
1189 if (ask ("Clear", 1)) 1187 if (ask("Clear", 1))
1190 unmark_inode (i); 1188 unmark_inode(i);
1191 continue; 1189 continue;
1192 } 1190 }
1193 if (!inode_in_use (i)) { 1191 if (!inode_in_use(i)) {
1194 printf ("Inode %d used, marked unused in the bitmap.", i); 1192 printf("Inode %d used, marked unused in the bitmap.", i);
1195 if (ask ("Set", 1)) 1193 if (ask("Set", 1))
1196 mark_inode (i); 1194 mark_inode(i);
1197 } 1195 }
1198 if (Inode2[i].i_nlinks != inode_count[i]) { 1196 if (Inode2[i].i_nlinks != inode_count[i]) {
1199 printf ("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", 1197 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.",
1200 i, Inode2[i].i_mode, Inode2[i].i_nlinks, inode_count[i]); 1198 i, Inode2[i].i_mode, Inode2[i].i_nlinks,
1201 if (ask ("Set i_nlinks to count", 1)) { 1199 inode_count[i]);
1200 if (ask("Set i_nlinks to count", 1)) {
1202 Inode2[i].i_nlinks = inode_count[i]; 1201 Inode2[i].i_nlinks = inode_count[i];
1203 changed = 1; 1202 changed = 1;
1204 } 1203 }
1205 } 1204 }
1206 } 1205 }
1207 for (i = FIRSTZONE; i < ZONES; i++) { 1206 for (i = FIRSTZONE; i < ZONES; i++) {
1208 if (zone_in_use (i) == zone_count[i]) 1207 if (zone_in_use(i) == zone_count[i])
1209 continue; 1208 continue;
1210 if (!zone_count[i]) { 1209 if (!zone_count[i]) {
1211 if (bad_zone (i)) 1210 if (bad_zone(i))
1212 continue; 1211 continue;
1213 printf ("Zone %d: marked in use, no file uses it.", i); 1212 printf("Zone %d: marked in use, no file uses it.", i);
1214 if (ask ("Unmark", 1)) 1213 if (ask("Unmark", 1))
1215 unmark_zone (i); 1214 unmark_zone(i);
1216 continue; 1215 continue;
1217 } 1216 }
1218 printf ("Zone %d: %sin use, counted=%d\n", 1217 printf("Zone %d: %sin use, counted=%d\n",
1219 i, zone_in_use (i) ? "" : "not ", zone_count[i]); 1218 i, zone_in_use(i) ? "" : "not ", zone_count[i]);
1220 } 1219 }
1221} 1220}
1222#endif 1221#endif
1223 1222
1224static void check(void) 1223static void check(void)
1225{ 1224{
1226 memset(inode_count,0,(INODES + 1) * sizeof(*inode_count)); 1225 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
1227 memset(zone_count,0,ZONES*sizeof(*zone_count)); 1226 memset(zone_count, 0, ZONES * sizeof(*zone_count));
1228 check_zones(ROOT_INO); 1227 check_zones(ROOT_INO);
1229 recursive_check(ROOT_INO); 1228 recursive_check(ROOT_INO);
1230 check_counts(); 1229 check_counts();
1231} 1230}
1232 1231
1233#ifdef HAVE_MINIX2 1232#ifdef HAVE_MINIX2
1234static void 1233static void check2(void)
1235check2 (void)
1236{ 1234{
1237 memset (inode_count, 0, (INODES + 1) * sizeof (*inode_count)); 1235 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
1238 memset (zone_count, 0, ZONES * sizeof (*zone_count)); 1236 memset(zone_count, 0, ZONES * sizeof(*zone_count));
1239 check_zones2 (ROOT_INO); 1237 check_zones2(ROOT_INO);
1240 recursive_check2 (ROOT_INO); 1238 recursive_check2(ROOT_INO);
1241 check_counts2 (); 1239 check_counts2();
1242} 1240}
1243#endif 1241#endif
1244 1242
1245extern int 1243extern int fsck_minix_main(int argc, char **argv)
1246fsck_minix_main(int argc, char ** argv)
1247{ 1244{
1248 struct termios tmp; 1245 struct termios tmp;
1249 int count; 1246 int count;
@@ -1264,29 +1261,47 @@ fsck_minix_main(int argc, char ** argv)
1264 show_usage(); 1261 show_usage();
1265 else 1262 else
1266 device_name = argv[0]; 1263 device_name = argv[0];
1267 } else while (*++argv[0]) 1264 } else
1268 switch (argv[0][0]) { 1265 while (*++argv[0])
1269 case 'l': list=1; break; 1266 switch (argv[0][0]) {
1270 case 'a': automatic=1; repair=1; break; 1267 case 'l':
1271 case 'r': automatic=0; repair=1; break; 1268 list = 1;
1272 case 'v': verbose=1; break; 1269 break;
1273 case 's': show=1; break; 1270 case 'a':
1274 case 'm': warn_mode=1; break; 1271 automatic = 1;
1275 case 'f': force=1; break; 1272 repair = 1;
1276 default: show_usage(); 1273 break;
1277 } 1274 case 'r':
1275 automatic = 0;
1276 repair = 1;
1277 break;
1278 case 'v':
1279 verbose = 1;
1280 break;
1281 case 's':
1282 show = 1;
1283 break;
1284 case 'm':
1285 warn_mode = 1;
1286 break;
1287 case 'f':
1288 force = 1;
1289 break;
1290 default:
1291 show_usage();
1292 }
1278 } 1293 }
1279 if (!device_name) 1294 if (!device_name)
1280 show_usage(); 1295 show_usage();
1281 check_mount(); /* trying to check a mounted filesystem? */ 1296 check_mount(); /* trying to check a mounted filesystem? */
1282 if (repair && !automatic) { 1297 if (repair && !automatic) {
1283 if (!isatty(0) || !isatty(1)) 1298 if (!isatty(0) || !isatty(1))
1284 die("need terminal for interactive repairs"); 1299 die("need terminal for interactive repairs");
1285 } 1300 }
1286 IN = open(device_name,repair?O_RDWR:O_RDONLY); 1301 IN = open(device_name, repair ? O_RDWR : O_RDONLY);
1287 if (IN < 0) 1302 if (IN < 0)
1288 die("unable to open '%s'"); 1303 die("unable to open '%s'");
1289 for (count=0 ; count<3 ; count++) 1304 for (count = 0; count < 3; count++)
1290 sync(); 1305 sync();
1291 read_superblock(); 1306 read_superblock();
1292 1307
@@ -1297,80 +1312,77 @@ fsck_minix_main(int argc, char ** argv)
1297 * command line. 1312 * command line.
1298 */ 1313 */
1299 printf("%s, %s\n", program_name, program_version); 1314 printf("%s, %s\n", program_name, program_version);
1300 if ( !(Super.s_state & MINIX_ERROR_FS) && 1315 if (!(Super.s_state & MINIX_ERROR_FS) &&
1301 (Super.s_state & MINIX_VALID_FS) && 1316 (Super.s_state & MINIX_VALID_FS) && !force) {
1302 !force ) {
1303 if (repair) 1317 if (repair)
1304 printf("%s is clean, no check.\n", device_name); 1318 printf("%s is clean, no check.\n", device_name);
1305 return retcode; 1319 return retcode;
1306 } 1320 } else if (force)
1307 else if (force)
1308 printf("Forcing filesystem check on %s.\n", device_name); 1321 printf("Forcing filesystem check on %s.\n", device_name);
1309 else if (repair) 1322 else if (repair)
1310 printf("Filesystem on %s is dirty, needs checking.\n",\ 1323 printf("Filesystem on %s is dirty, needs checking.\n",
1311 device_name); 1324 device_name);
1312 1325
1313 read_tables(); 1326 read_tables();
1314 1327
1315 if (repair && !automatic) { 1328 if (repair && !automatic) {
1316 tcgetattr(0,&termios); 1329 tcgetattr(0, &termios);
1317 tmp = termios; 1330 tmp = termios;
1318 tmp.c_lflag &= ~(ICANON|ECHO); 1331 tmp.c_lflag &= ~(ICANON | ECHO);
1319 tcsetattr(0,TCSANOW,&tmp); 1332 tcsetattr(0, TCSANOW, &tmp);
1320 termios_set = 1; 1333 termios_set = 1;
1321 } 1334 }
1322
1323#if HAVE_MINIX2 1335#if HAVE_MINIX2
1324 if (version2) { 1336 if (version2) {
1325 check_root2 (); 1337 check_root2();
1326 check2 (); 1338 check2();
1327 } else 1339 } else
1328#endif 1340#endif
1329 { 1341 {
1330 check_root(); 1342 check_root();
1331 check(); 1343 check();
1332 } 1344 }
1333 if (verbose) { 1345 if (verbose) {
1334 int i, free; 1346 int i, free;
1335 1347
1336 for (i=1,free=0 ; i <= INODES ; i++) 1348 for (i = 1, free = 0; i <= INODES; i++)
1337 if (!inode_in_use(i)) 1349 if (!inode_in_use(i))
1338 free++; 1350 free++;
1339 printf("\n%6ld inodes used (%ld%%)\n",(INODES-free), 1351 printf("\n%6ld inodes used (%ld%%)\n", (INODES - free),
1340 100*(INODES-free)/INODES); 1352 100 * (INODES - free) / INODES);
1341 for (i=FIRSTZONE,free=0 ; i < ZONES ; i++) 1353 for (i = FIRSTZONE, free = 0; i < ZONES; i++)
1342 if (!zone_in_use(i)) 1354 if (!zone_in_use(i))
1343 free++; 1355 free++;
1344 printf("%6ld zones used (%ld%%)\n",(ZONES-free), 1356 printf("%6ld zones used (%ld%%)\n", (ZONES - free),
1345 100*(ZONES-free)/ZONES); 1357 100 * (ZONES - free) / ZONES);
1346 printf("\n%6d regular files\n" 1358 printf("\n%6d regular files\n"
1347 "%6d directories\n" 1359 "%6d directories\n"
1348 "%6d character device files\n" 1360 "%6d character device files\n"
1349 "%6d block device files\n" 1361 "%6d block device files\n"
1350 "%6d links\n" 1362 "%6d links\n"
1351 "%6d symbolic links\n" 1363 "%6d symbolic links\n"
1352 "------\n" 1364 "------\n"
1353 "%6d files\n", 1365 "%6d files\n",
1354 regular,directory,chardev,blockdev, 1366 regular, directory, chardev, blockdev,
1355 links-2*directory+1,symlinks,total-2*directory+1); 1367 links - 2 * directory + 1, symlinks,
1368 total - 2 * directory + 1);
1356 } 1369 }
1357 if (changed) { 1370 if (changed) {
1358 write_tables(); 1371 write_tables();
1359 printf( "----------------------------\n" 1372 printf("----------------------------\n"
1360 "FILE SYSTEM HAS BEEN CHANGED\n" 1373 "FILE SYSTEM HAS BEEN CHANGED\n"
1361 "----------------------------\n"); 1374 "----------------------------\n");
1362 for (count=0 ; count<3 ; count++) 1375 for (count = 0; count < 3; count++)
1363 sync(); 1376 sync();
1364 } 1377 } else if (repair)
1365 else if ( repair )
1366 write_super_block(); 1378 write_super_block();
1367 1379
1368 if (repair && !automatic) 1380 if (repair && !automatic)
1369 tcsetattr(0,TCSANOW,&termios); 1381 tcsetattr(0, TCSANOW, &termios);
1370 1382
1371 if (changed) 1383 if (changed)
1372 retcode += 3; 1384 retcode += 3;
1373 if (errors_uncorrected) 1385 if (errors_uncorrected)
1374 retcode += 4; 1386 retcode += 4;
1375 return retcode; 1387 return retcode;
1376} 1388}
diff --git a/grep.c b/grep.c
index 287d9f80d..d8d2f1837 100644
--- a/grep.c
+++ b/grep.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini grep implementation for busybox 3 * Mini grep implementation for busybox
3 * 4 *
@@ -40,126 +41,125 @@
40#include <ctype.h> 41#include <ctype.h>
41 42
42static const char grep_usage[] = 43static const char grep_usage[] =
43"grep [OPTIONS]... PATTERN [FILE]...\n\n" 44 "grep [OPTIONS]... PATTERN [FILE]...\n\n"
44"Search for PATTERN in each FILE or standard input.\n\n" 45 "Search for PATTERN in each FILE or standard input.\n\n"
45"OPTIONS:\n" 46 "OPTIONS:\n"
46"\t-h\tsuppress the prefixing filename on output\n" 47 "\t-h\tsuppress the prefixing filename on output\n"
47"\t-i\tignore case distinctions\n" 48 "\t-i\tignore case distinctions\n"
48"\t-n\tprint line number with output lines\n" 49 "\t-n\tprint line number with output lines\n"
49"\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n\n" 50 "\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n\n"
50#if defined BB_REGEXP 51#if defined BB_REGEXP
51"This version of grep matches full regular expresions.\n"; 52 "This version of grep matches full regular expresions.\n";
52#else 53#else
53"This version of grep matches strings (not regular expresions).\n"; 54 "This version of grep matches strings (not regular expresions).\n";
54#endif 55#endif
55 56
56static int match = FALSE, beQuiet = FALSE; 57static int match = FALSE, beQuiet = FALSE;
57 58
58static void do_grep(FILE *fp, char* needle, char *fileName, int tellName, int ignoreCase, int tellLine) 59static void do_grep(FILE * fp, char *needle, char *fileName, int tellName,
60 int ignoreCase, int tellLine)
59{ 61{
60 char *cp; 62 char *cp;
61 long line = 0; 63 long line = 0;
62 char haystack[BUF_SIZE]; 64 char haystack[BUF_SIZE];
63 65
64 while (fgets (haystack, sizeof (haystack), fp)) { 66 while (fgets(haystack, sizeof(haystack), fp)) {
65 line++; 67 line++;
66 cp = &haystack[strlen (haystack) - 1]; 68 cp = &haystack[strlen(haystack) - 1];
67 69
68 if (*cp != '\n') 70 if (*cp != '\n')
69 fprintf (stderr, "%s: Line too long\n", fileName); 71 fprintf(stderr, "%s: Line too long\n", fileName);
70 72
71 if (find_match(haystack, needle, ignoreCase) == TRUE) { 73 if (find_match(haystack, needle, ignoreCase) == TRUE) {
72 if (tellName==TRUE) 74 if (tellName == TRUE)
73 printf ("%s:", fileName); 75 printf("%s:", fileName);
74 76
75 if (tellLine==TRUE) 77 if (tellLine == TRUE)
76 printf ("%ld:", line); 78 printf("%ld:", line);
77 79
78 if (beQuiet==FALSE) 80 if (beQuiet == FALSE)
79 fputs (haystack, stdout); 81 fputs(haystack, stdout);
80 82
81 match = TRUE; 83 match = TRUE;
84 }
82 } 85 }
83 }
84} 86}
85 87
86 88
87extern int grep_main (int argc, char **argv) 89extern int grep_main(int argc, char **argv)
88{ 90{
89 FILE *fp; 91 FILE *fp;
90 char *cp; 92 char *cp;
91 char *needle; 93 char *needle;
92 char *fileName; 94 char *fileName;
93 int tellName=TRUE; 95 int tellName = TRUE;
94 int ignoreCase=TRUE; 96 int ignoreCase = TRUE;
95 int tellLine=FALSE; 97 int tellLine = FALSE;
96 98
97 99
98 ignoreCase = FALSE; 100 ignoreCase = FALSE;
99 tellLine = FALSE; 101 tellLine = FALSE;
100 102
101 argc--;
102 argv++;
103 if (argc < 1) {
104 usage(grep_usage);
105 }
106
107 if (**argv == '-') {
108 argc--; 103 argc--;
109 cp = *argv++; 104 argv++;
105 if (argc < 1) {
106 usage(grep_usage);
107 }
110 108
111 while (*++cp) 109 if (**argv == '-') {
112 switch (*cp) { 110 argc--;
113 case 'i': 111 cp = *argv++;
114 ignoreCase = TRUE;
115 break;
116 112
117 case 'h': 113 while (*++cp)
118 tellName = FALSE; 114 switch (*cp) {
119 break; 115 case 'i':
116 ignoreCase = TRUE;
117 break;
120 118
121 case 'n': 119 case 'h':
122 tellLine = TRUE; 120 tellName = FALSE;
123 break; 121 break;
124 122
125 case 'q': 123 case 'n':
126 beQuiet = TRUE; 124 tellLine = TRUE;
127 break; 125 break;
128 126
129 default: 127 case 'q':
130 usage(grep_usage); 128 beQuiet = TRUE;
131 } 129 break;
132 } 130
133 131 default:
134 needle = *argv++; 132 usage(grep_usage);
135 argc--; 133 }
136
137 if (argc==0) {
138 do_grep( stdin, needle, "stdin", FALSE, ignoreCase, tellLine);
139 } else {
140 /* Never print the filename for just one file */
141 if (argc==1)
142 tellName=FALSE;
143 while (argc-- > 0) {
144 fileName = *argv++;
145
146 fp = fopen (fileName, "r");
147 if (fp == NULL) {
148 perror (fileName);
149 continue;
150 }
151
152 do_grep( fp, needle, fileName, tellName, ignoreCase, tellLine);
153
154 if (ferror (fp))
155 perror (fileName);
156 fclose (fp);
157 } 134 }
158 }
159 exit(match);
160}
161 135
136 needle = *argv++;
137 argc--;
162 138
163/* END CODE */ 139 if (argc == 0) {
140 do_grep(stdin, needle, "stdin", FALSE, ignoreCase, tellLine);
141 } else {
142 /* Never print the filename for just one file */
143 if (argc == 1)
144 tellName = FALSE;
145 while (argc-- > 0) {
146 fileName = *argv++;
147
148 fp = fopen(fileName, "r");
149 if (fp == NULL) {
150 perror(fileName);
151 continue;
152 }
153
154 do_grep(fp, needle, fileName, tellName, ignoreCase, tellLine);
155
156 if (ferror(fp))
157 perror(fileName);
158 fclose(fp);
159 }
160 }
161 exit(match);
162}
164 163
165 164
165/* END CODE */
diff --git a/gunzip.c b/gunzip.c
index db7fa1dfe..2bc490e3e 100644
--- a/gunzip.c
+++ b/gunzip.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* zcat : stripped version based on gzip sources 2/* zcat : stripped version based on gzip sources
2 Sven Rudolph <sr1@inf.tu-dresden.de> 3 Sven Rudolph <sr1@inf.tu-dresden.de>
3 */ 4 */
@@ -8,11 +9,12 @@
8#include "messages.c" 9#include "messages.c"
9 10
10static const char gunzip_usage[] = 11static const char gunzip_usage[] =
11 "gunzip [OPTION]... FILE\n\n" 12 "gunzip [OPTION]... FILE\n\n"
12 "Uncompress FILE (or standard input if FILE is '-').\n\n" 13 "Uncompress FILE (or standard input if FILE is '-').\n\n"
13 "Options:\n" 14 "Options:\n"
14 "\t-c\tWrite output to standard output\n" 15
15 "\t-t\tTest compressed file integrity\n"; 16 "\t-c\tWrite output to standard output\n"
17 "\t-t\tTest compressed file integrity\n";
16 18
17/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface 19/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
18 * Copyright (C) 1992-1993 Jean-loup Gailly 20 * Copyright (C) 1992-1993 Jean-loup Gailly
@@ -26,22 +28,23 @@ static const char gunzip_usage[] =
26 */ 28 */
27 29
28#if 0 30#if 0
29static char *license_msg[] = { 31static char *license_msg[] = {
30" Copyright (C) 1992-1993 Jean-loup Gailly", 32 " Copyright (C) 1992-1993 Jean-loup Gailly",
31" This program is free software; you can redistribute it and/or modify", 33 " This program is free software; you can redistribute it and/or modify",
32" it under the terms of the GNU General Public License as published by", 34 " it under the terms of the GNU General Public License as published by",
33" the Free Software Foundation; either version 2, or (at your option)", 35 " the Free Software Foundation; either version 2, or (at your option)",
34" any later version.", 36 " any later version.",
35"", 37 "",
36" This program is distributed in the hope that it will be useful,", 38 " This program is distributed in the hope that it will be useful,",
37" but WITHOUT ANY WARRANTY; without even the implied warranty of", 39 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
38" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", 40 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
39" GNU General Public License for more details.", 41 " GNU General Public License for more details.",
40"", 42 "",
41" You should have received a copy of the GNU General Public License", 43 " You should have received a copy of the GNU General Public License",
42" along with this program; if not, write to the Free Software", 44 " along with this program; if not, write to the Free Software",
43" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.", 45 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
440}; 46 0
47};
45#endif 48#endif
46 49
47/* Compress files with zip algorithm and 'compress' interface. 50/* Compress files with zip algorithm and 'compress' interface.
@@ -67,7 +70,7 @@ static char *license_msg[] = {
67#include <signal.h> 70#include <signal.h>
68#include <sys/stat.h> 71#include <sys/stat.h>
69#include <errno.h> 72#include <errno.h>
70#include <sys/param.h> /* for PATH_MAX */ 73#include <sys/param.h> /* for PATH_MAX */
71 74
72/* #include "tailor.h" */ 75/* #include "tailor.h" */
73 76
@@ -101,9 +104,9 @@ static char *license_msg[] = {
101#endif 104#endif
102 105
103#ifdef __STDC__ 106#ifdef __STDC__
104 typedef void *voidp; 107typedef void *voidp;
105#else 108#else
106 typedef char *voidp; 109typedef char *voidp;
107#endif 110#endif
108 111
109/* I don't like nested includes, but the string and io functions are used 112/* I don't like nested includes, but the string and io functions are used
@@ -118,10 +121,10 @@ static char *license_msg[] = {
118# define memzero(s, n) memset ((voidp)(s), 0, (n)) 121# define memzero(s, n) memset ((voidp)(s), 0, (n))
119#else 122#else
120# include <strings.h> 123# include <strings.h>
121# define strchr index 124# define strchr index
122# define strrchr rindex 125# define strrchr rindex
123# define memcpy(d, s, n) bcopy((s), (d), (n)) 126# define memcpy(d, s, n) bcopy((s), (d), (n))
124# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 127# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
125# define memzero(s, n) bzero((s), (n)) 128# define memzero(s, n) bzero((s), (n))
126#endif 129#endif
127 130
@@ -131,9 +134,9 @@ static char *license_msg[] = {
131 134
132#define local static 135#define local static
133 136
134typedef unsigned char uch; 137typedef unsigned char uch;
135typedef unsigned short ush; 138typedef unsigned short ush;
136typedef unsigned long ulg; 139typedef unsigned long ulg;
137 140
138/* Return codes from gzip */ 141/* Return codes from gzip */
139#define OK 0 142#define OK 0
@@ -143,7 +146,7 @@ typedef unsigned long ulg;
143/* Compression methods (see algorithm.doc) */ 146/* Compression methods (see algorithm.doc) */
144#define DEFLATED 8 147#define DEFLATED 8
145 148
146extern int method; /* compression method */ 149extern int method; /* compression method */
147 150
148/* To save memory for 16 bit systems, some arrays are overlaid between 151/* To save memory for 16 bit systems, some arrays are overlaid between
149 * the various modules: 152 * the various modules:
@@ -158,29 +161,29 @@ extern int method; /* compression method */
158 161
159#ifndef INBUFSIZ 162#ifndef INBUFSIZ
160# ifdef SMALL_MEM 163# ifdef SMALL_MEM
161# define INBUFSIZ 0x2000 /* input buffer size */ 164# define INBUFSIZ 0x2000 /* input buffer size */
162# else 165# else
163# define INBUFSIZ 0x8000 /* input buffer size */ 166# define INBUFSIZ 0x8000 /* input buffer size */
164# endif 167# endif
165#endif 168#endif
166#define INBUF_EXTRA 64 /* required by unlzw() */ 169#define INBUF_EXTRA 64 /* required by unlzw() */
167 170
168#ifndef OUTBUFSIZ 171#ifndef OUTBUFSIZ
169# ifdef SMALL_MEM 172# ifdef SMALL_MEM
170# define OUTBUFSIZ 8192 /* output buffer size */ 173# define OUTBUFSIZ 8192 /* output buffer size */
171# else 174# else
172# define OUTBUFSIZ 16384 /* output buffer size */ 175# define OUTBUFSIZ 16384 /* output buffer size */
173# endif 176# endif
174#endif 177#endif
175#define OUTBUF_EXTRA 2048 /* required by unlzw() */ 178#define OUTBUF_EXTRA 2048 /* required by unlzw() */
176 179
177#define SMALL_MEM 180#define SMALL_MEM
178 181
179#ifndef DIST_BUFSIZE 182#ifndef DIST_BUFSIZE
180# ifdef SMALL_MEM 183# ifdef SMALL_MEM
181# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ 184# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
182# else 185# else
183# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ 186# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
184# endif 187# endif
185#endif 188#endif
186 189
@@ -201,50 +204,51 @@ extern int method; /* compression method */
201# define FREE(array) 204# define FREE(array)
202#endif 205#endif
203 206
204EXTERN(uch, inbuf); /* input buffer */ 207EXTERN(uch, inbuf); /* input buffer */
205EXTERN(uch, outbuf); /* output buffer */ 208EXTERN(uch, outbuf); /* output buffer */
206EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ 209EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
207EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ 210EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
208#define tab_suffix window 211#define tab_suffix window
209#ifndef MAXSEG_64K 212#ifndef MAXSEG_64K
210# define tab_prefix prev /* hash link (see deflate.c) */ 213# define tab_prefix prev /* hash link (see deflate.c) */
211# define head (prev+WSIZE) /* hash head (see deflate.c) */ 214# define head (prev+WSIZE) /* hash head (see deflate.c) */
212 EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ 215EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
213#else 216#else
214# define tab_prefix0 prev 217# define tab_prefix0 prev
215# define head tab_prefix1 218# define head tab_prefix1
216 EXTERN(ush, tab_prefix0); /* prefix for even codes */ 219EXTERN(ush, tab_prefix0); /* prefix for even codes */
217 EXTERN(ush, tab_prefix1); /* prefix for odd codes */ 220EXTERN(ush, tab_prefix1); /* prefix for odd codes */
218#endif 221#endif
219 222
220extern unsigned insize; /* valid bytes in inbuf */ 223extern unsigned insize; /* valid bytes in inbuf */
221extern unsigned inptr; /* index of next byte to be processed in inbuf */ 224extern unsigned inptr; /* index of next byte to be processed in inbuf */
222extern unsigned outcnt; /* bytes in output buffer */ 225extern unsigned outcnt; /* bytes in output buffer */
226
227extern long bytes_in; /* number of input bytes */
228extern long bytes_out; /* number of output bytes */
229extern long header_bytes; /* number of bytes in gzip header */
223 230
224extern long bytes_in; /* number of input bytes */ 231extern long ifile_size; /* input file size, -1 for devices (debug only) */
225extern long bytes_out; /* number of output bytes */
226extern long header_bytes;/* number of bytes in gzip header */
227 232
228extern long ifile_size; /* input file size, -1 for devices (debug only) */ 233typedef int file_t; /* Do not use stdio */
229 234
230typedef int file_t; /* Do not use stdio */ 235#define NO_FILE (-1) /* in memory compression */
231#define NO_FILE (-1) /* in memory compression */
232 236
233 237
234#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ 238#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
235 239
236/* gzip flag byte */ 240/* gzip flag byte */
237#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 241#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
238#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 242#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
239#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 243#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
240#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 244#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
241#define COMMENT 0x10 /* bit 4 set: file comment present */ 245#define COMMENT 0x10 /* bit 4 set: file comment present */
242#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 246#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
243#define RESERVED 0xC0 /* bit 6,7: reserved */ 247#define RESERVED 0xC0 /* bit 6,7: reserved */
244 248
245#ifndef WSIZE 249#ifndef WSIZE
246# define WSIZE 0x8000 /* window size--must be a power of two, and */ 250# define WSIZE 0x8000 /* window size--must be a power of two, and */
247#endif /* at least 32K for zip's deflate method */ 251#endif /* at least 32K for zip's deflate method */
248 252
249#define MIN_MATCH 3 253#define MIN_MATCH 3
250#define MAX_MATCH 258 254#define MAX_MATCH 258
@@ -260,11 +264,11 @@ typedef int file_t; /* Do not use stdio */
260 * distances are limited to MAX_DIST instead of WSIZE. 264 * distances are limited to MAX_DIST instead of WSIZE.
261 */ 265 */
262 266
263extern int exit_code; /* program exit code */ 267extern int exit_code; /* program exit code */
264extern int verbose; /* be verbose (-v) */ 268extern int verbose; /* be verbose (-v) */
265extern int level; /* compression level */ 269extern int level; /* compression level */
266extern int test; /* check .z file integrity */ 270extern int test; /* check .z file integrity */
267extern int save_orig_name; /* set if original name must be saved */ 271extern int save_orig_name; /* set if original name must be saved */
268 272
269#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) 273#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
270#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) 274#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
@@ -296,10 +300,10 @@ extern int save_orig_name; /* set if original name must be saved */
296 put_short(((ulg)(n)) >> 16); \ 300 put_short(((ulg)(n)) >> 16); \
297} 301}
298 302
299#define seekable() 0 /* force sequential output */ 303#define seekable() 0 /* force sequential output */
300#define translate_eol 0 /* no option -a yet */ 304#define translate_eol 0 /* no option -a yet */
301 305
302#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ 306#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
303 307
304/* Macros for getting two-byte and four-byte header values */ 308/* Macros for getting two-byte and four-byte header values */
305#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) 309#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
@@ -329,43 +333,44 @@ extern int save_orig_name; /* set if original name must be saved */
329 333
330 334
331 /* in unzip.c */ 335 /* in unzip.c */
332extern int unzip OF((int in, int out)); 336extern int unzip OF((int in, int out));
333 337
334 /* in gzip.c */ 338 /* in gzip.c */
335RETSIGTYPE abort_gzip OF((void)); 339RETSIGTYPE abort_gzip OF((void));
336 340
337 /* in deflate.c */ 341 /* in deflate.c */
338void lm_init OF((int pack_level, ush *flags)); 342void lm_init OF((int pack_level, ush * flags));
339ulg deflate OF((void)); 343ulg deflate OF((void));
340 344
341 /* in trees.c */ 345 /* in trees.c */
342void ct_init OF((ush *attr, int *method)); 346void ct_init OF((ush * attr, int *method));
343int ct_tally OF((int dist, int lc)); 347int ct_tally OF((int dist, int lc));
344ulg flush_block OF((char *buf, ulg stored_len, int eof)); 348ulg flush_block OF((char *buf, ulg stored_len, int eof));
345 349
346 /* in bits.c */ 350 /* in bits.c */
347void bi_init OF((file_t zipfile)); 351void bi_init OF((file_t zipfile));
348void send_bits OF((int value, int length)); 352void send_bits OF((int value, int length));
349unsigned bi_reverse OF((unsigned value, int length)); 353unsigned bi_reverse OF((unsigned value, int length));
350void bi_windup OF((void)); 354void bi_windup OF((void));
351void copy_block OF((char *buf, unsigned len, int header)); 355void copy_block OF((char *buf, unsigned len, int header));
352extern int (*read_buf) OF((char *buf, unsigned size)); 356extern int (*read_buf) OF((char *buf, unsigned size));
353 357
354 /* in util.c: */ 358 /* in util.c: */
355extern int copy OF((int in, int out)); 359extern int copy OF((int in, int out));
356extern ulg updcrc OF((uch *s, unsigned n)); 360extern ulg updcrc OF((uch * s, unsigned n));
357extern void clear_bufs OF((void)); 361extern void clear_bufs OF((void));
358extern int fill_inbuf OF((int eof_ok)); 362extern int fill_inbuf OF((int eof_ok));
359extern void flush_outbuf OF((void)); 363extern void flush_outbuf OF((void));
360extern void flush_window OF((void)); 364extern void flush_window OF((void));
361extern void write_buf OF((int fd, voidp buf, unsigned cnt)); 365extern void write_buf OF((int fd, voidp buf, unsigned cnt));
366
362#ifndef __linux__ 367#ifndef __linux__
363extern char *basename OF((char *fname)); 368extern char *basename OF((char *fname));
364#endif /* not __linux__ */ 369#endif /* not __linux__ */
365extern void error OF((char *m)); 370extern void error OF((char *m));
366extern void warn OF((char *a, char *b)); 371extern void warn OF((char *a, char *b));
367extern void read_error OF((void)); 372extern void read_error OF((void));
368extern void write_error OF((void)); 373extern void write_error OF((void));
369 374
370 /* in inflate.c */ 375 /* in inflate.c */
371extern int inflate OF((void)); 376extern int inflate OF((void));
@@ -385,11 +390,11 @@ extern int inflate OF((void));
385#ifndef BITS 390#ifndef BITS
386# define BITS 16 391# define BITS 16
387#endif 392#endif
388#define INIT_BITS 9 /* Initial number of bits per code */ 393#define INIT_BITS 9 /* Initial number of bits per code */
389 394
390#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */ 395#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
391 396
392#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ 397#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
393/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. 398/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
394 * It's a pity that old uncompress does not check bit 0x20. That makes 399 * It's a pity that old uncompress does not check bit 0x20. That makes
395 * extension of the format actually undesirable because old compress 400 * extension of the format actually undesirable because old compress
@@ -404,16 +409,16 @@ extern int inflate OF((void));
404 * clear the dictionary. 409 * clear the dictionary.
405 */ 410 */
406 411
407#define LZW_RESERVED 0x60 /* reserved bits */ 412#define LZW_RESERVED 0x60 /* reserved bits */
408 413
409#define CLEAR 256 /* flush the dictionary */ 414#define CLEAR 256 /* flush the dictionary */
410#define FIRST (CLEAR+1) /* first free entry */ 415#define FIRST (CLEAR+1) /* first free entry */
411 416
412extern int maxbits; /* max bits per code for LZW */ 417extern int maxbits; /* max bits per code for LZW */
413extern int block_mode; /* block compress mode -C compatible with 2.0 */ 418extern int block_mode; /* block compress mode -C compatible with 2.0 */
414 419
415extern int lzw OF((int in, int out)); 420extern int lzw OF((int in, int out));
416extern int unlzw OF((int in, int out)); 421extern int unlzw OF((int in, int out));
417 422
418 423
419/* #include "revision.h" */ 424/* #include "revision.h" */
@@ -458,14 +463,12 @@ extern int unlzw OF((int in, int out));
458#ifdef __cplusplus 463#ifdef __cplusplus
459extern "C" { 464extern "C" {
460#endif 465#endif
461
462/* For communication from `getopt' to the caller. 466/* For communication from `getopt' to the caller.
463 When `getopt' finds an option that takes an argument, 467 When `getopt' finds an option that takes an argument,
464 the argument value is returned here. 468 the argument value is returned here.
465 Also, when `ordering' is RETURN_IN_ORDER, 469 Also, when `ordering' is RETURN_IN_ORDER,
466 each non-option ARGV-element is returned here. */ 470 each non-option ARGV-element is returned here. */
467 471 extern char *optarg;
468extern char *optarg;
469 472
470/* Index in ARGV of the next element to be scanned. 473/* Index in ARGV of the next element to be scanned.
471 This is used for communication to and from the caller 474 This is used for communication to and from the caller
@@ -479,16 +482,16 @@ extern char *optarg;
479 Otherwise, `optind' communicates from one call to the next 482 Otherwise, `optind' communicates from one call to the next
480 how much of ARGV has been scanned so far. */ 483 how much of ARGV has been scanned so far. */
481 484
482extern int optind; 485 extern int optind;
483 486
484/* Callers store zero here to inhibit the error message `getopt' prints 487/* Callers store zero here to inhibit the error message `getopt' prints
485 for unrecognized options. */ 488 for unrecognized options. */
486 489
487extern int opterr; 490 extern int opterr;
488 491
489/* Set to an option character which was unrecognized. */ 492/* Set to an option character which was unrecognized. */
490 493
491extern int optopt; 494 extern int optopt;
492 495
493/* Describe the long-named options requested by the application. 496/* Describe the long-named options requested by the application.
494 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 497 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
@@ -511,19 +514,18 @@ extern int optopt;
511 one). For long options that have a zero `flag' field, `getopt' 514 one). For long options that have a zero `flag' field, `getopt'
512 returns the contents of the `val' field. */ 515 returns the contents of the `val' field. */
513 516
514struct option 517 struct option {
515{
516#if __STDC__ 518#if __STDC__
517 const char *name; 519 const char *name;
518#else 520#else
519 char *name; 521 char *name;
520#endif 522#endif
521 /* has_arg can't be an enum because some compilers complain about 523 /* has_arg can't be an enum because some compilers complain about
522 type mismatches in all the code that assumes it is an int. */ 524 type mismatches in all the code that assumes it is an int. */
523 int has_arg; 525 int has_arg;
524 int *flag; 526 int *flag;
525 int val; 527 int val;
526}; 528 };
527 529
528/* Names for the values of the `has_arg' field of `struct option'. */ 530/* Names for the values of the `has_arg' field of `struct option'. */
529 531
@@ -536,60 +538,61 @@ struct option
536/* Many other libraries have conflicting prototypes for getopt, with 538/* Many other libraries have conflicting prototypes for getopt, with
537 differences in the consts, in stdlib.h. To avoid compilation 539 differences in the consts, in stdlib.h. To avoid compilation
538 errors, only prototype getopt for the GNU C library. */ 540 errors, only prototype getopt for the GNU C library. */
539extern int getopt (int argc, char *const *argv, const char *shortopts); 541 extern int getopt(int argc, char *const *argv, const char *shortopts);
540#endif /* not __GNU_LIBRARY__ */ 542#endif /* not __GNU_LIBRARY__ */
541extern int getopt_long (int argc, char *const *argv, const char *shortopts, 543 extern int getopt_long(int argc, char *const *argv,
542 const struct option *longopts, int *longind); 544 const char *shortopts,
543extern int getopt_long_only (int argc, char *const *argv, 545 const struct option *longopts, int *longind);
544 const char *shortopts, 546 extern int getopt_long_only(int argc, char *const *argv,
545 const struct option *longopts, int *longind); 547 const char *shortopts,
548 const struct option *longopts,
549 int *longind);
546 550
547/* Internal only. Users should not call this directly. */ 551/* Internal only. Users should not call this directly. */
548extern int _getopt_internal (int argc, char *const *argv, 552 extern int _getopt_internal(int argc, char *const *argv,
549 const char *shortopts, 553 const char *shortopts,
550 const struct option *longopts, int *longind, 554 const struct option *longopts,
551 int long_only); 555 int *longind, int long_only);
552#else /* not __STDC__ */ 556#else /* not __STDC__ */
553extern int getopt (); 557 extern int getopt();
554extern int getopt_long (); 558 extern int getopt_long();
555extern int getopt_long_only (); 559 extern int getopt_long_only();
556 560
557extern int _getopt_internal (); 561 extern int _getopt_internal();
558#endif /* not __STDC__ */ 562#endif /* not __STDC__ */
559 563
560#ifdef __cplusplus 564#ifdef __cplusplus
561} 565}
562#endif 566#endif
563 567#endif /* _GETOPT_H */
564#endif /* _GETOPT_H */
565
566
567#include <time.h> 568#include <time.h>
568#include <fcntl.h> 569#include <fcntl.h>
569#include <unistd.h> 570#include <unistd.h>
570
571#include <stdlib.h> 571#include <stdlib.h>
572
573#if defined(DIRENT) 572#if defined(DIRENT)
574# include <dirent.h> 573# include <dirent.h>
575 typedef struct dirent dir_type; 574typedef struct dirent dir_type;
575
576# define NLENGTH(dirent) ((int)strlen((dirent)->d_name)) 576# define NLENGTH(dirent) ((int)strlen((dirent)->d_name))
577# define DIR_OPT "DIRENT" 577# define DIR_OPT "DIRENT"
578#else 578#else
579# define NLENGTH(dirent) ((dirent)->d_namlen) 579# define NLENGTH(dirent) ((dirent)->d_namlen)
580# ifdef SYSDIR 580# ifdef SYSDIR
581# include <sys/dir.h> 581# include <sys/dir.h>
582 typedef struct direct dir_type; 582typedef struct direct dir_type;
583
583# define DIR_OPT "SYSDIR" 584# define DIR_OPT "SYSDIR"
584# else 585# else
585# ifdef SYSNDIR 586# ifdef SYSNDIR
586# include <sys/ndir.h> 587# include <sys/ndir.h>
587 typedef struct direct dir_type; 588typedef struct direct dir_type;
589
588# define DIR_OPT "SYSNDIR" 590# define DIR_OPT "SYSNDIR"
589# else 591# else
590# ifdef NDIR 592# ifdef NDIR
591# include <ndir.h> 593# include <ndir.h>
592 typedef struct direct dir_type; 594typedef struct direct dir_type;
595
593# define DIR_OPT "NDIR" 596# define DIR_OPT "NDIR"
594# else 597# else
595# define NO_DIR 598# define NO_DIR
@@ -598,18 +601,16 @@ extern int _getopt_internal ();
598# endif 601# endif
599# endif 602# endif
600#endif 603#endif
601
602#if !defined(S_ISDIR) && defined(S_IFDIR) 604#if !defined(S_ISDIR) && defined(S_IFDIR)
603# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 605# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
604#endif 606#endif
605#if !defined(S_ISREG) && defined(S_IFREG) 607#if !defined(S_ISREG) && defined(S_IFREG)
606# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 608# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
607#endif 609#endif
608 610typedef RETSIGTYPE(*sig_type) OF((int));
609typedef RETSIGTYPE (*sig_type) OF((int));
610 611
611#ifndef O_BINARY 612#ifndef O_BINARY
612# define O_BINARY 0 /* creation mode for open() */ 613# define O_BINARY 0 /* creation mode for open() */
613#endif 614#endif
614 615
615#ifndef O_CREAT 616#ifndef O_CREAT
@@ -629,9 +630,9 @@ typedef RETSIGTYPE (*sig_type) OF((int));
629#ifndef S_IWUSR 630#ifndef S_IWUSR
630# define S_IWUSR 0200 631# define S_IWUSR 0200
631#endif 632#endif
632#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ 633#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
633 634
634#ifndef MAX_PATH_LEN /* max pathname length */ 635#ifndef MAX_PATH_LEN /* max pathname length */
635# ifdef PATH_MAX 636# ifdef PATH_MAX
636# define MAX_PATH_LEN PATH_MAX 637# define MAX_PATH_LEN PATH_MAX
637# else 638# else
@@ -644,224 +645,224 @@ typedef RETSIGTYPE (*sig_type) OF((int));
644#endif 645#endif
645 646
646#ifdef NO_OFF_T 647#ifdef NO_OFF_T
647 typedef long off_t; 648typedef long off_t;
648 off_t lseek OF((int fd, off_t offset, int whence)); 649off_t lseek OF((int fd, off_t offset, int whence));
649#endif 650#endif
650 651
651 652
652 /* global buffers */ 653 /* global buffers */
653 654
654DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 655DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
655DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 656DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
656DECLARE(ush, d_buf, DIST_BUFSIZE); 657DECLARE(ush, d_buf, DIST_BUFSIZE);
657DECLARE(uch, window, 2L*WSIZE); 658DECLARE(uch, window, 2L * WSIZE);
658#ifndef MAXSEG_64K 659#ifndef MAXSEG_64K
659 DECLARE(ush, tab_prefix, 1L<<BITS); 660DECLARE(ush, tab_prefix, 1L << BITS);
660#else 661#else
661 DECLARE(ush, tab_prefix0, 1L<<(BITS-1)); 662DECLARE(ush, tab_prefix0, 1L << (BITS - 1));
662 DECLARE(ush, tab_prefix1, 1L<<(BITS-1)); 663DECLARE(ush, tab_prefix1, 1L << (BITS - 1));
663#endif 664#endif
664 665
665 /* local variables */ 666 /* local variables */
666 667
667int test_mode = 0; /* check file integrity option */ 668int test_mode = 0; /* check file integrity option */
668int foreground; /* set if program run in foreground */ 669int foreground; /* set if program run in foreground */
669int maxbits = BITS; /* max bits per code for LZW */ 670int maxbits = BITS; /* max bits per code for LZW */
670int method = DEFLATED;/* compression method */ 671int method = DEFLATED; /* compression method */
671int exit_code = OK; /* program exit code */ 672int exit_code = OK; /* program exit code */
672int last_member; /* set for .zip and .Z files */ 673int last_member; /* set for .zip and .Z files */
673int part_nb; /* number of parts in .gz file */ 674int part_nb; /* number of parts in .gz file */
674long ifile_size; /* input file size, -1 for devices (debug only) */ 675long ifile_size; /* input file size, -1 for devices (debug only) */
675 676
676long bytes_in; /* number of input bytes */ 677long bytes_in; /* number of input bytes */
677long bytes_out; /* number of output bytes */ 678long bytes_out; /* number of output bytes */
678long total_in = 0; /* input bytes for all files */ 679long total_in = 0; /* input bytes for all files */
679long total_out = 0; /* output bytes for all files */ 680long total_out = 0; /* output bytes for all files */
680struct stat istat; /* status for input file */ 681struct stat istat; /* status for input file */
681int ifd; /* input file descriptor */ 682int ifd; /* input file descriptor */
682int ofd; /* output file descriptor */ 683int ofd; /* output file descriptor */
683unsigned insize; /* valid bytes in inbuf */ 684unsigned insize; /* valid bytes in inbuf */
684unsigned inptr; /* index of next byte to be processed in inbuf */ 685unsigned inptr; /* index of next byte to be processed in inbuf */
685unsigned outcnt; /* bytes in output buffer */ 686unsigned outcnt; /* bytes in output buffer */
686 687
687long header_bytes; /* number of bytes in gzip header */ 688long header_bytes; /* number of bytes in gzip header */
688 689
689/* local functions */ 690/* local functions */
690 691
691local int get_method OF((int in)); 692local int get_method OF((int in));
692 693
693#define strequ(s1, s2) (strcmp((s1),(s2)) == 0) 694#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
694 695
695/* ======================================================================== */ 696/* ======================================================================== */
696int gunzip_main (int argc, char** argv) 697int gunzip_main(int argc, char **argv)
697{ 698{
698 int file_count; /* number of files to precess */ 699 int file_count; /* number of files to precess */
699 int to_stdout = 0; 700 int to_stdout = 0;
700 int fromstdin = 0; 701 int fromstdin = 0;
701 int result; 702 int result;
702 int inFileNum; 703 int inFileNum;
703 int outFileNum; 704 int outFileNum;
704 int delInputFile=0; 705 int delInputFile = 0;
705 struct stat statBuf; 706 struct stat statBuf;
706 char* delFileName; 707 char *delFileName;
707 char ifname[MAX_PATH_LEN + 1]; /* input file name */ 708 char ifname[MAX_PATH_LEN + 1]; /* input file name */
708 char ofname[MAX_PATH_LEN + 1]; /* output file name */ 709 char ofname[MAX_PATH_LEN + 1]; /* output file name */
709 710
710 if (argc==1) 711 if (argc == 1)
711 usage(gunzip_usage); 712 usage(gunzip_usage);
712 713
713 if (strcmp(*argv, "zcat")==0) 714 if (strcmp(*argv, "zcat") == 0)
714 to_stdout = 1;
715
716 /* Parse any options */
717 while (--argc > 0 && **(++argv) == '-') {
718 if (*((*argv)+1) == '\0') {
719 fromstdin = 1;
720 to_stdout = 1;
721 }
722 while (*(++(*argv))) {
723 switch (**argv) {
724 case 'c':
725 to_stdout = 1; 715 to_stdout = 1;
726 break;
727 case 't':
728 test_mode = 1;
729 break;
730 716
731 default: 717 /* Parse any options */
732 usage(gunzip_usage); 718 while (--argc > 0 && **(++argv) == '-') {
733 } 719 if (*((*argv) + 1) == '\0') {
720 fromstdin = 1;
721 to_stdout = 1;
722 }
723 while (*(++(*argv))) {
724 switch (**argv) {
725 case 'c':
726 to_stdout = 1;
727 break;
728 case 't':
729 test_mode = 1;
730 break;
731
732 default:
733 usage(gunzip_usage);
734 }
735 }
734 } 736 }
735 }
736 737
737 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; 738 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
738 if (foreground) { 739 if (foreground) {
739 (void) signal (SIGINT, (sig_type)abort_gzip); 740 (void) signal(SIGINT, (sig_type) abort_gzip);
740 } 741 }
741#ifdef SIGTERM 742#ifdef SIGTERM
742 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 743 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
743 (void) signal(SIGTERM, (sig_type)abort_gzip); 744 (void) signal(SIGTERM, (sig_type) abort_gzip);
744 } 745 }
745#endif 746#endif
746#ifdef SIGHUP 747#ifdef SIGHUP
747 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 748 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
748 (void) signal(SIGHUP, (sig_type)abort_gzip); 749 (void) signal(SIGHUP, (sig_type) abort_gzip);
749 } 750 }
750#endif 751#endif
751 752
752 file_count = argc - optind; 753 file_count = argc - optind;
753 754
754 /* Allocate all global buffers (for DYN_ALLOC option) */ 755 /* Allocate all global buffers (for DYN_ALLOC option) */
755 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 756 ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
756 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 757 ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
757 ALLOC(ush, d_buf, DIST_BUFSIZE); 758 ALLOC(ush, d_buf, DIST_BUFSIZE);
758 ALLOC(uch, window, 2L*WSIZE); 759 ALLOC(uch, window, 2L * WSIZE);
759#ifndef MAXSEG_64K 760#ifndef MAXSEG_64K
760 ALLOC(ush, tab_prefix, 1L<<BITS); 761 ALLOC(ush, tab_prefix, 1L << BITS);
761#else 762#else
762 ALLOC(ush, tab_prefix0, 1L<<(BITS-1)); 763 ALLOC(ush, tab_prefix0, 1L << (BITS - 1));
763 ALLOC(ush, tab_prefix1, 1L<<(BITS-1)); 764 ALLOC(ush, tab_prefix1, 1L << (BITS - 1));
764#endif 765#endif
765 766
766 if (fromstdin==1) { 767 if (fromstdin == 1) {
767 strcpy(ofname, "stdin"); 768 strcpy(ofname, "stdin");
768
769 inFileNum=fileno(stdin);
770 ifile_size = -1L; /* convention for unknown size */
771 } else {
772 /* Open up the input file */
773 if (*argv=='\0')
774 usage(gunzip_usage);
775 if (strlen(*argv) > MAX_PATH_LEN) {
776 fprintf(stderr, name_too_long, "gunzip");
777 do_exit(WARNING);
778 }
779 strcpy(ifname, *argv);
780 769
781 /* Open input fille */ 770 inFileNum = fileno(stdin);
782 inFileNum=open( ifname, O_RDONLY); 771 ifile_size = -1L; /* convention for unknown size */
783 if (inFileNum < 0) {
784 perror(ifname);
785 do_exit(WARNING);
786 }
787 /* Get the time stamp on the input file. */
788 result = stat(ifname, &statBuf);
789 if (result < 0) {
790 perror(ifname);
791 do_exit(WARNING);
792 }
793 ifile_size = statBuf.st_size;
794 }
795
796 if (to_stdout==1) {
797 /* And get to work */
798 strcpy(ofname, "stdout");
799 outFileNum=fileno(stdout);
800
801 clear_bufs(); /* clear input and output buffers */
802 part_nb = 0;
803
804 /* Actually do the compression/decompression. */
805 unzip(inFileNum, outFileNum);
806
807 } else if (test_mode) {
808 /* Actually do the compression/decompression. */
809 unzip(inFileNum, 2);
810 } else {
811 char* pos;
812
813 /* And get to work */
814 if (strlen(ifname) > MAX_PATH_LEN - 4) {
815 fprintf(stderr, name_too_long, "gunzip");
816 do_exit(WARNING);
817 }
818 strcpy(ofname, ifname);
819 pos=strstr(ofname, ".gz");
820 if (pos != NULL) {
821 *pos='\0';
822 delInputFile=1;
823 } else { 772 } else {
824 pos=strstr(ofname, ".tgz"); 773 /* Open up the input file */
825 if (pos != NULL) { 774 if (*argv == '\0')
826 *pos='\0'; 775 usage(gunzip_usage);
827 strcat( pos, ".tar"); 776 if (strlen(*argv) > MAX_PATH_LEN) {
828 delInputFile=1; 777 fprintf(stderr, name_too_long, "gunzip");
829 } 778 do_exit(WARNING);
779 }
780 strcpy(ifname, *argv);
781
782 /* Open input fille */
783 inFileNum = open(ifname, O_RDONLY);
784 if (inFileNum < 0) {
785 perror(ifname);
786 do_exit(WARNING);
787 }
788 /* Get the time stamp on the input file. */
789 result = stat(ifname, &statBuf);
790 if (result < 0) {
791 perror(ifname);
792 do_exit(WARNING);
793 }
794 ifile_size = statBuf.st_size;
830 } 795 }
831 796
832 /* Open output fille */ 797 if (to_stdout == 1) {
798 /* And get to work */
799 strcpy(ofname, "stdout");
800 outFileNum = fileno(stdout);
801
802 clear_bufs(); /* clear input and output buffers */
803 part_nb = 0;
804
805 /* Actually do the compression/decompression. */
806 unzip(inFileNum, outFileNum);
807
808 } else if (test_mode) {
809 /* Actually do the compression/decompression. */
810 unzip(inFileNum, 2);
811 } else {
812 char *pos;
813
814 /* And get to work */
815 if (strlen(ifname) > MAX_PATH_LEN - 4) {
816 fprintf(stderr, name_too_long, "gunzip");
817 do_exit(WARNING);
818 }
819 strcpy(ofname, ifname);
820 pos = strstr(ofname, ".gz");
821 if (pos != NULL) {
822 *pos = '\0';
823 delInputFile = 1;
824 } else {
825 pos = strstr(ofname, ".tgz");
826 if (pos != NULL) {
827 *pos = '\0';
828 strcat(pos, ".tar");
829 delInputFile = 1;
830 }
831 }
832
833 /* Open output fille */
833#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 834#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
834 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW); 835 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
835#else 836#else
836 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL); 837 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL);
837#endif 838#endif
838 if (outFileNum < 0) { 839 if (outFileNum < 0) {
839 perror(ofname); 840 perror(ofname);
840 do_exit(WARNING); 841 do_exit(WARNING);
841 } 842 }
842 /* Set permissions on the file */ 843 /* Set permissions on the file */
843 fchmod(outFileNum, statBuf.st_mode); 844 fchmod(outFileNum, statBuf.st_mode);
844 845
845 clear_bufs(); /* clear input and output buffers */ 846 clear_bufs(); /* clear input and output buffers */
846 part_nb = 0; 847 part_nb = 0;
847 848
848 /* Actually do the compression/decompression. */ 849 /* Actually do the compression/decompression. */
849 result=unzip(inFileNum, outFileNum); 850 result = unzip(inFileNum, outFileNum);
850 851
851 close( outFileNum); 852 close(outFileNum);
852 close( inFileNum); 853 close(inFileNum);
853 /* Delete the original file */ 854 /* Delete the original file */
854 if (result == OK) 855 if (result == OK)
855 delFileName=ifname; 856 delFileName = ifname;
856 else 857 else
857 delFileName=ofname; 858 delFileName = ofname;
858 859
859 if (delInputFile == 1 && unlink (delFileName) < 0) { 860 if (delInputFile == 1 && unlink(delFileName) < 0) {
860 perror (delFileName); 861 perror(delFileName);
861 exit( FALSE); 862 exit(FALSE);
863 }
862 } 864 }
863 } 865 do_exit(exit_code);
864 do_exit(exit_code);
865} 866}
866 867
867 868
@@ -877,71 +878,76 @@ int gunzip_main (int argc, char** argv)
877 * If the member is a zip file, it must be the only one. 878 * If the member is a zip file, it must be the only one.
878 */ 879 */
879local int get_method(in) 880local int get_method(in)
880 int in; /* input file descriptor */ 881int in; /* input file descriptor */
881{ 882{
882 uch flags; /* compression flags */ 883 uch flags; /* compression flags */
883 char magic[2]; /* magic header */ 884 char magic[2]; /* magic header */
884 885
885 magic[0] = (char)get_byte(); 886 magic[0] = (char) get_byte();
886 magic[1] = (char)get_byte(); 887 magic[1] = (char) get_byte();
887 method = -1; /* unknown yet */ 888 method = -1; /* unknown yet */
888 part_nb++; /* number of parts in gzip file */ 889 part_nb++; /* number of parts in gzip file */
889 header_bytes = 0; 890 header_bytes = 0;
890 last_member = RECORD_IO; 891 last_member = RECORD_IO;
891 /* assume multiple members in gzip file except for record oriented I/O */ 892 /* assume multiple members in gzip file except for record oriented I/O */
892 893
893 if (memcmp(magic, GZIP_MAGIC, 2) == 0) { 894 if (memcmp(magic, GZIP_MAGIC, 2) == 0) {
894 895
895 method = (int)get_byte(); 896 method = (int) get_byte();
896 if (method != DEFLATED) { 897 if (method != DEFLATED) {
897 fprintf(stderr, 898 fprintf(stderr,
898 "unknown method %d -- get newer version of gzip\n", 899 "unknown method %d -- get newer version of gzip\n",
899 method); 900 method);
900 exit_code = ERROR; 901 exit_code = ERROR;
901 return -1; 902 return -1;
902 } 903 }
903 flags = (uch)get_byte(); 904 flags = (uch) get_byte();
904 905
905 (ulg)get_byte(); /* Ignore time stamp */ 906 (ulg) get_byte(); /* Ignore time stamp */
906 (ulg)get_byte(); 907 (ulg) get_byte();
907 (ulg)get_byte(); 908 (ulg) get_byte();
908 (ulg)get_byte(); 909 (ulg) get_byte();
910
911 (void) get_byte(); /* Ignore extra flags for the moment */
912 (void) get_byte(); /* Ignore OS type for the moment */
913
914 if ((flags & EXTRA_FIELD) != 0) {
915 unsigned len = (unsigned) get_byte();
916
917 len |= ((unsigned) get_byte()) << 8;
918
919 while (len--)
920 (void) get_byte();
921 }
922
923 /* Discard original name if any */
924 if ((flags & ORIG_NAME) != 0) {
925 while (get_char() != 0) /* null */
926 ;
927 }
928
929 /* Discard file comment if any */
930 if ((flags & COMMENT) != 0) {
931 while (get_char() != 0) /* null */
932 ;
933 }
934 if (part_nb == 1) {
935 header_bytes = inptr + 2 * sizeof(long); /* include crc and size */
936 }
909 937
910 (void)get_byte(); /* Ignore extra flags for the moment */
911 (void)get_byte(); /* Ignore OS type for the moment */
912
913 if ((flags & EXTRA_FIELD) != 0) {
914 unsigned len = (unsigned)get_byte();
915 len |= ((unsigned)get_byte())<<8;
916
917 while (len--) (void)get_byte();
918 } 938 }
919 939
920 /* Discard original name if any */ 940 if (method >= 0)
921 if ((flags & ORIG_NAME) != 0) { 941 return method;
922 while (get_char() != 0) /* null */ ;
923 }
924 942
925 /* Discard file comment if any */
926 if ((flags & COMMENT) != 0) {
927 while (get_char() != 0) /* null */ ;
928 }
929 if (part_nb == 1) { 943 if (part_nb == 1) {
930 header_bytes = inptr + 2*sizeof(long); /* include crc and size */ 944 fprintf(stderr, "\nnot in gzip format\n");
945 exit_code = ERROR;
946 return -1;
947 } else {
948 WARN((stderr, "\ndecompression OK, trailing garbage ignored\n"));
949 return -2;
931 } 950 }
932
933 }
934
935 if (method >= 0) return method;
936
937 if (part_nb == 1) {
938 fprintf(stderr, "\nnot in gzip format\n");
939 exit_code = ERROR;
940 return -1;
941 } else {
942 WARN((stderr, "\ndecompression OK, trailing garbage ignored\n"));
943 return -2;
944 }
945} 951}
946 952
947/* ======================================================================== 953/* ========================================================================
@@ -949,8 +955,9 @@ local int get_method(in)
949 */ 955 */
950RETSIGTYPE abort_gzip() 956RETSIGTYPE abort_gzip()
951{ 957{
952 do_exit(ERROR); 958 do_exit(ERROR);
953} 959}
960
954/* unzip.c -- decompress files in gzip or pkzip format. 961/* unzip.c -- decompress files in gzip or pkzip format.
955 * Copyright (C) 1992-1993 Jean-loup Gailly 962 * Copyright (C) 1992-1993 Jean-loup Gailly
956 * This is free software; you can redistribute it and/or modify it under the 963 * This is free software; you can redistribute it and/or modify it under the
@@ -973,35 +980,35 @@ RETSIGTYPE abort_gzip()
973 */ 980 */
974 981
975#ifdef CRYPT 982#ifdef CRYPT
976# undef CRYPT /* dummy version */ 983# undef CRYPT /* dummy version */
977#endif 984#endif
978 985
979#define RAND_HEAD_LEN 12 /* length of encryption random header */ 986#define RAND_HEAD_LEN 12 /* length of encryption random header */
980 987
981#define zencode 988#define zencode
982#define zdecode 989#define zdecode
983 990
984/* PKZIP header definitions */ 991/* PKZIP header definitions */
985#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ 992#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
986#define LOCFLG 6 /* offset of bit flag */ 993#define LOCFLG 6 /* offset of bit flag */
987#define CRPFLG 1 /* bit for encrypted entry */ 994#define CRPFLG 1 /* bit for encrypted entry */
988#define EXTFLG 8 /* bit for extended local header */ 995#define EXTFLG 8 /* bit for extended local header */
989#define LOCHOW 8 /* offset of compression method */ 996#define LOCHOW 8 /* offset of compression method */
990#define LOCTIM 10 /* file mod time (for decryption) */ 997#define LOCTIM 10 /* file mod time (for decryption) */
991#define LOCCRC 14 /* offset of crc */ 998#define LOCCRC 14 /* offset of crc */
992#define LOCSIZ 18 /* offset of compressed size */ 999#define LOCSIZ 18 /* offset of compressed size */
993#define LOCLEN 22 /* offset of uncompressed length */ 1000#define LOCLEN 22 /* offset of uncompressed length */
994#define LOCFIL 26 /* offset of file name field length */ 1001#define LOCFIL 26 /* offset of file name field length */
995#define LOCEXT 28 /* offset of extra field length */ 1002#define LOCEXT 28 /* offset of extra field length */
996#define LOCHDR 30 /* size of local header, including sig */ 1003#define LOCHDR 30 /* size of local header, including sig */
997#define EXTHDR 16 /* size of extended local header, inc sig */ 1004#define EXTHDR 16 /* size of extended local header, inc sig */
998 1005
999 1006
1000/* Globals */ 1007/* Globals */
1001 1008
1002char *key; /* not used--needed to link crypt.c */ 1009char *key; /* not used--needed to link crypt.c */
1003int pkzip = 0; /* set for a pkzip file */ 1010int pkzip = 0; /* set for a pkzip file */
1004int ext_header = 0; /* set if extended local header */ 1011int ext_header = 0; /* set if extended local header */
1005 1012
1006/* =========================================================================== 1013/* ===========================================================================
1007 * Unzip in to out. This routine works on both gzip and pkzip files. 1014 * Unzip in to out. This routine works on both gzip and pkzip files.
@@ -1011,81 +1018,82 @@ int ext_header = 0; /* set if extended local header */
1011 * The magic header has already been checked. The output buffer is cleared. 1018 * The magic header has already been checked. The output buffer is cleared.
1012 */ 1019 */
1013int unzip(in, out) 1020int unzip(in, out)
1014 int in, out; /* input and output file descriptors */ 1021int in, out; /* input and output file descriptors */
1015{ 1022{
1016 ulg orig_crc = 0; /* original crc */ 1023 ulg orig_crc = 0; /* original crc */
1017 ulg orig_len = 0; /* original uncompressed length */ 1024 ulg orig_len = 0; /* original uncompressed length */
1018 int n; 1025 int n;
1019 uch buf[EXTHDR]; /* extended local header */ 1026 uch buf[EXTHDR]; /* extended local header */
1020 1027
1021 ifd = in; 1028 ifd = in;
1022 ofd = out; 1029 ofd = out;
1023 method = get_method(ifd); 1030 method = get_method(ifd);
1024 if (method < 0) { 1031 if (method < 0) {
1025 do_exit(exit_code); /* error message already emitted */ 1032 do_exit(exit_code); /* error message already emitted */
1026 }
1027
1028 updcrc(NULL, 0); /* initialize crc */
1029
1030 if (pkzip && !ext_header) { /* crc and length at the end otherwise */
1031 orig_crc = LG(inbuf + LOCCRC);
1032 orig_len = LG(inbuf + LOCLEN);
1033 }
1034
1035 /* Decompress */
1036 if (method == DEFLATED) {
1037
1038 int res = inflate();
1039
1040 if (res == 3) {
1041 error("out of memory");
1042 } else if (res != 0) {
1043 error("invalid compressed data--format violated");
1044 } 1033 }
1045 1034
1046 } else { 1035 updcrc(NULL, 0); /* initialize crc */
1047 error("internal error, invalid method"); 1036
1048 } 1037 if (pkzip && !ext_header) { /* crc and length at the end otherwise */
1049 1038 orig_crc = LG(inbuf + LOCCRC);
1050 /* Get the crc and original length */ 1039 orig_len = LG(inbuf + LOCLEN);
1051 if (!pkzip) {
1052 /* crc32 (see algorithm.doc)
1053 * uncompressed input size modulo 2^32
1054 */
1055 for (n = 0; n < 8; n++) {
1056 buf[n] = (uch)get_byte(); /* may cause an error if EOF */
1057 } 1040 }
1058 orig_crc = LG(buf); 1041
1059 orig_len = LG(buf+4); 1042 /* Decompress */
1060 1043 if (method == DEFLATED) {
1061 } else if (ext_header) { /* If extended header, check it */ 1044
1062 /* signature - 4bytes: 0x50 0x4b 0x07 0x08 1045 int res = inflate();
1063 * CRC-32 value 1046
1064 * compressed size 4-bytes 1047 if (res == 3) {
1065 * uncompressed size 4-bytes 1048 error("out of memory");
1066 */ 1049 } else if (res != 0) {
1067 for (n = 0; n < EXTHDR; n++) { 1050 error("invalid compressed data--format violated");
1068 buf[n] = (uch)get_byte(); /* may cause an error if EOF */ 1051 }
1052
1053 } else {
1054 error("internal error, invalid method");
1055 }
1056
1057 /* Get the crc and original length */
1058 if (!pkzip) {
1059 /* crc32 (see algorithm.doc)
1060 * uncompressed input size modulo 2^32
1061 */
1062 for (n = 0; n < 8; n++) {
1063 buf[n] = (uch) get_byte(); /* may cause an error if EOF */
1064 }
1065 orig_crc = LG(buf);
1066 orig_len = LG(buf + 4);
1067
1068 } else if (ext_header) { /* If extended header, check it */
1069 /* signature - 4bytes: 0x50 0x4b 0x07 0x08
1070 * CRC-32 value
1071 * compressed size 4-bytes
1072 * uncompressed size 4-bytes
1073 */
1074 for (n = 0; n < EXTHDR; n++) {
1075 buf[n] = (uch) get_byte(); /* may cause an error if EOF */
1076 }
1077 orig_crc = LG(buf + 4);
1078 orig_len = LG(buf + 12);
1079 }
1080
1081 /* Validate decompression */
1082 if (orig_crc != updcrc(outbuf, 0)) {
1083 error("invalid compressed data--crc error");
1069 } 1084 }
1070 orig_crc = LG(buf+4); 1085 if (orig_len != (ulg) bytes_out) {
1071 orig_len = LG(buf+12); 1086 error("invalid compressed data--length error");
1072 } 1087 }
1073 1088
1074 /* Validate decompression */ 1089 /* Check if there are more entries in a pkzip file */
1075 if (orig_crc != updcrc(outbuf, 0)) { 1090 if (pkzip && inptr + 4 < insize && LG(inbuf + inptr) == LOCSIG) {
1076 error("invalid compressed data--crc error"); 1091 WARN((stderr, "has more than one entry--rest ignored\n"));
1077 } 1092 }
1078 if (orig_len != (ulg)bytes_out) { 1093 ext_header = pkzip = 0; /* for next file */
1079 error("invalid compressed data--length error"); 1094 return OK;
1080 }
1081
1082 /* Check if there are more entries in a pkzip file */
1083 if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
1084 WARN((stderr,"has more than one entry--rest ignored\n"));
1085 }
1086 ext_header = pkzip = 0; /* for next file */
1087 return OK;
1088} 1095}
1096
1089/* util.c -- utility functions for gzip support 1097/* util.c -- utility functions for gzip support
1090 * Copyright (C) 1992-1993 Jean-loup Gailly 1098 * Copyright (C) 1992-1993 Jean-loup Gailly
1091 * This is free software; you can redistribute it and/or modify it under the 1099 * This is free software; you can redistribute it and/or modify it under the
@@ -1106,10 +1114,10 @@ int unzip(in, out)
1106#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 1114#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
1107# include <stdlib.h> 1115# include <stdlib.h>
1108#else 1116#else
1109 extern int errno; 1117extern int errno;
1110#endif 1118#endif
1111 1119
1112static const ulg crc_32_tab[]; /* crc table, defined below */ 1120static const ulg crc_32_tab[]; /* crc table, defined below */
1113 1121
1114/* =========================================================================== 1122/* ===========================================================================
1115 * Run a set of bytes through the crc shift register. If s is a NULL 1123 * Run a set of bytes through the crc shift register. If s is a NULL
@@ -1117,23 +1125,24 @@ static const ulg crc_32_tab[]; /* crc table, defined below */
1117 * Return the current crc in either case. 1125 * Return the current crc in either case.
1118 */ 1126 */
1119ulg updcrc(s, n) 1127ulg updcrc(s, n)
1120 uch *s; /* pointer to bytes to pump through */ 1128uch *s; /* pointer to bytes to pump through */
1121 unsigned n; /* number of bytes in s[] */ 1129unsigned n; /* number of bytes in s[] */
1122{ 1130{
1123 register ulg c; /* temporary variable */ 1131 register ulg c; /* temporary variable */
1124 1132
1125 static ulg crc = (ulg)0xffffffffL; /* shift register contents */ 1133 static ulg crc = (ulg) 0xffffffffL; /* shift register contents */
1126 1134
1127 if (s == NULL) { 1135 if (s == NULL) {
1128 c = 0xffffffffL; 1136 c = 0xffffffffL;
1129 } else { 1137 } else {
1130 c = crc; 1138 c = crc;
1131 if (n) do { 1139 if (n)
1132 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); 1140 do {
1133 } while (--n); 1141 c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8);
1134 } 1142 } while (--n);
1135 crc = c; 1143 }
1136 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ 1144 crc = c;
1145 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
1137} 1146}
1138 1147
1139/* =========================================================================== 1148/* ===========================================================================
@@ -1141,35 +1150,37 @@ ulg updcrc(s, n)
1141 */ 1150 */
1142void clear_bufs() 1151void clear_bufs()
1143{ 1152{
1144 outcnt = 0; 1153 outcnt = 0;
1145 insize = inptr = 0; 1154 insize = inptr = 0;
1146 bytes_in = bytes_out = 0L; 1155 bytes_in = bytes_out = 0L;
1147} 1156}
1148 1157
1149/* =========================================================================== 1158/* ===========================================================================
1150 * Fill the input buffer. This is called only when the buffer is empty. 1159 * Fill the input buffer. This is called only when the buffer is empty.
1151 */ 1160 */
1152int fill_inbuf(eof_ok) 1161int fill_inbuf(eof_ok)
1153 int eof_ok; /* set if EOF acceptable as a result */ 1162int eof_ok; /* set if EOF acceptable as a result */
1154{ 1163{
1155 int len; 1164 int len;
1156 1165
1157 /* Read as much as possible */ 1166 /* Read as much as possible */
1158 insize = 0; 1167 insize = 0;
1159 errno = 0; 1168 errno = 0;
1160 do { 1169 do {
1161 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize); 1170 len = read(ifd, (char *) inbuf + insize, INBUFSIZ - insize);
1162 if (len == 0 || len == EOF) break; 1171 if (len == 0 || len == EOF)
1163 insize += len; 1172 break;
1164 } while (insize < INBUFSIZ); 1173 insize += len;
1165 1174 } while (insize < INBUFSIZ);
1166 if (insize == 0) { 1175
1167 if (eof_ok) return EOF; 1176 if (insize == 0) {
1168 read_error(); 1177 if (eof_ok)
1169 } 1178 return EOF;
1170 bytes_in += (ulg)insize; 1179 read_error();
1171 inptr = 1; 1180 }
1172 return inbuf[0]; 1181 bytes_in += (ulg) insize;
1182 inptr = 1;
1183 return inbuf[0];
1173} 1184}
1174 1185
1175/* =========================================================================== 1186/* ===========================================================================
@@ -1178,12 +1189,13 @@ int fill_inbuf(eof_ok)
1178 */ 1189 */
1179void flush_outbuf() 1190void flush_outbuf()
1180{ 1191{
1181 if (outcnt == 0) return; 1192 if (outcnt == 0)
1193 return;
1182 1194
1183 if (!test_mode) 1195 if (!test_mode)
1184 write_buf(ofd, (char *)outbuf, outcnt); 1196 write_buf(ofd, (char *) outbuf, outcnt);
1185 bytes_out += (ulg)outcnt; 1197 bytes_out += (ulg) outcnt;
1186 outcnt = 0; 1198 outcnt = 0;
1187} 1199}
1188 1200
1189/* =========================================================================== 1201/* ===========================================================================
@@ -1192,13 +1204,14 @@ void flush_outbuf()
1192 */ 1204 */
1193void flush_window() 1205void flush_window()
1194{ 1206{
1195 if (outcnt == 0) return; 1207 if (outcnt == 0)
1196 updcrc(window, outcnt); 1208 return;
1197 1209 updcrc(window, outcnt);
1198 if (!test_mode) 1210
1199 write_buf(ofd, (char *)window, outcnt); 1211 if (!test_mode)
1200 bytes_out += (ulg)outcnt; 1212 write_buf(ofd, (char *) window, outcnt);
1201 outcnt = 0; 1213 bytes_out += (ulg) outcnt;
1214 outcnt = 0;
1202} 1215}
1203 1216
1204/* =========================================================================== 1217/* ===========================================================================
@@ -1206,19 +1219,19 @@ void flush_window()
1206 * for error return. 1219 * for error return.
1207 */ 1220 */
1208void write_buf(fd, buf, cnt) 1221void write_buf(fd, buf, cnt)
1209 int fd; 1222int fd;
1210 voidp buf; 1223voidp buf;
1211 unsigned cnt; 1224unsigned cnt;
1212{ 1225{
1213 unsigned n; 1226 unsigned n;
1214 1227
1215 while ((n = write(fd, buf, cnt)) != cnt) { 1228 while ((n = write(fd, buf, cnt)) != cnt) {
1216 if (n == (unsigned)(-1)) { 1229 if (n == (unsigned) (-1)) {
1217 write_error(); 1230 write_error();
1231 }
1232 cnt -= n;
1233 buf = (voidp) ((char *) buf + n);
1218 } 1234 }
1219 cnt -= n;
1220 buf = (voidp)((char*)buf+n);
1221 }
1222} 1235}
1223 1236
1224#if defined(NO_STRING_H) && !defined(STDC_HEADERS) 1237#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
@@ -1229,7 +1242,7 @@ void write_buf(fd, buf, cnt)
1229# define const 1242# define const
1230# endif 1243# endif
1231 1244
1232int strspn OF((const char *s, const char *accept)); 1245int strspn OF((const char *s, const char *accept));
1233int strcspn OF((const char *s, const char *reject)); 1246int strcspn OF((const char *s, const char *reject));
1234 1247
1235/* ======================================================================== 1248/* ========================================================================
@@ -1237,21 +1250,23 @@ int strcspn OF((const char *s, const char *reject));
1237 * of s which contains only characters in accept. 1250 * of s which contains only characters in accept.
1238 */ 1251 */
1239int strspn(s, accept) 1252int strspn(s, accept)
1240 const char *s; 1253const char *s;
1241 const char *accept; 1254const char *accept;
1242{ 1255{
1243 register const char *p; 1256 register const char *p;
1244 register const char *a; 1257 register const char *a;
1245 register int count = 0; 1258 register int count = 0;
1246 1259
1247 for (p = s; *p != '\0'; ++p) { 1260 for (p = s; *p != '\0'; ++p) {
1248 for (a = accept; *a != '\0'; ++a) { 1261 for (a = accept; *a != '\0'; ++a) {
1249 if (*p == *a) break; 1262 if (*p == *a)
1263 break;
1264 }
1265 if (*a == '\0')
1266 return count;
1267 ++count;
1250 } 1268 }
1251 if (*a == '\0') return count; 1269 return count;
1252 ++count;
1253 }
1254 return count;
1255} 1270}
1256 1271
1257/* ======================================================================== 1272/* ========================================================================
@@ -1259,46 +1274,47 @@ int strspn(s, accept)
1259 * which contains no characters from reject. 1274 * which contains no characters from reject.
1260 */ 1275 */
1261int strcspn(s, reject) 1276int strcspn(s, reject)
1262 const char *s; 1277const char *s;
1263 const char *reject; 1278const char *reject;
1264{ 1279{
1265 register int count = 0; 1280 register int count = 0;
1266 1281
1267 while (*s != '\0') { 1282 while (*s != '\0') {
1268 if (strchr(reject, *s++) != NULL) return count; 1283 if (strchr(reject, *s++) != NULL)
1269 ++count; 1284 return count;
1270 } 1285 ++count;
1271 return count; 1286 }
1287 return count;
1272} 1288}
1273 1289
1274#endif /* NO_STRING_H */ 1290#endif /* NO_STRING_H */
1275 1291
1276 1292
1277/* ======================================================================== 1293/* ========================================================================
1278 * Error handlers. 1294 * Error handlers.
1279 */ 1295 */
1280void warn(a, b) 1296void warn(a, b)
1281 char *a, *b; /* message strings juxtaposed in output */ 1297char *a, *b; /* message strings juxtaposed in output */
1282{ 1298{
1283 WARN((stderr, "warning: %s%s\n", a, b)); 1299 WARN((stderr, "warning: %s%s\n", a, b));
1284} 1300}
1285 1301
1286void read_error() 1302void read_error()
1287{ 1303{
1288 fprintf(stderr, "\n"); 1304 fprintf(stderr, "\n");
1289 if (errno != 0) { 1305 if (errno != 0) {
1290 perror(""); 1306 perror("");
1291 } else { 1307 } else {
1292 fprintf(stderr, "unexpected end of file\n"); 1308 fprintf(stderr, "unexpected end of file\n");
1293 } 1309 }
1294 abort_gzip(); 1310 abort_gzip();
1295} 1311}
1296 1312
1297void write_error() 1313void write_error()
1298{ 1314{
1299 fprintf(stderr, "\n"); 1315 fprintf(stderr, "\n");
1300 perror(""); 1316 perror("");
1301 abort_gzip(); 1317 abort_gzip();
1302} 1318}
1303 1319
1304 1320
@@ -1306,59 +1322,60 @@ void write_error()
1306 * Table of CRC-32's of all single-byte values (made by makecrc.c) 1322 * Table of CRC-32's of all single-byte values (made by makecrc.c)
1307 */ 1323 */
1308static const ulg crc_32_tab[] = { 1324static const ulg crc_32_tab[] = {
1309 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 1325 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
1310 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 1326 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
1311 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 1327 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
1312 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 1328 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
1313 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 1329 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
1314 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 1330 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
1315 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 1331 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
1316 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 1332 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
1317 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 1333 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
1318 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 1334 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
1319 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 1335 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
1320 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 1336 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
1321 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 1337 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
1322 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 1338 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
1323 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 1339 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
1324 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 1340 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
1325 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 1341 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
1326 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 1342 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
1327 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 1343 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
1328 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 1344 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
1329 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 1345 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
1330 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 1346 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
1331 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 1347 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
1332 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 1348 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
1333 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 1349 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
1334 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 1350 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
1335 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 1351 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
1336 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 1352 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
1337 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 1353 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
1338 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 1354 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
1339 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 1355 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
1340 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 1356 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
1341 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 1357 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
1342 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 1358 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
1343 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 1359 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
1344 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 1360 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
1345 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 1361 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
1346 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 1362 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
1347 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 1363 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
1348 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 1364 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
1349 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 1365 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
1350 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 1366 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
1351 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 1367 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
1352 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 1368 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
1353 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 1369 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
1354 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 1370 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
1355 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 1371 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
1356 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 1372 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
1357 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 1373 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
1358 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 1374 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
1359 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 1375 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
1360 0x2d02ef8dL 1376 0x2d02ef8dL
1361}; 1377};
1378
1362/* inflate.c -- Not copyrighted 1992 by Mark Adler 1379/* inflate.c -- Not copyrighted 1992 by Mark Adler
1363 version c10p1, 10 January 1993 */ 1380 version c10p1, 10 January 1993 */
1364 1381
@@ -1474,18 +1491,18 @@ static const ulg crc_32_tab[] = {
1474 an unused code. If a code with e == 99 is looked up, this implies an 1491 an unused code. If a code with e == 99 is looked up, this implies an
1475 error in the data. */ 1492 error in the data. */
1476struct huft { 1493struct huft {
1477 uch e; /* number of extra bits or operation */ 1494 uch e; /* number of extra bits or operation */
1478 uch b; /* number of bits in this code or subcode */ 1495 uch b; /* number of bits in this code or subcode */
1479 union { 1496 union {
1480 ush n; /* literal, length base, or distance base */ 1497 ush n; /* literal, length base, or distance base */
1481 struct huft *t; /* pointer to next level of table */ 1498 struct huft *t; /* pointer to next level of table */
1482 } v; 1499 } v;
1483}; 1500};
1484 1501
1485 1502
1486/* Function prototypes */ 1503/* Function prototypes */
1487int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *, 1504int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
1488 struct huft **, int *)); 1505 struct huft **, int *));
1489int huft_free OF((struct huft *)); 1506int huft_free OF((struct huft *));
1490int inflate_codes OF((struct huft *, struct huft *, int, int)); 1507int inflate_codes OF((struct huft *, struct huft *, int, int));
1491int inflate_stored OF((void)); 1508int inflate_stored OF((void));
@@ -1508,23 +1525,29 @@ int inflate OF((void));
1508#define flush_output(w) (wp=(w),flush_window()) 1525#define flush_output(w) (wp=(w),flush_window())
1509 1526
1510/* Tables for deflate from PKZIP's appnote.txt. */ 1527/* Tables for deflate from PKZIP's appnote.txt. */
1511static unsigned border[] = { /* Order of the bit length code lengths */ 1528static unsigned border[] = { /* Order of the bit length code lengths */
1512 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 1529 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
1513static ush cplens[] = { /* Copy lengths for literal codes 257..285 */ 1530};
1514 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 1531static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
1515 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 1532 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
1516 /* note: see note #13 above about the 258 in this list. */ 1533 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
1517static ush cplext[] = { /* Extra bits for literal codes 257..285 */ 1534};
1518 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 1535
1519 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ 1536 /* note: see note #13 above about the 258 in this list. */
1520static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ 1537static ush cplext[] = { /* Extra bits for literal codes 257..285 */
1521 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1538 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
1522 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 1539 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
1523 8193, 12289, 16385, 24577}; 1540}; /* 99==invalid */
1524static ush cpdext[] = { /* Extra bits for distance codes */ 1541static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
1525 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 1542 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
1526 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 1543 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
1527 12, 12, 13, 13}; 1544 8193, 12289, 16385, 24577
1545};
1546static ush cpdext[] = { /* Extra bits for distance codes */
1547 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
1548 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
1549 12, 12, 13, 13
1550};
1528 1551
1529 1552
1530 1553
@@ -1558,17 +1581,18 @@ static ush cpdext[] = { /* Extra bits for distance codes */
1558 the stream. 1581 the stream.
1559 */ 1582 */
1560 1583
1561ulg bb; /* bit buffer */ 1584ulg bb; /* bit buffer */
1562unsigned bk; /* bits in bit buffer */ 1585unsigned bk; /* bits in bit buffer */
1563 1586
1564ush mask_bits[] = { 1587ush mask_bits[] = {
1565 0x0000, 1588 0x0000,
1566 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 1589 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
1567 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 1590 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
1568}; 1591};
1569 1592
1570#ifdef CRYPT 1593#ifdef CRYPT
1571 uch cc; 1594uch cc;
1595
1572# define NEXTBYTE() (cc = get_byte(), zdecode(cc), cc) 1596# define NEXTBYTE() (cc = get_byte(), zdecode(cc), cc)
1573#else 1597#else
1574# define NEXTBYTE() (uch)get_byte() 1598# define NEXTBYTE() (uch)get_byte()
@@ -1610,342 +1634,342 @@ ush mask_bits[] = {
1610 */ 1634 */
1611 1635
1612 1636
1613int lbits = 9; /* bits in base literal/length lookup table */ 1637int lbits = 9; /* bits in base literal/length lookup table */
1614int dbits = 6; /* bits in base distance lookup table */ 1638int dbits = 6; /* bits in base distance lookup table */
1615 1639
1616 1640
1617/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ 1641/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
1618#define BMAX 16 /* maximum bit length of any code (16 for explode) */ 1642#define BMAX 16 /* maximum bit length of any code (16 for explode) */
1619#define N_MAX 288 /* maximum number of codes in any set */ 1643#define N_MAX 288 /* maximum number of codes in any set */
1620 1644
1621 1645
1622unsigned hufts; /* track memory usage */ 1646unsigned hufts; /* track memory usage */
1623 1647
1624 1648
1625int huft_build(b, n, s, d, e, t, m) 1649int huft_build(b, n, s, d, e, t, m)
1626unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ 1650unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
1627unsigned n; /* number of codes (assumed <= N_MAX) */ 1651unsigned n; /* number of codes (assumed <= N_MAX) */
1628unsigned s; /* number of simple-valued codes (0..s-1) */ 1652unsigned s; /* number of simple-valued codes (0..s-1) */
1629ush *d; /* list of base values for non-simple codes */ 1653ush *d; /* list of base values for non-simple codes */
1630ush *e; /* list of extra bits for non-simple codes */ 1654ush *e; /* list of extra bits for non-simple codes */
1631struct huft **t; /* result: starting table */ 1655struct huft **t; /* result: starting table */
1632int *m; /* maximum lookup bits, returns actual */ 1656int *m; /* maximum lookup bits, returns actual */
1657
1633/* Given a list of code lengths and a maximum table size, make a set of 1658/* Given a list of code lengths and a maximum table size, make a set of
1634 tables to decode that set of codes. Return zero on success, one if 1659 tables to decode that set of codes. Return zero on success, one if
1635 the given code set is incomplete (the tables are still built in this 1660 the given code set is incomplete (the tables are still built in this
1636 case), two if the input is invalid (all zero length codes or an 1661 case), two if the input is invalid (all zero length codes or an
1637 oversubscribed set of lengths), and three if not enough memory. */ 1662 oversubscribed set of lengths), and three if not enough memory. */
1638{ 1663{
1639 unsigned a; /* counter for codes of length k */ 1664 unsigned a; /* counter for codes of length k */
1640 unsigned c[BMAX+1]; /* bit length count table */ 1665 unsigned c[BMAX + 1]; /* bit length count table */
1641 unsigned f; /* i repeats in table every f entries */ 1666 unsigned f; /* i repeats in table every f entries */
1642 int g; /* maximum code length */ 1667 int g; /* maximum code length */
1643 int h; /* table level */ 1668 int h; /* table level */
1644 register unsigned i; /* counter, current code */ 1669 register unsigned i; /* counter, current code */
1645 register unsigned j; /* counter */ 1670 register unsigned j; /* counter */
1646 register int k; /* number of bits in current code */ 1671 register int k; /* number of bits in current code */
1647 int l; /* bits per table (returned in m) */ 1672 int l; /* bits per table (returned in m) */
1648 register unsigned *p; /* pointer into c[], b[], or v[] */ 1673 register unsigned *p; /* pointer into c[], b[], or v[] */
1649 register struct huft *q; /* points to current table */ 1674 register struct huft *q; /* points to current table */
1650 struct huft r; /* table entry for structure assignment */ 1675 struct huft r; /* table entry for structure assignment */
1651 struct huft *u[BMAX]; /* table stack */ 1676 struct huft *u[BMAX]; /* table stack */
1652 unsigned v[N_MAX]; /* values in order of bit length */ 1677 unsigned v[N_MAX]; /* values in order of bit length */
1653 register int w; /* bits before this table == (l * h) */ 1678 register int w; /* bits before this table == (l * h) */
1654 unsigned x[BMAX+1]; /* bit offsets, then code stack */ 1679 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
1655 unsigned *xp; /* pointer into x */ 1680 unsigned *xp; /* pointer into x */
1656 int y; /* number of dummy codes added */ 1681 int y; /* number of dummy codes added */
1657 unsigned z; /* number of entries in current table */ 1682 unsigned z; /* number of entries in current table */
1658 1683
1659 1684
1660 /* Generate counts for each bit length */ 1685 /* Generate counts for each bit length */
1661 memzero(c, sizeof(c)); 1686 memzero(c, sizeof(c));
1662 p = b; i = n; 1687 p = b;
1663 do { 1688 i = n;
1664 Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 1689 do {
1665 n-i, *p)); 1690 Tracecv(*p,
1666 c[*p]++; /* assume all entries <= BMAX */ 1691 (stderr,
1667 p++; /* Can't combine with above line (Solaris bug) */ 1692 (n - i >= ' '
1668 } while (--i); 1693 && n - i <= '~' ? "%c %d\n" : "0x%x %d\n"), n - i, *p));
1669 if (c[0] == n) /* null input--all zero length codes */ 1694 c[*p]++; /* assume all entries <= BMAX */
1670 { 1695 p++; /* Can't combine with above line (Solaris bug) */
1671 *t = (struct huft *)NULL; 1696 } while (--i);
1672 *m = 0; 1697 if (c[0] == n) { /* null input--all zero length codes */
1673 return 0; 1698 *t = (struct huft *) NULL;
1674 } 1699 *m = 0;
1675 1700 return 0;
1676 1701 }
1677 /* Find minimum and maximum length, bound *m by those */ 1702
1678 l = *m; 1703
1679 for (j = 1; j <= BMAX; j++) 1704 /* Find minimum and maximum length, bound *m by those */
1680 if (c[j]) 1705 l = *m;
1681 break; 1706 for (j = 1; j <= BMAX; j++)
1682 k = j; /* minimum code length */ 1707 if (c[j])
1683 if ((unsigned)l < j) 1708 break;
1684 l = j; 1709 k = j; /* minimum code length */
1685 for (i = BMAX; i; i--) 1710 if ((unsigned) l < j)
1686 if (c[i]) 1711 l = j;
1687 break; 1712 for (i = BMAX; i; i--)
1688 g = i; /* maximum code length */ 1713 if (c[i])
1689 if ((unsigned)l > i) 1714 break;
1690 l = i; 1715 g = i; /* maximum code length */
1691 *m = l; 1716 if ((unsigned) l > i)
1692 1717 l = i;
1693 1718 *m = l;
1694 /* Adjust last length count to fill out codes, if needed */ 1719
1695 for (y = 1 << j; j < i; j++, y <<= 1) 1720
1696 if ((y -= c[j]) < 0) 1721 /* Adjust last length count to fill out codes, if needed */
1697 return 2; /* bad input: more codes than bits */ 1722 for (y = 1 << j; j < i; j++, y <<= 1)
1698 if ((y -= c[i]) < 0) 1723 if ((y -= c[j]) < 0)
1699 return 2; 1724 return 2; /* bad input: more codes than bits */
1700 c[i] += y; 1725 if ((y -= c[i]) < 0)
1701 1726 return 2;
1702 1727 c[i] += y;
1703 /* Generate starting offsets into the value table for each length */ 1728
1704 x[1] = j = 0; 1729
1705 p = c + 1; xp = x + 2; 1730 /* Generate starting offsets into the value table for each length */
1706 while (--i) { /* note that i == g from above */ 1731 x[1] = j = 0;
1707 *xp++ = (j += *p++); 1732 p = c + 1;
1708 } 1733 xp = x + 2;
1709 1734 while (--i) { /* note that i == g from above */
1710 1735 *xp++ = (j += *p++);
1711 /* Make a table of values in order of bit lengths */ 1736 }
1712 p = b; i = 0; 1737
1713 do { 1738
1714 if ((j = *p++) != 0) 1739 /* Make a table of values in order of bit lengths */
1715 v[x[j]++] = i; 1740 p = b;
1716 } while (++i < n); 1741 i = 0;
1717 1742 do {
1718 1743 if ((j = *p++) != 0)
1719 /* Generate the Huffman codes and for each, make the table entries */ 1744 v[x[j]++] = i;
1720 x[0] = i = 0; /* first Huffman code is zero */ 1745 } while (++i < n);
1721 p = v; /* grab values in bit order */ 1746
1722 h = -1; /* no tables yet--level -1 */ 1747
1723 w = -l; /* bits decoded == (l * h) */ 1748 /* Generate the Huffman codes and for each, make the table entries */
1724 u[0] = (struct huft *)NULL; /* just to keep compilers happy */ 1749 x[0] = i = 0; /* first Huffman code is zero */
1725 q = (struct huft *)NULL; /* ditto */ 1750 p = v; /* grab values in bit order */
1726 z = 0; /* ditto */ 1751 h = -1; /* no tables yet--level -1 */
1727 1752 w = -l; /* bits decoded == (l * h) */
1728 /* go through the bit lengths (k already is bits in shortest code) */ 1753 u[0] = (struct huft *) NULL; /* just to keep compilers happy */
1729 for (; k <= g; k++) 1754 q = (struct huft *) NULL; /* ditto */
1730 { 1755 z = 0; /* ditto */
1731 a = c[k]; 1756
1732 while (a--) 1757 /* go through the bit lengths (k already is bits in shortest code) */
1733 { 1758 for (; k <= g; k++) {
1734 /* here i is the Huffman code of length k bits for value *p */ 1759 a = c[k];
1735 /* make tables up to required level */ 1760 while (a--) {
1736 while (k > w + l) 1761 /* here i is the Huffman code of length k bits for value *p */
1737 { 1762 /* make tables up to required level */
1738 h++; 1763 while (k > w + l) {
1739 w += l; /* previous table always l bits */ 1764 h++;
1740 1765 w += l; /* previous table always l bits */
1741 /* compute minimum size table less than or equal to l bits */ 1766
1742 z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ 1767 /* compute minimum size table less than or equal to l bits */
1743 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ 1768 z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */
1744 { /* too few codes for k-w bit table */ 1769 if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table *//* too few codes for k-w bit table */
1745 f -= a + 1; /* deduct codes from patterns left */ 1770 f -= a + 1; /* deduct codes from patterns left */
1746 xp = c + k; 1771 xp = c + k;
1747 while (++j < z) /* try smaller tables up to z bits */ 1772 while (++j < z) { /* try smaller tables up to z bits */
1748 { 1773 if ((f <<= 1) <= *++xp)
1749 if ((f <<= 1) <= *++xp) 1774 break; /* enough codes to use up j bits */
1750 break; /* enough codes to use up j bits */ 1775 f -= *xp; /* else deduct codes from patterns */
1751 f -= *xp; /* else deduct codes from patterns */ 1776 }
1752 } 1777 }
1753 } 1778 z = 1 << j; /* table entries for j-bit table */
1754 z = 1 << j; /* table entries for j-bit table */ 1779
1755 1780 /* allocate and link in new table */
1756 /* allocate and link in new table */ 1781 if (
1757 if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == 1782 (q =
1758 (struct huft *)NULL) 1783 (struct huft *) malloc((z + 1) *
1759 { 1784 sizeof(struct huft))) ==
1760 if (h) 1785 (struct huft *) NULL) {
1761 huft_free(u[0]); 1786 if (h)
1762 return 3; /* not enough memory */ 1787 huft_free(u[0]);
1763 } 1788 return 3; /* not enough memory */
1764 hufts += z + 1; /* track memory usage */ 1789 }
1765 *t = q + 1; /* link to list for huft_free() */ 1790 hufts += z + 1; /* track memory usage */
1766 *(t = &(q->v.t)) = (struct huft *)NULL; 1791 *t = q + 1; /* link to list for huft_free() */
1767 u[h] = ++q; /* table starts after link */ 1792 *(t = &(q->v.t)) = (struct huft *) NULL;
1768 1793 u[h] = ++q; /* table starts after link */
1769 /* connect to last table, if there is one */ 1794
1770 if (h) 1795 /* connect to last table, if there is one */
1771 { 1796 if (h) {
1772 x[h] = i; /* save pattern for backing up */ 1797 x[h] = i; /* save pattern for backing up */
1773 r.b = (uch)l; /* bits to dump before this table */ 1798 r.b = (uch) l; /* bits to dump before this table */
1774 r.e = (uch)(16 + j); /* bits in this table */ 1799 r.e = (uch) (16 + j); /* bits in this table */
1775 r.v.t = q; /* pointer to this table */ 1800 r.v.t = q; /* pointer to this table */
1776 j = i >> (w - l); /* (get around Turbo C bug) */ 1801 j = i >> (w - l); /* (get around Turbo C bug) */
1777 u[h-1][j] = r; /* connect to last table */ 1802 u[h - 1][j] = r; /* connect to last table */
1778 } 1803 }
1779 } 1804 }
1780 1805
1781 /* set up table entry in r */ 1806 /* set up table entry in r */
1782 r.b = (uch)(k - w); 1807 r.b = (uch) (k - w);
1783 if (p >= v + n) 1808 if (p >= v + n)
1784 r.e = 99; /* out of values--invalid code */ 1809 r.e = 99; /* out of values--invalid code */
1785 else if (*p < s) 1810 else if (*p < s) {
1786 { 1811 r.e = (uch) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1787 r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ 1812 r.v.n = (ush) (*p); /* simple code is just the value */
1788 r.v.n = (ush)(*p); /* simple code is just the value */ 1813 p++; /* one compiler does not like *p++ */
1789 p++; /* one compiler does not like *p++ */ 1814 } else {
1790 } 1815 r.e = (uch) e[*p - s]; /* non-simple--look up in lists */
1791 else 1816 r.v.n = d[*p++ - s];
1792 { 1817 }
1793 r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ 1818
1794 r.v.n = d[*p++ - s]; 1819 /* fill code-like entries with r */
1795 } 1820 f = 1 << (k - w);
1796 1821 for (j = i >> w; j < z; j += f)
1797 /* fill code-like entries with r */ 1822 q[j] = r;
1798 f = 1 << (k - w); 1823
1799 for (j = i >> w; j < z; j += f) 1824 /* backwards increment the k-bit code i */
1800 q[j] = r; 1825 for (j = 1 << (k - 1); i & j; j >>= 1)
1801 1826 i ^= j;
1802 /* backwards increment the k-bit code i */ 1827 i ^= j;
1803 for (j = 1 << (k - 1); i & j; j >>= 1) 1828
1804 i ^= j; 1829 /* backup over finished tables */
1805 i ^= j; 1830 while ((i & ((1 << w) - 1)) != x[h]) {
1806 1831 h--; /* don't need to update q */
1807 /* backup over finished tables */ 1832 w -= l;
1808 while ((i & ((1 << w) - 1)) != x[h]) 1833 }
1809 { 1834 }
1810 h--; /* don't need to update q */ 1835 }
1811 w -= l; 1836
1812 } 1837
1813 } 1838 /* Return true (1) if we were given an incomplete table */
1814 } 1839 return y != 0 && g != 1;
1815
1816
1817 /* Return true (1) if we were given an incomplete table */
1818 return y != 0 && g != 1;
1819} 1840}
1820 1841
1821 1842
1822 1843
1823int huft_free(t) 1844int huft_free(t)
1824struct huft *t; /* table to free */ 1845struct huft *t; /* table to free */
1846
1825/* Free the malloc'ed tables built by huft_build(), which makes a linked 1847/* Free the malloc'ed tables built by huft_build(), which makes a linked
1826 list of the tables it made, with the links in a dummy first entry of 1848 list of the tables it made, with the links in a dummy first entry of
1827 each table. */ 1849 each table. */
1828{ 1850{
1829 register struct huft *p, *q; 1851 register struct huft *p, *q;
1830 1852
1831 1853
1832 /* Go through linked list, freeing from the malloced (t[-1]) address. */ 1854 /* Go through linked list, freeing from the malloced (t[-1]) address. */
1833 p = t; 1855 p = t;
1834 while (p != (struct huft *)NULL) 1856 while (p != (struct huft *) NULL) {
1835 { 1857 q = (--p)->v.t;
1836 q = (--p)->v.t; 1858 free((char *) p);
1837 free((char*)p); 1859 p = q;
1838 p = q; 1860 }
1839 } 1861 return 0;
1840 return 0;
1841} 1862}
1842 1863
1843 1864
1844int inflate_codes(tl, td, bl, bd) 1865int inflate_codes(tl, td, bl, bd)
1845struct huft *tl, *td; /* literal/length and distance decoder tables */ 1866struct huft *tl, *td; /* literal/length and distance decoder tables */
1846int bl, bd; /* number of bits decoded by tl[] and td[] */ 1867int bl, bd; /* number of bits decoded by tl[] and td[] */
1868
1847/* inflate (decompress) the codes in a deflated (compressed) block. 1869/* inflate (decompress) the codes in a deflated (compressed) block.
1848 Return an error code or zero if it all goes ok. */ 1870 Return an error code or zero if it all goes ok. */
1849{ 1871{
1850 register unsigned e; /* table entry flag/number of extra bits */ 1872 register unsigned e; /* table entry flag/number of extra bits */
1851 unsigned n, d; /* length and index for copy */ 1873 unsigned n, d; /* length and index for copy */
1852 unsigned w; /* current window position */ 1874 unsigned w; /* current window position */
1853 struct huft *t; /* pointer to table entry */ 1875 struct huft *t; /* pointer to table entry */
1854 unsigned ml, md; /* masks for bl and bd bits */ 1876 unsigned ml, md; /* masks for bl and bd bits */
1855 register ulg b; /* bit buffer */ 1877 register ulg b; /* bit buffer */
1856 register unsigned k; /* number of bits in bit buffer */ 1878 register unsigned k; /* number of bits in bit buffer */
1857 1879
1858 1880
1859 /* make local copies of globals */ 1881 /* make local copies of globals */
1860 b = bb; /* initialize bit buffer */ 1882 b = bb; /* initialize bit buffer */
1861 k = bk; 1883 k = bk;
1862 w = wp; /* initialize window position */ 1884 w = wp; /* initialize window position */
1863 1885
1864 /* inflate the coded data */ 1886 /* inflate the coded data */
1865 ml = mask_bits[bl]; /* precompute masks for speed */ 1887 ml = mask_bits[bl]; /* precompute masks for speed */
1866 md = mask_bits[bd]; 1888 md = mask_bits[bd];
1867 for (;;) /* do until end of block */ 1889 for (;;) { /* do until end of block */
1868 { 1890 NEEDBITS((unsigned) bl)
1869 NEEDBITS((unsigned)bl) 1891 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
1870 if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) 1892 do {
1871 do { 1893 if (e == 99)
1872 if (e == 99) 1894 return 1;
1873 return 1; 1895 DUMPBITS(t->b)
1874 DUMPBITS(t->b) 1896 e -= 16;
1875 e -= 16; 1897 NEEDBITS(e)
1876 NEEDBITS(e) 1898 } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
1877 } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); 1899 > 16);
1878 DUMPBITS(t->b) 1900 DUMPBITS(t->b)
1879 if (e == 16) /* then it's a literal */ 1901 if (e == 16) { /* then it's a literal */
1880 { 1902 slide[w++] = (uch) t->v.n;
1881 slide[w++] = (uch)t->v.n; 1903 Tracevv((stderr, "%c", slide[w - 1]));
1882 Tracevv((stderr, "%c", slide[w-1])); 1904 if (w == WSIZE) {
1883 if (w == WSIZE) 1905 flush_output(w);
1884 { 1906 w = 0;
1885 flush_output(w); 1907 }
1886 w = 0; 1908 } else { /* it's an EOB or a length */
1887 } 1909
1888 } 1910 /* exit if end of block */
1889 else /* it's an EOB or a length */ 1911 if (e == 15)
1890 { 1912 break;
1891 /* exit if end of block */ 1913
1892 if (e == 15) 1914 /* get length of block to copy */
1893 break; 1915 NEEDBITS(e)
1894 1916 n = t->v.n + ((unsigned) b & mask_bits[e]);
1895 /* get length of block to copy */ 1917 DUMPBITS(e);
1896 NEEDBITS(e) 1918
1897 n = t->v.n + ((unsigned)b & mask_bits[e]); 1919 /* decode distance of block to copy */
1898 DUMPBITS(e); 1920 NEEDBITS((unsigned) bd)
1899 1921 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
1900 /* decode distance of block to copy */ 1922 do {
1901 NEEDBITS((unsigned)bd) 1923 if (e == 99)
1902 if ((e = (t = td + ((unsigned)b & md))->e) > 16) 1924 return 1;
1903 do { 1925 DUMPBITS(t->b)
1904 if (e == 99) 1926 e -= 16;
1905 return 1; 1927 NEEDBITS(e)
1906 DUMPBITS(t->b) 1928 }
1907 e -= 16; 1929 while (
1908 NEEDBITS(e) 1930 (e =
1909 } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); 1931 (t =
1910 DUMPBITS(t->b) 1932 t->v.t + ((unsigned) b & mask_bits[e]))->e) >
1911 NEEDBITS(e) 1933 16);
1912 d = w - t->v.n - ((unsigned)b & mask_bits[e]); 1934 DUMPBITS(t->b)
1913 DUMPBITS(e) 1935 NEEDBITS(e)
1914 Tracevv((stderr,"\\[%d,%d]", w-d, n)); 1936 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
1915 1937 DUMPBITS(e)
1916 /* do the copy */ 1938 Tracevv((stderr, "\\[%d,%d]", w - d, n));
1917 do { 1939
1918 n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); 1940 /* do the copy */
1941 do {
1942 n -= (e =
1943 (e =
1944 WSIZE - ((d &= WSIZE - 1) > w ? d : w)) >
1945 n ? n : e);
1919#if !defined(NOMEMCPY) && !defined(DEBUG) 1946#if !defined(NOMEMCPY) && !defined(DEBUG)
1920 if (w - d >= e) /* (this test assumes unsigned comparison) */ 1947 if (w - d >= e) { /* (this test assumes unsigned comparison) */
1921 { 1948 memcpy(slide + w, slide + d, e);
1922 memcpy(slide + w, slide + d, e); 1949 w += e;
1923 w += e; 1950 d += e;
1924 d += e; 1951 } else /* do it slow to avoid memcpy() overlap */
1925 } 1952#endif /* !NOMEMCPY */
1926 else /* do it slow to avoid memcpy() overlap */ 1953 do {
1927#endif /* !NOMEMCPY */ 1954 slide[w++] = slide[d++];
1928 do { 1955 Tracevv((stderr, "%c", slide[w - 1]));
1929 slide[w++] = slide[d++]; 1956 } while (--e);
1930 Tracevv((stderr, "%c", slide[w-1])); 1957 if (w == WSIZE) {
1931 } while (--e); 1958 flush_output(w);
1932 if (w == WSIZE) 1959 w = 0;
1933 { 1960 }
1934 flush_output(w); 1961 } while (n);
1935 w = 0; 1962 }
1936 } 1963 }
1937 } while (n); 1964
1938 } 1965
1939 } 1966 /* restore the globals from the locals */
1940 1967 wp = w; /* restore global window pointer */
1941 1968 bb = b; /* restore global bit buffer */
1942 /* restore the globals from the locals */ 1969 bk = k;
1943 wp = w; /* restore global window pointer */ 1970
1944 bb = b; /* restore global bit buffer */ 1971 /* done */
1945 bk = k; 1972 return 0;
1946
1947 /* done */
1948 return 0;
1949} 1973}
1950 1974
1951 1975
@@ -1953,52 +1977,50 @@ int bl, bd; /* number of bits decoded by tl[] and td[] */
1953int inflate_stored() 1977int inflate_stored()
1954/* "decompress" an inflated type 0 (stored) block. */ 1978/* "decompress" an inflated type 0 (stored) block. */
1955{ 1979{
1956 unsigned n; /* number of bytes in block */ 1980 unsigned n; /* number of bytes in block */
1957 unsigned w; /* current window position */ 1981 unsigned w; /* current window position */
1958 register ulg b; /* bit buffer */ 1982 register ulg b; /* bit buffer */
1959 register unsigned k; /* number of bits in bit buffer */ 1983 register unsigned k; /* number of bits in bit buffer */
1960 1984
1961 1985
1962 /* make local copies of globals */ 1986 /* make local copies of globals */
1963 b = bb; /* initialize bit buffer */ 1987 b = bb; /* initialize bit buffer */
1964 k = bk; 1988 k = bk;
1965 w = wp; /* initialize window position */ 1989 w = wp; /* initialize window position */
1966 1990
1967 1991
1968 /* go to byte boundary */ 1992 /* go to byte boundary */
1969 n = k & 7; 1993 n = k & 7;
1970 DUMPBITS(n); 1994 DUMPBITS(n);
1971 1995
1972 1996
1973 /* get the length and its complement */ 1997 /* get the length and its complement */
1974 NEEDBITS(16) 1998 NEEDBITS(16)
1975 n = ((unsigned)b & 0xffff); 1999 n = ((unsigned) b & 0xffff);
1976 DUMPBITS(16) 2000 DUMPBITS(16)
1977 NEEDBITS(16) 2001 NEEDBITS(16)
1978 if (n != (unsigned)((~b) & 0xffff)) 2002 if (n != (unsigned) ((~b) & 0xffff))
1979 return 1; /* error in compressed data */ 2003 return 1; /* error in compressed data */
1980 DUMPBITS(16) 2004 DUMPBITS(16)
1981 2005
1982 2006
1983 /* read and output the compressed data */ 2007 /* read and output the compressed data */
1984 while (n--) 2008 while (n--) {
1985 { 2009 NEEDBITS(8)
1986 NEEDBITS(8) 2010 slide[w++] = (uch) b;
1987 slide[w++] = (uch)b; 2011 if (w == WSIZE) {
1988 if (w == WSIZE) 2012 flush_output(w);
1989 { 2013 w = 0;
1990 flush_output(w); 2014 }
1991 w = 0; 2015 DUMPBITS(8)
1992 } 2016 }
1993 DUMPBITS(8) 2017
1994 } 2018
1995 2019 /* restore the globals from the locals */
1996 2020 wp = w; /* restore global window pointer */
1997 /* restore the globals from the locals */ 2021 bb = b; /* restore global bit buffer */
1998 wp = w; /* restore global window pointer */ 2022 bk = k;
1999 bb = b; /* restore global bit buffer */ 2023 return 0;
2000 bk = k;
2001 return 0;
2002} 2024}
2003 2025
2004 2026
@@ -2008,48 +2030,47 @@ int inflate_fixed()
2008 either replace this with a custom decoder, or at least precompute the 2030 either replace this with a custom decoder, or at least precompute the
2009 Huffman tables. */ 2031 Huffman tables. */
2010{ 2032{
2011 int i; /* temporary variable */ 2033 int i; /* temporary variable */
2012 struct huft *tl; /* literal/length code table */ 2034 struct huft *tl; /* literal/length code table */
2013 struct huft *td; /* distance code table */ 2035 struct huft *td; /* distance code table */
2014 int bl; /* lookup bits for tl */ 2036 int bl; /* lookup bits for tl */
2015 int bd; /* lookup bits for td */ 2037 int bd; /* lookup bits for td */
2016 unsigned l[288]; /* length list for huft_build */ 2038 unsigned l[288]; /* length list for huft_build */
2017 2039
2018 2040
2019 /* set up literal table */ 2041 /* set up literal table */
2020 for (i = 0; i < 144; i++) 2042 for (i = 0; i < 144; i++)
2021 l[i] = 8; 2043 l[i] = 8;
2022 for (; i < 256; i++) 2044 for (; i < 256; i++)
2023 l[i] = 9; 2045 l[i] = 9;
2024 for (; i < 280; i++) 2046 for (; i < 280; i++)
2025 l[i] = 7; 2047 l[i] = 7;
2026 for (; i < 288; i++) /* make a complete, but wrong code set */ 2048 for (; i < 288; i++) /* make a complete, but wrong code set */
2027 l[i] = 8; 2049 l[i] = 8;
2028 bl = 7; 2050 bl = 7;
2029 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) 2051 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
2030 return i; 2052 return i;
2031 2053
2032 2054
2033 /* set up distance table */ 2055 /* set up distance table */
2034 for (i = 0; i < 30; i++) /* make an incomplete code set */ 2056 for (i = 0; i < 30; i++) /* make an incomplete code set */
2035 l[i] = 5; 2057 l[i] = 5;
2036 bd = 5; 2058 bd = 5;
2037 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) 2059 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
2038 { 2060 huft_free(tl);
2039 huft_free(tl); 2061 return i;
2040 return i; 2062 }
2041 } 2063
2042 2064
2043 2065 /* decompress until an end-of-block code */
2044 /* decompress until an end-of-block code */ 2066 if (inflate_codes(tl, td, bl, bd))
2045 if (inflate_codes(tl, td, bl, bd)) 2067 return 1;
2046 return 1; 2068
2047 2069
2048 2070 /* free the decoding tables, return */
2049 /* free the decoding tables, return */ 2071 huft_free(tl);
2050 huft_free(tl); 2072 huft_free(td);
2051 huft_free(td); 2073 return 0;
2052 return 0;
2053} 2074}
2054 2075
2055 2076
@@ -2057,209 +2078,202 @@ int inflate_fixed()
2057int inflate_dynamic() 2078int inflate_dynamic()
2058/* decompress an inflated type 2 (dynamic Huffman codes) block. */ 2079/* decompress an inflated type 2 (dynamic Huffman codes) block. */
2059{ 2080{
2060 int i; /* temporary variables */ 2081 int i; /* temporary variables */
2061 unsigned j; 2082 unsigned j;
2062 unsigned l; /* last length */ 2083 unsigned l; /* last length */
2063 unsigned m; /* mask for bit lengths table */ 2084 unsigned m; /* mask for bit lengths table */
2064 unsigned n; /* number of lengths to get */ 2085 unsigned n; /* number of lengths to get */
2065 struct huft *tl; /* literal/length code table */ 2086 struct huft *tl; /* literal/length code table */
2066 struct huft *td; /* distance code table */ 2087 struct huft *td; /* distance code table */
2067 int bl; /* lookup bits for tl */ 2088 int bl; /* lookup bits for tl */
2068 int bd; /* lookup bits for td */ 2089 int bd; /* lookup bits for td */
2069 unsigned nb; /* number of bit length codes */ 2090 unsigned nb; /* number of bit length codes */
2070 unsigned nl; /* number of literal/length codes */ 2091 unsigned nl; /* number of literal/length codes */
2071 unsigned nd; /* number of distance codes */ 2092 unsigned nd; /* number of distance codes */
2093
2072#ifdef PKZIP_BUG_WORKAROUND 2094#ifdef PKZIP_BUG_WORKAROUND
2073 unsigned ll[288+32]; /* literal/length and distance code lengths */ 2095 unsigned ll[288 + 32]; /* literal/length and distance code lengths */
2074#else 2096#else
2075 unsigned ll[286+30]; /* literal/length and distance code lengths */ 2097 unsigned ll[286 + 30]; /* literal/length and distance code lengths */
2076#endif 2098#endif
2077 register ulg b; /* bit buffer */ 2099 register ulg b; /* bit buffer */
2078 register unsigned k; /* number of bits in bit buffer */ 2100 register unsigned k; /* number of bits in bit buffer */
2079 2101
2080 2102
2081 /* make local bit buffer */ 2103 /* make local bit buffer */
2082 b = bb; 2104 b = bb;
2083 k = bk; 2105 k = bk;
2084 2106
2085 2107
2086 /* read in table lengths */ 2108 /* read in table lengths */
2087 NEEDBITS(5) 2109 NEEDBITS(5)
2088 nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ 2110 nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */
2089 DUMPBITS(5) 2111 DUMPBITS(5)
2090 NEEDBITS(5) 2112 NEEDBITS(5)
2091 nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ 2113 nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */
2092 DUMPBITS(5) 2114 DUMPBITS(5)
2093 NEEDBITS(4) 2115 NEEDBITS(4)
2094 nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ 2116 nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */
2095 DUMPBITS(4) 2117 DUMPBITS(4)
2096#ifdef PKZIP_BUG_WORKAROUND 2118#ifdef PKZIP_BUG_WORKAROUND
2097 if (nl > 288 || nd > 32) 2119 if (nl > 288 || nd > 32)
2098#else 2120#else
2099 if (nl > 286 || nd > 30) 2121 if (nl > 286 || nd > 30)
2100#endif 2122#endif
2101 return 1; /* bad lengths */ 2123 return 1; /* bad lengths */
2102 2124
2103 2125
2104 /* read in bit-length-code lengths */ 2126 /* read in bit-length-code lengths */
2105 for (j = 0; j < nb; j++) 2127 for (j = 0; j < nb; j++) {
2106 { 2128 NEEDBITS(3)
2107 NEEDBITS(3) 2129 ll[border[j]] = (unsigned) b & 7;
2108 ll[border[j]] = (unsigned)b & 7; 2130 DUMPBITS(3)
2109 DUMPBITS(3) 2131 }
2110 } 2132 for (; j < 19; j++)
2111 for (; j < 19; j++) 2133 ll[border[j]] = 0;
2112 ll[border[j]] = 0; 2134
2113 2135
2114 2136 /* build decoding table for trees--single level, 7 bit lookup */
2115 /* build decoding table for trees--single level, 7 bit lookup */ 2137 bl = 7;
2116 bl = 7; 2138 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) {
2117 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) 2139 if (i == 1)
2118 { 2140 huft_free(tl);
2119 if (i == 1) 2141 return i; /* incomplete code set */
2120 huft_free(tl); 2142 }
2121 return i; /* incomplete code set */ 2143
2122 } 2144
2123 2145 /* read in literal and distance code lengths */
2124 2146 n = nl + nd;
2125 /* read in literal and distance code lengths */ 2147 m = mask_bits[bl];
2126 n = nl + nd; 2148 i = l = 0;
2127 m = mask_bits[bl]; 2149 while ((unsigned) i < n) {
2128 i = l = 0; 2150 NEEDBITS((unsigned) bl)
2129 while ((unsigned)i < n) 2151 j = (td = tl + ((unsigned) b & m))->b;
2130 { 2152 DUMPBITS(j)
2131 NEEDBITS((unsigned)bl) 2153 j = td->v.n;
2132 j = (td = tl + ((unsigned)b & m))->b; 2154 if (j < 16) /* length of code in bits (0..15) */
2133 DUMPBITS(j) 2155 ll[i++] = l = j; /* save last length in l */
2134 j = td->v.n; 2156 else if (j == 16) { /* repeat last length 3 to 6 times */
2135 if (j < 16) /* length of code in bits (0..15) */ 2157 NEEDBITS(2)
2136 ll[i++] = l = j; /* save last length in l */ 2158 j = 3 + ((unsigned) b & 3);
2137 else if (j == 16) /* repeat last length 3 to 6 times */ 2159 DUMPBITS(2)
2138 { 2160 if ((unsigned) i + j > n)
2139 NEEDBITS(2) 2161 return 1;
2140 j = 3 + ((unsigned)b & 3); 2162 while (j--)
2141 DUMPBITS(2) 2163 ll[i++] = l;
2142 if ((unsigned)i + j > n) 2164 } else if (j == 17) { /* 3 to 10 zero length codes */
2143 return 1; 2165 NEEDBITS(3)
2144 while (j--) 2166 j = 3 + ((unsigned) b & 7);
2145 ll[i++] = l; 2167 DUMPBITS(3)
2146 } 2168 if ((unsigned) i + j > n)
2147 else if (j == 17) /* 3 to 10 zero length codes */ 2169 return 1;
2148 { 2170 while (j--)
2149 NEEDBITS(3) 2171 ll[i++] = 0;
2150 j = 3 + ((unsigned)b & 7); 2172 l = 0;
2151 DUMPBITS(3) 2173 } else { /* j == 18: 11 to 138 zero length codes */
2152 if ((unsigned)i + j > n) 2174
2153 return 1; 2175 NEEDBITS(7)
2154 while (j--) 2176 j = 11 + ((unsigned) b & 0x7f);
2155 ll[i++] = 0; 2177 DUMPBITS(7)
2156 l = 0; 2178 if ((unsigned) i + j > n)
2157 } 2179 return 1;
2158 else /* j == 18: 11 to 138 zero length codes */ 2180 while (j--)
2159 { 2181 ll[i++] = 0;
2160 NEEDBITS(7) 2182 l = 0;
2161 j = 11 + ((unsigned)b & 0x7f); 2183 }
2162 DUMPBITS(7) 2184 }
2163 if ((unsigned)i + j > n) 2185
2164 return 1; 2186
2165 while (j--) 2187 /* free decoding table for trees */
2166 ll[i++] = 0; 2188 huft_free(tl);
2167 l = 0; 2189
2168 } 2190
2169 } 2191 /* restore the global bit buffer */
2170 2192 bb = b;
2171 2193 bk = k;
2172 /* free decoding table for trees */ 2194
2173 huft_free(tl); 2195
2174 2196 /* build the decoding tables for literal/length and distance codes */
2175 2197 bl = lbits;
2176 /* restore the global bit buffer */ 2198 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
2177 bb = b; 2199 if (i == 1) {
2178 bk = k; 2200 fprintf(stderr, " incomplete literal tree\n");
2179 2201 huft_free(tl);
2180 2202 }
2181 /* build the decoding tables for literal/length and distance codes */ 2203 return i; /* incomplete code set */
2182 bl = lbits; 2204 }
2183 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) 2205 bd = dbits;
2184 { 2206 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
2185 if (i == 1) { 2207 if (i == 1) {
2186 fprintf(stderr, " incomplete literal tree\n"); 2208 fprintf(stderr, " incomplete distance tree\n");
2187 huft_free(tl);
2188 }
2189 return i; /* incomplete code set */
2190 }
2191 bd = dbits;
2192 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
2193 {
2194 if (i == 1) {
2195 fprintf(stderr, " incomplete distance tree\n");
2196#ifdef PKZIP_BUG_WORKAROUND 2209#ifdef PKZIP_BUG_WORKAROUND
2197 i = 0; 2210 i = 0;
2198 } 2211 }
2199#else 2212#else
2200 huft_free(td); 2213 huft_free(td);
2201 } 2214 }
2202 huft_free(tl); 2215 huft_free(tl);
2203 return i; /* incomplete code set */ 2216 return i; /* incomplete code set */
2204#endif 2217#endif
2205 } 2218 }
2206 2219
2207 2220
2208 /* decompress until an end-of-block code */ 2221 /* decompress until an end-of-block code */
2209 if (inflate_codes(tl, td, bl, bd)) 2222 if (inflate_codes(tl, td, bl, bd))
2210 return 1; 2223 return 1;
2211 2224
2212 2225
2213 /* free the decoding tables, return */ 2226 /* free the decoding tables, return */
2214 huft_free(tl); 2227 huft_free(tl);
2215 huft_free(td); 2228 huft_free(td);
2216 return 0; 2229 return 0;
2217} 2230}
2218 2231
2219 2232
2220 2233
2221int inflate_block(e) 2234int inflate_block(e)
2222int *e; /* last block flag */ 2235int *e; /* last block flag */
2236
2223/* decompress an inflated block */ 2237/* decompress an inflated block */
2224{ 2238{
2225 unsigned t; /* block type */ 2239 unsigned t; /* block type */
2226 register ulg b; /* bit buffer */ 2240 register ulg b; /* bit buffer */
2227 register unsigned k; /* number of bits in bit buffer */ 2241 register unsigned k; /* number of bits in bit buffer */
2228 2242
2229 2243
2230 /* make local bit buffer */ 2244 /* make local bit buffer */
2231 b = bb; 2245 b = bb;
2232 k = bk; 2246 k = bk;
2233 2247
2234 2248
2235 /* read in last block bit */ 2249 /* read in last block bit */
2236 NEEDBITS(1) 2250 NEEDBITS(1)
2237 *e = (int)b & 1; 2251 * e = (int) b & 1;
2238 DUMPBITS(1) 2252 DUMPBITS(1)
2239 2253
2240 2254
2241 /* read in block type */ 2255 /* read in block type */
2242 NEEDBITS(2) 2256 NEEDBITS(2)
2243 t = (unsigned)b & 3; 2257 t = (unsigned) b & 3;
2244 DUMPBITS(2) 2258 DUMPBITS(2)
2245 2259
2246 2260
2247 /* restore the global bit buffer */ 2261 /* restore the global bit buffer */
2248 bb = b; 2262 bb = b;
2249 bk = k; 2263 bk = k;
2250 2264
2251 2265
2252 /* inflate that block type */ 2266 /* inflate that block type */
2253 if (t == 2) 2267 if (t == 2)
2254 return inflate_dynamic(); 2268 return inflate_dynamic();
2255 if (t == 0) 2269 if (t == 0)
2256 return inflate_stored(); 2270 return inflate_stored();
2257 if (t == 1) 2271 if (t == 1)
2258 return inflate_fixed(); 2272 return inflate_fixed();
2259 2273
2260 2274
2261 /* bad block type */ 2275 /* bad block type */
2262 return 2; 2276 return 2;
2263} 2277}
2264 2278
2265 2279
@@ -2267,42 +2281,42 @@ int *e; /* last block flag */
2267int inflate() 2281int inflate()
2268/* decompress an inflated entry */ 2282/* decompress an inflated entry */
2269{ 2283{
2270 int e; /* last block flag */ 2284 int e; /* last block flag */
2271 int r; /* result code */ 2285 int r; /* result code */
2272 unsigned h; /* maximum struct huft's malloc'ed */ 2286 unsigned h; /* maximum struct huft's malloc'ed */
2273 2287
2274 2288
2275 /* initialize window, bit buffer */ 2289 /* initialize window, bit buffer */
2276 wp = 0; 2290 wp = 0;
2277 bk = 0; 2291 bk = 0;
2278 bb = 0; 2292 bb = 0;
2279 2293
2280 2294
2281 /* decompress until the last block */ 2295 /* decompress until the last block */
2282 h = 0; 2296 h = 0;
2283 do { 2297 do {
2284 hufts = 0; 2298 hufts = 0;
2285 if ((r = inflate_block(&e)) != 0) 2299 if ((r = inflate_block(&e)) != 0)
2286 return r; 2300 return r;
2287 if (hufts > h) 2301 if (hufts > h)
2288 h = hufts; 2302 h = hufts;
2289 } while (!e); 2303 } while (!e);
2290 2304
2291 /* Undo too much lookahead. The next read will be byte aligned so we 2305 /* Undo too much lookahead. The next read will be byte aligned so we
2292 * can discard unused bits in the last meaningful byte. 2306 * can discard unused bits in the last meaningful byte.
2293 */ 2307 */
2294 while (bk >= 8) { 2308 while (bk >= 8) {
2295 bk -= 8; 2309 bk -= 8;
2296 inptr--; 2310 inptr--;
2297 } 2311 }
2298 2312
2299 /* flush out slide */ 2313 /* flush out slide */
2300 flush_output(wp); 2314 flush_output(wp);
2301 2315
2302 2316
2303 /* return success */ 2317 /* return success */
2304#ifdef DEBUG 2318#ifdef DEBUG
2305 fprintf(stderr, "<%u> ", h); 2319 fprintf(stderr, "<%u> ", h);
2306#endif /* DEBUG */ 2320#endif /* DEBUG */
2307 return 0; 2321 return 0;
2308} 2322}
diff --git a/gzip.c b/gzip.c
index 3438ee42f..f132679f7 100644
--- a/gzip.c
+++ b/gzip.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* gzip.c -- this is a stripped down version of gzip I put into busybox, it does 2/* gzip.c -- this is a stripped down version of gzip I put into busybox, it does
2 * only standard in to standard out with -9 compression. It also requires the 3 * only standard in to standard out with -9 compression. It also requires the
3 * zcat module for some important functions. 4 * zcat module for some important functions.
@@ -12,11 +13,12 @@
12//#endif 13//#endif
13 14
14static const char gzip_usage[] = 15static const char gzip_usage[] =
15 "gzip [OPTION]... FILE\n\n" 16 "gzip [OPTION]... FILE\n\n"
16 "Compress FILE with maximum compression.\n" 17 "Compress FILE with maximum compression.\n"
17 "When FILE is -, reads standard input. Implies -c.\n\n" 18 "When FILE is -, reads standard input. Implies -c.\n\n"
18 "Options:\n" 19
19 "\t-c\tWrite output to standard output instead of FILE.gz\n"; 20 "Options:\n"
21 "\t-c\tWrite output to standard output instead of FILE.gz\n";
20 22
21 23
22/* gzip.h -- common declarations for all gzip modules 24/* gzip.h -- common declarations for all gzip modules
@@ -32,9 +34,9 @@ static const char gzip_usage[] =
32#endif 34#endif
33 35
34#ifdef __STDC__ 36#ifdef __STDC__
35 typedef void *voidp; 37typedef void *voidp;
36#else 38#else
37 typedef char *voidp; 39typedef char *voidp;
38#endif 40#endif
39 41
40/* I don't like nested includes, but the string and io functions are used 42/* I don't like nested includes, but the string and io functions are used
@@ -49,10 +51,10 @@ static const char gzip_usage[] =
49# define memzero(s, n) memset ((voidp)(s), 0, (n)) 51# define memzero(s, n) memset ((voidp)(s), 0, (n))
50#else 52#else
51# include <strings.h> 53# include <strings.h>
52# define strchr index 54# define strchr index
53# define strrchr rindex 55# define strrchr rindex
54# define memcpy(d, s, n) bcopy((s), (d), (n)) 56# define memcpy(d, s, n) bcopy((s), (d), (n))
55# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 57# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
56# define memzero(s, n) bzero((s), (n)) 58# define memzero(s, n) bzero((s), (n))
57#endif 59#endif
58 60
@@ -62,9 +64,9 @@ static const char gzip_usage[] =
62 64
63#define local static 65#define local static
64 66
65typedef unsigned char uch; 67typedef unsigned char uch;
66typedef unsigned short ush; 68typedef unsigned short ush;
67typedef unsigned long ulg; 69typedef unsigned long ulg;
68 70
69/* Return codes from gzip */ 71/* Return codes from gzip */
70#define OK 0 72#define OK 0
@@ -79,7 +81,7 @@ typedef unsigned long ulg;
79/* methods 4 to 7 reserved */ 81/* methods 4 to 7 reserved */
80#define DEFLATED 8 82#define DEFLATED 8
81#define MAX_METHODS 9 83#define MAX_METHODS 9
82extern int method; /* compression method */ 84extern int method; /* compression method */
83 85
84/* To save memory for 16 bit systems, some arrays are overlaid between 86/* To save memory for 16 bit systems, some arrays are overlaid between
85 * the various modules: 87 * the various modules:
@@ -94,27 +96,27 @@ extern int method; /* compression method */
94 96
95#ifndef INBUFSIZ 97#ifndef INBUFSIZ
96# ifdef SMALL_MEM 98# ifdef SMALL_MEM
97# define INBUFSIZ 0x2000 /* input buffer size */ 99# define INBUFSIZ 0x2000 /* input buffer size */
98# else 100# else
99# define INBUFSIZ 0x8000 /* input buffer size */ 101# define INBUFSIZ 0x8000 /* input buffer size */
100# endif 102# endif
101#endif 103#endif
102#define INBUF_EXTRA 64 /* required by unlzw() */ 104#define INBUF_EXTRA 64 /* required by unlzw() */
103 105
104#ifndef OUTBUFSIZ 106#ifndef OUTBUFSIZ
105# ifdef SMALL_MEM 107# ifdef SMALL_MEM
106# define OUTBUFSIZ 8192 /* output buffer size */ 108# define OUTBUFSIZ 8192 /* output buffer size */
107# else 109# else
108# define OUTBUFSIZ 16384 /* output buffer size */ 110# define OUTBUFSIZ 16384 /* output buffer size */
109# endif 111# endif
110#endif 112#endif
111#define OUTBUF_EXTRA 2048 /* required by unlzw() */ 113#define OUTBUF_EXTRA 2048 /* required by unlzw() */
112 114
113#ifndef DIST_BUFSIZE 115#ifndef DIST_BUFSIZE
114# ifdef SMALL_MEM 116# ifdef SMALL_MEM
115# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ 117# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
116# else 118# else
117# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ 119# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
118# endif 120# endif
119#endif 121#endif
120 122
@@ -133,60 +135,61 @@ extern int method; /* compression method */
133# define FREE(array) 135# define FREE(array)
134#endif 136#endif
135 137
136EXTERN(uch, inbuf); /* input buffer */ 138EXTERN(uch, inbuf); /* input buffer */
137EXTERN(uch, outbuf); /* output buffer */ 139EXTERN(uch, outbuf); /* output buffer */
138EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ 140EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
139EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ 141EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
140#define tab_suffix window 142#define tab_suffix window
141#ifndef MAXSEG_64K 143#ifndef MAXSEG_64K
142# define tab_prefix prev /* hash link (see deflate.c) */ 144# define tab_prefix prev /* hash link (see deflate.c) */
143# define head (prev+WSIZE) /* hash head (see deflate.c) */ 145# define head (prev+WSIZE) /* hash head (see deflate.c) */
144 EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ 146EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
145#else 147#else
146# define tab_prefix0 prev 148# define tab_prefix0 prev
147# define head tab_prefix1 149# define head tab_prefix1
148 EXTERN(ush, tab_prefix0); /* prefix for even codes */ 150EXTERN(ush, tab_prefix0); /* prefix for even codes */
149 EXTERN(ush, tab_prefix1); /* prefix for odd codes */ 151EXTERN(ush, tab_prefix1); /* prefix for odd codes */
150#endif 152#endif
151 153
152extern unsigned insize; /* valid bytes in inbuf */ 154extern unsigned insize; /* valid bytes in inbuf */
153extern unsigned inptr; /* index of next byte to be processed in inbuf */ 155extern unsigned inptr; /* index of next byte to be processed in inbuf */
154extern unsigned outcnt; /* bytes in output buffer */ 156extern unsigned outcnt; /* bytes in output buffer */
155 157
156extern long bytes_in; /* number of input bytes */ 158extern long bytes_in; /* number of input bytes */
157extern long bytes_out; /* number of output bytes */ 159extern long bytes_out; /* number of output bytes */
158extern long header_bytes;/* number of bytes in gzip header */ 160extern long header_bytes; /* number of bytes in gzip header */
159 161
160#define isize bytes_in 162#define isize bytes_in
161/* for compatibility with old zip sources (to be cleaned) */ 163/* for compatibility with old zip sources (to be cleaned) */
162 164
163extern int ifd; /* input file descriptor */ 165extern int ifd; /* input file descriptor */
164extern int ofd; /* output file descriptor */ 166extern int ofd; /* output file descriptor */
165extern char ifname[]; /* input file name or "stdin" */ 167extern char ifname[]; /* input file name or "stdin" */
166extern char ofname[]; /* output file name or "stdout" */ 168extern char ofname[]; /* output file name or "stdout" */
167extern char *progname; /* program name */ 169extern char *progname; /* program name */
170
171extern long time_stamp; /* original time stamp (modification time) */
172extern long ifile_size; /* input file size, -1 for devices (debug only) */
168 173
169extern long time_stamp; /* original time stamp (modification time) */ 174typedef int file_t; /* Do not use stdio */
170extern long ifile_size; /* input file size, -1 for devices (debug only) */
171 175
172typedef int file_t; /* Do not use stdio */ 176#define NO_FILE (-1) /* in memory compression */
173#define NO_FILE (-1) /* in memory compression */
174 177
175 178
176#define PACK_MAGIC "\037\036" /* Magic header for packed files */ 179#define PACK_MAGIC "\037\036" /* Magic header for packed files */
177#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ 180#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
178#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ 181#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
179#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/ 182#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files */
180#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */ 183#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */
181 184
182/* gzip flag byte */ 185/* gzip flag byte */
183#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 186#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
184#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 187#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
185#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 188#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
186#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 189#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
187#define COMMENT 0x10 /* bit 4 set: file comment present */ 190#define COMMENT 0x10 /* bit 4 set: file comment present */
188#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 191#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
189#define RESERVED 0xC0 /* bit 6,7: reserved */ 192#define RESERVED 0xC0 /* bit 6,7: reserved */
190 193
191/* internal file attribute */ 194/* internal file attribute */
192#define UNKNOWN 0xffff 195#define UNKNOWN 0xffff
@@ -194,8 +197,8 @@ typedef int file_t; /* Do not use stdio */
194#define ASCII 1 197#define ASCII 1
195 198
196#ifndef WSIZE 199#ifndef WSIZE
197# define WSIZE 0x8000 /* window size--must be a power of two, and */ 200# define WSIZE 0x8000 /* window size--must be a power of two, and */
198#endif /* at least 32K for zip's deflate method */ 201#endif /* at least 32K for zip's deflate method */
199 202
200#define MIN_MATCH 3 203#define MIN_MATCH 3
201#define MAX_MATCH 258 204#define MAX_MATCH 258
@@ -211,12 +214,12 @@ typedef int file_t; /* Do not use stdio */
211 * distances are limited to MAX_DIST instead of WSIZE. 214 * distances are limited to MAX_DIST instead of WSIZE.
212 */ 215 */
213 216
214extern int decrypt; /* flag to turn on decryption */ 217extern int decrypt; /* flag to turn on decryption */
215extern int exit_code; /* program exit code */ 218extern int exit_code; /* program exit code */
216extern int verbose; /* be verbose (-v) */ 219extern int verbose; /* be verbose (-v) */
217extern int quiet; /* be quiet (-q) */ 220extern int quiet; /* be quiet (-q) */
218extern int test; /* check .z file integrity */ 221extern int test; /* check .z file integrity */
219extern int save_orig_name; /* set if original name must be saved */ 222extern int save_orig_name; /* set if original name must be saved */
220 223
221#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) 224#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
222#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) 225#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
@@ -248,10 +251,10 @@ extern int save_orig_name; /* set if original name must be saved */
248 put_short(((ulg)(n)) >> 16); \ 251 put_short(((ulg)(n)) >> 16); \
249} 252}
250 253
251#define seekable() 0 /* force sequential output */ 254#define seekable() 0 /* force sequential output */
252#define translate_eol 0 /* no option -a yet */ 255#define translate_eol 0 /* no option -a yet */
253 256
254#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ 257#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
255 258
256/* Macros for getting two-byte and four-byte header values */ 259/* Macros for getting two-byte and four-byte header values */
257#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) 260#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
@@ -281,57 +284,58 @@ extern int save_orig_name; /* set if original name must be saved */
281 284
282 285
283 /* in zip.c: */ 286 /* in zip.c: */
284extern int zip OF((int in, int out)); 287extern int zip OF((int in, int out));
285extern int file_read OF((char *buf, unsigned size)); 288extern int file_read OF((char *buf, unsigned size));
286 289
287 /* in unzip.c */ 290 /* in unzip.c */
288extern int unzip OF((int in, int out)); 291extern int unzip OF((int in, int out));
289extern int check_zipfile OF((int in)); 292extern int check_zipfile OF((int in));
290 293
291 /* in unpack.c */ 294 /* in unpack.c */
292extern int unpack OF((int in, int out)); 295extern int unpack OF((int in, int out));
293 296
294 /* in unlzh.c */ 297 /* in unlzh.c */
295extern int unlzh OF((int in, int out)); 298extern int unlzh OF((int in, int out));
296 299
297 /* in gzip.c */ 300 /* in gzip.c */
298RETSIGTYPE abort_gzip OF((void)); 301RETSIGTYPE abort_gzip OF((void));
299 302
300 /* in deflate.c */ 303 /* in deflate.c */
301void lm_init OF((ush *flags)); 304void lm_init OF((ush * flags));
302ulg deflate OF((void)); 305ulg deflate OF((void));
303 306
304 /* in trees.c */ 307 /* in trees.c */
305void ct_init OF((ush *attr, int *method)); 308void ct_init OF((ush * attr, int *method));
306int ct_tally OF((int dist, int lc)); 309int ct_tally OF((int dist, int lc));
307ulg flush_block OF((char *buf, ulg stored_len, int eof)); 310ulg flush_block OF((char *buf, ulg stored_len, int eof));
308 311
309 /* in bits.c */ 312 /* in bits.c */
310void bi_init OF((file_t zipfile)); 313void bi_init OF((file_t zipfile));
311void send_bits OF((int value, int length)); 314void send_bits OF((int value, int length));
312unsigned bi_reverse OF((unsigned value, int length)); 315unsigned bi_reverse OF((unsigned value, int length));
313void bi_windup OF((void)); 316void bi_windup OF((void));
314void copy_block OF((char *buf, unsigned len, int header)); 317void copy_block OF((char *buf, unsigned len, int header));
315extern int (*read_buf) OF((char *buf, unsigned size)); 318extern int (*read_buf) OF((char *buf, unsigned size));
316 319
317 /* in util.c: */ 320 /* in util.c: */
318extern int copy OF((int in, int out)); 321extern int copy OF((int in, int out));
319extern ulg updcrc OF((uch *s, unsigned n)); 322extern ulg updcrc OF((uch * s, unsigned n));
320extern void clear_bufs OF((void)); 323extern void clear_bufs OF((void));
321extern int fill_inbuf OF((int eof_ok)); 324extern int fill_inbuf OF((int eof_ok));
322extern void flush_outbuf OF((void)); 325extern void flush_outbuf OF((void));
323extern void flush_window OF((void)); 326extern void flush_window OF((void));
324extern void write_buf OF((int fd, voidp buf, unsigned cnt)); 327extern void write_buf OF((int fd, voidp buf, unsigned cnt));
325extern char *strlwr OF((char *s)); 328extern char *strlwr OF((char *s));
326extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); 329extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
327extern void error OF((char *m)); 330extern void error OF((char *m));
328extern void warn OF((char *a, char *b)); 331extern void warn OF((char *a, char *b));
329extern void read_error OF((void)); 332extern void read_error OF((void));
330extern void write_error OF((void)); 333extern void write_error OF((void));
331extern void display_ratio OF((long num, long den, FILE *file)); 334extern void display_ratio OF((long num, long den, FILE * file));
332 335
333 /* in inflate.c */ 336 /* in inflate.c */
334extern int inflate OF((void)); 337extern int inflate OF((void));
338
335/* lzw.h -- define the lzw functions. 339/* lzw.h -- define the lzw functions.
336 * Copyright (C) 1992-1993 Jean-loup Gailly. 340 * Copyright (C) 1992-1993 Jean-loup Gailly.
337 * This is free software; you can redistribute it and/or modify it under the 341 * This is free software; you can redistribute it and/or modify it under the
@@ -345,9 +349,9 @@ extern int inflate OF((void));
345#ifndef BITS 349#ifndef BITS
346# define BITS 16 350# define BITS 16
347#endif 351#endif
348#define INIT_BITS 9 /* Initial number of bits per code */ 352#define INIT_BITS 9 /* Initial number of bits per code */
349 353
350#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ 354#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
351/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. 355/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
352 * It's a pity that old uncompress does not check bit 0x20. That makes 356 * It's a pity that old uncompress does not check bit 0x20. That makes
353 * extension of the format actually undesirable because old compress 357 * extension of the format actually undesirable because old compress
@@ -362,13 +366,13 @@ extern int inflate OF((void));
362 * clear the dictionary. 366 * clear the dictionary.
363 */ 367 */
364 368
365#define LZW_RESERVED 0x60 /* reserved bits */ 369#define LZW_RESERVED 0x60 /* reserved bits */
366 370
367#define CLEAR 256 /* flush the dictionary */ 371#define CLEAR 256 /* flush the dictionary */
368#define FIRST (CLEAR+1) /* first free entry */ 372#define FIRST (CLEAR+1) /* first free entry */
369 373
370extern int maxbits; /* max bits per code for LZW */ 374extern int maxbits; /* max bits per code for LZW */
371extern int block_mode; /* block compress mode -C compatible with 2.0 */ 375extern int block_mode; /* block compress mode -C compatible with 2.0 */
372 376
373/* revision.h -- define the version number 377/* revision.h -- define the version number
374 * Copyright (C) 1992-1993 Jean-loup Gailly. 378 * Copyright (C) 1992-1993 Jean-loup Gailly.
@@ -404,18 +408,18 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
404# define OS2 408# define OS2
405#endif 409#endif
406 410
407#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */ 411#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
408# undef MSDOS 412# undef MSDOS
409#endif 413#endif
410 414
411#ifdef MSDOS 415#ifdef MSDOS
412# ifdef __GNUC__ 416# ifdef __GNUC__
413 /* DJGPP version 1.09+ on MS-DOS. 417 /* DJGPP version 1.09+ on MS-DOS.
414 * The DJGPP 1.09 stat() function must be upgraded before gzip will 418 * The DJGPP 1.09 stat() function must be upgraded before gzip will
415 * fully work. 419 * fully work.
416 * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which 420 * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
417 * implies DIRENT. 421 * implies DIRENT.
418 */ 422 */
419# define near 423# define near
420# else 424# else
421# define MAXSEG_64K 425# define MAXSEG_64K
@@ -426,7 +430,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
426# else 430# else
427# define NO_UTIME 431# define NO_UTIME
428# endif 432# endif
429# else /* MSC */ 433# else /* MSC */
430# define HAVE_SYS_UTIME_H 434# define HAVE_SYS_UTIME_H
431# define NO_UTIME_H 435# define NO_UTIME_H
432# endif 436# endif
@@ -441,7 +445,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
441# define PROTO 445# define PROTO
442# define STDC_HEADERS 446# define STDC_HEADERS
443# define NO_SIZE_CHECK 447# define NO_SIZE_CHECK
444# define casemap(c) tolow(c) /* Force file names to lower case */ 448# define casemap(c) tolow(c) /* Force file names to lower case */
445# include <io.h> 449# include <io.h>
446# define OS_CODE 0x00 450# define OS_CODE 0x00
447# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) 451# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
@@ -494,7 +498,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
494# endif 498# endif
495#endif 499#endif
496 500
497#ifdef WIN32 /* Windows NT */ 501#ifdef WIN32 /* Windows NT */
498# define HAVE_SYS_UTIME_H 502# define HAVE_SYS_UTIME_H
499# define NO_UTIME_H 503# define NO_UTIME_H
500# define PATH_SEP2 '\\' 504# define PATH_SEP2 '\\'
@@ -510,7 +514,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
510# define NO_MULTIPLE_DOTS 514# define NO_MULTIPLE_DOTS
511# define MAX_EXT_CHARS 3 515# define MAX_EXT_CHARS 3
512# define Z_SUFFIX "z" 516# define Z_SUFFIX "z"
513# define casemap(c) tolow(c) /* Force file names to lower case */ 517# define casemap(c) tolow(c) /* Force file names to lower case */
514# endif 518# endif
515# define OS_CODE 0x0b 519# define OS_CODE 0x0b
516#endif 520#endif
@@ -519,10 +523,10 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
519# ifdef __TURBOC__ 523# ifdef __TURBOC__
520# include <alloc.h> 524# include <alloc.h>
521# define DYN_ALLOC 525# define DYN_ALLOC
522 /* Turbo C 2.0 does not accept static allocations of large arrays */ 526 /* Turbo C 2.0 does not accept static allocations of large arrays */
523 void * fcalloc (unsigned items, unsigned size); 527void *fcalloc(unsigned items, unsigned size);
524 void fcfree (void *ptr); 528void fcfree(void *ptr);
525# else /* MSC */ 529# else /* MSC */
526# include <malloc.h> 530# include <malloc.h>
527# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize)) 531# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
528# define fcfree(ptr) hfree(ptr) 532# define fcfree(ptr) hfree(ptr)
@@ -565,17 +569,18 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
565# ifdef __GNUC__ 569# ifdef __GNUC__
566# define DIRENT 570# define DIRENT
567# define HAVE_UNISTD_H 571# define HAVE_UNISTD_H
568# else /* SASC */ 572# else /* SASC */
569# define NO_STDIN_FSTAT 573# define NO_STDIN_FSTAT
570# define SYSDIR 574# define SYSDIR
571# define NO_SYMLINK 575# define NO_SYMLINK
572# define NO_CHOWN 576# define NO_CHOWN
573# define NO_FCNTL_H 577# define NO_FCNTL_H
574# include <fcntl.h> /* for read() and write() */ 578# include <fcntl.h> /* for read() and write() */
575# define direct dirent 579# define direct dirent
576 extern void _expand_args(int *argc, char ***argv); 580extern void _expand_args(int *argc, char ***argv);
581
577# define EXPAND(argc,argv) _expand_args(&argc,&argv); 582# define EXPAND(argc,argv) _expand_args(&argc,&argv);
578# undef O_BINARY /* disable useless --ascii option */ 583# undef O_BINARY /* disable useless --ascii option */
579# endif 584# endif
580#endif 585#endif
581 586
@@ -595,7 +600,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
595# define MAX_EXT_CHARS 3 600# define MAX_EXT_CHARS 3
596# define Z_SUFFIX "z" 601# define Z_SUFFIX "z"
597# define NO_CHOWN 602# define NO_CHOWN
598# define casemap(c) tolow(c) /* Force file names to lower case */ 603# define casemap(c) tolow(c) /* Force file names to lower case */
599# define NO_SYMLINK 604# define NO_SYMLINK
600# endif 605# endif
601#endif 606#endif
@@ -615,28 +620,28 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
615# endif 620# endif
616#endif 621#endif
617 622
618#ifdef __50SERIES /* Prime/PRIMOS */ 623#ifdef __50SERIES /* Prime/PRIMOS */
619# define PATH_SEP '>' 624# define PATH_SEP '>'
620# define STDC_HEADERS 625# define STDC_HEADERS
621# define NO_MEMORY_H 626# define NO_MEMORY_H
622# define NO_UTIME_H 627# define NO_UTIME_H
623# define NO_UTIME 628# define NO_UTIME
624# define NO_CHOWN 629# define NO_CHOWN
625# define NO_STDIN_FSTAT 630# define NO_STDIN_FSTAT
626# define NO_SIZE_CHECK 631# define NO_SIZE_CHECK
627# define NO_SYMLINK 632# define NO_SYMLINK
628# define RECORD_IO 1 633# define RECORD_IO 1
629# define casemap(c) tolow(c) /* Force file names to lower case */ 634# define casemap(c) tolow(c) /* Force file names to lower case */
630# define put_char(c) put_byte((c) & 0x7F) 635# define put_char(c) put_byte((c) & 0x7F)
631# define get_char(c) ascii2pascii(get_byte()) 636# define get_char(c) ascii2pascii(get_byte())
632# define OS_CODE 0x0F /* temporary, subject to change */ 637# define OS_CODE 0x0F /* temporary, subject to change */
633# ifdef SIGTERM 638# ifdef SIGTERM
634# undef SIGTERM /* We don't want a signal handler for SIGTERM */ 639# undef SIGTERM /* We don't want a signal handler for SIGTERM */
635# endif 640# endif
636#endif 641#endif
637 642
638#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */ 643#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */
639# define NOMEMCPY /* problem with overlapping copies */ 644# define NOMEMCPY /* problem with overlapping copies */
640#endif 645#endif
641 646
642#ifdef TOPS20 647#ifdef TOPS20
@@ -644,14 +649,14 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
644#endif 649#endif
645 650
646#ifndef unix 651#ifndef unix
647# define NO_ST_INO /* don't rely on inode numbers */ 652# define NO_ST_INO /* don't rely on inode numbers */
648#endif 653#endif
649 654
650 655
651 /* Common defaults */ 656 /* Common defaults */
652 657
653#ifndef OS_CODE 658#ifndef OS_CODE
654# define OS_CODE 0x03 /* assume Unix */ 659# define OS_CODE 0x03 /* assume Unix */
655#endif 660#endif
656 661
657#ifndef PATH_SEP 662#ifndef PATH_SEP
@@ -773,9 +778,10 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
773 * Local data used by the "bit string" routines. 778 * Local data used by the "bit string" routines.
774 */ 779 */
775 780
776local file_t zfile; /* output gzip file */ 781local file_t zfile; /* output gzip file */
777 782
778local unsigned short bi_buf; 783local unsigned short bi_buf;
784
779/* Output buffer. bits are inserted starting at the bottom (least significant 785/* Output buffer. bits are inserted starting at the bottom (least significant
780 * bits). 786 * bits).
781 */ 787 */
@@ -786,36 +792,38 @@ local unsigned short bi_buf;
786 */ 792 */
787 793
788local int bi_valid; 794local int bi_valid;
795
789/* Number of valid bits in bi_buf. All bits above the last valid bit 796/* Number of valid bits in bi_buf. All bits above the last valid bit
790 * are always zero. 797 * are always zero.
791 */ 798 */
792 799
793int (*read_buf) OF((char *buf, unsigned size)); 800int (*read_buf) OF((char *buf, unsigned size));
801
794/* Current input function. Set to mem_read for in-memory compression */ 802/* Current input function. Set to mem_read for in-memory compression */
795 803
796#ifdef DEBUG 804#ifdef DEBUG
797 ulg bits_sent; /* bit length of the compressed data */ 805ulg bits_sent; /* bit length of the compressed data */
798#endif 806#endif
799 807
800/* =========================================================================== 808/* ===========================================================================
801 * Initialize the bit string routines. 809 * Initialize the bit string routines.
802 */ 810 */
803void bi_init (zipfile) 811void bi_init(zipfile)
804 file_t zipfile; /* output zip file, NO_FILE for in-memory compression */ 812file_t zipfile; /* output zip file, NO_FILE for in-memory compression */
805{ 813{
806 zfile = zipfile; 814 zfile = zipfile;
807 bi_buf = 0; 815 bi_buf = 0;
808 bi_valid = 0; 816 bi_valid = 0;
809#ifdef DEBUG 817#ifdef DEBUG
810 bits_sent = 0L; 818 bits_sent = 0L;
811#endif 819#endif
812 820
813 /* Set the defaults for file compression. They are set by memcompress 821 /* Set the defaults for file compression. They are set by memcompress
814 * for in-memory compression. 822 * for in-memory compression.
815 */ 823 */
816 if (zfile != NO_FILE) { 824 if (zfile != NO_FILE) {
817 read_buf = file_read; 825 read_buf = file_read;
818 } 826 }
819} 827}
820 828
821/* =========================================================================== 829/* ===========================================================================
@@ -823,27 +831,27 @@ void bi_init (zipfile)
823 * IN assertion: length <= 16 and value fits in length bits. 831 * IN assertion: length <= 16 and value fits in length bits.
824 */ 832 */
825void send_bits(value, length) 833void send_bits(value, length)
826 int value; /* value to send */ 834int value; /* value to send */
827 int length; /* number of bits */ 835int length; /* number of bits */
828{ 836{
829#ifdef DEBUG 837#ifdef DEBUG
830 Tracev((stderr," l %2d v %4x ", length, value)); 838 Tracev((stderr, " l %2d v %4x ", length, value));
831 Assert(length > 0 && length <= 15, "invalid length"); 839 Assert(length > 0 && length <= 15, "invalid length");
832 bits_sent += (ulg)length; 840 bits_sent += (ulg) length;
833#endif 841#endif
834 /* If not enough room in bi_buf, use (valid) bits from bi_buf and 842 /* If not enough room in bi_buf, use (valid) bits from bi_buf and
835 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) 843 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
836 * unused bits in value. 844 * unused bits in value.
837 */ 845 */
838 if (bi_valid > (int)Buf_size - length) { 846 if (bi_valid > (int) Buf_size - length) {
839 bi_buf |= (value << bi_valid); 847 bi_buf |= (value << bi_valid);
840 put_short(bi_buf); 848 put_short(bi_buf);
841 bi_buf = (ush)value >> (Buf_size - bi_valid); 849 bi_buf = (ush) value >> (Buf_size - bi_valid);
842 bi_valid += length - Buf_size; 850 bi_valid += length - Buf_size;
843 } else { 851 } else {
844 bi_buf |= value << bi_valid; 852 bi_buf |= value << bi_valid;
845 bi_valid += length; 853 bi_valid += length;
846 } 854 }
847} 855}
848 856
849/* =========================================================================== 857/* ===========================================================================
@@ -852,15 +860,16 @@ void send_bits(value, length)
852 * IN assertion: 1 <= len <= 15 860 * IN assertion: 1 <= len <= 15
853 */ 861 */
854unsigned bi_reverse(code, len) 862unsigned bi_reverse(code, len)
855 unsigned code; /* the value to invert */ 863unsigned code; /* the value to invert */
856 int len; /* its bit length */ 864int len; /* its bit length */
857{ 865{
858 register unsigned res = 0; 866 register unsigned res = 0;
859 do { 867
860 res |= code & 1; 868 do {
861 code >>= 1, res <<= 1; 869 res |= code & 1;
862 } while (--len > 0); 870 code >>= 1, res <<= 1;
863 return res >> 1; 871 } while (--len > 0);
872 return res >> 1;
864} 873}
865 874
866/* =========================================================================== 875/* ===========================================================================
@@ -868,15 +877,15 @@ unsigned bi_reverse(code, len)
868 */ 877 */
869void bi_windup() 878void bi_windup()
870{ 879{
871 if (bi_valid > 8) { 880 if (bi_valid > 8) {
872 put_short(bi_buf); 881 put_short(bi_buf);
873 } else if (bi_valid > 0) { 882 } else if (bi_valid > 0) {
874 put_byte(bi_buf); 883 put_byte(bi_buf);
875 } 884 }
876 bi_buf = 0; 885 bi_buf = 0;
877 bi_valid = 0; 886 bi_valid = 0;
878#ifdef DEBUG 887#ifdef DEBUG
879 bits_sent = (bits_sent+7) & ~7; 888 bits_sent = (bits_sent + 7) & ~7;
880#endif 889#endif
881} 890}
882 891
@@ -885,30 +894,33 @@ void bi_windup()
885 * one's complement if requested. 894 * one's complement if requested.
886 */ 895 */
887void copy_block(buf, len, header) 896void copy_block(buf, len, header)
888 char *buf; /* the input data */ 897char *buf; /* the input data */
889 unsigned len; /* its length */ 898unsigned len; /* its length */
890 int header; /* true if block header must be written */ 899int header; /* true if block header must be written */
891{ 900{
892 bi_windup(); /* align on byte boundary */ 901 bi_windup(); /* align on byte boundary */
893 902
894 if (header) { 903 if (header) {
895 put_short((ush)len); 904 put_short((ush) len);
896 put_short((ush)~len); 905 put_short((ush) ~ len);
897#ifdef DEBUG 906#ifdef DEBUG
898 bits_sent += 2*16; 907 bits_sent += 2 * 16;
899#endif 908#endif
900 } 909 }
901#ifdef DEBUG 910#ifdef DEBUG
902 bits_sent += (ulg)len<<3; 911 bits_sent += (ulg) len << 3;
903#endif 912#endif
904 while (len--) { 913 while (len--) {
905#ifdef CRYPT 914#ifdef CRYPT
906 int t; 915 int t;
907 if (key) zencode(*buf, t); 916
917 if (key)
918 zencode(*buf, t);
908#endif 919#endif
909 put_byte(*buf++); 920 put_byte(*buf++);
910 } 921 }
911} 922}
923
912/* deflate.c -- compress data using the deflation algorithm 924/* deflate.c -- compress data using the deflation algorithm
913 * Copyright (C) 1992-1993 Jean-loup Gailly 925 * Copyright (C) 1992-1993 Jean-loup Gailly
914 * This is free software; you can redistribute it and/or modify it under the 926 * This is free software; you can redistribute it and/or modify it under the
@@ -987,7 +999,7 @@ void copy_block(buf, len, header)
987 */ 999 */
988 1000
989#ifdef SMALL_MEM 1001#ifdef SMALL_MEM
990# define HASH_BITS 13 /* Number of bits used to hash strings */ 1002# define HASH_BITS 13 /* Number of bits used to hash strings */
991#endif 1003#endif
992#ifdef MEDIUM_MEM 1004#ifdef MEDIUM_MEM
993# define HASH_BITS 14 1005# define HASH_BITS 14
@@ -1001,35 +1013,30 @@ void copy_block(buf, len, header)
1001 * window with tab_suffix. Check that we can do this: 1013 * window with tab_suffix. Check that we can do this:
1002 */ 1014 */
1003#if (WSIZE<<1) > (1<<BITS) 1015#if (WSIZE<<1) > (1<<BITS)
1004 error: cannot overlay window with tab_suffix and prev with tab_prefix0 1016error:cannot overlay window with tab_suffix and prev with tab_prefix0
1005#endif 1017#endif
1006#if HASH_BITS > BITS-1 1018#if HASH_BITS > BITS-1
1007 error: cannot overlay head with tab_prefix1 1019error:cannot overlay head with tab_prefix1
1008#endif 1020#endif
1009
1010#define HASH_SIZE (unsigned)(1<<HASH_BITS) 1021#define HASH_SIZE (unsigned)(1<<HASH_BITS)
1011#define HASH_MASK (HASH_SIZE-1) 1022#define HASH_MASK (HASH_SIZE-1)
1012#define WMASK (WSIZE-1) 1023#define WMASK (WSIZE-1)
1013/* HASH_SIZE and WSIZE must be powers of two */ 1024/* HASH_SIZE and WSIZE must be powers of two */
1014
1015#define NIL 0 1025#define NIL 0
1016/* Tail of hash chains */ 1026/* Tail of hash chains */
1017
1018#define FAST 4 1027#define FAST 4
1019#define SLOW 2 1028#define SLOW 2
1020/* speed options for the general purpose bit flag */ 1029/* speed options for the general purpose bit flag */
1021
1022#ifndef TOO_FAR 1030#ifndef TOO_FAR
1023# define TOO_FAR 4096 1031# define TOO_FAR 4096
1024#endif 1032#endif
1025/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ 1033/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
1026
1027/* =========================================================================== 1034/* ===========================================================================
1028 * Local data used by the "longest match" routines. 1035 * Local data used by the "longest match" routines.
1029 */ 1036 */
1030
1031typedef ush Pos; 1037typedef ush Pos;
1032typedef unsigned IPos; 1038typedef unsigned IPos;
1039
1033/* A Pos is an index in the character window. We use short instead of int to 1040/* A Pos is an index in the character window. We use short instead of int to
1034 * save space in the various tables. IPos is used only for parameter passing. 1041 * save space in the various tables. IPos is used only for parameter passing.
1035 */ 1042 */
@@ -1054,17 +1061,19 @@ typedef unsigned IPos;
1054/* DECLARE(Pos, head, 1<<HASH_BITS); */ 1061/* DECLARE(Pos, head, 1<<HASH_BITS); */
1055/* Heads of the hash chains or NIL. */ 1062/* Heads of the hash chains or NIL. */
1056 1063
1057ulg window_size = (ulg)2*WSIZE; 1064ulg window_size = (ulg) 2 * WSIZE;
1065
1058/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the 1066/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
1059 * input file length plus MIN_LOOKAHEAD. 1067 * input file length plus MIN_LOOKAHEAD.
1060 */ 1068 */
1061 1069
1062long block_start; 1070long block_start;
1071
1063/* window position at the beginning of the current output block. Gets 1072/* window position at the beginning of the current output block. Gets
1064 * negative when the window is moved backwards. 1073 * negative when the window is moved backwards.
1065 */ 1074 */
1066 1075
1067local unsigned ins_h; /* hash index of string to be inserted */ 1076local unsigned ins_h; /* hash index of string to be inserted */
1068 1077
1069#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH) 1078#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
1070/* Number of bits by which ins_h and del_h must be shifted at each 1079/* Number of bits by which ins_h and del_h must be shifted at each
@@ -1074,21 +1083,24 @@ local unsigned ins_h; /* hash index of string to be inserted */
1074 */ 1083 */
1075 1084
1076unsigned int near prev_length; 1085unsigned int near prev_length;
1086
1077/* Length of the best match at previous step. Matches not greater than this 1087/* Length of the best match at previous step. Matches not greater than this
1078 * are discarded. This is used in the lazy match evaluation. 1088 * are discarded. This is used in the lazy match evaluation.
1079 */ 1089 */
1080 1090
1081 unsigned near strstart; /* start of string to insert */ 1091unsigned near strstart; /* start of string to insert */
1082 unsigned near match_start; /* start of matching string */ 1092unsigned near match_start; /* start of matching string */
1083local int eofile; /* flag set at end of input file */ 1093local int eofile; /* flag set at end of input file */
1084local unsigned lookahead; /* number of valid bytes ahead in window */ 1094local unsigned lookahead; /* number of valid bytes ahead in window */
1085 1095
1086unsigned near max_chain_length; 1096unsigned near max_chain_length;
1097
1087/* To speed up deflation, hash chains are never searched beyond this length. 1098/* To speed up deflation, hash chains are never searched beyond this length.
1088 * A higher limit improves compression ratio but degrades the speed. 1099 * A higher limit improves compression ratio but degrades the speed.
1089 */ 1100 */
1090 1101
1091local unsigned int max_lazy_match; 1102local unsigned int max_lazy_match;
1103
1092/* Attempt to find a better match only when the current match is strictly 1104/* Attempt to find a better match only when the current match is strictly
1093 * smaller than this value. This mechanism is used only for compression 1105 * smaller than this value. This mechanism is used only for compression
1094 * levels >= 4. 1106 * levels >= 4.
@@ -1100,6 +1112,7 @@ local unsigned int max_lazy_match;
1100 */ 1112 */
1101 1113
1102unsigned near good_match; 1114unsigned near good_match;
1115
1103/* Use a faster search when the previous match is longer than this */ 1116/* Use a faster search when the previous match is longer than this */
1104 1117
1105 1118
@@ -1110,20 +1123,21 @@ unsigned near good_match;
1110 */ 1123 */
1111 1124
1112typedef struct config { 1125typedef struct config {
1113 ush good_length; /* reduce lazy search above this match length */ 1126 ush good_length; /* reduce lazy search above this match length */
1114 ush max_lazy; /* do not perform lazy search above this match length */ 1127 ush max_lazy; /* do not perform lazy search above this match length */
1115 ush nice_length; /* quit search above this match length */ 1128 ush nice_length; /* quit search above this match length */
1116 ush max_chain; 1129 ush max_chain;
1117} config; 1130} config;
1118 1131
1119#ifdef FULL_SEARCH 1132#ifdef FULL_SEARCH
1120# define nice_match MAX_MATCH 1133# define nice_match MAX_MATCH
1121#else 1134#else
1122 int near nice_match; /* Stop searching when current match exceeds this */ 1135int near nice_match; /* Stop searching when current match exceeds this */
1123#endif 1136#endif
1124 1137
1125local config configuration_table = 1138local config configuration_table =
1126/* 9 */ {32, 258, 258, 4096}; /* maximum compression */ 1139 /* 9 */ { 32, 258, 258, 4096 };
1140 /* maximum compression */
1127 1141
1128/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 1142/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
1129 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different 1143 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
@@ -1136,15 +1150,16 @@ local config configuration_table =
1136/* =========================================================================== 1150/* ===========================================================================
1137 * Prototypes for local functions. 1151 * Prototypes for local functions.
1138 */ 1152 */
1139local void fill_window OF((void)); 1153local void fill_window OF((void));
1154
1155int longest_match OF((IPos cur_match));
1140 1156
1141 int longest_match OF((IPos cur_match));
1142#ifdef ASMV 1157#ifdef ASMV
1143 void match_init OF((void)); /* asm code initialization */ 1158void match_init OF((void)); /* asm code initialization */
1144#endif 1159#endif
1145 1160
1146#ifdef DEBUG 1161#ifdef DEBUG
1147local void check_match OF((IPos start, IPos match, int length)); 1162local void check_match OF((IPos start, IPos match, int length));
1148#endif 1163#endif
1149 1164
1150/* =========================================================================== 1165/* ===========================================================================
@@ -1171,54 +1186,57 @@ local void check_match OF((IPos start, IPos match, int length));
1171/* =========================================================================== 1186/* ===========================================================================
1172 * Initialize the "longest match" routines for a new file 1187 * Initialize the "longest match" routines for a new file
1173 */ 1188 */
1174void lm_init (flags) 1189void lm_init(flags)
1175 ush *flags; /* general purpose bit flag */ 1190ush *flags; /* general purpose bit flag */
1176{ 1191{
1177 register unsigned j; 1192 register unsigned j;
1178 1193
1179 /* Initialize the hash table. */ 1194 /* Initialize the hash table. */
1180#if defined(MAXSEG_64K) && HASH_BITS == 15 1195#if defined(MAXSEG_64K) && HASH_BITS == 15
1181 for (j = 0; j < HASH_SIZE; j++) head[j] = NIL; 1196 for (j = 0; j < HASH_SIZE; j++)
1197 head[j] = NIL;
1182#else 1198#else
1183 memzero((char*)head, HASH_SIZE*sizeof(*head)); 1199 memzero((char *) head, HASH_SIZE * sizeof(*head));
1184#endif 1200#endif
1185 /* prev will be initialized on the fly */ 1201 /* prev will be initialized on the fly */
1186 1202
1187 /* Set the default configuration parameters: 1203 /* Set the default configuration parameters:
1188 */ 1204 */
1189 max_lazy_match = configuration_table.max_lazy; 1205 max_lazy_match = configuration_table.max_lazy;
1190 good_match = configuration_table.good_length; 1206 good_match = configuration_table.good_length;
1191#ifndef FULL_SEARCH 1207#ifndef FULL_SEARCH
1192 nice_match = configuration_table.nice_length; 1208 nice_match = configuration_table.nice_length;
1193#endif 1209#endif
1194 max_chain_length = configuration_table.max_chain; 1210 max_chain_length = configuration_table.max_chain;
1195 *flags |= SLOW; 1211 *flags |= SLOW;
1196 /* ??? reduce max_chain_length for binary files */ 1212 /* ??? reduce max_chain_length for binary files */
1197 1213
1198 strstart = 0; 1214 strstart = 0;
1199 block_start = 0L; 1215 block_start = 0L;
1200#ifdef ASMV 1216#ifdef ASMV
1201 match_init(); /* initialize the asm code */ 1217 match_init(); /* initialize the asm code */
1202#endif 1218#endif
1203 1219
1204 lookahead = read_buf((char*)window, 1220 lookahead = read_buf((char *) window,
1205 sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE); 1221 sizeof(int) <= 2 ? (unsigned) WSIZE : 2 * WSIZE);
1206 1222
1207 if (lookahead == 0 || lookahead == (unsigned)EOF) { 1223 if (lookahead == 0 || lookahead == (unsigned) EOF) {
1208 eofile = 1, lookahead = 0; 1224 eofile = 1, lookahead = 0;
1209 return; 1225 return;
1210 } 1226 }
1211 eofile = 0; 1227 eofile = 0;
1212 /* Make sure that we always have enough lookahead. This is important 1228 /* Make sure that we always have enough lookahead. This is important
1213 * if input comes from a device such as a tty. 1229 * if input comes from a device such as a tty.
1214 */ 1230 */
1215 while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); 1231 while (lookahead < MIN_LOOKAHEAD && !eofile)
1216 1232 fill_window();
1217 ins_h = 0; 1233
1218 for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]); 1234 ins_h = 0;
1219 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is 1235 for (j = 0; j < MIN_MATCH - 1; j++)
1220 * not important since only literal bytes will be emitted. 1236 UPDATE_HASH(ins_h, window[j]);
1221 */ 1237 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
1238 * not important since only literal bytes will be emitted.
1239 */
1222} 1240}
1223 1241
1224/* =========================================================================== 1242/* ===========================================================================
@@ -1235,151 +1253,157 @@ void lm_init (flags)
1235 * if desired. 1253 * if desired.
1236 */ 1254 */
1237int longest_match(cur_match) 1255int longest_match(cur_match)
1238 IPos cur_match; /* current match */ 1256IPos cur_match; /* current match */
1239{ 1257{
1240 unsigned chain_length = max_chain_length; /* max hash chain length */ 1258 unsigned chain_length = max_chain_length; /* max hash chain length */
1241 register uch *scan = window + strstart; /* current string */ 1259 register uch *scan = window + strstart; /* current string */
1242 register uch *match; /* matched string */ 1260 register uch *match; /* matched string */
1243 register int len; /* length of current match */ 1261 register int len; /* length of current match */
1244 int best_len = prev_length; /* best match length so far */ 1262 int best_len = prev_length; /* best match length so far */
1245 IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL; 1263 IPos limit =
1246 /* Stop when cur_match becomes <= limit. To simplify the code, 1264
1247 * we prevent matches with the string of window index 0. 1265 strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL;
1248 */ 1266 /* Stop when cur_match becomes <= limit. To simplify the code,
1267 * we prevent matches with the string of window index 0.
1268 */
1249 1269
1250/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 1270/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
1251 * It is easy to get rid of this optimization if necessary. 1271 * It is easy to get rid of this optimization if necessary.
1252 */ 1272 */
1253#if HASH_BITS < 8 || MAX_MATCH != 258 1273#if HASH_BITS < 8 || MAX_MATCH != 258
1254 error: Code too clever 1274 error:Code too clever
1255#endif 1275#endif
1256
1257#ifdef UNALIGNED_OK 1276#ifdef UNALIGNED_OK
1258 /* Compare two bytes at a time. Note: this is not always beneficial. 1277 /* Compare two bytes at a time. Note: this is not always beneficial.
1259 * Try with and without -DUNALIGNED_OK to check. 1278 * Try with and without -DUNALIGNED_OK to check.
1260 */ 1279 */
1261 register uch *strend = window + strstart + MAX_MATCH - 1; 1280 register uch *strend = window + strstart + MAX_MATCH - 1;
1262 register ush scan_start = *(ush*)scan; 1281 register ush scan_start = *(ush *) scan;
1263 register ush scan_end = *(ush*)(scan+best_len-1); 1282 register ush scan_end = *(ush *) (scan + best_len - 1);
1264#else 1283#else
1265 register uch *strend = window + strstart + MAX_MATCH; 1284 register uch *strend = window + strstart + MAX_MATCH;
1266 register uch scan_end1 = scan[best_len-1]; 1285 register uch scan_end1 = scan[best_len - 1];
1267 register uch scan_end = scan[best_len]; 1286 register uch scan_end = scan[best_len];
1268#endif 1287#endif
1269 1288
1270 /* Do not waste too much time if we already have a good match: */ 1289 /* Do not waste too much time if we already have a good match: */
1271 if (prev_length >= good_match) { 1290 if (prev_length >= good_match) {
1272 chain_length >>= 2; 1291 chain_length >>= 2;
1273 } 1292 }
1274 Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); 1293 Assert(strstart <= window_size - MIN_LOOKAHEAD,
1294 "insufficient lookahead");
1275 1295
1276 do { 1296 do {
1277 Assert(cur_match < strstart, "no future"); 1297 Assert(cur_match < strstart, "no future");
1278 match = window + cur_match; 1298 match = window + cur_match;
1279 1299
1280 /* Skip to next match if the match length cannot increase 1300 /* Skip to next match if the match length cannot increase
1281 * or if the match length is less than 2: 1301 * or if the match length is less than 2:
1282 */ 1302 */
1283#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) 1303#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
1284 /* This code assumes sizeof(unsigned short) == 2. Do not use 1304 /* This code assumes sizeof(unsigned short) == 2. Do not use
1285 * UNALIGNED_OK if your compiler uses a different size. 1305 * UNALIGNED_OK if your compiler uses a different size.
1286 */ 1306 */
1287 if (*(ush*)(match+best_len-1) != scan_end || 1307 if (*(ush *) (match + best_len - 1) != scan_end ||
1288 *(ush*)match != scan_start) continue; 1308 *(ush *) match != scan_start)
1289 1309 continue;
1290 /* It is not necessary to compare scan[2] and match[2] since they are 1310
1291 * always equal when the other bytes match, given that the hash keys 1311 /* It is not necessary to compare scan[2] and match[2] since they are
1292 * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at 1312 * always equal when the other bytes match, given that the hash keys
1293 * strstart+3, +5, ... up to strstart+257. We check for insufficient 1313 * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
1294 * lookahead only every 4th comparison; the 128th check will be made 1314 * strstart+3, +5, ... up to strstart+257. We check for insufficient
1295 * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is 1315 * lookahead only every 4th comparison; the 128th check will be made
1296 * necessary to put more guard bytes at the end of the window, or 1316 * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
1297 * to check more often for insufficient lookahead. 1317 * necessary to put more guard bytes at the end of the window, or
1298 */ 1318 * to check more often for insufficient lookahead.
1299 scan++, match++; 1319 */
1300 do { 1320 scan++, match++;
1301 } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && 1321 do {
1302 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1322 } while (*(ush *) (scan += 2) == *(ush *) (match += 2) &&
1303 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1323 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1304 *(ush*)(scan+=2) == *(ush*)(match+=2) && 1324 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1305 scan < strend); 1325 *(ush *) (scan += 2) == *(ush *) (match += 2) &&
1306 /* The funny "do {}" generates better code on most compilers */ 1326 scan < strend);
1307 1327 /* The funny "do {}" generates better code on most compilers */
1308 /* Here, scan <= window+strstart+257 */ 1328
1309 Assert(scan <= window+(unsigned)(window_size-1), "wild scan"); 1329 /* Here, scan <= window+strstart+257 */
1310 if (*scan == *match) scan++; 1330 Assert(scan <= window + (unsigned) (window_size - 1), "wild scan");
1311 1331 if (*scan == *match)
1312 len = (MAX_MATCH - 1) - (int)(strend-scan); 1332 scan++;
1313 scan = strend - (MAX_MATCH-1); 1333
1314 1334 len = (MAX_MATCH - 1) - (int) (strend - scan);
1315#else /* UNALIGNED_OK */ 1335 scan = strend - (MAX_MATCH - 1);
1316 1336
1317 if (match[best_len] != scan_end || 1337#else /* UNALIGNED_OK */
1318 match[best_len-1] != scan_end1 || 1338
1319 *match != *scan || 1339 if (match[best_len] != scan_end ||
1320 *++match != scan[1]) continue; 1340 match[best_len - 1] != scan_end1 ||
1321 1341 *match != *scan || *++match != scan[1])
1322 /* The check at best_len-1 can be removed because it will be made 1342 continue;
1323 * again later. (This heuristic is not always a win.) 1343
1324 * It is not necessary to compare scan[2] and match[2] since they 1344 /* The check at best_len-1 can be removed because it will be made
1325 * are always equal when the other bytes match, given that 1345 * again later. (This heuristic is not always a win.)
1326 * the hash keys are equal and that HASH_BITS >= 8. 1346 * It is not necessary to compare scan[2] and match[2] since they
1327 */ 1347 * are always equal when the other bytes match, given that
1328 scan += 2, match++; 1348 * the hash keys are equal and that HASH_BITS >= 8.
1329 1349 */
1330 /* We check for insufficient lookahead only every 8th comparison; 1350 scan += 2, match++;
1331 * the 256th check will be made at strstart+258. 1351
1332 */ 1352 /* We check for insufficient lookahead only every 8th comparison;
1333 do { 1353 * the 256th check will be made at strstart+258.
1334 } while (*++scan == *++match && *++scan == *++match && 1354 */
1335 *++scan == *++match && *++scan == *++match && 1355 do {
1336 *++scan == *++match && *++scan == *++match && 1356 } while (*++scan == *++match && *++scan == *++match &&
1337 *++scan == *++match && *++scan == *++match && 1357 *++scan == *++match && *++scan == *++match &&
1338 scan < strend); 1358 *++scan == *++match && *++scan == *++match &&
1339 1359 *++scan == *++match && *++scan == *++match &&
1340 len = MAX_MATCH - (int)(strend - scan); 1360 scan < strend);
1341 scan = strend - MAX_MATCH; 1361
1342 1362 len = MAX_MATCH - (int) (strend - scan);
1343#endif /* UNALIGNED_OK */ 1363 scan = strend - MAX_MATCH;
1344 1364
1345 if (len > best_len) { 1365#endif /* UNALIGNED_OK */
1346 match_start = cur_match; 1366
1347 best_len = len; 1367 if (len > best_len) {
1348 if (len >= nice_match) break; 1368 match_start = cur_match;
1369 best_len = len;
1370 if (len >= nice_match)
1371 break;
1349#ifdef UNALIGNED_OK 1372#ifdef UNALIGNED_OK
1350 scan_end = *(ush*)(scan+best_len-1); 1373 scan_end = *(ush *) (scan + best_len - 1);
1351#else 1374#else
1352 scan_end1 = scan[best_len-1]; 1375 scan_end1 = scan[best_len - 1];
1353 scan_end = scan[best_len]; 1376 scan_end = scan[best_len];
1354#endif 1377#endif
1355 } 1378 }
1356 } while ((cur_match = prev[cur_match & WMASK]) > limit 1379 } while ((cur_match = prev[cur_match & WMASK]) > limit
1357 && --chain_length != 0); 1380 && --chain_length != 0);
1358 1381
1359 return best_len; 1382 return best_len;
1360} 1383}
1361#endif /* ASMV */ 1384#endif /* ASMV */
1362 1385
1363#ifdef DEBUG 1386#ifdef DEBUG
1364/* =========================================================================== 1387/* ===========================================================================
1365 * Check that the match at match_start is indeed a match. 1388 * Check that the match at match_start is indeed a match.
1366 */ 1389 */
1367local void check_match(start, match, length) 1390local void check_match(start, match, length)
1368 IPos start, match; 1391IPos start, match;
1369 int length; 1392int length;
1370{ 1393{
1371 /* check that the match is indeed a match */ 1394 /* check that the match is indeed a match */
1372 if (memcmp((char*)window + match, 1395 if (memcmp((char *) window + match,
1373 (char*)window + start, length) != EQUAL) { 1396 (char *) window + start, length) != EQUAL) {
1374 fprintf(stderr, 1397 fprintf(stderr,
1375 " start %d, match %d, length %d\n", 1398 " start %d, match %d, length %d\n", start, match, length);
1376 start, match, length); 1399 error("invalid match");
1377 error("invalid match"); 1400 }
1378 } 1401 if (verbose > 1) {
1379 if (verbose > 1) { 1402 fprintf(stderr, "\\[%d,%d]", start - match, length);
1380 fprintf(stderr,"\\[%d,%d]", start-match, length); 1403 do {
1381 do { putc(window[start++], stderr); } while (--length != 0); 1404 putc(window[start++], stderr);
1382 } 1405 } while (--length != 0);
1406 }
1383} 1407}
1384#else 1408#else
1385# define check_match(start, match, length) 1409# define check_match(start, match, length)
@@ -1395,52 +1419,54 @@ local void check_match(start, match, length)
1395 */ 1419 */
1396local void fill_window() 1420local void fill_window()
1397{ 1421{
1398 register unsigned n, m; 1422 register unsigned n, m;
1399 unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart); 1423 unsigned more =
1400 /* Amount of free space at the end of the window. */ 1424
1401 1425 (unsigned) (window_size - (ulg) lookahead - (ulg) strstart);
1402 /* If the window is almost full and there is insufficient lookahead, 1426 /* Amount of free space at the end of the window. */
1403 * move the upper half to the lower one to make room in the upper half. 1427
1404 */ 1428 /* If the window is almost full and there is insufficient lookahead,
1405 if (more == (unsigned)EOF) { 1429 * move the upper half to the lower one to make room in the upper half.
1406 /* Very unlikely, but possible on 16 bit machine if strstart == 0 1430 */
1407 * and lookahead == 1 (input done one byte at time) 1431 if (more == (unsigned) EOF) {
1408 */ 1432 /* Very unlikely, but possible on 16 bit machine if strstart == 0
1409 more--; 1433 * and lookahead == 1 (input done one byte at time)
1410 } else if (strstart >= WSIZE+MAX_DIST) { 1434 */
1411 /* By the IN assertion, the window is not empty so we can't confuse 1435 more--;
1412 * more == 0 with more == 64K on a 16 bit machine. 1436 } else if (strstart >= WSIZE + MAX_DIST) {
1413 */ 1437 /* By the IN assertion, the window is not empty so we can't confuse
1414 Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); 1438 * more == 0 with more == 64K on a 16 bit machine.
1415 1439 */
1416 memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE); 1440 Assert(window_size == (ulg) 2 * WSIZE, "no sliding with BIG_MEM");
1417 match_start -= WSIZE; 1441
1418 strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ 1442 memcpy((char *) window, (char *) window + WSIZE, (unsigned) WSIZE);
1419 1443 match_start -= WSIZE;
1420 block_start -= (long) WSIZE; 1444 strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
1421 1445
1422 for (n = 0; n < HASH_SIZE; n++) { 1446 block_start -= (long) WSIZE;
1423 m = head[n]; 1447
1424 head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1448 for (n = 0; n < HASH_SIZE; n++) {
1425 } 1449 m = head[n];
1426 for (n = 0; n < WSIZE; n++) { 1450 head[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1427 m = prev[n]; 1451 }
1428 prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1452 for (n = 0; n < WSIZE; n++) {
1429 /* If n is not on any hash chain, prev[n] is garbage but 1453 m = prev[n];
1430 * its value will never be used. 1454 prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1431 */ 1455 /* If n is not on any hash chain, prev[n] is garbage but
1432 } 1456 * its value will never be used.
1433 more += WSIZE; 1457 */
1434 } 1458 }
1435 /* At this point, more >= 2 */ 1459 more += WSIZE;
1436 if (!eofile) { 1460 }
1437 n = read_buf((char*)window+strstart+lookahead, more); 1461 /* At this point, more >= 2 */
1438 if (n == 0 || n == (unsigned)EOF) { 1462 if (!eofile) {
1439 eofile = 1; 1463 n = read_buf((char *) window + strstart + lookahead, more);
1440 } else { 1464 if (n == 0 || n == (unsigned) EOF) {
1441 lookahead += n; 1465 eofile = 1;
1442 } 1466 } else {
1443 } 1467 lookahead += n;
1468 }
1469 }
1444} 1470}
1445 1471
1446/* =========================================================================== 1472/* ===========================================================================
@@ -1458,105 +1484,114 @@ local void fill_window()
1458 */ 1484 */
1459ulg deflate() 1485ulg deflate()
1460{ 1486{
1461 IPos hash_head; /* head of hash chain */ 1487 IPos hash_head; /* head of hash chain */
1462 IPos prev_match; /* previous match */ 1488 IPos prev_match; /* previous match */
1463 int flush; /* set if current block must be flushed */ 1489 int flush; /* set if current block must be flushed */
1464 int match_available = 0; /* set if previous match exists */ 1490 int match_available = 0; /* set if previous match exists */
1465 register unsigned match_length = MIN_MATCH-1; /* length of best match */ 1491 register unsigned match_length = MIN_MATCH - 1; /* length of best match */
1492
1466#ifdef DEBUG 1493#ifdef DEBUG
1467 extern long isize; /* byte length of input file, for debug only */ 1494 extern long isize; /* byte length of input file, for debug only */
1468#endif 1495#endif
1469 1496
1470 /* Process the input block. */ 1497 /* Process the input block. */
1471 while (lookahead != 0) { 1498 while (lookahead != 0) {
1472 /* Insert the string window[strstart .. strstart+2] in the 1499 /* Insert the string window[strstart .. strstart+2] in the
1473 * dictionary, and set hash_head to the head of the hash chain: 1500 * dictionary, and set hash_head to the head of the hash chain:
1474 */ 1501 */
1475 INSERT_STRING(strstart, hash_head); 1502 INSERT_STRING(strstart, hash_head);
1476 1503
1477 /* Find the longest match, discarding those <= prev_length. 1504 /* Find the longest match, discarding those <= prev_length.
1478 */ 1505 */
1479 prev_length = match_length, prev_match = match_start; 1506 prev_length = match_length, prev_match = match_start;
1480 match_length = MIN_MATCH-1; 1507 match_length = MIN_MATCH - 1;
1481 1508
1482 if (hash_head != NIL && prev_length < max_lazy_match && 1509 if (hash_head != NIL && prev_length < max_lazy_match &&
1483 strstart - hash_head <= MAX_DIST) { 1510 strstart - hash_head <= MAX_DIST) {
1484 /* To simplify the code, we prevent matches with the string 1511 /* To simplify the code, we prevent matches with the string
1485 * of window index 0 (in particular we have to avoid a match 1512 * of window index 0 (in particular we have to avoid a match
1486 * of the string with itself at the start of the input file). 1513 * of the string with itself at the start of the input file).
1487 */ 1514 */
1488 match_length = longest_match (hash_head); 1515 match_length = longest_match(hash_head);
1489 /* longest_match() sets match_start */ 1516 /* longest_match() sets match_start */
1490 if (match_length > lookahead) match_length = lookahead; 1517 if (match_length > lookahead)
1491 1518 match_length = lookahead;
1492 /* Ignore a length 3 match if it is too distant: */ 1519
1493 if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){ 1520 /* Ignore a length 3 match if it is too distant: */
1494 /* If prev_match is also MIN_MATCH, match_start is garbage 1521 if (match_length == MIN_MATCH
1495 * but we will ignore the current match anyway. 1522 && strstart - match_start > TOO_FAR) {
1496 */ 1523 /* If prev_match is also MIN_MATCH, match_start is garbage
1497 match_length--; 1524 * but we will ignore the current match anyway.
1498 } 1525 */
1499 } 1526 match_length--;
1500 /* If there was a match at the previous step and the current 1527 }
1501 * match is not better, output the previous match: 1528 }
1502 */ 1529 /* If there was a match at the previous step and the current
1503 if (prev_length >= MIN_MATCH && match_length <= prev_length) { 1530 * match is not better, output the previous match:
1504 1531 */
1505 check_match(strstart-1, prev_match, prev_length); 1532 if (prev_length >= MIN_MATCH && match_length <= prev_length) {
1506 1533
1507 flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); 1534 check_match(strstart - 1, prev_match, prev_length);
1508 1535
1509 /* Insert in hash table all strings up to the end of the match. 1536 flush =
1510 * strstart-1 and strstart are already inserted. 1537 ct_tally(strstart - 1 - prev_match,
1511 */ 1538 prev_length - MIN_MATCH);
1512 lookahead -= prev_length-1; 1539
1513 prev_length -= 2; 1540 /* Insert in hash table all strings up to the end of the match.
1514 do { 1541 * strstart-1 and strstart are already inserted.
1515 strstart++; 1542 */
1516 INSERT_STRING(strstart, hash_head); 1543 lookahead -= prev_length - 1;
1517 /* strstart never exceeds WSIZE-MAX_MATCH, so there are 1544 prev_length -= 2;
1518 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH 1545 do {
1519 * these bytes are garbage, but it does not matter since the 1546 strstart++;
1520 * next lookahead bytes will always be emitted as literals. 1547 INSERT_STRING(strstart, hash_head);
1521 */ 1548 /* strstart never exceeds WSIZE-MAX_MATCH, so there are
1522 } while (--prev_length != 0); 1549 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
1523 match_available = 0; 1550 * these bytes are garbage, but it does not matter since the
1524 match_length = MIN_MATCH-1; 1551 * next lookahead bytes will always be emitted as literals.
1525 strstart++; 1552 */
1526 if (flush) FLUSH_BLOCK(0), block_start = strstart; 1553 } while (--prev_length != 0);
1527 1554 match_available = 0;
1528 } else if (match_available) { 1555 match_length = MIN_MATCH - 1;
1529 /* If there was no match at the previous position, output a 1556 strstart++;
1530 * single literal. If there was a match but the current match 1557 if (flush)
1531 * is longer, truncate the previous match to a single literal. 1558 FLUSH_BLOCK(0), block_start = strstart;
1532 */ 1559
1533 Tracevv((stderr,"%c",window[strstart-1])); 1560 } else if (match_available) {
1534 if (ct_tally (0, window[strstart-1])) { 1561 /* If there was no match at the previous position, output a
1535 FLUSH_BLOCK(0), block_start = strstart; 1562 * single literal. If there was a match but the current match
1536 } 1563 * is longer, truncate the previous match to a single literal.
1537 strstart++; 1564 */
1538 lookahead--; 1565 Tracevv((stderr, "%c", window[strstart - 1]));
1539 } else { 1566 if (ct_tally(0, window[strstart - 1])) {
1540 /* There is no previous match to compare with, wait for 1567 FLUSH_BLOCK(0), block_start = strstart;
1541 * the next step to decide. 1568 }
1542 */ 1569 strstart++;
1543 match_available = 1; 1570 lookahead--;
1544 strstart++; 1571 } else {
1545 lookahead--; 1572 /* There is no previous match to compare with, wait for
1546 } 1573 * the next step to decide.
1547 Assert (strstart <= isize && lookahead <= isize, "a bit too far"); 1574 */
1548 1575 match_available = 1;
1549 /* Make sure that we always have enough lookahead, except 1576 strstart++;
1550 * at the end of the input file. We need MAX_MATCH bytes 1577 lookahead--;
1551 * for the next match, plus MIN_MATCH bytes to insert the 1578 }
1552 * string following the next match. 1579 Assert(strstart <= isize && lookahead <= isize, "a bit too far");
1553 */ 1580
1554 while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); 1581 /* Make sure that we always have enough lookahead, except
1555 } 1582 * at the end of the input file. We need MAX_MATCH bytes
1556 if (match_available) ct_tally (0, window[strstart-1]); 1583 * for the next match, plus MIN_MATCH bytes to insert the
1557 1584 * string following the next match.
1558 return FLUSH_BLOCK(1); /* eof */ 1585 */
1586 while (lookahead < MIN_LOOKAHEAD && !eofile)
1587 fill_window();
1588 }
1589 if (match_available)
1590 ct_tally(0, window[strstart - 1]);
1591
1592 return FLUSH_BLOCK(1); /* eof */
1559} 1593}
1594
1560/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface 1595/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
1561 * Copyright (C) 1992-1993 Jean-loup Gailly 1596 * Copyright (C) 1992-1993 Jean-loup Gailly
1562 * The unzip code was written and put in the public domain by Mark Adler. 1597 * The unzip code was written and put in the public domain by Mark Adler.
@@ -1611,29 +1646,33 @@ ulg deflate()
1611#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 1646#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
1612# include <stdlib.h> 1647# include <stdlib.h>
1613#else 1648#else
1614 extern int errno; 1649extern int errno;
1615#endif 1650#endif
1616 1651
1617#if defined(DIRENT) 1652#if defined(DIRENT)
1618# include <dirent.h> 1653# include <dirent.h>
1619 typedef struct dirent dir_type; 1654typedef struct dirent dir_type;
1655
1620# define NLENGTH(dirent) ((int)strlen((dirent)->d_name)) 1656# define NLENGTH(dirent) ((int)strlen((dirent)->d_name))
1621# define DIR_OPT "DIRENT" 1657# define DIR_OPT "DIRENT"
1622#else 1658#else
1623# define NLENGTH(dirent) ((dirent)->d_namlen) 1659# define NLENGTH(dirent) ((dirent)->d_namlen)
1624# ifdef SYSDIR 1660# ifdef SYSDIR
1625# include <sys/dir.h> 1661# include <sys/dir.h>
1626 typedef struct direct dir_type; 1662typedef struct direct dir_type;
1663
1627# define DIR_OPT "SYSDIR" 1664# define DIR_OPT "SYSDIR"
1628# else 1665# else
1629# ifdef SYSNDIR 1666# ifdef SYSNDIR
1630# include <sys/ndir.h> 1667# include <sys/ndir.h>
1631 typedef struct direct dir_type; 1668typedef struct direct dir_type;
1669
1632# define DIR_OPT "SYSNDIR" 1670# define DIR_OPT "SYSNDIR"
1633# else 1671# else
1634# ifdef NDIR 1672# ifdef NDIR
1635# include <ndir.h> 1673# include <ndir.h>
1636 typedef struct direct dir_type; 1674typedef struct direct dir_type;
1675
1637# define DIR_OPT "NDIR" 1676# define DIR_OPT "NDIR"
1638# else 1677# else
1639# define NO_DIR 1678# define NO_DIR
@@ -1652,10 +1691,11 @@ ulg deflate()
1652# include <sys/utime.h> 1691# include <sys/utime.h>
1653# define TIME_OPT "SYS_UTIME" 1692# define TIME_OPT "SYS_UTIME"
1654# else 1693# else
1655 struct utimbuf { 1694struct utimbuf {
1656 time_t actime; 1695 time_t actime;
1657 time_t modtime; 1696 time_t modtime;
1658 }; 1697};
1698
1659# define TIME_OPT "" 1699# define TIME_OPT ""
1660# endif 1700# endif
1661# endif 1701# endif
@@ -1670,10 +1710,10 @@ ulg deflate()
1670# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 1710# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1671#endif 1711#endif
1672 1712
1673typedef RETSIGTYPE (*sig_type) OF((int)); 1713typedef RETSIGTYPE(*sig_type) OF((int));
1674 1714
1675#ifndef O_BINARY 1715#ifndef O_BINARY
1676# define O_BINARY 0 /* creation mode for open() */ 1716# define O_BINARY 0 /* creation mode for open() */
1677#endif 1717#endif
1678 1718
1679#ifndef O_CREAT 1719#ifndef O_CREAT
@@ -1693,10 +1733,10 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1693#ifndef S_IWUSR 1733#ifndef S_IWUSR
1694# define S_IWUSR 0200 1734# define S_IWUSR 0200
1695#endif 1735#endif
1696#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ 1736#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
1697 1737
1698#ifndef MAX_PATH_LEN 1738#ifndef MAX_PATH_LEN
1699# define MAX_PATH_LEN 1024 /* max pathname length */ 1739# define MAX_PATH_LEN 1024 /* max pathname length */
1700#endif 1740#endif
1701 1741
1702#ifndef SEEK_END 1742#ifndef SEEK_END
@@ -1704,8 +1744,8 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1704#endif 1744#endif
1705 1745
1706#ifdef NO_OFF_T 1746#ifdef NO_OFF_T
1707 typedef long off_t; 1747typedef long off_t;
1708 off_t lseek OF((int fd, off_t offset, int whence)); 1748off_t lseek OF((int fd, off_t offset, int whence));
1709#endif 1749#endif
1710 1750
1711/* Separator for file name parts (see shorten_name()) */ 1751/* Separator for file name parts (see shorten_name()) */
@@ -1717,48 +1757,48 @@ typedef RETSIGTYPE (*sig_type) OF((int));
1717 1757
1718 /* global buffers */ 1758 /* global buffers */
1719 1759
1720DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 1760DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
1721DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 1761DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
1722DECLARE(ush, d_buf, DIST_BUFSIZE); 1762DECLARE(ush, d_buf, DIST_BUFSIZE);
1723DECLARE(uch, window, 2L*WSIZE); 1763DECLARE(uch, window, 2L * WSIZE);
1724#ifndef MAXSEG_64K 1764#ifndef MAXSEG_64K
1725 DECLARE(ush, tab_prefix, 1L<<BITS); 1765DECLARE(ush, tab_prefix, 1L << BITS);
1726#else 1766#else
1727 DECLARE(ush, tab_prefix0, 1L<<(BITS-1)); 1767DECLARE(ush, tab_prefix0, 1L << (BITS - 1));
1728 DECLARE(ush, tab_prefix1, 1L<<(BITS-1)); 1768DECLARE(ush, tab_prefix1, 1L << (BITS - 1));
1729#endif 1769#endif
1730 1770
1731 /* local variables */ 1771 /* local variables */
1732 1772
1733int ascii = 0; /* convert end-of-lines to local OS conventions */ 1773int ascii = 0; /* convert end-of-lines to local OS conventions */
1734int decompress = 0; /* decompress (-d) */ 1774int decompress = 0; /* decompress (-d) */
1735int no_name = -1; /* don't save or restore the original file name */ 1775int no_name = -1; /* don't save or restore the original file name */
1736int no_time = -1; /* don't save or restore the original file time */ 1776int no_time = -1; /* don't save or restore the original file time */
1737int foreground; /* set if program run in foreground */ 1777int foreground; /* set if program run in foreground */
1738char *progname; /* program name */ 1778char *progname; /* program name */
1739static int method = DEFLATED;/* compression method */ 1779static int method = DEFLATED; /* compression method */
1740static int exit_code = OK; /* program exit code */ 1780static int exit_code = OK; /* program exit code */
1741int save_orig_name; /* set if original name must be saved */ 1781int save_orig_name; /* set if original name must be saved */
1742int last_member; /* set for .zip and .Z files */ 1782int last_member; /* set for .zip and .Z files */
1743int part_nb; /* number of parts in .gz file */ 1783int part_nb; /* number of parts in .gz file */
1744long time_stamp; /* original time stamp (modification time) */ 1784long time_stamp; /* original time stamp (modification time) */
1745long ifile_size; /* input file size, -1 for devices (debug only) */ 1785long ifile_size; /* input file size, -1 for devices (debug only) */
1746char *env; /* contents of GZIP env variable */ 1786char *env; /* contents of GZIP env variable */
1747char **args = NULL; /* argv pointer if GZIP env variable defined */ 1787char **args = NULL; /* argv pointer if GZIP env variable defined */
1748char z_suffix[MAX_SUFFIX+1]; /* default suffix (can be set with --suffix) */ 1788char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */
1749int z_len; /* strlen(z_suffix) */ 1789int z_len; /* strlen(z_suffix) */
1750 1790
1751long bytes_in; /* number of input bytes */ 1791long bytes_in; /* number of input bytes */
1752long bytes_out; /* number of output bytes */ 1792long bytes_out; /* number of output bytes */
1753char ifname[MAX_PATH_LEN]; /* input file name */ 1793char ifname[MAX_PATH_LEN]; /* input file name */
1754char ofname[MAX_PATH_LEN]; /* output file name */ 1794char ofname[MAX_PATH_LEN]; /* output file name */
1755int remove_ofname = 0; /* remove output file on error */ 1795int remove_ofname = 0; /* remove output file on error */
1756struct stat istat; /* status for input file */ 1796struct stat istat; /* status for input file */
1757int ifd; /* input file descriptor */ 1797int ifd; /* input file descriptor */
1758int ofd; /* output file descriptor */ 1798int ofd; /* output file descriptor */
1759unsigned insize; /* valid bytes in inbuf */ 1799unsigned insize; /* valid bytes in inbuf */
1760unsigned inptr; /* index of next byte to be processed in inbuf */ 1800unsigned inptr; /* index of next byte to be processed in inbuf */
1761unsigned outcnt; /* bytes in output buffer */ 1801unsigned outcnt; /* bytes in output buffer */
1762 1802
1763/* local functions */ 1803/* local functions */
1764 1804
@@ -1768,148 +1808,148 @@ unsigned outcnt; /* bytes in output buffer */
1768// int main (argc, argv) 1808// int main (argc, argv)
1769// int argc; 1809// int argc;
1770// char **argv; 1810// char **argv;
1771int gzip_main(int argc, char ** argv) 1811int gzip_main(int argc, char **argv)
1772{ 1812{
1773 int result; 1813 int result;
1774 int inFileNum; 1814 int inFileNum;
1775 int outFileNum; 1815 int outFileNum;
1776 struct stat statBuf; 1816 struct stat statBuf;
1777 char* delFileName; 1817 char *delFileName;
1778 int tostdout = 0; 1818 int tostdout = 0;
1779 int fromstdin = 0; 1819 int fromstdin = 0;
1780 1820
1781 if (argc==1) 1821 if (argc == 1)
1782 usage(gzip_usage);
1783
1784 /* Parse any options */
1785 while (--argc > 0 && **(++argv) == '-') {
1786 if (*((*argv)+1) == '\0') {
1787 fromstdin = 1;
1788 tostdout = 1;
1789 }
1790 while (*(++(*argv))) {
1791 switch (**argv) {
1792 case 'c':
1793 tostdout = 1;
1794 break;
1795 default:
1796 usage(gzip_usage); 1822 usage(gzip_usage);
1797 } 1823
1824 /* Parse any options */
1825 while (--argc > 0 && **(++argv) == '-') {
1826 if (*((*argv) + 1) == '\0') {
1827 fromstdin = 1;
1828 tostdout = 1;
1829 }
1830 while (*(++(*argv))) {
1831 switch (**argv) {
1832 case 'c':
1833 tostdout = 1;
1834 break;
1835 default:
1836 usage(gzip_usage);
1837 }
1838 }
1798 } 1839 }
1799 }
1800 1840
1801 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; 1841 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
1802 if (foreground) { 1842 if (foreground) {
1803 (void) signal (SIGINT, (sig_type)abort_gzip); 1843 (void) signal(SIGINT, (sig_type) abort_gzip);
1804 } 1844 }
1805#ifdef SIGTERM 1845#ifdef SIGTERM
1806 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 1846 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
1807 (void) signal(SIGTERM, (sig_type)abort_gzip); 1847 (void) signal(SIGTERM, (sig_type) abort_gzip);
1808 } 1848 }
1809#endif 1849#endif
1810#ifdef SIGHUP 1850#ifdef SIGHUP
1811 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 1851 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
1812 (void) signal(SIGHUP, (sig_type)abort_gzip); 1852 (void) signal(SIGHUP, (sig_type) abort_gzip);
1813 } 1853 }
1814#endif 1854#endif
1815 1855
1816 strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1); 1856 strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1);
1817 z_len = strlen(z_suffix); 1857 z_len = strlen(z_suffix);
1818 1858
1819 /* Allocate all global buffers (for DYN_ALLOC option) */ 1859 /* Allocate all global buffers (for DYN_ALLOC option) */
1820 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); 1860 ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
1821 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); 1861 ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
1822 ALLOC(ush, d_buf, DIST_BUFSIZE); 1862 ALLOC(ush, d_buf, DIST_BUFSIZE);
1823 ALLOC(uch, window, 2L*WSIZE); 1863 ALLOC(uch, window, 2L * WSIZE);
1824#ifndef MAXSEG_64K 1864#ifndef MAXSEG_64K
1825 ALLOC(ush, tab_prefix, 1L<<BITS); 1865 ALLOC(ush, tab_prefix, 1L << BITS);
1826#else 1866#else
1827 ALLOC(ush, tab_prefix0, 1L<<(BITS-1)); 1867 ALLOC(ush, tab_prefix0, 1L << (BITS - 1));
1828 ALLOC(ush, tab_prefix1, 1L<<(BITS-1)); 1868 ALLOC(ush, tab_prefix1, 1L << (BITS - 1));
1829#endif 1869#endif
1830 1870
1831 if (fromstdin==1) { 1871 if (fromstdin == 1) {
1832 strcpy(ofname, "stdin"); 1872 strcpy(ofname, "stdin");
1833 1873
1834 inFileNum=fileno(stdin); 1874 inFileNum = fileno(stdin);
1835 time_stamp = 0; /* time unknown by default */ 1875 time_stamp = 0; /* time unknown by default */
1836 ifile_size = -1L; /* convention for unknown size */ 1876 ifile_size = -1L; /* convention for unknown size */
1837 } else { 1877 } else {
1838 /* Open up the input file */ 1878 /* Open up the input file */
1839 if (*argv=='\0') 1879 if (*argv == '\0')
1840 usage(gzip_usage); 1880 usage(gzip_usage);
1841 strncpy(ifname, *argv, MAX_PATH_LEN); 1881 strncpy(ifname, *argv, MAX_PATH_LEN);
1842 1882
1843 /* Open input fille */ 1883 /* Open input fille */
1844 inFileNum=open( ifname, O_RDONLY); 1884 inFileNum = open(ifname, O_RDONLY);
1845 if (inFileNum < 0) { 1885 if (inFileNum < 0) {
1846 perror(ifname); 1886 perror(ifname);
1847 do_exit(WARNING); 1887 do_exit(WARNING);
1848 } 1888 }
1849 /* Get the time stamp on the input file. */ 1889 /* Get the time stamp on the input file. */
1850 result = stat(ifname, &statBuf); 1890 result = stat(ifname, &statBuf);
1851 if (result < 0) { 1891 if (result < 0) {
1852 perror(ifname); 1892 perror(ifname);
1853 do_exit(WARNING); 1893 do_exit(WARNING);
1894 }
1895 time_stamp = statBuf.st_ctime;
1896 ifile_size = statBuf.st_size;
1854 } 1897 }
1855 time_stamp = statBuf.st_ctime;
1856 ifile_size = statBuf.st_size;
1857 }
1858 1898
1859 1899
1860 if (tostdout==1) { 1900 if (tostdout == 1) {
1861 /* And get to work */ 1901 /* And get to work */
1862 strcpy(ofname, "stdout"); 1902 strcpy(ofname, "stdout");
1863 outFileNum=fileno(stdout); 1903 outFileNum = fileno(stdout);
1864 SET_BINARY_MODE(fileno(stdout)); 1904 SET_BINARY_MODE(fileno(stdout));
1865 1905
1866 clear_bufs(); /* clear input and output buffers */ 1906 clear_bufs(); /* clear input and output buffers */
1867 part_nb = 0; 1907 part_nb = 0;
1868 1908
1869 /* Actually do the compression/decompression. */ 1909 /* Actually do the compression/decompression. */
1870 zip(inFileNum, outFileNum); 1910 zip(inFileNum, outFileNum);
1871 1911
1872 } else { 1912 } else {
1873 1913
1874 /* And get to work */ 1914 /* And get to work */
1875 strncpy(ofname, ifname, MAX_PATH_LEN-4); 1915 strncpy(ofname, ifname, MAX_PATH_LEN - 4);
1876 strcat(ofname, ".gz"); 1916 strcat(ofname, ".gz");
1877 1917
1878 1918
1879 /* Open output fille */ 1919 /* Open output fille */
1880#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 1920#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
1881 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW); 1921 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
1882#else 1922#else
1883 outFileNum=open( ofname, O_RDWR|O_CREAT|O_EXCL); 1923 outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL);
1884#endif 1924#endif
1885 if (outFileNum < 0) { 1925 if (outFileNum < 0) {
1886 perror(ofname); 1926 perror(ofname);
1887 do_exit(WARNING); 1927 do_exit(WARNING);
1888 } 1928 }
1889 SET_BINARY_MODE(outFileNum); 1929 SET_BINARY_MODE(outFileNum);
1890 /* Set permissions on the file */ 1930 /* Set permissions on the file */
1891 fchmod(outFileNum, statBuf.st_mode); 1931 fchmod(outFileNum, statBuf.st_mode);
1892 1932
1893 clear_bufs(); /* clear input and output buffers */ 1933 clear_bufs(); /* clear input and output buffers */
1894 part_nb = 0; 1934 part_nb = 0;
1895 1935
1896 /* Actually do the compression/decompression. */ 1936 /* Actually do the compression/decompression. */
1897 result=zip(inFileNum, outFileNum); 1937 result = zip(inFileNum, outFileNum);
1898 close( outFileNum); 1938 close(outFileNum);
1899 close( inFileNum); 1939 close(inFileNum);
1900 /* Delete the original file */ 1940 /* Delete the original file */
1901 if (result == OK) 1941 if (result == OK)
1902 delFileName=ifname; 1942 delFileName = ifname;
1903 else 1943 else
1904 delFileName=ofname; 1944 delFileName = ofname;
1905 1945
1906 if (unlink (delFileName) < 0) { 1946 if (unlink(delFileName) < 0) {
1907 perror (delFileName); 1947 perror(delFileName);
1908 exit( FALSE); 1948 exit(FALSE);
1949 }
1909 } 1950 }
1910 }
1911 1951
1912 do_exit(exit_code); 1952 do_exit(exit_code);
1913} 1953}
1914 1954
1915/* trees.c -- output deflated data using Huffman coding 1955/* trees.c -- output deflated data using Huffman coding
@@ -1998,14 +2038,16 @@ int gzip_main(int argc, char ** argv)
1998/* number of codes used to transfer the bit lengths */ 2038/* number of codes used to transfer the bit lengths */
1999 2039
2000 2040
2001local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */ 2041local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */
2002 = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; 2042 = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2043 4, 4, 5, 5, 5, 5, 0 };
2003 2044
2004local int near extra_dbits[D_CODES] /* extra bits for each distance code */ 2045local int near extra_dbits[D_CODES] /* extra bits for each distance code */
2005 = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; 2046 = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
2047 10, 10, 11, 11, 12, 12, 13, 13 };
2006 2048
2007local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */ 2049local int near extra_blbits[BL_CODES] /* extra bits for each bit length code */
2008 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; 2050= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
2009 2051
2010#define STORED_BLOCK 0 2052#define STORED_BLOCK 0
2011#define STATIC_TREES 1 2053#define STATIC_TREES 1
@@ -2047,32 +2089,24 @@ local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */
2047 * if we rely on DIST_BUFSIZE == LIT_BUFSIZE. 2089 * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
2048 */ 2090 */
2049#if LIT_BUFSIZE > INBUFSIZ 2091#if LIT_BUFSIZE > INBUFSIZ
2050 error cannot overlay l_buf and inbuf 2092error cannot overlay l_buf and inbuf
2051#endif 2093#endif
2052
2053#define REP_3_6 16 2094#define REP_3_6 16
2054/* repeat previous bit length 3-6 times (2 bits of repeat count) */ 2095/* repeat previous bit length 3-6 times (2 bits of repeat count) */
2055
2056#define REPZ_3_10 17 2096#define REPZ_3_10 17
2057/* repeat a zero length 3-10 times (3 bits of repeat count) */ 2097/* repeat a zero length 3-10 times (3 bits of repeat count) */
2058
2059#define REPZ_11_138 18 2098#define REPZ_11_138 18
2060/* repeat a zero length 11-138 times (7 bits of repeat count) */ 2099/* repeat a zero length 11-138 times (7 bits of repeat count) *//* ===========================================================================
2061
2062/* ===========================================================================
2063 * Local data 2100 * Local data
2064 */ 2101 *//* Data structure describing a single value and its code string. */ typedef struct ct_data {
2065 2102 union {
2066/* Data structure describing a single value and its code string. */ 2103 ush freq; /* frequency count */
2067typedef struct ct_data { 2104 ush code; /* bit string */
2068 union { 2105 } fc;
2069 ush freq; /* frequency count */ 2106 union {
2070 ush code; /* bit string */ 2107 ush dad; /* father node in Huffman tree */
2071 } fc; 2108 ush len; /* length of bit string */
2072 union { 2109 } dl;
2073 ush dad; /* father node in Huffman tree */
2074 ush len; /* length of bit string */
2075 } dl;
2076} ct_data; 2110} ct_data;
2077 2111
2078#define Freq fc.freq 2112#define Freq fc.freq
@@ -2083,10 +2117,11 @@ typedef struct ct_data {
2083#define HEAP_SIZE (2*L_CODES+1) 2117#define HEAP_SIZE (2*L_CODES+1)
2084/* maximum heap size */ 2118/* maximum heap size */
2085 2119
2086local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */ 2120local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */
2087local ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */ 2121local ct_data near dyn_dtree[2 * D_CODES + 1]; /* distance tree */
2122
2123local ct_data near static_ltree[L_CODES + 2];
2088 2124
2089local ct_data near static_ltree[L_CODES+2];
2090/* The static literal tree. Since the bit lengths are imposed, there is no 2125/* The static literal tree. Since the bit lengths are imposed, there is no
2091 * need for the L_CODES extra codes used during heap construction. However 2126 * need for the L_CODES extra codes used during heap construction. However
2092 * The codes 286 and 287 are needed to build a canonical tree (see ct_init 2127 * The codes 286 and 287 are needed to build a canonical tree (see ct_init
@@ -2094,65 +2129,77 @@ local ct_data near static_ltree[L_CODES+2];
2094 */ 2129 */
2095 2130
2096local ct_data near static_dtree[D_CODES]; 2131local ct_data near static_dtree[D_CODES];
2132
2097/* The static distance tree. (Actually a trivial tree since all codes use 2133/* The static distance tree. (Actually a trivial tree since all codes use
2098 * 5 bits.) 2134 * 5 bits.)
2099 */ 2135 */
2100 2136
2101local ct_data near bl_tree[2*BL_CODES+1]; 2137local ct_data near bl_tree[2 * BL_CODES + 1];
2138
2102/* Huffman tree for the bit lengths */ 2139/* Huffman tree for the bit lengths */
2103 2140
2104typedef struct tree_desc { 2141typedef struct tree_desc {
2105 ct_data near *dyn_tree; /* the dynamic tree */ 2142 ct_data near *dyn_tree; /* the dynamic tree */
2106 ct_data near *static_tree; /* corresponding static tree or NULL */ 2143 ct_data near *static_tree; /* corresponding static tree or NULL */
2107 int near *extra_bits; /* extra bits for each code or NULL */ 2144 int near *extra_bits; /* extra bits for each code or NULL */
2108 int extra_base; /* base index for extra_bits */ 2145 int extra_base; /* base index for extra_bits */
2109 int elems; /* max number of elements in the tree */ 2146 int elems; /* max number of elements in the tree */
2110 int max_length; /* max bit length for the codes */ 2147 int max_length; /* max bit length for the codes */
2111 int max_code; /* largest code with non zero frequency */ 2148 int max_code; /* largest code with non zero frequency */
2112} tree_desc; 2149} tree_desc;
2113 2150
2114local tree_desc near l_desc = 2151local tree_desc near l_desc =
2115{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0}; 2152 { dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES,
2153 MAX_BITS, 0 };
2116 2154
2117local tree_desc near d_desc = 2155local tree_desc near d_desc =
2118{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0}; 2156 { dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 };
2119 2157
2120local tree_desc near bl_desc = 2158local tree_desc near bl_desc =
2121{bl_tree, (ct_data near *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0}; 2159 { bl_tree, (ct_data near *) 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS,
2160 0 };
2122 2161
2123 2162
2124local ush near bl_count[MAX_BITS+1]; 2163local ush near bl_count[MAX_BITS + 1];
2164
2125/* number of codes at each bit length for an optimal tree */ 2165/* number of codes at each bit length for an optimal tree */
2126 2166
2127local uch near bl_order[BL_CODES] 2167local uch near bl_order[BL_CODES]
2128 = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; 2168= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2169
2129/* The lengths of the bit length codes are sent in order of decreasing 2170/* The lengths of the bit length codes are sent in order of decreasing
2130 * probability, to avoid transmitting the lengths for unused bit length codes. 2171 * probability, to avoid transmitting the lengths for unused bit length codes.
2131 */ 2172 */
2132 2173
2133local int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ 2174local int near heap[2 * L_CODES + 1]; /* heap used to build the Huffman trees */
2134local int heap_len; /* number of elements in the heap */ 2175local int heap_len; /* number of elements in the heap */
2135local int heap_max; /* element of largest frequency */ 2176local int heap_max; /* element of largest frequency */
2177
2136/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. 2178/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
2137 * The same heap array is used to build all trees. 2179 * The same heap array is used to build all trees.
2138 */ 2180 */
2139 2181
2140local uch near depth[2*L_CODES+1]; 2182local uch near depth[2 * L_CODES + 1];
2183
2141/* Depth of each subtree used as tie breaker for trees of equal frequency */ 2184/* Depth of each subtree used as tie breaker for trees of equal frequency */
2142 2185
2143local uch length_code[MAX_MATCH-MIN_MATCH+1]; 2186local uch length_code[MAX_MATCH - MIN_MATCH + 1];
2187
2144/* length code for each normalized match length (0 == MIN_MATCH) */ 2188/* length code for each normalized match length (0 == MIN_MATCH) */
2145 2189
2146local uch dist_code[512]; 2190local uch dist_code[512];
2191
2147/* distance codes. The first 256 values correspond to the distances 2192/* distance codes. The first 256 values correspond to the distances
2148 * 3 .. 258, the last 256 values correspond to the top 8 bits of 2193 * 3 .. 258, the last 256 values correspond to the top 8 bits of
2149 * the 15 bit distances. 2194 * the 15 bit distances.
2150 */ 2195 */
2151 2196
2152local int near base_length[LENGTH_CODES]; 2197local int near base_length[LENGTH_CODES];
2198
2153/* First normalized length for each code (0 = MIN_MATCH) */ 2199/* First normalized length for each code (0 = MIN_MATCH) */
2154 2200
2155local int near base_dist[D_CODES]; 2201local int near base_dist[D_CODES];
2202
2156/* First normalized distance for each code (0 = distance of 1) */ 2203/* First normalized distance for each code (0 = distance of 1) */
2157 2204
2158#define l_buf inbuf 2205#define l_buf inbuf
@@ -2160,62 +2207,65 @@ local int near base_dist[D_CODES];
2160 2207
2161/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */ 2208/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
2162 2209
2163local uch near flag_buf[(LIT_BUFSIZE/8)]; 2210local uch near flag_buf[(LIT_BUFSIZE / 8)];
2211
2164/* flag_buf is a bit array distinguishing literals from lengths in 2212/* flag_buf is a bit array distinguishing literals from lengths in
2165 * l_buf, thus indicating the presence or absence of a distance. 2213 * l_buf, thus indicating the presence or absence of a distance.
2166 */ 2214 */
2167 2215
2168local unsigned last_lit; /* running index in l_buf */ 2216local unsigned last_lit; /* running index in l_buf */
2169local unsigned last_dist; /* running index in d_buf */ 2217local unsigned last_dist; /* running index in d_buf */
2170local unsigned last_flags; /* running index in flag_buf */ 2218local unsigned last_flags; /* running index in flag_buf */
2171local uch flags; /* current flags not yet saved in flag_buf */ 2219local uch flags; /* current flags not yet saved in flag_buf */
2172local uch flag_bit; /* current bit used in flags */ 2220local uch flag_bit; /* current bit used in flags */
2221
2173/* bits are filled in flags starting at bit 0 (least significant). 2222/* bits are filled in flags starting at bit 0 (least significant).
2174 * Note: these flags are overkill in the current code since we don't 2223 * Note: these flags are overkill in the current code since we don't
2175 * take advantage of DIST_BUFSIZE == LIT_BUFSIZE. 2224 * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
2176 */ 2225 */
2177 2226
2178local ulg opt_len; /* bit length of current block with optimal trees */ 2227local ulg opt_len; /* bit length of current block with optimal trees */
2179local ulg static_len; /* bit length of current block with static trees */ 2228local ulg static_len; /* bit length of current block with static trees */
2229
2230local ulg compressed_len; /* total bit length of compressed file */
2180 2231
2181local ulg compressed_len; /* total bit length of compressed file */ 2232local ulg input_len; /* total byte length of input file */
2182 2233
2183local ulg input_len; /* total byte length of input file */
2184/* input_len is for debugging only since we can get it by other means. */ 2234/* input_len is for debugging only since we can get it by other means. */
2185 2235
2186ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */ 2236ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */
2187int *file_method; /* pointer to DEFLATE or STORE */ 2237int *file_method; /* pointer to DEFLATE or STORE */
2188 2238
2189#ifdef DEBUG 2239#ifdef DEBUG
2190extern ulg bits_sent; /* bit length of the compressed data */ 2240extern ulg bits_sent; /* bit length of the compressed data */
2191extern long isize; /* byte length of input file */ 2241extern long isize; /* byte length of input file */
2192#endif 2242#endif
2193 2243
2194extern long block_start; /* window offset of current block */ 2244extern long block_start; /* window offset of current block */
2195extern unsigned near strstart; /* window offset of current string */ 2245extern unsigned near strstart; /* window offset of current string */
2196 2246
2197/* =========================================================================== 2247/* ===========================================================================
2198 * Local (static) routines in this file. 2248 * Local (static) routines in this file.
2199 */ 2249 */
2200 2250
2201local void init_block OF((void)); 2251local void init_block OF((void));
2202local void pqdownheap OF((ct_data near *tree, int k)); 2252local void pqdownheap OF((ct_data near * tree, int k));
2203local void gen_bitlen OF((tree_desc near *desc)); 2253local void gen_bitlen OF((tree_desc near * desc));
2204local void gen_codes OF((ct_data near *tree, int max_code)); 2254local void gen_codes OF((ct_data near * tree, int max_code));
2205local void build_tree OF((tree_desc near *desc)); 2255local void build_tree OF((tree_desc near * desc));
2206local void scan_tree OF((ct_data near *tree, int max_code)); 2256local void scan_tree OF((ct_data near * tree, int max_code));
2207local void send_tree OF((ct_data near *tree, int max_code)); 2257local void send_tree OF((ct_data near * tree, int max_code));
2208local int build_bl_tree OF((void)); 2258local int build_bl_tree OF((void));
2209local void send_all_trees OF((int lcodes, int dcodes, int blcodes)); 2259local void send_all_trees OF((int lcodes, int dcodes, int blcodes));
2210local void compress_block OF((ct_data near *ltree, ct_data near *dtree)); 2260local void compress_block OF((ct_data near * ltree, ct_data near * dtree));
2211local void set_file_type OF((void)); 2261local void set_file_type OF((void));
2212 2262
2213 2263
2214#ifndef DEBUG 2264#ifndef DEBUG
2215# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len) 2265# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
2216 /* Send a code of the given tree. c and tree must not have side effects */ 2266 /* Send a code of the given tree. c and tree must not have side effects */
2217 2267
2218#else /* DEBUG */ 2268#else /* DEBUG */
2219# define send_code(c, tree) \ 2269# define send_code(c, tree) \
2220 { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \ 2270 { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
2221 send_bits(tree[c].Code, tree[c].Len); } 2271 send_bits(tree[c].Code, tree[c].Len); }
@@ -2237,75 +2287,81 @@ local void set_file_type OF((void));
2237 * (DEFLATE/STORE). 2287 * (DEFLATE/STORE).
2238 */ 2288 */
2239void ct_init(attr, methodp) 2289void ct_init(attr, methodp)
2240 ush *attr; /* pointer to internal file attribute */ 2290ush *attr; /* pointer to internal file attribute */
2241 int *methodp; /* pointer to compression method */ 2291int *methodp; /* pointer to compression method */
2242{ 2292{
2243 int n; /* iterates over tree elements */ 2293 int n; /* iterates over tree elements */
2244 int bits; /* bit counter */ 2294 int bits; /* bit counter */
2245 int length; /* length value */ 2295 int length; /* length value */
2246 int code; /* code value */ 2296 int code; /* code value */
2247 int dist; /* distance index */ 2297 int dist; /* distance index */
2248 2298
2249 file_type = attr; 2299 file_type = attr;
2250 file_method = methodp; 2300 file_method = methodp;
2251 compressed_len = input_len = 0L; 2301 compressed_len = input_len = 0L;
2252 2302
2253 if (static_dtree[0].Len != 0) return; /* ct_init already called */ 2303 if (static_dtree[0].Len != 0)
2254 2304 return; /* ct_init already called */
2255 /* Initialize the mapping length (0..255) -> length code (0..28) */ 2305
2256 length = 0; 2306 /* Initialize the mapping length (0..255) -> length code (0..28) */
2257 for (code = 0; code < LENGTH_CODES-1; code++) { 2307 length = 0;
2258 base_length[code] = length; 2308 for (code = 0; code < LENGTH_CODES - 1; code++) {
2259 for (n = 0; n < (1<<extra_lbits[code]); n++) { 2309 base_length[code] = length;
2260 length_code[length++] = (uch)code; 2310 for (n = 0; n < (1 << extra_lbits[code]); n++) {
2261 } 2311 length_code[length++] = (uch) code;
2262 } 2312 }
2263 Assert (length == 256, "ct_init: length != 256"); 2313 }
2264 /* Note that the length 255 (match length 258) can be represented 2314 Assert(length == 256, "ct_init: length != 256");
2265 * in two different ways: code 284 + 5 bits or code 285, so we 2315 /* Note that the length 255 (match length 258) can be represented
2266 * overwrite length_code[255] to use the best encoding: 2316 * in two different ways: code 284 + 5 bits or code 285, so we
2267 */ 2317 * overwrite length_code[255] to use the best encoding:
2268 length_code[length-1] = (uch)code; 2318 */
2269 2319 length_code[length - 1] = (uch) code;
2270 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ 2320
2271 dist = 0; 2321 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
2272 for (code = 0 ; code < 16; code++) { 2322 dist = 0;
2273 base_dist[code] = dist; 2323 for (code = 0; code < 16; code++) {
2274 for (n = 0; n < (1<<extra_dbits[code]); n++) { 2324 base_dist[code] = dist;
2275 dist_code[dist++] = (uch)code; 2325 for (n = 0; n < (1 << extra_dbits[code]); n++) {
2276 } 2326 dist_code[dist++] = (uch) code;
2277 } 2327 }
2278 Assert (dist == 256, "ct_init: dist != 256"); 2328 }
2279 dist >>= 7; /* from now on, all distances are divided by 128 */ 2329 Assert(dist == 256, "ct_init: dist != 256");
2280 for ( ; code < D_CODES; code++) { 2330 dist >>= 7; /* from now on, all distances are divided by 128 */
2281 base_dist[code] = dist << 7; 2331 for (; code < D_CODES; code++) {
2282 for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { 2332 base_dist[code] = dist << 7;
2283 dist_code[256 + dist++] = (uch)code; 2333 for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
2284 } 2334 dist_code[256 + dist++] = (uch) code;
2285 } 2335 }
2286 Assert (dist == 256, "ct_init: 256+dist != 512"); 2336 }
2287 2337 Assert(dist == 256, "ct_init: 256+dist != 512");
2288 /* Construct the codes of the static literal tree */ 2338
2289 for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; 2339 /* Construct the codes of the static literal tree */
2290 n = 0; 2340 for (bits = 0; bits <= MAX_BITS; bits++)
2291 while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; 2341 bl_count[bits] = 0;
2292 while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; 2342 n = 0;
2293 while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; 2343 while (n <= 143)
2294 while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; 2344 static_ltree[n++].Len = 8, bl_count[8]++;
2295 /* Codes 286 and 287 do not exist, but we must include them in the 2345 while (n <= 255)
2296 * tree construction to get a canonical Huffman tree (longest code 2346 static_ltree[n++].Len = 9, bl_count[9]++;
2297 * all ones) 2347 while (n <= 279)
2298 */ 2348 static_ltree[n++].Len = 7, bl_count[7]++;
2299 gen_codes((ct_data near *)static_ltree, L_CODES+1); 2349 while (n <= 287)
2300 2350 static_ltree[n++].Len = 8, bl_count[8]++;
2301 /* The static distance tree is trivial: */ 2351 /* Codes 286 and 287 do not exist, but we must include them in the
2302 for (n = 0; n < D_CODES; n++) { 2352 * tree construction to get a canonical Huffman tree (longest code
2303 static_dtree[n].Len = 5; 2353 * all ones)
2304 static_dtree[n].Code = bi_reverse(n, 5); 2354 */
2305 } 2355 gen_codes((ct_data near *) static_ltree, L_CODES + 1);
2306 2356
2307 /* Initialize the first block of the first file: */ 2357 /* The static distance tree is trivial: */
2308 init_block(); 2358 for (n = 0; n < D_CODES; n++) {
2359 static_dtree[n].Len = 5;
2360 static_dtree[n].Code = bi_reverse(n, 5);
2361 }
2362
2363 /* Initialize the first block of the first file: */
2364 init_block();
2309} 2365}
2310 2366
2311/* =========================================================================== 2367/* ===========================================================================
@@ -2313,17 +2369,21 @@ void ct_init(attr, methodp)
2313 */ 2369 */
2314local void init_block() 2370local void init_block()
2315{ 2371{
2316 int n; /* iterates over tree elements */ 2372 int n; /* iterates over tree elements */
2317 2373
2318 /* Initialize the trees. */ 2374 /* Initialize the trees. */
2319 for (n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0; 2375 for (n = 0; n < L_CODES; n++)
2320 for (n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0; 2376 dyn_ltree[n].Freq = 0;
2321 for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0; 2377 for (n = 0; n < D_CODES; n++)
2322 2378 dyn_dtree[n].Freq = 0;
2323 dyn_ltree[END_BLOCK].Freq = 1; 2379 for (n = 0; n < BL_CODES; n++)
2324 opt_len = static_len = 0L; 2380 bl_tree[n].Freq = 0;
2325 last_lit = last_dist = last_flags = 0; 2381
2326 flags = 0; flag_bit = 1; 2382 dyn_ltree[END_BLOCK].Freq = 1;
2383 opt_len = static_len = 0L;
2384 last_lit = last_dist = last_flags = 0;
2385 flags = 0;
2386 flag_bit = 1;
2327} 2387}
2328 2388
2329#define SMALLEST 1 2389#define SMALLEST 1
@@ -2356,25 +2416,29 @@ local void init_block()
2356 * two sons). 2416 * two sons).
2357 */ 2417 */
2358local void pqdownheap(tree, k) 2418local void pqdownheap(tree, k)
2359 ct_data near *tree; /* the tree to restore */ 2419ct_data near *tree; /* the tree to restore */
2360 int k; /* node to move down */ 2420int k; /* node to move down */
2361{ 2421{
2362 int v = heap[k]; 2422 int v = heap[k];
2363 int j = k << 1; /* left son of k */ 2423 int j = k << 1; /* left son of k */
2364 while (j <= heap_len) { 2424
2365 /* Set j to the smallest of the two sons: */ 2425 while (j <= heap_len) {
2366 if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++; 2426 /* Set j to the smallest of the two sons: */
2367 2427 if (j < heap_len && smaller(tree, heap[j + 1], heap[j]))
2368 /* Exit if v is smaller than both sons */ 2428 j++;
2369 if (smaller(tree, v, heap[j])) break; 2429
2370 2430 /* Exit if v is smaller than both sons */
2371 /* Exchange v with the smallest son */ 2431 if (smaller(tree, v, heap[j]))
2372 heap[k] = heap[j]; k = j; 2432 break;
2373 2433
2374 /* And continue down the tree, setting j to the left son of k */ 2434 /* Exchange v with the smallest son */
2375 j <<= 1; 2435 heap[k] = heap[j];
2376 } 2436 k = j;
2377 heap[k] = v; 2437
2438 /* And continue down the tree, setting j to the left son of k */
2439 j <<= 1;
2440 }
2441 heap[k] = v;
2378} 2442}
2379 2443
2380/* =========================================================================== 2444/* ===========================================================================
@@ -2388,80 +2452,93 @@ local void pqdownheap(tree, k)
2388 * not null. 2452 * not null.
2389 */ 2453 */
2390local void gen_bitlen(desc) 2454local void gen_bitlen(desc)
2391 tree_desc near *desc; /* the tree descriptor */ 2455tree_desc near *desc; /* the tree descriptor */
2392{ 2456{
2393 ct_data near *tree = desc->dyn_tree; 2457 ct_data near *tree = desc->dyn_tree;
2394 int near *extra = desc->extra_bits; 2458 int near *extra = desc->extra_bits;
2395 int base = desc->extra_base; 2459 int base = desc->extra_base;
2396 int max_code = desc->max_code; 2460 int max_code = desc->max_code;
2397 int max_length = desc->max_length; 2461 int max_length = desc->max_length;
2398 ct_data near *stree = desc->static_tree; 2462 ct_data near *stree = desc->static_tree;
2399 int h; /* heap index */ 2463 int h; /* heap index */
2400 int n, m; /* iterate over the tree elements */ 2464 int n, m; /* iterate over the tree elements */
2401 int bits; /* bit length */ 2465 int bits; /* bit length */
2402 int xbits; /* extra bits */ 2466 int xbits; /* extra bits */
2403 ush f; /* frequency */ 2467 ush f; /* frequency */
2404 int overflow = 0; /* number of elements with bit length too large */ 2468 int overflow = 0; /* number of elements with bit length too large */
2405 2469
2406 for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; 2470 for (bits = 0; bits <= MAX_BITS; bits++)
2407 2471 bl_count[bits] = 0;
2408 /* In a first pass, compute the optimal bit lengths (which may 2472
2409 * overflow in the case of the bit length tree). 2473 /* In a first pass, compute the optimal bit lengths (which may
2410 */ 2474 * overflow in the case of the bit length tree).
2411 tree[heap[heap_max]].Len = 0; /* root of the heap */ 2475 */
2412 2476 tree[heap[heap_max]].Len = 0; /* root of the heap */
2413 for (h = heap_max+1; h < HEAP_SIZE; h++) { 2477
2414 n = heap[h]; 2478 for (h = heap_max + 1; h < HEAP_SIZE; h++) {
2415 bits = tree[tree[n].Dad].Len + 1; 2479 n = heap[h];
2416 if (bits > max_length) bits = max_length, overflow++; 2480 bits = tree[tree[n].Dad].Len + 1;
2417 tree[n].Len = (ush)bits; 2481 if (bits > max_length)
2418 /* We overwrite tree[n].Dad which is no longer needed */ 2482 bits = max_length, overflow++;
2419 2483 tree[n].Len = (ush) bits;
2420 if (n > max_code) continue; /* not a leaf node */ 2484 /* We overwrite tree[n].Dad which is no longer needed */
2421 2485
2422 bl_count[bits]++; 2486 if (n > max_code)
2423 xbits = 0; 2487 continue; /* not a leaf node */
2424 if (n >= base) xbits = extra[n-base]; 2488
2425 f = tree[n].Freq; 2489 bl_count[bits]++;
2426 opt_len += (ulg)f * (bits + xbits); 2490 xbits = 0;
2427 if (stree) static_len += (ulg)f * (stree[n].Len + xbits); 2491 if (n >= base)
2428 } 2492 xbits = extra[n - base];
2429 if (overflow == 0) return; 2493 f = tree[n].Freq;
2430 2494 opt_len += (ulg) f *(bits + xbits);
2431 Trace((stderr,"\nbit length overflow\n")); 2495
2432 /* This happens for example on obj2 and pic of the Calgary corpus */ 2496 if (stree)
2433 2497 static_len += (ulg) f *(stree[n].Len + xbits);
2434 /* Find the first bit length which could increase: */ 2498 }
2435 do { 2499 if (overflow == 0)
2436 bits = max_length-1; 2500 return;
2437 while (bl_count[bits] == 0) bits--; 2501
2438 bl_count[bits]--; /* move one leaf down the tree */ 2502 Trace((stderr, "\nbit length overflow\n"));
2439 bl_count[bits+1] += 2; /* move one overflow item as its brother */ 2503 /* This happens for example on obj2 and pic of the Calgary corpus */
2440 bl_count[max_length]--; 2504
2441 /* The brother of the overflow item also moves one step up, 2505 /* Find the first bit length which could increase: */
2442 * but this does not affect bl_count[max_length] 2506 do {
2443 */ 2507 bits = max_length - 1;
2444 overflow -= 2; 2508 while (bl_count[bits] == 0)
2445 } while (overflow > 0); 2509 bits--;
2446 2510 bl_count[bits]--; /* move one leaf down the tree */
2447 /* Now recompute all bit lengths, scanning in increasing frequency. 2511 bl_count[bits + 1] += 2; /* move one overflow item as its brother */
2448 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all 2512 bl_count[max_length]--;
2449 * lengths instead of fixing only the wrong ones. This idea is taken 2513 /* The brother of the overflow item also moves one step up,
2450 * from 'ar' written by Haruhiko Okumura.) 2514 * but this does not affect bl_count[max_length]
2451 */ 2515 */
2452 for (bits = max_length; bits != 0; bits--) { 2516 overflow -= 2;
2453 n = bl_count[bits]; 2517 } while (overflow > 0);
2454 while (n != 0) { 2518
2455 m = heap[--h]; 2519 /* Now recompute all bit lengths, scanning in increasing frequency.
2456 if (m > max_code) continue; 2520 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
2457 if (tree[m].Len != (unsigned) bits) { 2521 * lengths instead of fixing only the wrong ones. This idea is taken
2458 Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); 2522 * from 'ar' written by Haruhiko Okumura.)
2459 opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq; 2523 */
2460 tree[m].Len = (ush)bits; 2524 for (bits = max_length; bits != 0; bits--) {
2461 } 2525 n = bl_count[bits];
2462 n--; 2526 while (n != 0) {
2463 } 2527 m = heap[--h];
2464 } 2528 if (m > max_code)
2529 continue;
2530 if (tree[m].Len != (unsigned) bits) {
2531 Trace(
2532 (stderr, "code %d bits %d->%d\n", m, tree[m].Len,
2533 bits));
2534 opt_len +=
2535 ((long) bits -
2536 (long) tree[m].Len) * (long) tree[m].Freq;
2537 tree[m].Len = (ush) bits;
2538 }
2539 n--;
2540 }
2541 }
2465} 2542}
2466 2543
2467/* =========================================================================== 2544/* ===========================================================================
@@ -2472,37 +2549,41 @@ local void gen_bitlen(desc)
2472 * OUT assertion: the field code is set for all tree elements of non 2549 * OUT assertion: the field code is set for all tree elements of non
2473 * zero code length. 2550 * zero code length.
2474 */ 2551 */
2475local void gen_codes (tree, max_code) 2552local void gen_codes(tree, max_code)
2476 ct_data near *tree; /* the tree to decorate */ 2553ct_data near *tree; /* the tree to decorate */
2477 int max_code; /* largest code with non zero frequency */ 2554int max_code; /* largest code with non zero frequency */
2478{ 2555{
2479 ush next_code[MAX_BITS+1]; /* next code value for each bit length */ 2556 ush next_code[MAX_BITS + 1]; /* next code value for each bit length */
2480 ush code = 0; /* running code value */ 2557 ush code = 0; /* running code value */
2481 int bits; /* bit index */ 2558 int bits; /* bit index */
2482 int n; /* code index */ 2559 int n; /* code index */
2483 2560
2484 /* The distribution counts are first used to generate the code values 2561 /* The distribution counts are first used to generate the code values
2485 * without bit reversal. 2562 * without bit reversal.
2486 */ 2563 */
2487 for (bits = 1; bits <= MAX_BITS; bits++) { 2564 for (bits = 1; bits <= MAX_BITS; bits++) {
2488 next_code[bits] = code = (code + bl_count[bits-1]) << 1; 2565 next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
2489 } 2566 }
2490 /* Check that the bit counts in bl_count are consistent. The last code 2567 /* Check that the bit counts in bl_count are consistent. The last code
2491 * must be all ones. 2568 * must be all ones.
2492 */ 2569 */
2493 Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, 2570 Assert(code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
2494 "inconsistent bit counts"); 2571 "inconsistent bit counts");
2495 Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); 2572 Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
2496 2573
2497 for (n = 0; n <= max_code; n++) { 2574 for (n = 0; n <= max_code; n++) {
2498 int len = tree[n].Len; 2575 int len = tree[n].Len;
2499 if (len == 0) continue; 2576
2500 /* Now reverse the bits */ 2577 if (len == 0)
2501 tree[n].Code = bi_reverse(next_code[len]++, len); 2578 continue;
2502 2579 /* Now reverse the bits */
2503 Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", 2580 tree[n].Code = bi_reverse(next_code[len]++, len);
2504 n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); 2581
2505 } 2582 Tracec(tree != static_ltree,
2583 (stderr, "\nn %3d %c l %2d c %4x (%x) ", n,
2584 (isgraph(n) ? n : ' '), len, tree[n].Code,
2585 next_code[len] - 1));
2586 }
2506} 2587}
2507 2588
2508/* =========================================================================== 2589/* ===========================================================================
@@ -2514,84 +2595,89 @@ local void gen_codes (tree, max_code)
2514 * also updated if stree is not null. The field max_code is set. 2595 * also updated if stree is not null. The field max_code is set.
2515 */ 2596 */
2516local void build_tree(desc) 2597local void build_tree(desc)
2517 tree_desc near *desc; /* the tree descriptor */ 2598tree_desc near *desc; /* the tree descriptor */
2518{ 2599{
2519 ct_data near *tree = desc->dyn_tree; 2600 ct_data near *tree = desc->dyn_tree;
2520 ct_data near *stree = desc->static_tree; 2601 ct_data near *stree = desc->static_tree;
2521 int elems = desc->elems; 2602 int elems = desc->elems;
2522 int n, m; /* iterate over heap elements */ 2603 int n, m; /* iterate over heap elements */
2523 int max_code = -1; /* largest code with non zero frequency */ 2604 int max_code = -1; /* largest code with non zero frequency */
2524 int node = elems; /* next internal node of the tree */ 2605 int node = elems; /* next internal node of the tree */
2525 2606
2526 /* Construct the initial heap, with least frequent element in 2607 /* Construct the initial heap, with least frequent element in
2527 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. 2608 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
2528 * heap[0] is not used. 2609 * heap[0] is not used.
2529 */ 2610 */
2530 heap_len = 0, heap_max = HEAP_SIZE; 2611 heap_len = 0, heap_max = HEAP_SIZE;
2531 2612
2532 for (n = 0; n < elems; n++) { 2613 for (n = 0; n < elems; n++) {
2533 if (tree[n].Freq != 0) { 2614 if (tree[n].Freq != 0) {
2534 heap[++heap_len] = max_code = n; 2615 heap[++heap_len] = max_code = n;
2535 depth[n] = 0; 2616 depth[n] = 0;
2536 } else { 2617 } else {
2537 tree[n].Len = 0; 2618 tree[n].Len = 0;
2538 } 2619 }
2539 } 2620 }
2540 2621
2541 /* The pkzip format requires that at least one distance code exists, 2622 /* The pkzip format requires that at least one distance code exists,
2542 * and that at least one bit should be sent even if there is only one 2623 * and that at least one bit should be sent even if there is only one
2543 * possible code. So to avoid special checks later on we force at least 2624 * possible code. So to avoid special checks later on we force at least
2544 * two codes of non zero frequency. 2625 * two codes of non zero frequency.
2545 */ 2626 */
2546 while (heap_len < 2) { 2627 while (heap_len < 2) {
2547 int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0); 2628 int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
2548 tree[new].Freq = 1; 2629
2549 depth[new] = 0; 2630 tree[new].Freq = 1;
2550 opt_len--; if (stree) static_len -= stree[new].Len; 2631 depth[new] = 0;
2551 /* new is 0 or 1 so it does not have extra bits */ 2632 opt_len--;
2552 } 2633 if (stree)
2553 desc->max_code = max_code; 2634 static_len -= stree[new].Len;
2554 2635 /* new is 0 or 1 so it does not have extra bits */
2555 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, 2636 }
2556 * establish sub-heaps of increasing lengths: 2637 desc->max_code = max_code;
2557 */ 2638
2558 for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n); 2639 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
2559 2640 * establish sub-heaps of increasing lengths:
2560 /* Construct the Huffman tree by repeatedly combining the least two 2641 */
2561 * frequent nodes. 2642 for (n = heap_len / 2; n >= 1; n--)
2562 */ 2643 pqdownheap(tree, n);
2563 do { 2644
2564 pqremove(tree, n); /* n = node of least frequency */ 2645 /* Construct the Huffman tree by repeatedly combining the least two
2565 m = heap[SMALLEST]; /* m = node of next least frequency */ 2646 * frequent nodes.
2566 2647 */
2567 heap[--heap_max] = n; /* keep the nodes sorted by frequency */ 2648 do {
2568 heap[--heap_max] = m; 2649 pqremove(tree, n); /* n = node of least frequency */
2569 2650 m = heap[SMALLEST]; /* m = node of next least frequency */
2570 /* Create a new node father of n and m */ 2651
2571 tree[node].Freq = tree[n].Freq + tree[m].Freq; 2652 heap[--heap_max] = n; /* keep the nodes sorted by frequency */
2572 depth[node] = (uch) (MAX(depth[n], depth[m]) + 1); 2653 heap[--heap_max] = m;
2573 tree[n].Dad = tree[m].Dad = (ush)node; 2654
2655 /* Create a new node father of n and m */
2656 tree[node].Freq = tree[n].Freq + tree[m].Freq;
2657 depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
2658 tree[n].Dad = tree[m].Dad = (ush) node;
2574#ifdef DUMP_BL_TREE 2659#ifdef DUMP_BL_TREE
2575 if (tree == bl_tree) { 2660 if (tree == bl_tree) {
2576 fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", 2661 fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)",
2577 node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); 2662 node, tree[node].Freq, n, tree[n].Freq, m,
2578 } 2663 tree[m].Freq);
2664 }
2579#endif 2665#endif
2580 /* and insert the new node in the heap */ 2666 /* and insert the new node in the heap */
2581 heap[SMALLEST] = node++; 2667 heap[SMALLEST] = node++;
2582 pqdownheap(tree, SMALLEST); 2668 pqdownheap(tree, SMALLEST);
2583 2669
2584 } while (heap_len >= 2); 2670 } while (heap_len >= 2);
2585 2671
2586 heap[--heap_max] = heap[SMALLEST]; 2672 heap[--heap_max] = heap[SMALLEST];
2587 2673
2588 /* At this point, the fields freq and dad are set. We can now 2674 /* At this point, the fields freq and dad are set. We can now
2589 * generate the bit lengths. 2675 * generate the bit lengths.
2590 */ 2676 */
2591 gen_bitlen((tree_desc near *)desc); 2677 gen_bitlen((tree_desc near *) desc);
2592 2678
2593 /* The field len is now set, we can generate the bit codes */ 2679 /* The field len is now set, we can generate the bit codes */
2594 gen_codes ((ct_data near *)tree, max_code); 2680 gen_codes((ct_data near *) tree, max_code);
2595} 2681}
2596 2682
2597/* =========================================================================== 2683/* ===========================================================================
@@ -2600,94 +2686,107 @@ local void build_tree(desc)
2600 * counts. (The contribution of the bit length codes will be added later 2686 * counts. (The contribution of the bit length codes will be added later
2601 * during the construction of bl_tree.) 2687 * during the construction of bl_tree.)
2602 */ 2688 */
2603local void scan_tree (tree, max_code) 2689local void scan_tree(tree, max_code)
2604 ct_data near *tree; /* the tree to be scanned */ 2690ct_data near *tree; /* the tree to be scanned */
2605 int max_code; /* and its largest code of non zero frequency */ 2691int max_code; /* and its largest code of non zero frequency */
2606{ 2692{
2607 int n; /* iterates over all tree elements */ 2693 int n; /* iterates over all tree elements */
2608 int prevlen = -1; /* last emitted length */ 2694 int prevlen = -1; /* last emitted length */
2609 int curlen; /* length of current code */ 2695 int curlen; /* length of current code */
2610 int nextlen = tree[0].Len; /* length of next code */ 2696 int nextlen = tree[0].Len; /* length of next code */
2611 int count = 0; /* repeat count of the current code */ 2697 int count = 0; /* repeat count of the current code */
2612 int max_count = 7; /* max repeat count */ 2698 int max_count = 7; /* max repeat count */
2613 int min_count = 4; /* min repeat count */ 2699 int min_count = 4; /* min repeat count */
2614 2700
2615 if (nextlen == 0) max_count = 138, min_count = 3; 2701 if (nextlen == 0)
2616 tree[max_code+1].Len = (ush)0xffff; /* guard */ 2702 max_count = 138, min_count = 3;
2617 2703 tree[max_code + 1].Len = (ush) 0xffff; /* guard */
2618 for (n = 0; n <= max_code; n++) { 2704
2619 curlen = nextlen; nextlen = tree[n+1].Len; 2705 for (n = 0; n <= max_code; n++) {
2620 if (++count < max_count && curlen == nextlen) { 2706 curlen = nextlen;
2621 continue; 2707 nextlen = tree[n + 1].Len;
2622 } else if (count < min_count) { 2708 if (++count < max_count && curlen == nextlen) {
2623 bl_tree[curlen].Freq += count; 2709 continue;
2624 } else if (curlen != 0) { 2710 } else if (count < min_count) {
2625 if (curlen != prevlen) bl_tree[curlen].Freq++; 2711 bl_tree[curlen].Freq += count;
2626 bl_tree[REP_3_6].Freq++; 2712 } else if (curlen != 0) {
2627 } else if (count <= 10) { 2713 if (curlen != prevlen)
2628 bl_tree[REPZ_3_10].Freq++; 2714 bl_tree[curlen].Freq++;
2629 } else { 2715 bl_tree[REP_3_6].Freq++;
2630 bl_tree[REPZ_11_138].Freq++; 2716 } else if (count <= 10) {
2631 } 2717 bl_tree[REPZ_3_10].Freq++;
2632 count = 0; prevlen = curlen; 2718 } else {
2633 if (nextlen == 0) { 2719 bl_tree[REPZ_11_138].Freq++;
2634 max_count = 138, min_count = 3; 2720 }
2635 } else if (curlen == nextlen) { 2721 count = 0;
2636 max_count = 6, min_count = 3; 2722 prevlen = curlen;
2637 } else { 2723 if (nextlen == 0) {
2638 max_count = 7, min_count = 4; 2724 max_count = 138, min_count = 3;
2639 } 2725 } else if (curlen == nextlen) {
2640 } 2726 max_count = 6, min_count = 3;
2727 } else {
2728 max_count = 7, min_count = 4;
2729 }
2730 }
2641} 2731}
2642 2732
2643/* =========================================================================== 2733/* ===========================================================================
2644 * Send a literal or distance tree in compressed form, using the codes in 2734 * Send a literal or distance tree in compressed form, using the codes in
2645 * bl_tree. 2735 * bl_tree.
2646 */ 2736 */
2647local void send_tree (tree, max_code) 2737local void send_tree(tree, max_code)
2648 ct_data near *tree; /* the tree to be scanned */ 2738ct_data near *tree; /* the tree to be scanned */
2649 int max_code; /* and its largest code of non zero frequency */ 2739int max_code; /* and its largest code of non zero frequency */
2650{ 2740{
2651 int n; /* iterates over all tree elements */ 2741 int n; /* iterates over all tree elements */
2652 int prevlen = -1; /* last emitted length */ 2742 int prevlen = -1; /* last emitted length */
2653 int curlen; /* length of current code */ 2743 int curlen; /* length of current code */
2654 int nextlen = tree[0].Len; /* length of next code */ 2744 int nextlen = tree[0].Len; /* length of next code */
2655 int count = 0; /* repeat count of the current code */ 2745 int count = 0; /* repeat count of the current code */
2656 int max_count = 7; /* max repeat count */ 2746 int max_count = 7; /* max repeat count */
2657 int min_count = 4; /* min repeat count */ 2747 int min_count = 4; /* min repeat count */
2658 2748
2659 /* tree[max_code+1].Len = -1; */ /* guard already set */ 2749/* tree[max_code+1].Len = -1; *//* guard already set */
2660 if (nextlen == 0) max_count = 138, min_count = 3; 2750 if (nextlen == 0)
2661 2751 max_count = 138, min_count = 3;
2662 for (n = 0; n <= max_code; n++) { 2752
2663 curlen = nextlen; nextlen = tree[n+1].Len; 2753 for (n = 0; n <= max_code; n++) {
2664 if (++count < max_count && curlen == nextlen) { 2754 curlen = nextlen;
2665 continue; 2755 nextlen = tree[n + 1].Len;
2666 } else if (count < min_count) { 2756 if (++count < max_count && curlen == nextlen) {
2667 do { send_code(curlen, bl_tree); } while (--count != 0); 2757 continue;
2668 2758 } else if (count < min_count) {
2669 } else if (curlen != 0) { 2759 do {
2670 if (curlen != prevlen) { 2760 send_code(curlen, bl_tree);
2671 send_code(curlen, bl_tree); count--; 2761 } while (--count != 0);
2672 } 2762
2673 Assert(count >= 3 && count <= 6, " 3_6?"); 2763 } else if (curlen != 0) {
2674 send_code(REP_3_6, bl_tree); send_bits(count-3, 2); 2764 if (curlen != prevlen) {
2675 2765 send_code(curlen, bl_tree);
2676 } else if (count <= 10) { 2766 count--;
2677 send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3); 2767 }
2678 2768 Assert(count >= 3 && count <= 6, " 3_6?");
2679 } else { 2769 send_code(REP_3_6, bl_tree);
2680 send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7); 2770 send_bits(count - 3, 2);
2681 } 2771
2682 count = 0; prevlen = curlen; 2772 } else if (count <= 10) {
2683 if (nextlen == 0) { 2773 send_code(REPZ_3_10, bl_tree);
2684 max_count = 138, min_count = 3; 2774 send_bits(count - 3, 3);
2685 } else if (curlen == nextlen) { 2775
2686 max_count = 6, min_count = 3; 2776 } else {
2687 } else { 2777 send_code(REPZ_11_138, bl_tree);
2688 max_count = 7, min_count = 4; 2778 send_bits(count - 11, 7);
2689 } 2779 }
2690 } 2780 count = 0;
2781 prevlen = curlen;
2782 if (nextlen == 0) {
2783 max_count = 138, min_count = 3;
2784 } else if (curlen == nextlen) {
2785 max_count = 6, min_count = 3;
2786 } else {
2787 max_count = 7, min_count = 4;
2788 }
2789 }
2691} 2790}
2692 2791
2693/* =========================================================================== 2792/* ===========================================================================
@@ -2696,30 +2795,33 @@ local void send_tree (tree, max_code)
2696 */ 2795 */
2697local int build_bl_tree() 2796local int build_bl_tree()
2698{ 2797{
2699 int max_blindex; /* index of last bit length code of non zero freq */ 2798 int max_blindex; /* index of last bit length code of non zero freq */
2700 2799
2701 /* Determine the bit length frequencies for literal and distance trees */ 2800 /* Determine the bit length frequencies for literal and distance trees */
2702 scan_tree((ct_data near *)dyn_ltree, l_desc.max_code); 2801 scan_tree((ct_data near *) dyn_ltree, l_desc.max_code);
2703 scan_tree((ct_data near *)dyn_dtree, d_desc.max_code); 2802 scan_tree((ct_data near *) dyn_dtree, d_desc.max_code);
2704 2803
2705 /* Build the bit length tree: */ 2804 /* Build the bit length tree: */
2706 build_tree((tree_desc near *)(&bl_desc)); 2805 build_tree((tree_desc near *) (&bl_desc));
2707 /* opt_len now includes the length of the tree representations, except 2806 /* opt_len now includes the length of the tree representations, except
2708 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. 2807 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
2709 */ 2808 */
2710 2809
2711 /* Determine the number of bit length codes to send. The pkzip format 2810 /* Determine the number of bit length codes to send. The pkzip format
2712 * requires that at least 4 bit length codes be sent. (appnote.txt says 2811 * requires that at least 4 bit length codes be sent. (appnote.txt says
2713 * 3 but the actual value used is 4.) 2812 * 3 but the actual value used is 4.)
2714 */ 2813 */
2715 for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { 2814 for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
2716 if (bl_tree[bl_order[max_blindex]].Len != 0) break; 2815 if (bl_tree[bl_order[max_blindex]].Len != 0)
2717 } 2816 break;
2718 /* Update opt_len to include the bit length tree and counts */ 2817 }
2719 opt_len += 3*(max_blindex+1) + 5+5+4; 2818 /* Update opt_len to include the bit length tree and counts */
2720 Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len)); 2819 opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
2721 2820 Tracev(
2722 return max_blindex; 2821 (stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len,
2822 static_len));
2823
2824 return max_blindex;
2723} 2825}
2724 2826
2725/* =========================================================================== 2827/* ===========================================================================
@@ -2728,28 +2830,29 @@ local int build_bl_tree()
2728 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. 2830 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
2729 */ 2831 */
2730local void send_all_trees(lcodes, dcodes, blcodes) 2832local void send_all_trees(lcodes, dcodes, blcodes)
2731 int lcodes, dcodes, blcodes; /* number of codes for each tree */ 2833int lcodes, dcodes, blcodes; /* number of codes for each tree */
2732{ 2834{
2733 int rank; /* index in bl_order */ 2835 int rank; /* index in bl_order */
2734 2836
2735 Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); 2837 Assert(lcodes >= 257 && dcodes >= 1
2736 Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, 2838 && blcodes >= 4, "not enough codes");
2737 "too many codes"); 2839 Assert(lcodes <= L_CODES && dcodes <= D_CODES
2738 Tracev((stderr, "\nbl counts: ")); 2840 && blcodes <= BL_CODES, "too many codes");
2739 send_bits(lcodes-257, 5); /* not +255 as stated in appnote.txt */ 2841 Tracev((stderr, "\nbl counts: "));
2740 send_bits(dcodes-1, 5); 2842 send_bits(lcodes - 257, 5); /* not +255 as stated in appnote.txt */
2741 send_bits(blcodes-4, 4); /* not -3 as stated in appnote.txt */ 2843 send_bits(dcodes - 1, 5);
2742 for (rank = 0; rank < blcodes; rank++) { 2844 send_bits(blcodes - 4, 4); /* not -3 as stated in appnote.txt */
2743 Tracev((stderr, "\nbl code %2d ", bl_order[rank])); 2845 for (rank = 0; rank < blcodes; rank++) {
2744 send_bits(bl_tree[bl_order[rank]].Len, 3); 2846 Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
2745 } 2847 send_bits(bl_tree[bl_order[rank]].Len, 3);
2746 Tracev((stderr, "\nbl tree: sent %ld", bits_sent)); 2848 }
2747 2849 Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
2748 send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */ 2850
2749 Tracev((stderr, "\nlit tree: sent %ld", bits_sent)); 2851 send_tree((ct_data near *) dyn_ltree, lcodes - 1); /* send the literal tree */
2750 2852 Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
2751 send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */ 2853
2752 Tracev((stderr, "\ndist tree: sent %ld", bits_sent)); 2854 send_tree((ct_data near *) dyn_dtree, dcodes - 1); /* send the distance tree */
2855 Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
2753} 2856}
2754 2857
2755/* =========================================================================== 2858/* ===========================================================================
@@ -2758,204 +2861,222 @@ local void send_all_trees(lcodes, dcodes, blcodes)
2758 * returns the total compressed length for the file so far. 2861 * returns the total compressed length for the file so far.
2759 */ 2862 */
2760ulg flush_block(buf, stored_len, eof) 2863ulg flush_block(buf, stored_len, eof)
2761 char *buf; /* input block, or NULL if too old */ 2864char *buf; /* input block, or NULL if too old */
2762 ulg stored_len; /* length of input block */ 2865ulg stored_len; /* length of input block */
2763 int eof; /* true if this is the last block for a file */ 2866int eof; /* true if this is the last block for a file */
2764{ 2867{
2765 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ 2868 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
2766 int max_blindex; /* index of last bit length code of non zero freq */ 2869 int max_blindex; /* index of last bit length code of non zero freq */
2767 2870
2768 flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ 2871 flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
2769 2872
2770 /* Check if the file is ascii or binary */ 2873 /* Check if the file is ascii or binary */
2771 if (*file_type == (ush)UNKNOWN) set_file_type(); 2874 if (*file_type == (ush) UNKNOWN)
2772 2875 set_file_type();
2773 /* Construct the literal and distance trees */ 2876
2774 build_tree((tree_desc near *)(&l_desc)); 2877 /* Construct the literal and distance trees */
2775 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); 2878 build_tree((tree_desc near *) (&l_desc));
2776 2879 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
2777 build_tree((tree_desc near *)(&d_desc)); 2880
2778 Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len)); 2881 build_tree((tree_desc near *) (&d_desc));
2779 /* At this point, opt_len and static_len are the total bit lengths of 2882 Tracev(
2780 * the compressed block data, excluding the tree representations. 2883 (stderr, "\ndist data: dyn %ld, stat %ld", opt_len,
2781 */ 2884 static_len));
2782 2885 /* At this point, opt_len and static_len are the total bit lengths of
2783 /* Build the bit length tree for the above two trees, and get the index 2886 * the compressed block data, excluding the tree representations.
2784 * in bl_order of the last bit length code to send. 2887 */
2785 */ 2888
2786 max_blindex = build_bl_tree(); 2889 /* Build the bit length tree for the above two trees, and get the index
2787 2890 * in bl_order of the last bit length code to send.
2788 /* Determine the best encoding. Compute first the block length in bytes */ 2891 */
2789 opt_lenb = (opt_len+3+7)>>3; 2892 max_blindex = build_bl_tree();
2790 static_lenb = (static_len+3+7)>>3; 2893
2791 input_len += stored_len; /* for debugging only */ 2894 /* Determine the best encoding. Compute first the block length in bytes */
2792 2895 opt_lenb = (opt_len + 3 + 7) >> 3;
2793 Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", 2896 static_lenb = (static_len + 3 + 7) >> 3;
2794 opt_lenb, opt_len, static_lenb, static_len, stored_len, 2897 input_len += stored_len; /* for debugging only */
2795 last_lit, last_dist)); 2898
2796 2899 Trace(
2797 if (static_lenb <= opt_lenb) opt_lenb = static_lenb; 2900 (stderr,
2798 2901 "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
2799 /* If compression failed and this is the first and last block, 2902 opt_lenb, opt_len, static_lenb, static_len, stored_len,
2800 * and if the zip file can be seeked (to rewrite the local header), 2903 last_lit, last_dist));
2801 * the whole file is transformed into a stored file: 2904
2802 */ 2905 if (static_lenb <= opt_lenb)
2906 opt_lenb = static_lenb;
2907
2908 /* If compression failed and this is the first and last block,
2909 * and if the zip file can be seeked (to rewrite the local header),
2910 * the whole file is transformed into a stored file:
2911 */
2803#ifdef FORCE_METHOD 2912#ifdef FORCE_METHOD
2804#else 2913#else
2805 if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) { 2914 if (stored_len <= opt_lenb && eof && compressed_len == 0L
2915 && seekable()) {
2806#endif 2916#endif
2807 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ 2917 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
2808 if (buf == (char*)0) error ("block vanished"); 2918 if (buf == (char *) 0)
2919 error("block vanished");
2809 2920
2810 copy_block(buf, (unsigned)stored_len, 0); /* without header */ 2921 copy_block(buf, (unsigned) stored_len, 0); /* without header */
2811 compressed_len = stored_len << 3; 2922 compressed_len = stored_len << 3;
2812 *file_method = STORED; 2923 *file_method = STORED;
2813 2924
2814#ifdef FORCE_METHOD 2925#ifdef FORCE_METHOD
2815#else 2926#else
2816 } else if (stored_len+4 <= opt_lenb && buf != (char*)0) { 2927 } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
2817 /* 4: two words for the lengths */ 2928 /* 4: two words for the lengths */
2818#endif 2929#endif
2819 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. 2930 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
2820 * Otherwise we can't have processed more than WSIZE input bytes since 2931 * Otherwise we can't have processed more than WSIZE input bytes since
2821 * the last block flush, because compression would have been 2932 * the last block flush, because compression would have been
2822 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 2933 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
2823 * transform a block into a stored block. 2934 * transform a block into a stored block.
2824 */ 2935 */
2825 send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */ 2936 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */
2826 compressed_len = (compressed_len + 3 + 7) & ~7L; 2937 compressed_len = (compressed_len + 3 + 7) & ~7L;
2827 compressed_len += (stored_len + 4) << 3; 2938 compressed_len += (stored_len + 4) << 3;
2828 2939
2829 copy_block(buf, (unsigned)stored_len, 1); /* with header */ 2940 copy_block(buf, (unsigned) stored_len, 1); /* with header */
2830 2941
2831#ifdef FORCE_METHOD 2942#ifdef FORCE_METHOD
2832#else 2943#else
2833 } else if (static_lenb == opt_lenb) { 2944 } else if (static_lenb == opt_lenb) {
2834#endif 2945#endif
2835 send_bits((STATIC_TREES<<1)+eof, 3); 2946 send_bits((STATIC_TREES << 1) + eof, 3);
2836 compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree); 2947 compress_block((ct_data near *) static_ltree,
2837 compressed_len += 3 + static_len; 2948 (ct_data near *) static_dtree);
2838 } else { 2949 compressed_len += 3 + static_len;
2839 send_bits((DYN_TREES<<1)+eof, 3); 2950 } else {
2840 send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); 2951 send_bits((DYN_TREES << 1) + eof, 3);
2841 compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree); 2952 send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
2842 compressed_len += 3 + opt_len; 2953 max_blindex + 1);
2843 } 2954 compress_block((ct_data near *) dyn_ltree,
2844 Assert (compressed_len == bits_sent, "bad compressed size"); 2955 (ct_data near *) dyn_dtree);
2845 init_block(); 2956 compressed_len += 3 + opt_len;
2846 2957 }
2847 if (eof) { 2958 Assert(compressed_len == bits_sent, "bad compressed size");
2848 Assert (input_len == isize, "bad input size"); 2959 init_block();
2849 bi_windup(); 2960
2850 compressed_len += 7; /* align on byte boundary */ 2961 if (eof) {
2851 } 2962 Assert(input_len == isize, "bad input size");
2852 Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3, 2963 bi_windup();
2853 compressed_len-7*eof)); 2964 compressed_len += 7; /* align on byte boundary */
2854 2965 }
2855 return compressed_len >> 3; 2966 Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
2967 compressed_len - 7 * eof));
2968
2969 return compressed_len >> 3;
2856} 2970}
2857 2971
2858/* =========================================================================== 2972/* ===========================================================================
2859 * Save the match info and tally the frequency counts. Return true if 2973 * Save the match info and tally the frequency counts. Return true if
2860 * the current block must be flushed. 2974 * the current block must be flushed.
2861 */ 2975 */
2862int ct_tally (dist, lc) 2976int ct_tally(dist, lc)
2863 int dist; /* distance of matched string */ 2977int dist; /* distance of matched string */
2864 int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ 2978int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
2865{ 2979{
2866 l_buf[last_lit++] = (uch)lc; 2980 l_buf[last_lit++] = (uch) lc;
2867 if (dist == 0) { 2981 if (dist == 0) {
2868 /* lc is the unmatched char */ 2982 /* lc is the unmatched char */
2869 dyn_ltree[lc].Freq++; 2983 dyn_ltree[lc].Freq++;
2870 } else { 2984 } else {
2871 /* Here, lc is the match length - MIN_MATCH */ 2985 /* Here, lc is the match length - MIN_MATCH */
2872 dist--; /* dist = match distance - 1 */ 2986 dist--; /* dist = match distance - 1 */
2873 Assert((ush)dist < (ush)MAX_DIST && 2987 Assert((ush) dist < (ush) MAX_DIST &&
2874 (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && 2988 (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH) &&
2875 (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); 2989 (ush) d_code(dist) < (ush) D_CODES, "ct_tally: bad match");
2876 2990
2877 dyn_ltree[length_code[lc]+LITERALS+1].Freq++; 2991 dyn_ltree[length_code[lc] + LITERALS + 1].Freq++;
2878 dyn_dtree[d_code(dist)].Freq++; 2992 dyn_dtree[d_code(dist)].Freq++;
2879 2993
2880 d_buf[last_dist++] = (ush)dist; 2994 d_buf[last_dist++] = (ush) dist;
2881 flags |= flag_bit; 2995 flags |= flag_bit;
2882 } 2996 }
2883 flag_bit <<= 1; 2997 flag_bit <<= 1;
2884 2998
2885 /* Output the flags if they fill a byte: */ 2999 /* Output the flags if they fill a byte: */
2886 if ((last_lit & 7) == 0) { 3000 if ((last_lit & 7) == 0) {
2887 flag_buf[last_flags++] = flags; 3001 flag_buf[last_flags++] = flags;
2888 flags = 0, flag_bit = 1; 3002 flags = 0, flag_bit = 1;
2889 } 3003 }
2890 /* Try to guess if it is profitable to stop the current block here */ 3004 /* Try to guess if it is profitable to stop the current block here */
2891 if ((last_lit & 0xfff) == 0) { 3005 if ((last_lit & 0xfff) == 0) {
2892 /* Compute an upper bound for the compressed length */ 3006 /* Compute an upper bound for the compressed length */
2893 ulg out_length = (ulg)last_lit*8L; 3007 ulg out_length = (ulg) last_lit * 8L;
2894 ulg in_length = (ulg)strstart-block_start; 3008 ulg in_length = (ulg) strstart - block_start;
2895 int dcode; 3009 int dcode;
2896 for (dcode = 0; dcode < D_CODES; dcode++) { 3010
2897 out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]); 3011 for (dcode = 0; dcode < D_CODES; dcode++) {
2898 } 3012 out_length +=
2899 out_length >>= 3; 3013 (ulg) dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]);
2900 Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", 3014 }
2901 last_lit, last_dist, in_length, out_length, 3015 out_length >>= 3;
2902 100L - out_length*100L/in_length)); 3016 Trace(
2903 if (last_dist < last_lit/2 && out_length < in_length/2) return 1; 3017 (stderr,
2904 } 3018 "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
2905 return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE); 3019 last_lit, last_dist, in_length, out_length,
2906 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K 3020 100L - out_length * 100L / in_length));
2907 * on 16 bit machines and because stored blocks are restricted to 3021 if (last_dist < last_lit / 2 && out_length < in_length / 2)
2908 * 64K-1 bytes. 3022 return 1;
2909 */ 3023 }
3024 return (last_lit == LIT_BUFSIZE - 1 || last_dist == DIST_BUFSIZE);
3025 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
3026 * on 16 bit machines and because stored blocks are restricted to
3027 * 64K-1 bytes.
3028 */
2910} 3029}
2911 3030
2912/* =========================================================================== 3031/* ===========================================================================
2913 * Send the block data compressed using the given Huffman trees 3032 * Send the block data compressed using the given Huffman trees
2914 */ 3033 */
2915local void compress_block(ltree, dtree) 3034local void compress_block(ltree, dtree)
2916 ct_data near *ltree; /* literal tree */ 3035ct_data near *ltree; /* literal tree */
2917 ct_data near *dtree; /* distance tree */ 3036ct_data near *dtree; /* distance tree */
2918{ 3037{
2919 unsigned dist; /* distance of matched string */ 3038 unsigned dist; /* distance of matched string */
2920 int lc; /* match length or unmatched char (if dist == 0) */ 3039 int lc; /* match length or unmatched char (if dist == 0) */
2921 unsigned lx = 0; /* running index in l_buf */ 3040 unsigned lx = 0; /* running index in l_buf */
2922 unsigned dx = 0; /* running index in d_buf */ 3041 unsigned dx = 0; /* running index in d_buf */
2923 unsigned fx = 0; /* running index in flag_buf */ 3042 unsigned fx = 0; /* running index in flag_buf */
2924 uch flag = 0; /* current flags */ 3043 uch flag = 0; /* current flags */
2925 unsigned code; /* the code to send */ 3044 unsigned code; /* the code to send */
2926 int extra; /* number of extra bits to send */ 3045 int extra; /* number of extra bits to send */
2927 3046
2928 if (last_lit != 0) do { 3047 if (last_lit != 0)
2929 if ((lx & 7) == 0) flag = flag_buf[fx++]; 3048 do {
2930 lc = l_buf[lx++]; 3049 if ((lx & 7) == 0)
2931 if ((flag & 1) == 0) { 3050 flag = flag_buf[fx++];
2932 send_code(lc, ltree); /* send a literal byte */ 3051 lc = l_buf[lx++];
2933 Tracecv(isgraph(lc), (stderr," '%c' ", lc)); 3052 if ((flag & 1) == 0) {
2934 } else { 3053 send_code(lc, ltree); /* send a literal byte */
2935 /* Here, lc is the match length - MIN_MATCH */ 3054 Tracecv(isgraph(lc), (stderr, " '%c' ", lc));
2936 code = length_code[lc]; 3055 } else {
2937 send_code(code+LITERALS+1, ltree); /* send the length code */ 3056 /* Here, lc is the match length - MIN_MATCH */
2938 extra = extra_lbits[code]; 3057 code = length_code[lc];
2939 if (extra != 0) { 3058 send_code(code + LITERALS + 1, ltree); /* send the length code */
2940 lc -= base_length[code]; 3059 extra = extra_lbits[code];
2941 send_bits(lc, extra); /* send the extra length bits */ 3060 if (extra != 0) {
2942 } 3061 lc -= base_length[code];
2943 dist = d_buf[dx++]; 3062 send_bits(lc, extra); /* send the extra length bits */
2944 /* Here, dist is the match distance - 1 */ 3063 }
2945 code = d_code(dist); 3064 dist = d_buf[dx++];
2946 Assert (code < D_CODES, "bad d_code"); 3065 /* Here, dist is the match distance - 1 */
2947 3066 code = d_code(dist);
2948 send_code(code, dtree); /* send the distance code */ 3067 Assert(code < D_CODES, "bad d_code");
2949 extra = extra_dbits[code]; 3068
2950 if (extra != 0) { 3069 send_code(code, dtree); /* send the distance code */
2951 dist -= base_dist[code]; 3070 extra = extra_dbits[code];
2952 send_bits(dist, extra); /* send the extra distance bits */ 3071 if (extra != 0) {
2953 } 3072 dist -= base_dist[code];
2954 } /* literal or match pair ? */ 3073 send_bits(dist, extra); /* send the extra distance bits */
2955 flag >>= 1; 3074 }
2956 } while (lx < last_lit); 3075 } /* literal or match pair ? */
2957 3076 flag >>= 1;
2958 send_code(END_BLOCK, ltree); 3077 } while (lx < last_lit);
3078
3079 send_code(END_BLOCK, ltree);
2959} 3080}
2960 3081
2961/* =========================================================================== 3082/* ===========================================================================
@@ -2966,17 +3087,22 @@ local void compress_block(ltree, dtree)
2966 */ 3087 */
2967local void set_file_type() 3088local void set_file_type()
2968{ 3089{
2969 int n = 0; 3090 int n = 0;
2970 unsigned ascii_freq = 0; 3091 unsigned ascii_freq = 0;
2971 unsigned bin_freq = 0; 3092 unsigned bin_freq = 0;
2972 while (n < 7) bin_freq += dyn_ltree[n++].Freq; 3093
2973 while (n < 128) ascii_freq += dyn_ltree[n++].Freq; 3094 while (n < 7)
2974 while (n < LITERALS) bin_freq += dyn_ltree[n++].Freq; 3095 bin_freq += dyn_ltree[n++].Freq;
2975 *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; 3096 while (n < 128)
2976 if (*file_type == BINARY && translate_eol) { 3097 ascii_freq += dyn_ltree[n++].Freq;
2977 warn("-l used on binary file", ""); 3098 while (n < LITERALS)
2978 } 3099 bin_freq += dyn_ltree[n++].Freq;
3100 *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
3101 if (*file_type == BINARY && translate_eol) {
3102 warn("-l used on binary file", "");
3103 }
2979} 3104}
3105
2980/* util.c -- utility functions for gzip support 3106/* util.c -- utility functions for gzip support
2981 * Copyright (C) 1992-1993 Jean-loup Gailly 3107 * Copyright (C) 1992-1993 Jean-loup Gailly
2982 * This is free software; you can redistribute it and/or modify it under the 3108 * This is free software; you can redistribute it and/or modify it under the
@@ -2997,7 +3123,7 @@ local void set_file_type()
2997#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H) 3123#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
2998# include <stdlib.h> 3124# include <stdlib.h>
2999#else 3125#else
3000 extern int errno; 3126extern int errno;
3001#endif 3127#endif
3002 3128
3003/* =========================================================================== 3129/* ===========================================================================
@@ -3005,30 +3131,32 @@ local void set_file_type()
3005 * IN assertion: insize bytes have already been read in inbuf. 3131 * IN assertion: insize bytes have already been read in inbuf.
3006 */ 3132 */
3007int copy(in, out) 3133int copy(in, out)
3008 int in, out; /* input and output file descriptors */ 3134int in, out; /* input and output file descriptors */
3009{ 3135{
3010 errno = 0; 3136 errno = 0;
3011 while (insize != 0 && (int)insize != EOF) { 3137 while (insize != 0 && (int) insize != EOF) {
3012 write_buf(out, (char*)inbuf, insize); 3138 write_buf(out, (char *) inbuf, insize);
3013 bytes_out += insize; 3139 bytes_out += insize;
3014 insize = read(in, (char*)inbuf, INBUFSIZ); 3140 insize = read(in, (char *) inbuf, INBUFSIZ);
3015 } 3141 }
3016 if ((int)insize == EOF && errno != 0) { 3142 if ((int) insize == EOF && errno != 0) {
3017 read_error(); 3143 read_error();
3018 } 3144 }
3019 bytes_in = bytes_out; 3145 bytes_in = bytes_out;
3020 return OK; 3146 return OK;
3021} 3147}
3022 3148
3023/* ======================================================================== 3149/* ========================================================================
3024 * Put string s in lower case, return s. 3150 * Put string s in lower case, return s.
3025 */ 3151 */
3026char *strlwr(s) 3152char *strlwr(s)
3027 char *s; 3153char *s;
3028{ 3154{
3029 char *t; 3155 char *t;
3030 for (t = s; *t; t++) *t = tolow(*t); 3156
3031 return s; 3157 for (t = s; *t; t++)
3158 *t = tolow(*t);
3159 return s;
3032} 3160}
3033 3161
3034#if defined(NO_STRING_H) && !defined(STDC_HEADERS) 3162#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
@@ -3039,7 +3167,7 @@ char *strlwr(s)
3039# define const 3167# define const
3040# endif 3168# endif
3041 3169
3042int strspn OF((const char *s, const char *accept)); 3170int strspn OF((const char *s, const char *accept));
3043int strcspn OF((const char *s, const char *reject)); 3171int strcspn OF((const char *s, const char *reject));
3044 3172
3045/* ======================================================================== 3173/* ========================================================================
@@ -3047,21 +3175,23 @@ int strcspn OF((const char *s, const char *reject));
3047 * of s which contains only characters in accept. 3175 * of s which contains only characters in accept.
3048 */ 3176 */
3049int strspn(s, accept) 3177int strspn(s, accept)
3050 const char *s; 3178const char *s;
3051 const char *accept; 3179const char *accept;
3052{ 3180{
3053 register const char *p; 3181 register const char *p;
3054 register const char *a; 3182 register const char *a;
3055 register int count = 0; 3183 register int count = 0;
3056 3184
3057 for (p = s; *p != '\0'; ++p) { 3185 for (p = s; *p != '\0'; ++p) {
3058 for (a = accept; *a != '\0'; ++a) { 3186 for (a = accept; *a != '\0'; ++a) {
3059 if (*p == *a) break; 3187 if (*p == *a)
3188 break;
3189 }
3190 if (*a == '\0')
3191 return count;
3192 ++count;
3060 } 3193 }
3061 if (*a == '\0') return count; 3194 return count;
3062 ++count;
3063 }
3064 return count;
3065} 3195}
3066 3196
3067/* ======================================================================== 3197/* ========================================================================
@@ -3069,104 +3199,113 @@ int strspn(s, accept)
3069 * which contains no characters from reject. 3199 * which contains no characters from reject.
3070 */ 3200 */
3071int strcspn(s, reject) 3201int strcspn(s, reject)
3072 const char *s; 3202const char *s;
3073 const char *reject; 3203const char *reject;
3074{ 3204{
3075 register int count = 0; 3205 register int count = 0;
3076 3206
3077 while (*s != '\0') { 3207 while (*s != '\0') {
3078 if (strchr(reject, *s++) != NULL) return count; 3208 if (strchr(reject, *s++) != NULL)
3079 ++count; 3209 return count;
3080 } 3210 ++count;
3081 return count; 3211 }
3212 return count;
3082} 3213}
3083 3214
3084#endif /* NO_STRING_H */ 3215#endif /* NO_STRING_H */
3085 3216
3086/* ======================================================================== 3217/* ========================================================================
3087 * Add an environment variable (if any) before argv, and update argc. 3218 * Add an environment variable (if any) before argv, and update argc.
3088 * Return the expanded environment variable to be freed later, or NULL 3219 * Return the expanded environment variable to be freed later, or NULL
3089 * if no options were added to argv. 3220 * if no options were added to argv.
3090 */ 3221 */
3091#define SEPARATOR " \t" /* separators in env variable */ 3222#define SEPARATOR " \t" /* separators in env variable */
3092 3223
3093char *add_envopt(argcp, argvp, env) 3224char *add_envopt(argcp, argvp, env)
3094 int *argcp; /* pointer to argc */ 3225int *argcp; /* pointer to argc */
3095 char ***argvp; /* pointer to argv */ 3226char ***argvp; /* pointer to argv */
3096 char *env; /* name of environment variable */ 3227char *env; /* name of environment variable */
3097{ 3228{
3098 char *p; /* running pointer through env variable */ 3229 char *p; /* running pointer through env variable */
3099 char **oargv; /* runs through old argv array */ 3230 char **oargv; /* runs through old argv array */
3100 char **nargv; /* runs through new argv array */ 3231 char **nargv; /* runs through new argv array */
3101 int oargc = *argcp; /* old argc */ 3232 int oargc = *argcp; /* old argc */
3102 int nargc = 0; /* number of arguments in env variable */ 3233 int nargc = 0; /* number of arguments in env variable */
3103 3234
3104 env = (char*)getenv(env); 3235 env = (char *) getenv(env);
3105 if (env == NULL) return NULL; 3236 if (env == NULL)
3106 3237 return NULL;
3107 p = (char*)xmalloc(strlen(env)+1); 3238
3108 env = strcpy(p, env); /* keep env variable intact */ 3239 p = (char *) xmalloc(strlen(env) + 1);
3109 3240 env = strcpy(p, env); /* keep env variable intact */
3110 for (p = env; *p; nargc++ ) { /* move through env */ 3241
3111 p += strspn(p, SEPARATOR); /* skip leading separators */ 3242 for (p = env; *p; nargc++) { /* move through env */
3112 if (*p == '\0') break; 3243 p += strspn(p, SEPARATOR); /* skip leading separators */
3113 3244 if (*p == '\0')
3114 p += strcspn(p, SEPARATOR); /* find end of word */ 3245 break;
3115 if (*p) *p++ = '\0'; /* mark it */ 3246
3116 } 3247 p += strcspn(p, SEPARATOR); /* find end of word */
3117 if (nargc == 0) { 3248 if (*p)
3118 free(env); 3249 *p++ = '\0'; /* mark it */
3119 return NULL; 3250 }
3120 } 3251 if (nargc == 0) {
3121 *argcp += nargc; 3252 free(env);
3122 /* Allocate the new argv array, with an extra element just in case 3253 return NULL;
3123 * the original arg list did not end with a NULL. 3254 }
3124 */ 3255 *argcp += nargc;
3125 nargv = (char**)calloc(*argcp+1, sizeof(char *)); 3256 /* Allocate the new argv array, with an extra element just in case
3126 if (nargv == NULL) error("out of memory"); 3257 * the original arg list did not end with a NULL.
3127 oargv = *argvp; 3258 */
3128 *argvp = nargv; 3259 nargv = (char **) calloc(*argcp + 1, sizeof(char *));
3129 3260
3130 /* Copy the program name first */ 3261 if (nargv == NULL)
3131 if (oargc-- < 0) error("argc<=0"); 3262 error("out of memory");
3132 *(nargv++) = *(oargv++); 3263 oargv = *argvp;
3133 3264 *argvp = nargv;
3134 /* Then copy the environment args */ 3265
3135 for (p = env; nargc > 0; nargc--) { 3266 /* Copy the program name first */
3136 p += strspn(p, SEPARATOR); /* skip separators */ 3267 if (oargc-- < 0)
3137 *(nargv++) = p; /* store start */ 3268 error("argc<=0");
3138 while (*p++) ; /* skip over word */ 3269 *(nargv++) = *(oargv++);
3139 } 3270
3140 3271 /* Then copy the environment args */
3141 /* Finally copy the old args and add a NULL (usual convention) */ 3272 for (p = env; nargc > 0; nargc--) {
3142 while (oargc--) *(nargv++) = *(oargv++); 3273 p += strspn(p, SEPARATOR); /* skip separators */
3143 *nargv = NULL; 3274 *(nargv++) = p; /* store start */
3144 return env; 3275 while (*p++); /* skip over word */
3276 }
3277
3278 /* Finally copy the old args and add a NULL (usual convention) */
3279 while (oargc--)
3280 *(nargv++) = *(oargv++);
3281 *nargv = NULL;
3282 return env;
3145} 3283}
3284
3146/* ======================================================================== 3285/* ========================================================================
3147 * Display compression ratio on the given stream on 6 characters. 3286 * Display compression ratio on the given stream on 6 characters.
3148 */ 3287 */
3149void display_ratio(num, den, file) 3288void display_ratio(num, den, file)
3150 long num; 3289long num;
3151 long den; 3290long den;
3152 FILE *file; 3291FILE *file;
3153{ 3292{
3154 long ratio; /* 1000 times the compression ratio */ 3293 long ratio; /* 1000 times the compression ratio */
3155 3294
3156 if (den == 0) { 3295 if (den == 0) {
3157 ratio = 0; /* no compression */ 3296 ratio = 0; /* no compression */
3158 } else if (den < 2147483L) { /* (2**31 -1)/1000 */ 3297 } else if (den < 2147483L) { /* (2**31 -1)/1000 */
3159 ratio = 1000L*num/den; 3298 ratio = 1000L * num / den;
3160 } else { 3299 } else {
3161 ratio = num/(den/1000L); 3300 ratio = num / (den / 1000L);
3162 } 3301 }
3163 if (ratio < 0) { 3302 if (ratio < 0) {
3164 putc('-', file); 3303 putc('-', file);
3165 ratio = -ratio; 3304 ratio = -ratio;
3166 } else { 3305 } else {
3167 putc(' ', file); 3306 putc(' ', file);
3168 } 3307 }
3169 fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L); 3308 fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
3170} 3309}
3171 3310
3172 3311
@@ -3186,8 +3325,8 @@ void display_ratio(num, den, file)
3186# include <fcntl.h> 3325# include <fcntl.h>
3187#endif 3326#endif
3188 3327
3189local ulg crc; /* crc on uncompressed file data */ 3328local ulg crc; /* crc on uncompressed file data */
3190long header_bytes; /* number of bytes in gzip header */ 3329long header_bytes; /* number of bytes in gzip header */
3191 3330
3192/* =========================================================================== 3331/* ===========================================================================
3193 * Deflate in to out. 3332 * Deflate in to out.
@@ -3195,48 +3334,48 @@ long header_bytes; /* number of bytes in gzip header */
3195 * The variables time_stamp and save_orig_name are initialized. 3334 * The variables time_stamp and save_orig_name are initialized.
3196 */ 3335 */
3197int zip(in, out) 3336int zip(in, out)
3198 int in, out; /* input and output file descriptors */ 3337int in, out; /* input and output file descriptors */
3199{ 3338{
3200 uch flags = 0; /* general purpose bit flags */ 3339 uch flags = 0; /* general purpose bit flags */
3201 ush attr = 0; /* ascii/binary flag */ 3340 ush attr = 0; /* ascii/binary flag */
3202 ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ 3341 ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
3203 3342
3204 ifd = in; 3343 ifd = in;
3205 ofd = out; 3344 ofd = out;
3206 outcnt = 0; 3345 outcnt = 0;
3207 3346
3208 /* Write the header to the gzip file. See algorithm.doc for the format */ 3347 /* Write the header to the gzip file. See algorithm.doc for the format */
3209 3348
3210 3349
3211 method = DEFLATED; 3350 method = DEFLATED;
3212 put_byte(GZIP_MAGIC[0]); /* magic header */ 3351 put_byte(GZIP_MAGIC[0]); /* magic header */
3213 put_byte(GZIP_MAGIC[1]); 3352 put_byte(GZIP_MAGIC[1]);
3214 put_byte(DEFLATED); /* compression method */ 3353 put_byte(DEFLATED); /* compression method */
3215 3354
3216 put_byte(flags); /* general flags */ 3355 put_byte(flags); /* general flags */
3217 put_long(time_stamp); 3356 put_long(time_stamp);
3218 3357
3219 /* Write deflated file to zip file */ 3358 /* Write deflated file to zip file */
3220 crc = updcrc(0, 0); 3359 crc = updcrc(0, 0);
3221 3360
3222 bi_init(out); 3361 bi_init(out);
3223 ct_init(&attr, &method); 3362 ct_init(&attr, &method);
3224 lm_init(&deflate_flags); 3363 lm_init(&deflate_flags);
3225 3364
3226 put_byte((uch)deflate_flags); /* extra flags */ 3365 put_byte((uch) deflate_flags); /* extra flags */
3227 put_byte(OS_CODE); /* OS identifier */ 3366 put_byte(OS_CODE); /* OS identifier */
3228 3367
3229 header_bytes = (long)outcnt; 3368 header_bytes = (long) outcnt;
3230 3369
3231 (void)deflate(); 3370 (void) deflate();
3232 3371
3233 /* Write the crc and uncompressed size */ 3372 /* Write the crc and uncompressed size */
3234 put_long(crc); 3373 put_long(crc);
3235 put_long(isize); 3374 put_long(isize);
3236 header_bytes += 2*sizeof(long); 3375 header_bytes += 2 * sizeof(long);
3237 3376
3238 flush_outbuf(); 3377 flush_outbuf();
3239 return OK; 3378 return OK;
3240} 3379}
3241 3380
3242 3381
@@ -3246,18 +3385,19 @@ int zip(in, out)
3246 * IN assertion: size >= 2 (for end-of-line translation) 3385 * IN assertion: size >= 2 (for end-of-line translation)
3247 */ 3386 */
3248int file_read(buf, size) 3387int file_read(buf, size)
3249 char *buf; 3388char *buf;
3250 unsigned size; 3389unsigned size;
3251{ 3390{
3252 unsigned len; 3391 unsigned len;
3253 3392
3254 Assert(insize == 0, "inbuf not empty"); 3393 Assert(insize == 0, "inbuf not empty");
3255 3394
3256 len = read(ifd, buf, size); 3395 len = read(ifd, buf, size);
3257 if (len == (unsigned)(-1) || len == 0) return (int)len; 3396 if (len == (unsigned) (-1) || len == 0)
3397 return (int) len;
3258 3398
3259 crc = updcrc((uch*)buf, len); 3399 crc = updcrc((uch *) buf, len);
3260 isize += (ulg)len; 3400 isize += (ulg) len;
3261 return (int)len; 3401 return (int) len;
3262} 3402}
3263#endif 3403#endif
diff --git a/halt.c b/halt.c
index 23eb23c30..d61c38760 100644
--- a/halt.c
+++ b/halt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini halt implementation for busybox 3 * Mini halt implementation for busybox
3 * 4 *
@@ -23,10 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int halt_main(int argc, char **argv)
27halt_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR1)); 30 exit(kill(findInitPid(), SIGUSR1));
31} 31}
32
diff --git a/head.c b/head.c
index b80d06580..82a73de2a 100644
--- a/head.c
+++ b/head.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini head implementation for busybox 3 * Mini head implementation for busybox
3 * 4 *
@@ -26,83 +27,86 @@
26#include <stdio.h> 27#include <stdio.h>
27 28
28const char head_usage[] = 29const char head_usage[] =
29"head [OPTION] [FILE]...\n\n" 30 "head [OPTION] [FILE]...\n\n"
30"Print first 10 lines of each FILE to standard output.\n" 31 "Print first 10 lines of each FILE to standard output.\n"
31"With more than one FILE, precede each with a header giving the\n" 32 "With more than one FILE, precede each with a header giving the\n"
32"file name. With no FILE, or when FILE is -, read standard input.\n\n" 33 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
33"Options:\n"
34"\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
35 34
36int 35 "Options:\n" "\t-n NUM\t\tPrint first NUM lines instead of first 10\n";
37head(int len, FILE *src) 36
37int head(int len, FILE * src)
38{ 38{
39 int i; 39 int i;
40 char buffer[1024]; 40 char buffer[1024];
41 41
42 for (i = 0; i < len; i++) { 42 for (i = 0; i < len; i++) {
43 fgets(buffer, 1024, src); 43 fgets(buffer, 1024, src);
44 if (feof(src)) { break; } 44 if (feof(src)) {
45 fputs(buffer, stdout); 45 break;
46 } 46 }
47 return 0; 47 fputs(buffer, stdout);
48 }
49 return 0;
48} 50}
49 51
50/* BusyBoxed head(1) */ 52/* BusyBoxed head(1) */
51int 53int head_main(int argc, char **argv)
52head_main(int argc, char **argv)
53{ 54{
54 char opt; 55 char opt;
55 int len = 10, tmplen, i; 56 int len = 10, tmplen, i;
56 57
57 /* parse argv[] */ 58 /* parse argv[] */
58 for (i = 1; i < argc; i++) { 59 for (i = 1; i < argc; i++) {
59 if (argv[i][0] == '-') { 60 if (argv[i][0] == '-') {
60 opt = argv[i][1]; 61 opt = argv[i][1];
61 switch (opt) { 62 switch (opt) {
62 case 'n': 63 case 'n':
63 tmplen = 0; 64 tmplen = 0;
64 if (++i < argc) 65 if (++i < argc)
65 tmplen = atoi(argv[i]); 66 tmplen = atoi(argv[i]);
66 if (tmplen < 1) 67 if (tmplen < 1)
67 usage(head_usage); 68 usage(head_usage);
68 len = tmplen; 69 len = tmplen;
69 break; 70 break;
70 case '-': 71 case '-':
71 case 'h': 72 case 'h':
72 usage(head_usage); 73 usage(head_usage);
73 default: 74 default:
74 fprintf(stderr, "head: invalid option -- %c\n", opt); 75 fprintf(stderr, "head: invalid option -- %c\n", opt);
75 usage(head_usage); 76 usage(head_usage);
76 } 77 }
77 } else { 78 } else {
78 break; 79 break;
80 }
79 } 81 }
80 }
81 82
82 /* get rest of argv[] or stdin if nothing's left */ 83 /* get rest of argv[] or stdin if nothing's left */
83 if (i >= argc) { 84 if (i >= argc) {
84 head(len, stdin); 85 head(len, stdin);
85 86
86 } else { 87 } else {
87 int need_headers = ((argc - i) > 1); 88 int need_headers = ((argc - i) > 1);
88 for ( ; i < argc; i++) { 89
89 FILE *src; 90 for (; i < argc; i++) {
90 src = fopen(argv[i], "r"); 91 FILE *src;
91 if (!src) { 92
92 fprintf(stderr,"head: %s: %s\n", argv[i], strerror(errno)); 93 src = fopen(argv[i], "r");
93 } else { 94 if (!src) {
94 /* emulating GNU behaviour */ 95 fprintf(stderr, "head: %s: %s\n", argv[i],
95 if (need_headers) { 96 strerror(errno));
96 fprintf(stdout, "==> %s <==\n", argv[i]); 97 } else {
97 } 98 /* emulating GNU behaviour */
98 head(len, src); 99 if (need_headers) {
99 if (i < argc - 1) { 100 fprintf(stdout, "==> %s <==\n", argv[i]);
100 fprintf(stdout, "\n"); 101 }
102 head(len, src);
103 if (i < argc - 1) {
104 fprintf(stdout, "\n");
105 }
106 }
101 } 107 }
102 }
103 } 108 }
104 } 109 exit(0);
105 exit(0);
106} 110}
107 111
108/* $Id: head.c,v 1.7 2000/02/07 05:29:42 erik Exp $ */ 112/* $Id: head.c,v 1.8 2000/02/08 19:58:47 erik Exp $ */
diff --git a/hostid.c b/hostid.c
index f8d5862ae..9e503e598 100644
--- a/hostid.c
+++ b/hostid.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini hostid implementation for busybox 3 * Mini hostid implementation for busybox
3 * 4 *
@@ -22,7 +23,8 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int hostid_main(int argc, char **argv) { 26extern int hostid_main(int argc, char **argv)
26 printf ("%lx\n", gethostid()); 27{
27 exit( TRUE); 28 printf("%lx\n", gethostid());
29 exit(TRUE);
28} 30}
diff --git a/hostname.c b/hostname.c
index 68a560950..8cc334da0 100644
--- a/hostname.c
+++ b/hostname.c
@@ -1,5 +1,6 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * $Id: hostname.c,v 1.6 2000/02/07 05:29:42 erik Exp $ 3 * $Id: hostname.c,v 1.7 2000/02/08 19:58:47 erik Exp $
3 * Mini hostname implementation for busybox 4 * Mini hostname implementation for busybox
4 * 5 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -29,110 +30,116 @@
29#include <unistd.h> 30#include <unistd.h>
30#include <stdio.h> 31#include <stdio.h>
31 32
32static const char* hostname_usage = 33static const char *hostname_usage =
33"hostname [OPTION] {hostname | -F file}\n\n" 34 "hostname [OPTION] {hostname | -F file}\n\n"
34"Get or set the hostname or DNS domain name. If a hostname is given\n" 35 "Get or set the hostname or DNS domain name. If a hostname is given\n"
35"(or a file with the -F parameter), the host name will be set.\n\n" 36 "(or a file with the -F parameter), the host name will be set.\n\n"
36"Options:\n" 37 "Options:\n"
37"\t-s\t\tShort\n" 38 "\t-s\t\tShort\n"
38"\t-i\t\tAddresses for the hostname\n" 39
39"\t-d\t\tDNS domain name\n" 40 "\t-i\t\tAddresses for the hostname\n"
40"\t-F FILE\t\tUse the contents of FILE to specify the hostname\n"; 41 "\t-d\t\tDNS domain name\n"
42 "\t-F FILE\t\tUse the contents of FILE to specify the hostname\n";
41 43
42 44
43void do_sethostname(char *s, int isfile) 45void do_sethostname(char *s, int isfile)
44{ 46{
45 FILE *f; 47 FILE *f;
46 char buf[255]; 48 char buf[255];
47 49
48 if (!s) return; 50 if (!s)
49 if (!isfile) { 51 return;
50 if (sethostname(s, strlen(s)) < 0) { 52 if (!isfile) {
51 if (errno == EPERM) 53 if (sethostname(s, strlen(s)) < 0) {
52 fprintf(stderr, "hostname: you must be root to change the hostname\n"); 54 if (errno == EPERM)
53 else 55 fprintf(stderr,
54 perror("sethostname"); 56 "hostname: you must be root to change the hostname\n");
55 exit(1); 57 else
56 } 58 perror("sethostname");
57 } else { 59 exit(1);
58 if ((f = fopen(s, "r")) == NULL) { 60 }
59 perror(s);
60 exit(1);
61 } else { 61 } else {
62 fgets(buf, 255, f); 62 if ((f = fopen(s, "r")) == NULL) {
63 fclose(f); 63 perror(s);
64 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; 64 exit(1);
65 if (sethostname(buf, strlen(buf)) < 0) { 65 } else {
66 perror("sethostname"); 66 fgets(buf, 255, f);
67 exit(1); 67 fclose(f);
68 } 68 if (buf[strlen(buf) - 1] == '\n')
69 buf[strlen(buf) - 1] = 0;
70 if (sethostname(buf, strlen(buf)) < 0) {
71 perror("sethostname");
72 exit(1);
73 }
74 }
69 } 75 }
70 }
71} 76}
72 77
73int hostname_main(int argc, char **argv) 78int hostname_main(int argc, char **argv)
74{ 79{
75 int opt_short = 0; 80 int opt_short = 0;
76 int opt_domain = 0; 81 int opt_domain = 0;
77 int opt_ip = 0; 82 int opt_ip = 0;
78 struct hostent *h; 83 struct hostent *h;
79 char *filename = NULL; 84 char *filename = NULL;
80 char buf[255]; 85 char buf[255];
81 char *s = NULL; 86 char *s = NULL;
82
83 if (argc < 1) usage(hostname_usage);
84 87
85 while (--argc > 0 && **(++argv) == '-') { 88 if (argc < 1)
86 while (*(++(*argv))) {
87 switch (**argv) {
88 case 's':
89 opt_short = 1;
90 break;
91 case 'i':
92 opt_ip = 1;
93 break;
94 case 'd':
95 opt_domain = 1;
96 break;
97 case 'F':
98 filename = optarg;
99 if (--argc == 0) {
100 usage(hostname_usage);
101 }
102 filename = *(++argv);
103 break;
104 default:
105 usage(hostname_usage); 89 usage(hostname_usage);
106 } 90
107 if (filename!=NULL) 91 while (--argc > 0 && **(++argv) == '-') {
108 break; 92 while (*(++(*argv))) {
93 switch (**argv) {
94 case 's':
95 opt_short = 1;
96 break;
97 case 'i':
98 opt_ip = 1;
99 break;
100 case 'd':
101 opt_domain = 1;
102 break;
103 case 'F':
104 filename = optarg;
105 if (--argc == 0) {
106 usage(hostname_usage);
107 }
108 filename = *(++argv);
109 break;
110 default:
111 usage(hostname_usage);
112 }
113 if (filename != NULL)
114 break;
115 }
109 } 116 }
110 }
111 117
112 if (argc >= 1) { 118 if (argc >= 1) {
113 do_sethostname(*argv, 0); 119 do_sethostname(*argv, 0);
114 } else if (filename!=NULL) { 120 } else if (filename != NULL) {
115 do_sethostname(filename, 1); 121 do_sethostname(filename, 1);
116 } else { 122 } else {
117 gethostname(buf, 255); 123 gethostname(buf, 255);
118 if (opt_short) { 124 if (opt_short) {
119 s = strchr(buf, '.'); 125 s = strchr(buf, '.');
120 if (!s) s = buf; *s = 0; 126 if (!s)
121 printf("%s\n", buf); 127 s = buf;
122 } else if (opt_domain) { 128 *s = 0;
123 s = strchr(buf, '.'); 129 printf("%s\n", buf);
124 printf("%s\n", (s ? s+1 : "")); 130 } else if (opt_domain) {
125 } else if (opt_ip) { 131 s = strchr(buf, '.');
126 h = gethostbyname(buf); 132 printf("%s\n", (s ? s + 1 : ""));
127 if (!h) { 133 } else if (opt_ip) {
128 printf("Host not found\n"); 134 h = gethostbyname(buf);
129 exit(1); 135 if (!h) {
130 } 136 printf("Host not found\n");
131 printf("%s\n", inet_ntoa(*(struct in_addr *)(h->h_addr))); 137 exit(1);
132 } else { 138 }
133 printf("%s\n", buf); 139 printf("%s\n", inet_ntoa(*(struct in_addr *) (h->h_addr)));
134 } 140 } else {
135 } 141 printf("%s\n", buf);
136 exit( 0); 142 }
143 }
144 exit(0);
137} 145}
138
diff --git a/init.c b/init.c
index 6dad7181b..899dca48c 100644
--- a/init.c
+++ b/init.c
@@ -41,8 +41,8 @@
41#include <sys/kdaemon.h> 41#include <sys/kdaemon.h>
42#include <sys/sysmacros.h> 42#include <sys/sysmacros.h>
43#include <asm/types.h> 43#include <asm/types.h>
44#include <linux/serial.h> /* for serial_struct */ 44#include <linux/serial.h> /* for serial_struct */
45#include <sys/vt.h> /* for vt_stat */ 45#include <sys/vt.h> /* for vt_stat */
46#include <sys/ioctl.h> 46#include <sys/ioctl.h>
47#include <linux/version.h> 47#include <linux/version.h>
48#ifdef BB_SYSLOGD 48#ifdef BB_SYSLOGD
@@ -58,15 +58,15 @@
58#endif 58#endif
59 59
60 60
61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ 61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */
62#define VT_SECONDARY "/dev/tty2" /* Virtual console */ 62#define VT_SECONDARY "/dev/tty2" /* Virtual console */
63#define VT_LOG "/dev/tty3" /* Virtual console */ 63#define VT_LOG "/dev/tty3" /* Virtual console */
64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ 64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */
65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ 65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */
66#define SHELL "/bin/sh" /* Default shell */ 66#define SHELL "/bin/sh" /* Default shell */
67#define INITTAB "/etc/inittab" /* inittab file location */ 67#define INITTAB "/etc/inittab" /* inittab file location */
68#ifndef INIT_SCRIPT 68#ifndef INIT_SCRIPT
69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ 69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */
70#endif 70#endif
71 71
72#define LOG 0x1 72#define LOG 0x1
@@ -74,38 +74,38 @@
74 74
75/* Allowed init action types */ 75/* Allowed init action types */
76typedef enum { 76typedef enum {
77 SYSINIT=1, 77 SYSINIT = 1,
78 RESPAWN, 78 RESPAWN,
79 ASKFIRST, 79 ASKFIRST,
80 WAIT, 80 WAIT,
81 ONCE 81 ONCE
82} initActionEnum; 82} initActionEnum;
83 83
84/* And now a list of the actions we support in the version of init */ 84/* And now a list of the actions we support in the version of init */
85typedef struct initActionType{ 85typedef struct initActionType {
86 const char* name; 86 const char *name;
87 initActionEnum action; 87 initActionEnum action;
88} initActionType; 88} initActionType;
89 89
90static const struct initActionType actions[] = { 90static const struct initActionType actions[] = {
91 {"sysinit", SYSINIT}, 91 {"sysinit", SYSINIT},
92 {"respawn", RESPAWN}, 92 {"respawn", RESPAWN},
93 {"askfirst", ASKFIRST}, 93 {"askfirst", ASKFIRST},
94 {"wait", WAIT}, 94 {"wait", WAIT},
95 {"once", ONCE}, 95 {"once", ONCE},
96 {0} 96 {0}
97}; 97};
98 98
99/* Set up a linked list of initactions, to be read from inittab */ 99/* Set up a linked list of initactions, to be read from inittab */
100typedef struct initActionTag initAction; 100typedef struct initActionTag initAction;
101struct initActionTag { 101struct initActionTag {
102 pid_t pid; 102 pid_t pid;
103 char process[256]; 103 char process[256];
104 char console[256]; 104 char console[256];
105 initAction *nextPtr; 105 initAction *nextPtr;
106 initActionEnum action; 106 initActionEnum action;
107}; 107};
108initAction* initActionList = NULL; 108initAction *initActionList = NULL;
109 109
110 110
111static char *secondConsole = VT_SECONDARY; 111static char *secondConsole = VT_SECONDARY;
@@ -119,517 +119,533 @@ static char console[32] = _PATH_CONSOLE;
119 * device may be bitwise-or'd from LOG | CONSOLE */ 119 * device may be bitwise-or'd from LOG | CONSOLE */
120void message(int device, char *fmt, ...) 120void message(int device, char *fmt, ...)
121{ 121{
122 va_list arguments; 122 va_list arguments;
123 int fd; 123 int fd;
124 124
125#ifdef BB_SYSLOGD 125#ifdef BB_SYSLOGD
126 126
127 /* Log the message to syslogd */ 127 /* Log the message to syslogd */
128 if (device & LOG ) { 128 if (device & LOG) {
129 char msg[1024]; 129 char msg[1024];
130 va_start(arguments, fmt);
131 vsnprintf(msg, sizeof(msg), fmt, arguments);
132 va_end(arguments);
133 openlog( "init", 0, LOG_DAEMON);
134 syslog(LOG_DAEMON|LOG_NOTICE, msg);
135 closelog();
136 }
137 130
131 va_start(arguments, fmt);
132 vsnprintf(msg, sizeof(msg), fmt, arguments);
133 va_end(arguments);
134 openlog("init", 0, LOG_DAEMON);
135 syslog(LOG_DAEMON | LOG_NOTICE, msg);
136 closelog();
137 }
138#else 138#else
139 static int log_fd = -1; 139 static int log_fd = -1;
140 140
141 /* Take full control of the log tty, and never close it. 141 /* Take full control of the log tty, and never close it.
142 * It's mine, all mine! Muhahahaha! */ 142 * It's mine, all mine! Muhahahaha! */
143 if (log_fd < 0) { 143 if (log_fd < 0) {
144 if (log == NULL) { 144 if (log == NULL) {
145 /* don't even try to log, because there is no such console */ 145 /* don't even try to log, because there is no such console */
146 log_fd = -2; 146 log_fd = -2;
147 /* log to main console instead */ 147 /* log to main console instead */
148 device = CONSOLE; 148 device = CONSOLE;
149 } 149 } else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) {
150 else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { 150 log_fd = -1;
151 log_fd = -1; 151 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
152 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); 152 fflush(stderr);
153 fflush(stderr); 153 return;
154 return; 154 }
155 }
156 if ((device & LOG) && (log_fd >= 0)) {
157 va_start(arguments, fmt);
158 vdprintf(log_fd, fmt, arguments);
159 va_end(arguments);
155 } 160 }
156 }
157 if ( (device & LOG) && (log_fd >= 0) ) {
158 va_start(arguments, fmt);
159 vdprintf(log_fd, fmt, arguments);
160 va_end(arguments);
161 }
162#endif 161#endif
163 162
164 if (device & CONSOLE) { 163 if (device & CONSOLE) {
165 /* Always send console messages to /dev/console so people will see them. */ 164 /* Always send console messages to /dev/console so people will see them. */
166 if ((fd = device_open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) { 165 if (
167 va_start(arguments, fmt); 166 (fd =
168 vdprintf(fd, fmt, arguments); 167 device_open(_PATH_CONSOLE,
169 va_end(arguments); 168 O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) {
170 close(fd); 169 va_start(arguments, fmt);
171 } else { 170 vdprintf(fd, fmt, arguments);
172 fprintf(stderr, "Bummer, can't print: "); 171 va_end(arguments);
173 va_start(arguments, fmt); 172 close(fd);
174 vfprintf(stderr, fmt, arguments); 173 } else {
175 fflush(stderr); 174 fprintf(stderr, "Bummer, can't print: ");
176 va_end(arguments); 175 va_start(arguments, fmt);
176 vfprintf(stderr, fmt, arguments);
177 fflush(stderr);
178 va_end(arguments);
179 }
177 } 180 }
178 }
179} 181}
180 182
181 183
182/* Set terminal settings to reasonable defaults */ 184/* Set terminal settings to reasonable defaults */
183void set_term( int fd) 185void set_term(int fd)
184{ 186{
185 struct termios tty; 187 struct termios tty;
186 static const char control_characters[] = { 188 static const char control_characters[] = {
187 '\003', '\034', '\177', '\025', '\004', '\0', 189 '\003', '\034', '\177', '\025', '\004', '\0',
188 '\1', '\0', '\021', '\023', '\032', '\0', '\022', 190 '\1', '\0', '\021', '\023', '\032', '\0', '\022',
189 '\017', '\027', '\026', '\0' 191 '\017', '\027', '\026', '\0'
190 }; 192 };
191 193
192 tcgetattr(fd, &tty); 194 tcgetattr(fd, &tty);
193 195
194 /* set control chars */ 196 /* set control chars */
195 memcpy(tty.c_cc, control_characters, sizeof(control_characters)); 197 memcpy(tty.c_cc, control_characters, sizeof(control_characters));
196 198
197 /* use line dicipline 0 */ 199 /* use line dicipline 0 */
198 tty.c_line = 0; 200 tty.c_line = 0;
199 201
200 /* Make it be sane */ 202 /* Make it be sane */
201 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; 203 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
202 //tty.c_cflag |= HUPCL|CLOCAL; 204 //tty.c_cflag |= HUPCL|CLOCAL;
203 205
204 /* input modes */ 206 /* input modes */
205 tty.c_iflag = ICRNL|IXON|IXOFF; 207 tty.c_iflag = ICRNL | IXON | IXOFF;
206 208
207 /* output modes */ 209 /* output modes */
208 tty.c_oflag = OPOST|ONLCR; 210 tty.c_oflag = OPOST | ONLCR;
209 211
210 /* local modes */ 212 /* local modes */
211 tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; 213 tty.c_lflag =
214 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
212 215
213 tcsetattr(fd, TCSANOW, &tty); 216 tcsetattr(fd, TCSANOW, &tty);
214} 217}
215 218
216/* How much memory does this machine have? */ 219/* How much memory does this machine have? */
217static int mem_total() 220static int mem_total()
218{ 221{
219 char s[80]; 222 char s[80];
220 char *p = "/proc/meminfo"; 223 char *p = "/proc/meminfo";
221 FILE *f; 224 FILE *f;
222 const char pattern[] = "MemTotal:"; 225 const char pattern[] = "MemTotal:";
223 226
224 if ((f = fopen(p, "r")) < 0) { 227 if ((f = fopen(p, "r")) < 0) {
225 message(LOG, "Error opening %s: %s\n", p, strerror( errno)); 228 message(LOG, "Error opening %s: %s\n", p, strerror(errno));
226 return -1; 229 return -1;
227 } 230 }
228 while (NULL != fgets(s, 79, f)) { 231 while (NULL != fgets(s, 79, f)) {
229 p = strstr(s, pattern); 232 p = strstr(s, pattern);
230 if (NULL != p) { 233 if (NULL != p) {
231 fclose(f); 234 fclose(f);
232 return (atoi(p + strlen(pattern))); 235 return (atoi(p + strlen(pattern)));
236 }
233 } 237 }
234 } 238 return -1;
235 return -1;
236} 239}
237 240
238static void console_init() 241static void console_init()
239{ 242{
240 int fd; 243 int fd;
241 int tried_devcons = 0; 244 int tried_devcons = 0;
242 int tried_vtprimary = 0; 245 int tried_vtprimary = 0;
243 struct serial_struct sr; 246 struct serial_struct sr;
244 char *s; 247 char *s;
245 248
246 if ((s = getenv("TERM")) != NULL) { 249 if ((s = getenv("TERM")) != NULL) {
247 snprintf(termType,sizeof(termType)-1,"TERM=%s",s); 250 snprintf(termType, sizeof(termType) - 1, "TERM=%s", s);
248 } 251 }
249
250 if ((s = getenv("CONSOLE")) != NULL) {
251 snprintf(console, sizeof(console)-1, "%s",s);
252 }
253#if #cpu(sparc)
254 /* sparc kernel supports console=tty[ab] parameter which is also
255 * passed to init, so catch it here */
256 else if ((s = getenv("console")) != NULL) {
257 /* remap tty[ab] to /dev/ttyS[01] */
258 if (strcmp( s, "ttya" )==0)
259 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON0);
260 else if (strcmp( s, "ttyb" )==0)
261 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON1);
262 }
263#endif
264 else {
265 struct vt_stat vt;
266 252
267 /* 2.2 kernels: identify the real console backend and try to use it */ 253 if ((s = getenv("CONSOLE")) != NULL) {
268 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 254 snprintf(console, sizeof(console) - 1, "%s", s);
269 /* this is a serial console */
270 snprintf(console, sizeof(console)-1, "/dev/ttyS%d", sr.line);
271 } 255 }
272 else if (ioctl(0, VT_GETSTATE, &vt) == 0) { 256#if #cpu(sparc)
273 /* this is linux virtual tty */ 257 /* sparc kernel supports console=tty[ab] parameter which is also
274 snprintf(console, sizeof(console)-1, "/dev/tty%d", vt.v_active); 258 * passed to init, so catch it here */
275 } else { 259 else if ((s = getenv("console")) != NULL) {
276 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 260 /* remap tty[ab] to /dev/ttyS[01] */
277 tried_devcons++; 261 if (strcmp(s, "ttya") == 0)
262 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON0);
263 else if (strcmp(s, "ttyb") == 0)
264 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON1);
278 } 265 }
279 } 266#endif
280 267 else {
281 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { 268 struct vt_stat vt;
282 /* Can't open selected console -- try /dev/console */ 269
283 if (!tried_devcons) { 270 /* 2.2 kernels: identify the real console backend and try to use it */
284 tried_devcons++; 271 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
285 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 272 /* this is a serial console */
286 continue; 273 snprintf(console, sizeof(console) - 1, "/dev/ttyS%d", sr.line);
274 } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
275 /* this is linux virtual tty */
276 snprintf(console, sizeof(console) - 1, "/dev/tty%d",
277 vt.v_active);
278 } else {
279 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
280 tried_devcons++;
281 }
287 } 282 }
288 /* Can't open selected console -- try vt1 */ 283
289 if (!tried_vtprimary) { 284 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) {
290 tried_vtprimary++; 285 /* Can't open selected console -- try /dev/console */
291 snprintf(console, sizeof(console)-1, "%s", VT_PRIMARY); 286 if (!tried_devcons) {
292 continue; 287 tried_devcons++;
288 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
289 continue;
290 }
291 /* Can't open selected console -- try vt1 */
292 if (!tried_vtprimary) {
293 tried_vtprimary++;
294 snprintf(console, sizeof(console) - 1, "%s", VT_PRIMARY);
295 continue;
296 }
297 break;
293 } 298 }
294 break; 299 if (fd < 0) {
295 } 300 /* Perhaps we should panic here? */
296 if (fd < 0) { 301 snprintf(console, sizeof(console) - 1, "/dev/null");
297 /* Perhaps we should panic here? */ 302 } else {
298 snprintf(console, sizeof(console)-1, "/dev/null"); 303 /* check for serial console and disable logging to tty3 & running a
299 } else { 304 * shell to tty2 */
300 /* check for serial console and disable logging to tty3 & running a 305 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
301 * shell to tty2 */ 306 message(LOG | CONSOLE,
302 if (ioctl(0,TIOCGSERIAL,&sr) == 0) { 307 "serial console detected. Disabling virtual terminals.\r\n");
303 message(LOG|CONSOLE, "serial console detected. Disabling virtual terminals.\r\n" ); 308 log = NULL;
304 log = NULL; 309 secondConsole = NULL;
305 secondConsole = NULL; 310 }
311 close(fd);
306 } 312 }
307 close(fd); 313 message(LOG, "console=%s\n", console);
308 }
309 message(LOG, "console=%s\n", console );
310} 314}
311 315
312static pid_t run(char* command, 316static pid_t run(char *command, char *terminal, int get_enter)
313 char *terminal, int get_enter)
314{ 317{
315 int i, fd; 318 int i, fd;
316 pid_t pid; 319 pid_t pid;
317 char* tmpCmd; 320 char *tmpCmd;
318 char* cmd[255]; 321 char *cmd[255];
319 static const char press_enter[] = 322 static const char press_enter[] =
320 "\nPlease press Enter to activate this console. "; 323
321 char* environment[] = { 324 "\nPlease press Enter to activate this console. ";
322 "HOME=/", 325 char *environment[] = {
323 "PATH=/usr/bin:/bin:/usr/sbin:/sbin", 326 "HOME=/",
324 "SHELL=/bin/sh", 327 "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
325 termType, 328 "SHELL=/bin/sh",
326 "USER=root", 329 termType,
327 0 330 "USER=root",
328 }; 331 0
329 332 };
330
331 if ((pid = fork()) == 0) {
332 pid_t shell_pgid = getpid ();
333
334 /* Clean up */
335 close(0);
336 close(1);
337 close(2);
338 setsid();
339 333
340 /* Reset signal handlers set for parent process */
341 signal(SIGUSR1, SIG_DFL);
342 signal(SIGUSR2, SIG_DFL);
343 signal(SIGINT, SIG_DFL);
344 signal(SIGTERM, SIG_DFL);
345 signal(SIGHUP, SIG_DFL);
346 334
347 if ((fd = device_open(terminal, O_RDWR)) < 0) { 335 if ((pid = fork()) == 0) {
348 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); 336 pid_t shell_pgid = getpid();
349 exit(1);
350 }
351 dup2(fd, 0);
352 dup2(fd, 1);
353 dup2(fd, 2);
354 tcsetpgrp (0, getpgrp());
355 set_term(0);
356 337
357 if (get_enter==TRUE) { 338 /* Clean up */
358 /* 339 close(0);
359 * Save memory by not exec-ing anything large (like a shell) 340 close(1);
360 * before the user wants it. This is critical if swap is not 341 close(2);
361 * enabled and the system has low memory. Generally this will 342 setsid();
362 * be run on the second virtual console, and the first will 343
363 * be allowed to start a shell or whatever an init script 344 /* Reset signal handlers set for parent process */
364 * specifies. 345 signal(SIGUSR1, SIG_DFL);
365 */ 346 signal(SIGUSR2, SIG_DFL);
366 char c; 347 signal(SIGINT, SIG_DFL);
367 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", 348 signal(SIGTERM, SIG_DFL);
368 command, shell_pgid, terminal ); 349 signal(SIGHUP, SIG_DFL);
369 write(fileno(stdout), press_enter, sizeof(press_enter) - 1); 350
370 read(fileno(stdin), &c, 1); 351 if ((fd = device_open(terminal, O_RDWR)) < 0) {
371 } 352 message(LOG | CONSOLE, "Bummer, can't open %s\r\n", terminal);
353 exit(1);
354 }
355 dup2(fd, 0);
356 dup2(fd, 1);
357 dup2(fd, 2);
358 tcsetpgrp(0, getpgrp());
359 set_term(0);
360
361 if (get_enter == TRUE) {
362 /*
363 * Save memory by not exec-ing anything large (like a shell)
364 * before the user wants it. This is critical if swap is not
365 * enabled and the system has low memory. Generally this will
366 * be run on the second virtual console, and the first will
367 * be allowed to start a shell or whatever an init script
368 * specifies.
369 */
370 char c;
371
372 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
373 command, shell_pgid, terminal);
374 write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
375 read(fileno(stdin), &c, 1);
376 }
372 377
373 /* Log the process name and args */ 378 /* Log the process name and args */
374 message(LOG, "Starting pid %d, console %s: '", 379 message(LOG, "Starting pid %d, console %s: '",
375 shell_pgid, terminal, command); 380 shell_pgid, terminal, command);
376 381
377 /* Convert command (char*) into cmd (char**, one word per string) */ 382 /* Convert command (char*) into cmd (char**, one word per string) */
378 for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) { 383 for (tmpCmd = command, i = 0;
379 if (*tmpCmd != '\0') { 384 (tmpCmd = strsep(&command, " \t")) != NULL;) {
380 cmd[i] = tmpCmd; 385 if (*tmpCmd != '\0') {
381 message(LOG, "%s ", tmpCmd); 386 cmd[i] = tmpCmd;
382 tmpCmd++; 387#ifdef DEBUG_INIT
383 i++; 388 message(LOG, "%s ", tmpCmd);
384 } 389#endif
390 tmpCmd++;
391 i++;
392 }
393 }
394 cmd[i] = NULL;
395 message(LOG, "'\r\n");
396
397 /* Now run it. The new program will take over this PID,
398 * so nothing further in init.c should be run. */
399 execve(cmd[0], cmd, environment);
400
401 /* We're still here? Some error happened. */
402 message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
403 strerror(errno));
404 exit(-1);
385 } 405 }
386 cmd[i] = NULL; 406 return pid;
387 message(LOG, "'\r\n");
388
389 /* Now run it. The new program will take over this PID,
390 * so nothing further in init.c should be run. */
391 execve(cmd[0], cmd, environment);
392
393 /* We're still here? Some error happened. */
394 message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
395 strerror(errno));
396 exit(-1);
397 }
398 return pid;
399} 407}
400 408
401static int waitfor(char* command, 409static int waitfor(char *command, char *terminal, int get_enter)
402 char *terminal, int get_enter)
403{ 410{
404 int status, wpid; 411 int status, wpid;
405 int pid = run( command, terminal, get_enter); 412 int pid = run(command, terminal, get_enter);
406 413
407 while (1) { 414 while (1) {
408 wpid = wait(&status); 415 wpid = wait(&status);
409 if (wpid > 0 ) { 416 if (wpid > 0) {
410 message(LOG, "Process '%s' (pid %d) exited.\n", 417 message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid);
411 command, wpid); 418 break;
412 break; 419 }
420 if (wpid == pid)
421 break;
413 } 422 }
414 if (wpid == pid ) 423 return wpid;
415 break;
416 }
417 return wpid;
418} 424}
419 425
420/* Make sure there is enough memory to do something useful. * 426/* Make sure there is enough memory to do something useful. *
421 * Calls swapon if needed so be sure /proc is mounted. */ 427 * Calls swapon if needed so be sure /proc is mounted. */
422static void check_memory() 428static void check_memory()
423{ 429{
424 struct stat statBuf; 430 struct stat statBuf;
425 431
426 if (mem_total() > 3500) 432 if (mem_total() > 3500)
433 return;
434
435 if (stat("/etc/fstab", &statBuf) == 0) {
436 /* Try to turn on swap */
437 waitfor("/bin/swapon swapon -a", log, FALSE);
438 if (mem_total() < 3500)
439 goto goodnight;
440 } else
441 goto goodnight;
427 return; 442 return;
428 443
429 if (stat("/etc/fstab", &statBuf) == 0) { 444 goodnight:
430 /* Try to turn on swap */ 445 message(CONSOLE,
431 waitfor("/bin/swapon swapon -a", log, FALSE); 446 "Sorry, your computer does not have enough memory.\r\n");
432 if (mem_total() < 3500) 447 while (1)
433 goto goodnight; 448 sleep(1);
434 } else
435 goto goodnight;
436 return;
437
438goodnight:
439 message(CONSOLE, "Sorry, your computer does not have enough memory.\r\n");
440 while (1) sleep(1);
441} 449}
442 450
443#ifndef DEBUG_INIT 451#ifndef DEBUG_INIT
444static void shutdown_system(void) 452static void shutdown_system(void)
445{ 453{
446 /* first disable our SIGHUP signal */ 454 /* first disable our SIGHUP signal */
447 signal(SIGHUP, SIG_DFL); 455 signal(SIGHUP, SIG_DFL);
448 456
449 /* Allow Ctrl-Alt-Del to reboot system. */ 457 /* Allow Ctrl-Alt-Del to reboot system. */
450 reboot(RB_ENABLE_CAD); 458 reboot(RB_ENABLE_CAD);
451 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); 459 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
452 sync(); 460 sync();
453 461
454 /* Send signals to every process _except_ pid 1 */ 462 /* Send signals to every process _except_ pid 1 */
455 message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); 463 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
456 kill(-1, SIGTERM); 464 kill(-1, SIGTERM);
457 sleep(5); 465 sleep(5);
458 sync(); 466 sync();
459 467
460 message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); 468 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
461 kill(-1, SIGKILL); 469 kill(-1, SIGKILL);
462 sleep(5); 470 sleep(5);
463 471
464 message(CONSOLE, "Disabling swap.\r\n"); 472 message(CONSOLE, "Disabling swap.\r\n");
465 waitfor( "swapoff -a", console, FALSE); 473 waitfor("swapoff -a", console, FALSE);
466 message(CONSOLE, "Unmounting filesystems.\r\n"); 474 message(CONSOLE, "Unmounting filesystems.\r\n");
467 waitfor("umount -a -r", console, FALSE); 475 waitfor("umount -a -r", console, FALSE);
468 sync();
469 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
470 /* bdflush, kupdate not needed for kernels >2.2.11 */
471 bdflush(1, 0);
472 sync(); 476 sync();
473 } 477 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
478 /* bdflush, kupdate not needed for kernels >2.2.11 */
479 bdflush(1, 0);
480 sync();
481 }
474} 482}
475 483
476static void halt_signal(int sig) 484static void halt_signal(int sig)
477{ 485{
478 shutdown_system(); 486 shutdown_system();
479 message(CONSOLE, "The system is halted. Press %s or turn off power\r\n", 487 message(CONSOLE,
480 (secondConsole == NULL) /* serial console */ 488 "The system is halted. Press %s or turn off power\r\n",
481 ? "Reset" : "CTRL-ALT-DEL"); 489 (secondConsole == NULL) /* serial console */
482 sync(); 490 ? "Reset" : "CTRL-ALT-DEL");
491 sync();
483 492
484 /* allow time for last message to reach serial console */ 493 /* allow time for last message to reach serial console */
485 sleep(5); 494 sleep(5);
486 495
487#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 496#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
488 if (sig == SIGUSR2) 497 if (sig == SIGUSR2)
489 reboot(RB_POWER_OFF); 498 reboot(RB_POWER_OFF);
490 else 499 else
491#endif 500#endif
492 reboot(RB_HALT_SYSTEM); 501 reboot(RB_HALT_SYSTEM);
493 exit(0); 502 exit(0);
494} 503}
495 504
496static void reboot_signal(int sig) 505static void reboot_signal(int sig)
497{ 506{
498 shutdown_system(); 507 shutdown_system();
499 message(CONSOLE, "Please stand by while rebooting the system.\r\n"); 508 message(CONSOLE, "Please stand by while rebooting the system.\r\n");
500 sync(); 509 sync();
501 510
502 /* allow time for last message to reach serial console */ 511 /* allow time for last message to reach serial console */
503 sleep(2); 512 sleep(2);
504 513
505 reboot(RB_AUTOBOOT); 514 reboot(RB_AUTOBOOT);
506 exit(0); 515 exit(0);
507} 516}
508 517
509#if defined BB_FEATURE_INIT_CHROOT 518#if defined BB_FEATURE_INIT_CHROOT
510static void check_chroot(int sig) 519static void check_chroot(int sig)
511{ 520{
512 char *argv_init[2] = { "init", NULL, }; 521 char *argv_init[2] = { "init", NULL, };
513 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, }; 522 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, };
514 char rootpath[256], *tc; 523 char rootpath[256], *tc;
515 int fd; 524 int fd;
525
526 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) {
527 message(CONSOLE,
528 "SIGHUP recived, but could not open proc file\r\n");
529 sleep(2);
530 return;
531 }
532 if (read(fd, rootpath, sizeof(rootpath)) == -1) {
533 message(CONSOLE,
534 "SIGHUP recived, but could not read proc file\r\n");
535 sleep(2);
536 return;
537 }
538 close(fd);
516 539
517 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) { 540 if (rootpath[0] == '\0') {
518 message(CONSOLE, "SIGHUP recived, but could not open proc file\r\n"); 541 message(CONSOLE,
519 sleep(2); 542 "SIGHUP recived, but new root is not valid: %s\r\n",
520 return; 543 rootpath);
521 } 544 sleep(2);
522 if (read(fd, rootpath, sizeof(rootpath)) == -1) { 545 return;
523 message(CONSOLE, "SIGHUP recived, but could not read proc file\r\n"); 546 }
547
548 tc = strrchr(rootpath, '\n');
549 *tc = '\0';
550
551 /* Ok, making it this far means we commit */
552 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n",
553 rootpath);
554
555 /* kill all other programs first */
556 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
557 kill(-1, SIGTERM);
524 sleep(2); 558 sleep(2);
525 return; 559 sync();
526 }
527 close(fd);
528 560
529 if (rootpath[0] == '\0') { 561 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
530 message(CONSOLE, "SIGHUP recived, but new root is not valid: %s\r\n", 562 kill(-1, SIGKILL);
531 rootpath);
532 sleep(2); 563 sleep(2);
564 sync();
565
566 /* ok, we don't need /proc anymore. we also assume that the signaling
567 * process left the rest of the filesystems alone for us */
568 umount("/proc");
569
570 /* Ok, now we chroot. Hopefully we only have two things mounted, the
571 * new chroot'd mount point, and the old "/" mount. s,
572 * we go ahead and unmount the old "/". This should trigger the kernel
573 * to set things up the Right Way(tm). */
574
575 if (!chroot(rootpath))
576 umount("/dev/root");
577
578 /* If the chroot fails, we are already too far to turn back, so we
579 * continue and hope that executing init below will revive the system */
580
581 /* close all of our descriptors and open new ones */
582 close(0);
583 close(1);
584 close(2);
585 open("/dev/console", O_RDWR, 0);
586 dup(0);
587 dup(0);
588
589 message(CONSOLE, "Executing real init...\r\n");
590 /* execute init in the (hopefully) new root */
591 execve("/sbin/init", argv_init, envp_init);
592
593 message(CONSOLE,
594 "ERROR: Could not exec new init. Press %s to reboot.\r\n",
595 (secondConsole == NULL) /* serial console */
596 ? "Reset" : "CTRL-ALT-DEL");
533 return; 597 return;
534 } 598}
535 599#endif /* BB_FEATURE_INIT_CHROOT */
536 tc = strrchr(rootpath, '\n');
537 *tc = '\0';
538
539 /* Ok, making it this far means we commit */
540 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n", rootpath);
541
542 /* kill all other programs first */
543 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
544 kill(-1, SIGTERM);
545 sleep(2);
546 sync();
547
548 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
549 kill(-1, SIGKILL);
550 sleep(2);
551 sync();
552
553 /* ok, we don't need /proc anymore. we also assume that the signaling
554 * process left the rest of the filesystems alone for us */
555 umount("/proc");
556
557 /* Ok, now we chroot. Hopefully we only have two things mounted, the
558 * new chroot'd mount point, and the old "/" mount. s,
559 * we go ahead and unmount the old "/". This should trigger the kernel
560 * to set things up the Right Way(tm). */
561
562 if (!chroot(rootpath))
563 umount("/dev/root");
564
565 /* If the chroot fails, we are already too far to turn back, so we
566 * continue and hope that executing init below will revive the system */
567
568 /* close all of our descriptors and open new ones */
569 close(0);
570 close(1);
571 close(2);
572 open("/dev/console", O_RDWR, 0);
573 dup(0);
574 dup(0);
575
576 message(CONSOLE, "Executing real init...\r\n");
577 /* execute init in the (hopefully) new root */
578 execve("/sbin/init",argv_init,envp_init);
579
580 message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
581 (secondConsole == NULL) /* serial console */
582 ? "Reset" : "CTRL-ALT-DEL");
583 return;
584}
585#endif /* BB_FEATURE_INIT_CHROOT */
586
587#endif /* ! DEBUG_INIT */
588
589void new_initAction (initActionEnum action,
590 char* process, char* cons)
591{
592 initAction* newAction;
593
594 if (*cons == '\0')
595 cons = console;
596
597 /* If BusyBox detects that a serial console is in use,
598 * then entries not refering to the console or null devices will _not_ be run.
599 * The exception to this rule is the null device.
600 */
601 if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
602 return;
603 600
604 newAction = calloc ((size_t)(1), sizeof(initAction)); 601#endif /* ! DEBUG_INIT */
605 if (!newAction) { 602
606 message(LOG|CONSOLE,"Memory allocation failure\n"); 603void new_initAction(initActionEnum action, char *process, char *cons)
607 while (1) sleep(1); 604{
608 } 605 initAction *newAction;
609 newAction->nextPtr = initActionList; 606
610 initActionList = newAction; 607 if (*cons == '\0')
611 strncpy( newAction->process, process, 255); 608 cons = console;
612 newAction->action = action; 609
613 strncpy(newAction->console, cons, 255); 610 /* If BusyBox detects that a serial console is in use,
614 newAction->pid = 0; 611 * then entries not refering to the console or null devices will _not_ be run.
612 * The exception to this rule is the null device.
613 */
614 if (secondConsole == NULL && strcmp(cons, console)
615 && strcmp(cons, "/dev/null"))
616 return;
617
618 newAction = calloc((size_t) (1), sizeof(initAction));
619 if (!newAction) {
620 message(LOG | CONSOLE, "Memory allocation failure\n");
621 while (1)
622 sleep(1);
623 }
624 newAction->nextPtr = initActionList;
625 initActionList = newAction;
626 strncpy(newAction->process, process, 255);
627 newAction->action = action;
628 strncpy(newAction->console, cons, 255);
629 newAction->pid = 0;
615// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", 630// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
616// newAction->process, newAction->action, newAction->console); 631// newAction->process, newAction->action, newAction->console);
617} 632}
618 633
619void delete_initAction (initAction *action) 634void delete_initAction(initAction * action)
620{ 635{
621 initAction *a, *b=NULL; 636 initAction *a, *b = NULL;
622 for( a=initActionList ; a ; b=a, a=a->nextPtr) { 637
623 if (a == action) { 638 for (a = initActionList; a; b = a, a = a->nextPtr) {
624 if (b==NULL) { 639 if (a == action) {
625 initActionList=a->nextPtr; 640 if (b == NULL) {
626 } else { 641 initActionList = a->nextPtr;
627 b->nextPtr=a->nextPtr; 642 } else {
628 } 643 b->nextPtr = a->nextPtr;
629 free( a); 644 }
630 break; 645 free(a);
646 break;
647 }
631 } 648 }
632 }
633} 649}
634 650
635/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 651/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
@@ -639,253 +655,258 @@ void delete_initAction (initAction *action)
639 * _is_ defined, but /etc/inittab is missing, this 655 * _is_ defined, but /etc/inittab is missing, this
640 * results in the same set of default behaviors. 656 * results in the same set of default behaviors.
641 * */ 657 * */
642void parse_inittab(void) 658void parse_inittab(void)
643{ 659{
644#ifdef BB_FEATURE_USE_INITTAB 660#ifdef BB_FEATURE_USE_INITTAB
645 FILE* file; 661 FILE *file;
646 char buf[256], lineAsRead[256], tmpConsole[256]; 662 char buf[256], lineAsRead[256], tmpConsole[256];
647 char *p, *q, *r, *s; 663 char *p, *q, *r, *s;
648 const struct initActionType *a = actions; 664 const struct initActionType *a = actions;
649 int foundIt; 665 int foundIt;
650 666
651 667
652 file = fopen(INITTAB, "r"); 668 file = fopen(INITTAB, "r");
653 if (file == NULL) { 669 if (file == NULL) {
654 /* No inittab file -- set up some default behavior */ 670 /* No inittab file -- set up some default behavior */
655#endif 671#endif
656 /* Askfirst shell on tty1 */ 672 /* Askfirst shell on tty1 */
657 new_initAction( ASKFIRST, SHELL, console ); 673 new_initAction(ASKFIRST, SHELL, console);
658 /* Askfirst shell on tty2 */ 674 /* Askfirst shell on tty2 */
659 if (secondConsole != NULL) 675 if (secondConsole != NULL)
660 new_initAction( ASKFIRST, SHELL, secondConsole ); 676 new_initAction(ASKFIRST, SHELL, secondConsole);
661 /* sysinit */ 677 /* sysinit */
662 new_initAction( SYSINIT, INIT_SCRIPT, console ); 678 new_initAction(SYSINIT, INIT_SCRIPT, console);
663 679
664 return; 680 return;
665#ifdef BB_FEATURE_USE_INITTAB 681#ifdef BB_FEATURE_USE_INITTAB
666 }
667
668 while ( fgets(buf, 255, file) != NULL) {
669 foundIt=FALSE;
670 for(p = buf; *p == ' ' || *p == '\t'; p++);
671 if (*p == '#' || *p == '\n') continue;
672
673 /* Trim the trailing \n */
674 q = strrchr( p, '\n');
675 if (q != NULL)
676 *q='\0';
677
678 /* Keep a copy around for posterity's sake (and error msgs) */
679 strcpy(lineAsRead, buf);
680
681 /* Grab the ID field */
682 s=p;
683 p = strchr( p, ':');
684 if ( p != NULL || *(p+1) != '\0' ) {
685 *p='\0';
686 ++p;
687 } 682 }
688 683
689 /* Now peal off the process field from the end 684 while (fgets(buf, 255, file) != NULL) {
690 * of the string */ 685 foundIt = FALSE;
691 q = strrchr( p, ':'); 686 for (p = buf; *p == ' ' || *p == '\t'; p++);
692 if ( q == NULL || *(q+1) == '\0' ) { 687 if (*p == '#' || *p == '\n')
693 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 688 continue;
694 continue; 689
695 } else { 690 /* Trim the trailing \n */
696 *q='\0'; 691 q = strrchr(p, '\n');
697 ++q; 692 if (q != NULL)
698 } 693 *q = '\0';
694
695 /* Keep a copy around for posterity's sake (and error msgs) */
696 strcpy(lineAsRead, buf);
697
698 /* Grab the ID field */
699 s = p;
700 p = strchr(p, ':');
701 if (p != NULL || *(p + 1) != '\0') {
702 *p = '\0';
703 ++p;
704 }
699 705
700 /* Now peal off the action field */ 706 /* Now peal off the process field from the end
701 r = strrchr( p, ':'); 707 * of the string */
702 if ( r == NULL || *(r+1) == '\0') { 708 q = strrchr(p, ':');
703 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 709 if (q == NULL || *(q + 1) == '\0') {
704 continue; 710 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
705 } else { 711 continue;
706 ++r; 712 } else {
707 } 713 *q = '\0';
714 ++q;
715 }
708 716
709 /* Ok, now process it */ 717 /* Now peal off the action field */
710 a = actions; 718 r = strrchr(p, ':');
711 while (a->name != 0) { 719 if (r == NULL || *(r + 1) == '\0') {
712 if (strcmp(a->name, r) == 0) { 720 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
713 if (*s != '\0') { 721 continue;
714 struct stat statBuf; 722 } else {
715 strcpy(tmpConsole, "/dev/"); 723 ++r;
716 strncat(tmpConsole, s, 200); 724 }
717 if (stat(tmpConsole, &statBuf) != 0) { 725
718 message(LOG|CONSOLE, "device '%s' does not exist. Did you read the directions?\n", tmpConsole); 726 /* Ok, now process it */
719 break; 727 a = actions;
720 } 728 while (a->name != 0) {
721 s = tmpConsole; 729 if (strcmp(a->name, r) == 0) {
730 if (*s != '\0') {
731 struct stat statBuf;
732
733 strcpy(tmpConsole, "/dev/");
734 strncat(tmpConsole, s, 200);
735 if (stat(tmpConsole, &statBuf) != 0) {
736 message(LOG | CONSOLE,
737 "device '%s' does not exist. Did you read the directions?\n",
738 tmpConsole);
739 break;
740 }
741 s = tmpConsole;
742 }
743 new_initAction(a->action, q, s);
744 foundIt = TRUE;
745 }
746 a++;
747 }
748 if (foundIt == TRUE)
749 continue;
750 else {
751 /* Choke on an unknown action */
752 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
722 } 753 }
723 new_initAction( a->action, q, s);
724 foundIt=TRUE;
725 }
726 a++;
727 }
728 if (foundIt==TRUE)
729 continue;
730 else {
731 /* Choke on an unknown action */
732 message(LOG|CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
733 } 754 }
734 } 755 return;
735 return;
736#endif 756#endif
737} 757}
738 758
739extern int init_main(int argc, char **argv) 759extern int init_main(int argc, char **argv)
740{ 760{
741 initAction *a; 761 initAction *a;
742 pid_t wpid; 762 pid_t wpid;
743 int status; 763 int status;
744 764
745#ifndef DEBUG_INIT 765#ifndef DEBUG_INIT
746 /* Expect to be PID 1 if we are run as init (not linuxrc) */ 766 /* Expect to be PID 1 if we are run as init (not linuxrc) */
747 if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { 767 if (getpid() != 1 && strstr(argv[0], "init") != NULL) {
748 usage( "init\n\nInit is the parent of all processes.\n\n" 768 usage("init\n\nInit is the parent of all processes.\n\n"
749 "This version of init is designed to be run only by the kernel\n"); 769 "This version of init is designed to be run only by the kernel\n");
750 } 770 }
751 /* Fix up argv[0] to be certain we claim to be init */ 771 /* Fix up argv[0] to be certain we claim to be init */
752 strncpy(argv[0], "init", strlen(argv[0])); 772 strncpy(argv[0], "init", strlen(argv[0]));
753 773
754 /* Set up sig handlers -- be sure to 774 /* Set up sig handlers -- be sure to
755 * clear all of these in run() */ 775 * clear all of these in run() */
756 signal(SIGUSR1, halt_signal); 776 signal(SIGUSR1, halt_signal);
757 signal(SIGUSR2, reboot_signal); 777 signal(SIGUSR2, reboot_signal);
758 signal(SIGINT, reboot_signal); 778 signal(SIGINT, reboot_signal);
759 signal(SIGTERM, reboot_signal); 779 signal(SIGTERM, reboot_signal);
760#if defined BB_FEATURE_INIT_CHROOT 780#if defined BB_FEATURE_INIT_CHROOT
761 signal(SIGHUP, check_chroot); 781 signal(SIGHUP, check_chroot);
762#endif 782#endif
763 783
764 /* Turn off rebooting via CTL-ALT-DEL -- we get a 784 /* Turn off rebooting via CTL-ALT-DEL -- we get a
765 * SIGINT on CAD so we can shut things down gracefully... */ 785 * SIGINT on CAD so we can shut things down gracefully... */
766 reboot(RB_DISABLE_CAD); 786 reboot(RB_DISABLE_CAD);
767#endif 787#endif
768 788
769 /* Figure out where the default console should be */ 789 /* Figure out where the default console should be */
770 console_init(); 790 console_init();
771 791
772 /* Close whatever files are open, and reset the console. */ 792 /* Close whatever files are open, and reset the console. */
773 close(0); 793 close(0);
774 close(1); 794 close(1);
775 close(2); 795 close(2);
776 set_term(0); 796 set_term(0);
777 setsid(); 797 setsid();
778 798
779 /* Make sure PATH is set to something sane */ 799 /* Make sure PATH is set to something sane */
780 putenv(_PATH_STDPATH); 800 putenv(_PATH_STDPATH);
781 801
782 /* Hello world */ 802 /* Hello world */
783#ifndef DEBUG_INIT 803#ifndef DEBUG_INIT
784 message(LOG|CONSOLE, 804 message(LOG | CONSOLE,
785 "init started: BusyBox v%s (%s) multi-call binary\r\n", 805 "init started: BusyBox v%s (%s) multi-call binary\r\n",
786 BB_VER, BB_BT); 806 BB_VER, BB_BT);
787#else 807#else
788 message(LOG|CONSOLE, 808 message(LOG | CONSOLE,
789 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n", 809 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n",
790 getpid(), BB_VER, BB_BT); 810 getpid(), BB_VER, BB_BT);
791#endif 811#endif
792 812
793 813
794 /* Mount /proc */ 814 /* Mount /proc */
795 if (mount ("proc", "/proc", "proc", 0, 0) == 0) { 815 if (mount("proc", "/proc", "proc", 0, 0) == 0) {
796 message(LOG|CONSOLE, "Mounting /proc: done.\n"); 816 message(LOG | CONSOLE, "Mounting /proc: done.\n");
797 kernelVersion = get_kernel_revision(); 817 kernelVersion = get_kernel_revision();
798 } else 818 } else
799 message(LOG|CONSOLE, "Mounting /proc: failed!\n"); 819 message(LOG | CONSOLE, "Mounting /proc: failed!\n");
800 820
801 /* Make sure there is enough memory to do something useful. */ 821 /* Make sure there is enough memory to do something useful. */
802 check_memory(); 822 check_memory();
803 823
804 /* Check if we are supposed to be in single user mode */ 824 /* Check if we are supposed to be in single user mode */
805 if ( argc > 1 && (!strcmp(argv[1], "single") || 825 if (argc > 1 && (!strcmp(argv[1], "single") ||
806 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) 826 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
807 { 827 /* Ask first then start a shell on tty2 */
808 /* Ask first then start a shell on tty2 */ 828 if (secondConsole != NULL)
809 if (secondConsole != NULL) 829 new_initAction(ASKFIRST, SHELL, secondConsole);
810 new_initAction( ASKFIRST, SHELL, secondConsole); 830 /* Start a shell on tty1 */
811 /* Start a shell on tty1 */ 831 new_initAction(RESPAWN, SHELL, console);
812 new_initAction( RESPAWN, SHELL, console); 832 } else {
813 } else { 833 /* Not in single user mode -- see what inittab says */
814 /* Not in single user mode -- see what inittab says */ 834
815 835 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
816 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 836 * then parse_inittab() simply adds in some default
817 * then parse_inittab() simply adds in some default 837 * actions(i.e runs INIT_SCRIPT and then starts a pair
818 * actions(i.e runs INIT_SCRIPT and then starts a pair 838 * of "askfirst" shells */
819 * of "askfirst" shells */ 839 parse_inittab();
820 parse_inittab();
821 }
822
823 /* Now run everything that needs to be run */
824
825 /* First run the sysinit command */
826 for( a=initActionList ; a; a=a->nextPtr) {
827 if (a->action == SYSINIT) {
828 waitfor(a->process, a->console, FALSE);
829 /* Now remove the "sysinit" entry from the list */
830 delete_initAction( a);
831 } 840 }
832 } 841
833 /* Next run anything that wants to block */ 842 /* Now run everything that needs to be run */
834 for( a=initActionList ; a; a=a->nextPtr) { 843
835 if (a->action == WAIT) { 844 /* First run the sysinit command */
836 waitfor(a->process, a->console, FALSE); 845 for (a = initActionList; a; a = a->nextPtr) {
837 /* Now remove the "wait" entry from the list */ 846 if (a->action == SYSINIT) {
838 delete_initAction( a); 847 waitfor(a->process, a->console, FALSE);
848 /* Now remove the "sysinit" entry from the list */
849 delete_initAction(a);
850 }
839 } 851 }
840 } 852 /* Next run anything that wants to block */
841 /* Next run anything to be run only once */ 853 for (a = initActionList; a; a = a->nextPtr) {
842 for( a=initActionList ; a; a=a->nextPtr) { 854 if (a->action == WAIT) {
843 if (a->action == ONCE) { 855 waitfor(a->process, a->console, FALSE);
844 run(a->process, a->console, FALSE); 856 /* Now remove the "wait" entry from the list */
845 /* Now remove the "once" entry from the list */ 857 delete_initAction(a);
846 delete_initAction( a); 858 }
847 } 859 }
848 } 860 /* Next run anything to be run only once */
849 /* If there is nothing else to do, stop */ 861 for (a = initActionList; a; a = a->nextPtr) {
850 if (initActionList == NULL) { 862 if (a->action == ONCE) {
851 message(LOG|CONSOLE, "No more tasks for init -- sleeping forever.\n"); 863 run(a->process, a->console, FALSE);
852 while (1) sleep(1); 864 /* Now remove the "once" entry from the list */
853 } 865 delete_initAction(a);
854
855 /* Now run the looping stuff for the rest of forever */
856 while (1) {
857 for( a=initActionList ; a; a=a->nextPtr) {
858 /* Only run stuff with pid==0. If they have
859 * a pid, that means they are still running */
860 if (a->pid == 0) {
861 switch(a->action) {
862 case RESPAWN:
863 /* run the respawn stuff */
864 a->pid = run(a->process, a->console, FALSE);
865 break;
866 case ASKFIRST:
867 /* run the askfirst stuff */
868 a->pid = run(a->process, a->console, TRUE);
869 break;
870 /* silence the compiler's incessant whining */
871 default:
872 break;
873 } 866 }
874 }
875 } 867 }
876 /* Wait for a child process to exit */ 868 /* If there is nothing else to do, stop */
877 wpid = wait(&status); 869 if (initActionList == NULL) {
878 if (wpid > 0 ) { 870 message(LOG | CONSOLE,
879 /* Find out who died and clean up their corpse */ 871 "No more tasks for init -- sleeping forever.\n");
880 for( a=initActionList ; a; a=a->nextPtr) { 872 while (1)
881 if (a->pid==wpid) { 873 sleep(1);
882 a->pid=0; 874 }
883 message(LOG, "Process '%s' (pid %d) exited. Scheduling it for restart.\n", 875
884 a->process, wpid); 876 /* Now run the looping stuff for the rest of forever */
877 while (1) {
878 for (a = initActionList; a; a = a->nextPtr) {
879 /* Only run stuff with pid==0. If they have
880 * a pid, that means they are still running */
881 if (a->pid == 0) {
882 switch (a->action) {
883 case RESPAWN:
884 /* run the respawn stuff */
885 a->pid = run(a->process, a->console, FALSE);
886 break;
887 case ASKFIRST:
888 /* run the askfirst stuff */
889 a->pid = run(a->process, a->console, TRUE);
890 break;
891 /* silence the compiler's incessant whining */
892 default:
893 break;
894 }
895 }
896 }
897 /* Wait for a child process to exit */
898 wpid = wait(&status);
899 if (wpid > 0) {
900 /* Find out who died and clean up their corpse */
901 for (a = initActionList; a; a = a->nextPtr) {
902 if (a->pid == wpid) {
903 a->pid = 0;
904 message(LOG,
905 "Process '%s' (pid %d) exited. Scheduling it for restart.\n",
906 a->process, wpid);
907 }
908 }
885 } 909 }
886 } 910 sleep(1);
887 } 911 }
888 sleep(1);
889 }
890} 912}
891
diff --git a/init/halt.c b/init/halt.c
index 23eb23c30..d61c38760 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini halt implementation for busybox 3 * Mini halt implementation for busybox
3 * 4 *
@@ -23,10 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int halt_main(int argc, char **argv)
27halt_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR1)); 30 exit(kill(findInitPid(), SIGUSR1));
31} 31}
32
diff --git a/init/init.c b/init/init.c
index 6dad7181b..899dca48c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -41,8 +41,8 @@
41#include <sys/kdaemon.h> 41#include <sys/kdaemon.h>
42#include <sys/sysmacros.h> 42#include <sys/sysmacros.h>
43#include <asm/types.h> 43#include <asm/types.h>
44#include <linux/serial.h> /* for serial_struct */ 44#include <linux/serial.h> /* for serial_struct */
45#include <sys/vt.h> /* for vt_stat */ 45#include <sys/vt.h> /* for vt_stat */
46#include <sys/ioctl.h> 46#include <sys/ioctl.h>
47#include <linux/version.h> 47#include <linux/version.h>
48#ifdef BB_SYSLOGD 48#ifdef BB_SYSLOGD
@@ -58,15 +58,15 @@
58#endif 58#endif
59 59
60 60
61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ 61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */
62#define VT_SECONDARY "/dev/tty2" /* Virtual console */ 62#define VT_SECONDARY "/dev/tty2" /* Virtual console */
63#define VT_LOG "/dev/tty3" /* Virtual console */ 63#define VT_LOG "/dev/tty3" /* Virtual console */
64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ 64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */
65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ 65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */
66#define SHELL "/bin/sh" /* Default shell */ 66#define SHELL "/bin/sh" /* Default shell */
67#define INITTAB "/etc/inittab" /* inittab file location */ 67#define INITTAB "/etc/inittab" /* inittab file location */
68#ifndef INIT_SCRIPT 68#ifndef INIT_SCRIPT
69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ 69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */
70#endif 70#endif
71 71
72#define LOG 0x1 72#define LOG 0x1
@@ -74,38 +74,38 @@
74 74
75/* Allowed init action types */ 75/* Allowed init action types */
76typedef enum { 76typedef enum {
77 SYSINIT=1, 77 SYSINIT = 1,
78 RESPAWN, 78 RESPAWN,
79 ASKFIRST, 79 ASKFIRST,
80 WAIT, 80 WAIT,
81 ONCE 81 ONCE
82} initActionEnum; 82} initActionEnum;
83 83
84/* And now a list of the actions we support in the version of init */ 84/* And now a list of the actions we support in the version of init */
85typedef struct initActionType{ 85typedef struct initActionType {
86 const char* name; 86 const char *name;
87 initActionEnum action; 87 initActionEnum action;
88} initActionType; 88} initActionType;
89 89
90static const struct initActionType actions[] = { 90static const struct initActionType actions[] = {
91 {"sysinit", SYSINIT}, 91 {"sysinit", SYSINIT},
92 {"respawn", RESPAWN}, 92 {"respawn", RESPAWN},
93 {"askfirst", ASKFIRST}, 93 {"askfirst", ASKFIRST},
94 {"wait", WAIT}, 94 {"wait", WAIT},
95 {"once", ONCE}, 95 {"once", ONCE},
96 {0} 96 {0}
97}; 97};
98 98
99/* Set up a linked list of initactions, to be read from inittab */ 99/* Set up a linked list of initactions, to be read from inittab */
100typedef struct initActionTag initAction; 100typedef struct initActionTag initAction;
101struct initActionTag { 101struct initActionTag {
102 pid_t pid; 102 pid_t pid;
103 char process[256]; 103 char process[256];
104 char console[256]; 104 char console[256];
105 initAction *nextPtr; 105 initAction *nextPtr;
106 initActionEnum action; 106 initActionEnum action;
107}; 107};
108initAction* initActionList = NULL; 108initAction *initActionList = NULL;
109 109
110 110
111static char *secondConsole = VT_SECONDARY; 111static char *secondConsole = VT_SECONDARY;
@@ -119,517 +119,533 @@ static char console[32] = _PATH_CONSOLE;
119 * device may be bitwise-or'd from LOG | CONSOLE */ 119 * device may be bitwise-or'd from LOG | CONSOLE */
120void message(int device, char *fmt, ...) 120void message(int device, char *fmt, ...)
121{ 121{
122 va_list arguments; 122 va_list arguments;
123 int fd; 123 int fd;
124 124
125#ifdef BB_SYSLOGD 125#ifdef BB_SYSLOGD
126 126
127 /* Log the message to syslogd */ 127 /* Log the message to syslogd */
128 if (device & LOG ) { 128 if (device & LOG) {
129 char msg[1024]; 129 char msg[1024];
130 va_start(arguments, fmt);
131 vsnprintf(msg, sizeof(msg), fmt, arguments);
132 va_end(arguments);
133 openlog( "init", 0, LOG_DAEMON);
134 syslog(LOG_DAEMON|LOG_NOTICE, msg);
135 closelog();
136 }
137 130
131 va_start(arguments, fmt);
132 vsnprintf(msg, sizeof(msg), fmt, arguments);
133 va_end(arguments);
134 openlog("init", 0, LOG_DAEMON);
135 syslog(LOG_DAEMON | LOG_NOTICE, msg);
136 closelog();
137 }
138#else 138#else
139 static int log_fd = -1; 139 static int log_fd = -1;
140 140
141 /* Take full control of the log tty, and never close it. 141 /* Take full control of the log tty, and never close it.
142 * It's mine, all mine! Muhahahaha! */ 142 * It's mine, all mine! Muhahahaha! */
143 if (log_fd < 0) { 143 if (log_fd < 0) {
144 if (log == NULL) { 144 if (log == NULL) {
145 /* don't even try to log, because there is no such console */ 145 /* don't even try to log, because there is no such console */
146 log_fd = -2; 146 log_fd = -2;
147 /* log to main console instead */ 147 /* log to main console instead */
148 device = CONSOLE; 148 device = CONSOLE;
149 } 149 } else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) {
150 else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { 150 log_fd = -1;
151 log_fd = -1; 151 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
152 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); 152 fflush(stderr);
153 fflush(stderr); 153 return;
154 return; 154 }
155 }
156 if ((device & LOG) && (log_fd >= 0)) {
157 va_start(arguments, fmt);
158 vdprintf(log_fd, fmt, arguments);
159 va_end(arguments);
155 } 160 }
156 }
157 if ( (device & LOG) && (log_fd >= 0) ) {
158 va_start(arguments, fmt);
159 vdprintf(log_fd, fmt, arguments);
160 va_end(arguments);
161 }
162#endif 161#endif
163 162
164 if (device & CONSOLE) { 163 if (device & CONSOLE) {
165 /* Always send console messages to /dev/console so people will see them. */ 164 /* Always send console messages to /dev/console so people will see them. */
166 if ((fd = device_open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) { 165 if (
167 va_start(arguments, fmt); 166 (fd =
168 vdprintf(fd, fmt, arguments); 167 device_open(_PATH_CONSOLE,
169 va_end(arguments); 168 O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) {
170 close(fd); 169 va_start(arguments, fmt);
171 } else { 170 vdprintf(fd, fmt, arguments);
172 fprintf(stderr, "Bummer, can't print: "); 171 va_end(arguments);
173 va_start(arguments, fmt); 172 close(fd);
174 vfprintf(stderr, fmt, arguments); 173 } else {
175 fflush(stderr); 174 fprintf(stderr, "Bummer, can't print: ");
176 va_end(arguments); 175 va_start(arguments, fmt);
176 vfprintf(stderr, fmt, arguments);
177 fflush(stderr);
178 va_end(arguments);
179 }
177 } 180 }
178 }
179} 181}
180 182
181 183
182/* Set terminal settings to reasonable defaults */ 184/* Set terminal settings to reasonable defaults */
183void set_term( int fd) 185void set_term(int fd)
184{ 186{
185 struct termios tty; 187 struct termios tty;
186 static const char control_characters[] = { 188 static const char control_characters[] = {
187 '\003', '\034', '\177', '\025', '\004', '\0', 189 '\003', '\034', '\177', '\025', '\004', '\0',
188 '\1', '\0', '\021', '\023', '\032', '\0', '\022', 190 '\1', '\0', '\021', '\023', '\032', '\0', '\022',
189 '\017', '\027', '\026', '\0' 191 '\017', '\027', '\026', '\0'
190 }; 192 };
191 193
192 tcgetattr(fd, &tty); 194 tcgetattr(fd, &tty);
193 195
194 /* set control chars */ 196 /* set control chars */
195 memcpy(tty.c_cc, control_characters, sizeof(control_characters)); 197 memcpy(tty.c_cc, control_characters, sizeof(control_characters));
196 198
197 /* use line dicipline 0 */ 199 /* use line dicipline 0 */
198 tty.c_line = 0; 200 tty.c_line = 0;
199 201
200 /* Make it be sane */ 202 /* Make it be sane */
201 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; 203 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
202 //tty.c_cflag |= HUPCL|CLOCAL; 204 //tty.c_cflag |= HUPCL|CLOCAL;
203 205
204 /* input modes */ 206 /* input modes */
205 tty.c_iflag = ICRNL|IXON|IXOFF; 207 tty.c_iflag = ICRNL | IXON | IXOFF;
206 208
207 /* output modes */ 209 /* output modes */
208 tty.c_oflag = OPOST|ONLCR; 210 tty.c_oflag = OPOST | ONLCR;
209 211
210 /* local modes */ 212 /* local modes */
211 tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; 213 tty.c_lflag =
214 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
212 215
213 tcsetattr(fd, TCSANOW, &tty); 216 tcsetattr(fd, TCSANOW, &tty);
214} 217}
215 218
216/* How much memory does this machine have? */ 219/* How much memory does this machine have? */
217static int mem_total() 220static int mem_total()
218{ 221{
219 char s[80]; 222 char s[80];
220 char *p = "/proc/meminfo"; 223 char *p = "/proc/meminfo";
221 FILE *f; 224 FILE *f;
222 const char pattern[] = "MemTotal:"; 225 const char pattern[] = "MemTotal:";
223 226
224 if ((f = fopen(p, "r")) < 0) { 227 if ((f = fopen(p, "r")) < 0) {
225 message(LOG, "Error opening %s: %s\n", p, strerror( errno)); 228 message(LOG, "Error opening %s: %s\n", p, strerror(errno));
226 return -1; 229 return -1;
227 } 230 }
228 while (NULL != fgets(s, 79, f)) { 231 while (NULL != fgets(s, 79, f)) {
229 p = strstr(s, pattern); 232 p = strstr(s, pattern);
230 if (NULL != p) { 233 if (NULL != p) {
231 fclose(f); 234 fclose(f);
232 return (atoi(p + strlen(pattern))); 235 return (atoi(p + strlen(pattern)));
236 }
233 } 237 }
234 } 238 return -1;
235 return -1;
236} 239}
237 240
238static void console_init() 241static void console_init()
239{ 242{
240 int fd; 243 int fd;
241 int tried_devcons = 0; 244 int tried_devcons = 0;
242 int tried_vtprimary = 0; 245 int tried_vtprimary = 0;
243 struct serial_struct sr; 246 struct serial_struct sr;
244 char *s; 247 char *s;
245 248
246 if ((s = getenv("TERM")) != NULL) { 249 if ((s = getenv("TERM")) != NULL) {
247 snprintf(termType,sizeof(termType)-1,"TERM=%s",s); 250 snprintf(termType, sizeof(termType) - 1, "TERM=%s", s);
248 } 251 }
249
250 if ((s = getenv("CONSOLE")) != NULL) {
251 snprintf(console, sizeof(console)-1, "%s",s);
252 }
253#if #cpu(sparc)
254 /* sparc kernel supports console=tty[ab] parameter which is also
255 * passed to init, so catch it here */
256 else if ((s = getenv("console")) != NULL) {
257 /* remap tty[ab] to /dev/ttyS[01] */
258 if (strcmp( s, "ttya" )==0)
259 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON0);
260 else if (strcmp( s, "ttyb" )==0)
261 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON1);
262 }
263#endif
264 else {
265 struct vt_stat vt;
266 252
267 /* 2.2 kernels: identify the real console backend and try to use it */ 253 if ((s = getenv("CONSOLE")) != NULL) {
268 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 254 snprintf(console, sizeof(console) - 1, "%s", s);
269 /* this is a serial console */
270 snprintf(console, sizeof(console)-1, "/dev/ttyS%d", sr.line);
271 } 255 }
272 else if (ioctl(0, VT_GETSTATE, &vt) == 0) { 256#if #cpu(sparc)
273 /* this is linux virtual tty */ 257 /* sparc kernel supports console=tty[ab] parameter which is also
274 snprintf(console, sizeof(console)-1, "/dev/tty%d", vt.v_active); 258 * passed to init, so catch it here */
275 } else { 259 else if ((s = getenv("console")) != NULL) {
276 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 260 /* remap tty[ab] to /dev/ttyS[01] */
277 tried_devcons++; 261 if (strcmp(s, "ttya") == 0)
262 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON0);
263 else if (strcmp(s, "ttyb") == 0)
264 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON1);
278 } 265 }
279 } 266#endif
280 267 else {
281 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { 268 struct vt_stat vt;
282 /* Can't open selected console -- try /dev/console */ 269
283 if (!tried_devcons) { 270 /* 2.2 kernels: identify the real console backend and try to use it */
284 tried_devcons++; 271 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
285 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 272 /* this is a serial console */
286 continue; 273 snprintf(console, sizeof(console) - 1, "/dev/ttyS%d", sr.line);
274 } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
275 /* this is linux virtual tty */
276 snprintf(console, sizeof(console) - 1, "/dev/tty%d",
277 vt.v_active);
278 } else {
279 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
280 tried_devcons++;
281 }
287 } 282 }
288 /* Can't open selected console -- try vt1 */ 283
289 if (!tried_vtprimary) { 284 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) {
290 tried_vtprimary++; 285 /* Can't open selected console -- try /dev/console */
291 snprintf(console, sizeof(console)-1, "%s", VT_PRIMARY); 286 if (!tried_devcons) {
292 continue; 287 tried_devcons++;
288 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
289 continue;
290 }
291 /* Can't open selected console -- try vt1 */
292 if (!tried_vtprimary) {
293 tried_vtprimary++;
294 snprintf(console, sizeof(console) - 1, "%s", VT_PRIMARY);
295 continue;
296 }
297 break;
293 } 298 }
294 break; 299 if (fd < 0) {
295 } 300 /* Perhaps we should panic here? */
296 if (fd < 0) { 301 snprintf(console, sizeof(console) - 1, "/dev/null");
297 /* Perhaps we should panic here? */ 302 } else {
298 snprintf(console, sizeof(console)-1, "/dev/null"); 303 /* check for serial console and disable logging to tty3 & running a
299 } else { 304 * shell to tty2 */
300 /* check for serial console and disable logging to tty3 & running a 305 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
301 * shell to tty2 */ 306 message(LOG | CONSOLE,
302 if (ioctl(0,TIOCGSERIAL,&sr) == 0) { 307 "serial console detected. Disabling virtual terminals.\r\n");
303 message(LOG|CONSOLE, "serial console detected. Disabling virtual terminals.\r\n" ); 308 log = NULL;
304 log = NULL; 309 secondConsole = NULL;
305 secondConsole = NULL; 310 }
311 close(fd);
306 } 312 }
307 close(fd); 313 message(LOG, "console=%s\n", console);
308 }
309 message(LOG, "console=%s\n", console );
310} 314}
311 315
312static pid_t run(char* command, 316static pid_t run(char *command, char *terminal, int get_enter)
313 char *terminal, int get_enter)
314{ 317{
315 int i, fd; 318 int i, fd;
316 pid_t pid; 319 pid_t pid;
317 char* tmpCmd; 320 char *tmpCmd;
318 char* cmd[255]; 321 char *cmd[255];
319 static const char press_enter[] = 322 static const char press_enter[] =
320 "\nPlease press Enter to activate this console. "; 323
321 char* environment[] = { 324 "\nPlease press Enter to activate this console. ";
322 "HOME=/", 325 char *environment[] = {
323 "PATH=/usr/bin:/bin:/usr/sbin:/sbin", 326 "HOME=/",
324 "SHELL=/bin/sh", 327 "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
325 termType, 328 "SHELL=/bin/sh",
326 "USER=root", 329 termType,
327 0 330 "USER=root",
328 }; 331 0
329 332 };
330
331 if ((pid = fork()) == 0) {
332 pid_t shell_pgid = getpid ();
333
334 /* Clean up */
335 close(0);
336 close(1);
337 close(2);
338 setsid();
339 333
340 /* Reset signal handlers set for parent process */
341 signal(SIGUSR1, SIG_DFL);
342 signal(SIGUSR2, SIG_DFL);
343 signal(SIGINT, SIG_DFL);
344 signal(SIGTERM, SIG_DFL);
345 signal(SIGHUP, SIG_DFL);
346 334
347 if ((fd = device_open(terminal, O_RDWR)) < 0) { 335 if ((pid = fork()) == 0) {
348 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); 336 pid_t shell_pgid = getpid();
349 exit(1);
350 }
351 dup2(fd, 0);
352 dup2(fd, 1);
353 dup2(fd, 2);
354 tcsetpgrp (0, getpgrp());
355 set_term(0);
356 337
357 if (get_enter==TRUE) { 338 /* Clean up */
358 /* 339 close(0);
359 * Save memory by not exec-ing anything large (like a shell) 340 close(1);
360 * before the user wants it. This is critical if swap is not 341 close(2);
361 * enabled and the system has low memory. Generally this will 342 setsid();
362 * be run on the second virtual console, and the first will 343
363 * be allowed to start a shell or whatever an init script 344 /* Reset signal handlers set for parent process */
364 * specifies. 345 signal(SIGUSR1, SIG_DFL);
365 */ 346 signal(SIGUSR2, SIG_DFL);
366 char c; 347 signal(SIGINT, SIG_DFL);
367 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", 348 signal(SIGTERM, SIG_DFL);
368 command, shell_pgid, terminal ); 349 signal(SIGHUP, SIG_DFL);
369 write(fileno(stdout), press_enter, sizeof(press_enter) - 1); 350
370 read(fileno(stdin), &c, 1); 351 if ((fd = device_open(terminal, O_RDWR)) < 0) {
371 } 352 message(LOG | CONSOLE, "Bummer, can't open %s\r\n", terminal);
353 exit(1);
354 }
355 dup2(fd, 0);
356 dup2(fd, 1);
357 dup2(fd, 2);
358 tcsetpgrp(0, getpgrp());
359 set_term(0);
360
361 if (get_enter == TRUE) {
362 /*
363 * Save memory by not exec-ing anything large (like a shell)
364 * before the user wants it. This is critical if swap is not
365 * enabled and the system has low memory. Generally this will
366 * be run on the second virtual console, and the first will
367 * be allowed to start a shell or whatever an init script
368 * specifies.
369 */
370 char c;
371
372 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
373 command, shell_pgid, terminal);
374 write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
375 read(fileno(stdin), &c, 1);
376 }
372 377
373 /* Log the process name and args */ 378 /* Log the process name and args */
374 message(LOG, "Starting pid %d, console %s: '", 379 message(LOG, "Starting pid %d, console %s: '",
375 shell_pgid, terminal, command); 380 shell_pgid, terminal, command);
376 381
377 /* Convert command (char*) into cmd (char**, one word per string) */ 382 /* Convert command (char*) into cmd (char**, one word per string) */
378 for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) { 383 for (tmpCmd = command, i = 0;
379 if (*tmpCmd != '\0') { 384 (tmpCmd = strsep(&command, " \t")) != NULL;) {
380 cmd[i] = tmpCmd; 385 if (*tmpCmd != '\0') {
381 message(LOG, "%s ", tmpCmd); 386 cmd[i] = tmpCmd;
382 tmpCmd++; 387#ifdef DEBUG_INIT
383 i++; 388 message(LOG, "%s ", tmpCmd);
384 } 389#endif
390 tmpCmd++;
391 i++;
392 }
393 }
394 cmd[i] = NULL;
395 message(LOG, "'\r\n");
396
397 /* Now run it. The new program will take over this PID,
398 * so nothing further in init.c should be run. */
399 execve(cmd[0], cmd, environment);
400
401 /* We're still here? Some error happened. */
402 message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
403 strerror(errno));
404 exit(-1);
385 } 405 }
386 cmd[i] = NULL; 406 return pid;
387 message(LOG, "'\r\n");
388
389 /* Now run it. The new program will take over this PID,
390 * so nothing further in init.c should be run. */
391 execve(cmd[0], cmd, environment);
392
393 /* We're still here? Some error happened. */
394 message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
395 strerror(errno));
396 exit(-1);
397 }
398 return pid;
399} 407}
400 408
401static int waitfor(char* command, 409static int waitfor(char *command, char *terminal, int get_enter)
402 char *terminal, int get_enter)
403{ 410{
404 int status, wpid; 411 int status, wpid;
405 int pid = run( command, terminal, get_enter); 412 int pid = run(command, terminal, get_enter);
406 413
407 while (1) { 414 while (1) {
408 wpid = wait(&status); 415 wpid = wait(&status);
409 if (wpid > 0 ) { 416 if (wpid > 0) {
410 message(LOG, "Process '%s' (pid %d) exited.\n", 417 message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid);
411 command, wpid); 418 break;
412 break; 419 }
420 if (wpid == pid)
421 break;
413 } 422 }
414 if (wpid == pid ) 423 return wpid;
415 break;
416 }
417 return wpid;
418} 424}
419 425
420/* Make sure there is enough memory to do something useful. * 426/* Make sure there is enough memory to do something useful. *
421 * Calls swapon if needed so be sure /proc is mounted. */ 427 * Calls swapon if needed so be sure /proc is mounted. */
422static void check_memory() 428static void check_memory()
423{ 429{
424 struct stat statBuf; 430 struct stat statBuf;
425 431
426 if (mem_total() > 3500) 432 if (mem_total() > 3500)
433 return;
434
435 if (stat("/etc/fstab", &statBuf) == 0) {
436 /* Try to turn on swap */
437 waitfor("/bin/swapon swapon -a", log, FALSE);
438 if (mem_total() < 3500)
439 goto goodnight;
440 } else
441 goto goodnight;
427 return; 442 return;
428 443
429 if (stat("/etc/fstab", &statBuf) == 0) { 444 goodnight:
430 /* Try to turn on swap */ 445 message(CONSOLE,
431 waitfor("/bin/swapon swapon -a", log, FALSE); 446 "Sorry, your computer does not have enough memory.\r\n");
432 if (mem_total() < 3500) 447 while (1)
433 goto goodnight; 448 sleep(1);
434 } else
435 goto goodnight;
436 return;
437
438goodnight:
439 message(CONSOLE, "Sorry, your computer does not have enough memory.\r\n");
440 while (1) sleep(1);
441} 449}
442 450
443#ifndef DEBUG_INIT 451#ifndef DEBUG_INIT
444static void shutdown_system(void) 452static void shutdown_system(void)
445{ 453{
446 /* first disable our SIGHUP signal */ 454 /* first disable our SIGHUP signal */
447 signal(SIGHUP, SIG_DFL); 455 signal(SIGHUP, SIG_DFL);
448 456
449 /* Allow Ctrl-Alt-Del to reboot system. */ 457 /* Allow Ctrl-Alt-Del to reboot system. */
450 reboot(RB_ENABLE_CAD); 458 reboot(RB_ENABLE_CAD);
451 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); 459 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
452 sync(); 460 sync();
453 461
454 /* Send signals to every process _except_ pid 1 */ 462 /* Send signals to every process _except_ pid 1 */
455 message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); 463 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
456 kill(-1, SIGTERM); 464 kill(-1, SIGTERM);
457 sleep(5); 465 sleep(5);
458 sync(); 466 sync();
459 467
460 message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); 468 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
461 kill(-1, SIGKILL); 469 kill(-1, SIGKILL);
462 sleep(5); 470 sleep(5);
463 471
464 message(CONSOLE, "Disabling swap.\r\n"); 472 message(CONSOLE, "Disabling swap.\r\n");
465 waitfor( "swapoff -a", console, FALSE); 473 waitfor("swapoff -a", console, FALSE);
466 message(CONSOLE, "Unmounting filesystems.\r\n"); 474 message(CONSOLE, "Unmounting filesystems.\r\n");
467 waitfor("umount -a -r", console, FALSE); 475 waitfor("umount -a -r", console, FALSE);
468 sync();
469 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
470 /* bdflush, kupdate not needed for kernels >2.2.11 */
471 bdflush(1, 0);
472 sync(); 476 sync();
473 } 477 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
478 /* bdflush, kupdate not needed for kernels >2.2.11 */
479 bdflush(1, 0);
480 sync();
481 }
474} 482}
475 483
476static void halt_signal(int sig) 484static void halt_signal(int sig)
477{ 485{
478 shutdown_system(); 486 shutdown_system();
479 message(CONSOLE, "The system is halted. Press %s or turn off power\r\n", 487 message(CONSOLE,
480 (secondConsole == NULL) /* serial console */ 488 "The system is halted. Press %s or turn off power\r\n",
481 ? "Reset" : "CTRL-ALT-DEL"); 489 (secondConsole == NULL) /* serial console */
482 sync(); 490 ? "Reset" : "CTRL-ALT-DEL");
491 sync();
483 492
484 /* allow time for last message to reach serial console */ 493 /* allow time for last message to reach serial console */
485 sleep(5); 494 sleep(5);
486 495
487#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 496#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
488 if (sig == SIGUSR2) 497 if (sig == SIGUSR2)
489 reboot(RB_POWER_OFF); 498 reboot(RB_POWER_OFF);
490 else 499 else
491#endif 500#endif
492 reboot(RB_HALT_SYSTEM); 501 reboot(RB_HALT_SYSTEM);
493 exit(0); 502 exit(0);
494} 503}
495 504
496static void reboot_signal(int sig) 505static void reboot_signal(int sig)
497{ 506{
498 shutdown_system(); 507 shutdown_system();
499 message(CONSOLE, "Please stand by while rebooting the system.\r\n"); 508 message(CONSOLE, "Please stand by while rebooting the system.\r\n");
500 sync(); 509 sync();
501 510
502 /* allow time for last message to reach serial console */ 511 /* allow time for last message to reach serial console */
503 sleep(2); 512 sleep(2);
504 513
505 reboot(RB_AUTOBOOT); 514 reboot(RB_AUTOBOOT);
506 exit(0); 515 exit(0);
507} 516}
508 517
509#if defined BB_FEATURE_INIT_CHROOT 518#if defined BB_FEATURE_INIT_CHROOT
510static void check_chroot(int sig) 519static void check_chroot(int sig)
511{ 520{
512 char *argv_init[2] = { "init", NULL, }; 521 char *argv_init[2] = { "init", NULL, };
513 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, }; 522 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, };
514 char rootpath[256], *tc; 523 char rootpath[256], *tc;
515 int fd; 524 int fd;
525
526 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) {
527 message(CONSOLE,
528 "SIGHUP recived, but could not open proc file\r\n");
529 sleep(2);
530 return;
531 }
532 if (read(fd, rootpath, sizeof(rootpath)) == -1) {
533 message(CONSOLE,
534 "SIGHUP recived, but could not read proc file\r\n");
535 sleep(2);
536 return;
537 }
538 close(fd);
516 539
517 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) { 540 if (rootpath[0] == '\0') {
518 message(CONSOLE, "SIGHUP recived, but could not open proc file\r\n"); 541 message(CONSOLE,
519 sleep(2); 542 "SIGHUP recived, but new root is not valid: %s\r\n",
520 return; 543 rootpath);
521 } 544 sleep(2);
522 if (read(fd, rootpath, sizeof(rootpath)) == -1) { 545 return;
523 message(CONSOLE, "SIGHUP recived, but could not read proc file\r\n"); 546 }
547
548 tc = strrchr(rootpath, '\n');
549 *tc = '\0';
550
551 /* Ok, making it this far means we commit */
552 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n",
553 rootpath);
554
555 /* kill all other programs first */
556 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
557 kill(-1, SIGTERM);
524 sleep(2); 558 sleep(2);
525 return; 559 sync();
526 }
527 close(fd);
528 560
529 if (rootpath[0] == '\0') { 561 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
530 message(CONSOLE, "SIGHUP recived, but new root is not valid: %s\r\n", 562 kill(-1, SIGKILL);
531 rootpath);
532 sleep(2); 563 sleep(2);
564 sync();
565
566 /* ok, we don't need /proc anymore. we also assume that the signaling
567 * process left the rest of the filesystems alone for us */
568 umount("/proc");
569
570 /* Ok, now we chroot. Hopefully we only have two things mounted, the
571 * new chroot'd mount point, and the old "/" mount. s,
572 * we go ahead and unmount the old "/". This should trigger the kernel
573 * to set things up the Right Way(tm). */
574
575 if (!chroot(rootpath))
576 umount("/dev/root");
577
578 /* If the chroot fails, we are already too far to turn back, so we
579 * continue and hope that executing init below will revive the system */
580
581 /* close all of our descriptors and open new ones */
582 close(0);
583 close(1);
584 close(2);
585 open("/dev/console", O_RDWR, 0);
586 dup(0);
587 dup(0);
588
589 message(CONSOLE, "Executing real init...\r\n");
590 /* execute init in the (hopefully) new root */
591 execve("/sbin/init", argv_init, envp_init);
592
593 message(CONSOLE,
594 "ERROR: Could not exec new init. Press %s to reboot.\r\n",
595 (secondConsole == NULL) /* serial console */
596 ? "Reset" : "CTRL-ALT-DEL");
533 return; 597 return;
534 } 598}
535 599#endif /* BB_FEATURE_INIT_CHROOT */
536 tc = strrchr(rootpath, '\n');
537 *tc = '\0';
538
539 /* Ok, making it this far means we commit */
540 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n", rootpath);
541
542 /* kill all other programs first */
543 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
544 kill(-1, SIGTERM);
545 sleep(2);
546 sync();
547
548 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
549 kill(-1, SIGKILL);
550 sleep(2);
551 sync();
552
553 /* ok, we don't need /proc anymore. we also assume that the signaling
554 * process left the rest of the filesystems alone for us */
555 umount("/proc");
556
557 /* Ok, now we chroot. Hopefully we only have two things mounted, the
558 * new chroot'd mount point, and the old "/" mount. s,
559 * we go ahead and unmount the old "/". This should trigger the kernel
560 * to set things up the Right Way(tm). */
561
562 if (!chroot(rootpath))
563 umount("/dev/root");
564
565 /* If the chroot fails, we are already too far to turn back, so we
566 * continue and hope that executing init below will revive the system */
567
568 /* close all of our descriptors and open new ones */
569 close(0);
570 close(1);
571 close(2);
572 open("/dev/console", O_RDWR, 0);
573 dup(0);
574 dup(0);
575
576 message(CONSOLE, "Executing real init...\r\n");
577 /* execute init in the (hopefully) new root */
578 execve("/sbin/init",argv_init,envp_init);
579
580 message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
581 (secondConsole == NULL) /* serial console */
582 ? "Reset" : "CTRL-ALT-DEL");
583 return;
584}
585#endif /* BB_FEATURE_INIT_CHROOT */
586
587#endif /* ! DEBUG_INIT */
588
589void new_initAction (initActionEnum action,
590 char* process, char* cons)
591{
592 initAction* newAction;
593
594 if (*cons == '\0')
595 cons = console;
596
597 /* If BusyBox detects that a serial console is in use,
598 * then entries not refering to the console or null devices will _not_ be run.
599 * The exception to this rule is the null device.
600 */
601 if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
602 return;
603 600
604 newAction = calloc ((size_t)(1), sizeof(initAction)); 601#endif /* ! DEBUG_INIT */
605 if (!newAction) { 602
606 message(LOG|CONSOLE,"Memory allocation failure\n"); 603void new_initAction(initActionEnum action, char *process, char *cons)
607 while (1) sleep(1); 604{
608 } 605 initAction *newAction;
609 newAction->nextPtr = initActionList; 606
610 initActionList = newAction; 607 if (*cons == '\0')
611 strncpy( newAction->process, process, 255); 608 cons = console;
612 newAction->action = action; 609
613 strncpy(newAction->console, cons, 255); 610 /* If BusyBox detects that a serial console is in use,
614 newAction->pid = 0; 611 * then entries not refering to the console or null devices will _not_ be run.
612 * The exception to this rule is the null device.
613 */
614 if (secondConsole == NULL && strcmp(cons, console)
615 && strcmp(cons, "/dev/null"))
616 return;
617
618 newAction = calloc((size_t) (1), sizeof(initAction));
619 if (!newAction) {
620 message(LOG | CONSOLE, "Memory allocation failure\n");
621 while (1)
622 sleep(1);
623 }
624 newAction->nextPtr = initActionList;
625 initActionList = newAction;
626 strncpy(newAction->process, process, 255);
627 newAction->action = action;
628 strncpy(newAction->console, cons, 255);
629 newAction->pid = 0;
615// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", 630// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
616// newAction->process, newAction->action, newAction->console); 631// newAction->process, newAction->action, newAction->console);
617} 632}
618 633
619void delete_initAction (initAction *action) 634void delete_initAction(initAction * action)
620{ 635{
621 initAction *a, *b=NULL; 636 initAction *a, *b = NULL;
622 for( a=initActionList ; a ; b=a, a=a->nextPtr) { 637
623 if (a == action) { 638 for (a = initActionList; a; b = a, a = a->nextPtr) {
624 if (b==NULL) { 639 if (a == action) {
625 initActionList=a->nextPtr; 640 if (b == NULL) {
626 } else { 641 initActionList = a->nextPtr;
627 b->nextPtr=a->nextPtr; 642 } else {
628 } 643 b->nextPtr = a->nextPtr;
629 free( a); 644 }
630 break; 645 free(a);
646 break;
647 }
631 } 648 }
632 }
633} 649}
634 650
635/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 651/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
@@ -639,253 +655,258 @@ void delete_initAction (initAction *action)
639 * _is_ defined, but /etc/inittab is missing, this 655 * _is_ defined, but /etc/inittab is missing, this
640 * results in the same set of default behaviors. 656 * results in the same set of default behaviors.
641 * */ 657 * */
642void parse_inittab(void) 658void parse_inittab(void)
643{ 659{
644#ifdef BB_FEATURE_USE_INITTAB 660#ifdef BB_FEATURE_USE_INITTAB
645 FILE* file; 661 FILE *file;
646 char buf[256], lineAsRead[256], tmpConsole[256]; 662 char buf[256], lineAsRead[256], tmpConsole[256];
647 char *p, *q, *r, *s; 663 char *p, *q, *r, *s;
648 const struct initActionType *a = actions; 664 const struct initActionType *a = actions;
649 int foundIt; 665 int foundIt;
650 666
651 667
652 file = fopen(INITTAB, "r"); 668 file = fopen(INITTAB, "r");
653 if (file == NULL) { 669 if (file == NULL) {
654 /* No inittab file -- set up some default behavior */ 670 /* No inittab file -- set up some default behavior */
655#endif 671#endif
656 /* Askfirst shell on tty1 */ 672 /* Askfirst shell on tty1 */
657 new_initAction( ASKFIRST, SHELL, console ); 673 new_initAction(ASKFIRST, SHELL, console);
658 /* Askfirst shell on tty2 */ 674 /* Askfirst shell on tty2 */
659 if (secondConsole != NULL) 675 if (secondConsole != NULL)
660 new_initAction( ASKFIRST, SHELL, secondConsole ); 676 new_initAction(ASKFIRST, SHELL, secondConsole);
661 /* sysinit */ 677 /* sysinit */
662 new_initAction( SYSINIT, INIT_SCRIPT, console ); 678 new_initAction(SYSINIT, INIT_SCRIPT, console);
663 679
664 return; 680 return;
665#ifdef BB_FEATURE_USE_INITTAB 681#ifdef BB_FEATURE_USE_INITTAB
666 }
667
668 while ( fgets(buf, 255, file) != NULL) {
669 foundIt=FALSE;
670 for(p = buf; *p == ' ' || *p == '\t'; p++);
671 if (*p == '#' || *p == '\n') continue;
672
673 /* Trim the trailing \n */
674 q = strrchr( p, '\n');
675 if (q != NULL)
676 *q='\0';
677
678 /* Keep a copy around for posterity's sake (and error msgs) */
679 strcpy(lineAsRead, buf);
680
681 /* Grab the ID field */
682 s=p;
683 p = strchr( p, ':');
684 if ( p != NULL || *(p+1) != '\0' ) {
685 *p='\0';
686 ++p;
687 } 682 }
688 683
689 /* Now peal off the process field from the end 684 while (fgets(buf, 255, file) != NULL) {
690 * of the string */ 685 foundIt = FALSE;
691 q = strrchr( p, ':'); 686 for (p = buf; *p == ' ' || *p == '\t'; p++);
692 if ( q == NULL || *(q+1) == '\0' ) { 687 if (*p == '#' || *p == '\n')
693 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 688 continue;
694 continue; 689
695 } else { 690 /* Trim the trailing \n */
696 *q='\0'; 691 q = strrchr(p, '\n');
697 ++q; 692 if (q != NULL)
698 } 693 *q = '\0';
694
695 /* Keep a copy around for posterity's sake (and error msgs) */
696 strcpy(lineAsRead, buf);
697
698 /* Grab the ID field */
699 s = p;
700 p = strchr(p, ':');
701 if (p != NULL || *(p + 1) != '\0') {
702 *p = '\0';
703 ++p;
704 }
699 705
700 /* Now peal off the action field */ 706 /* Now peal off the process field from the end
701 r = strrchr( p, ':'); 707 * of the string */
702 if ( r == NULL || *(r+1) == '\0') { 708 q = strrchr(p, ':');
703 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 709 if (q == NULL || *(q + 1) == '\0') {
704 continue; 710 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
705 } else { 711 continue;
706 ++r; 712 } else {
707 } 713 *q = '\0';
714 ++q;
715 }
708 716
709 /* Ok, now process it */ 717 /* Now peal off the action field */
710 a = actions; 718 r = strrchr(p, ':');
711 while (a->name != 0) { 719 if (r == NULL || *(r + 1) == '\0') {
712 if (strcmp(a->name, r) == 0) { 720 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
713 if (*s != '\0') { 721 continue;
714 struct stat statBuf; 722 } else {
715 strcpy(tmpConsole, "/dev/"); 723 ++r;
716 strncat(tmpConsole, s, 200); 724 }
717 if (stat(tmpConsole, &statBuf) != 0) { 725
718 message(LOG|CONSOLE, "device '%s' does not exist. Did you read the directions?\n", tmpConsole); 726 /* Ok, now process it */
719 break; 727 a = actions;
720 } 728 while (a->name != 0) {
721 s = tmpConsole; 729 if (strcmp(a->name, r) == 0) {
730 if (*s != '\0') {
731 struct stat statBuf;
732
733 strcpy(tmpConsole, "/dev/");
734 strncat(tmpConsole, s, 200);
735 if (stat(tmpConsole, &statBuf) != 0) {
736 message(LOG | CONSOLE,
737 "device '%s' does not exist. Did you read the directions?\n",
738 tmpConsole);
739 break;
740 }
741 s = tmpConsole;
742 }
743 new_initAction(a->action, q, s);
744 foundIt = TRUE;
745 }
746 a++;
747 }
748 if (foundIt == TRUE)
749 continue;
750 else {
751 /* Choke on an unknown action */
752 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
722 } 753 }
723 new_initAction( a->action, q, s);
724 foundIt=TRUE;
725 }
726 a++;
727 }
728 if (foundIt==TRUE)
729 continue;
730 else {
731 /* Choke on an unknown action */
732 message(LOG|CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
733 } 754 }
734 } 755 return;
735 return;
736#endif 756#endif
737} 757}
738 758
739extern int init_main(int argc, char **argv) 759extern int init_main(int argc, char **argv)
740{ 760{
741 initAction *a; 761 initAction *a;
742 pid_t wpid; 762 pid_t wpid;
743 int status; 763 int status;
744 764
745#ifndef DEBUG_INIT 765#ifndef DEBUG_INIT
746 /* Expect to be PID 1 if we are run as init (not linuxrc) */ 766 /* Expect to be PID 1 if we are run as init (not linuxrc) */
747 if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { 767 if (getpid() != 1 && strstr(argv[0], "init") != NULL) {
748 usage( "init\n\nInit is the parent of all processes.\n\n" 768 usage("init\n\nInit is the parent of all processes.\n\n"
749 "This version of init is designed to be run only by the kernel\n"); 769 "This version of init is designed to be run only by the kernel\n");
750 } 770 }
751 /* Fix up argv[0] to be certain we claim to be init */ 771 /* Fix up argv[0] to be certain we claim to be init */
752 strncpy(argv[0], "init", strlen(argv[0])); 772 strncpy(argv[0], "init", strlen(argv[0]));
753 773
754 /* Set up sig handlers -- be sure to 774 /* Set up sig handlers -- be sure to
755 * clear all of these in run() */ 775 * clear all of these in run() */
756 signal(SIGUSR1, halt_signal); 776 signal(SIGUSR1, halt_signal);
757 signal(SIGUSR2, reboot_signal); 777 signal(SIGUSR2, reboot_signal);
758 signal(SIGINT, reboot_signal); 778 signal(SIGINT, reboot_signal);
759 signal(SIGTERM, reboot_signal); 779 signal(SIGTERM, reboot_signal);
760#if defined BB_FEATURE_INIT_CHROOT 780#if defined BB_FEATURE_INIT_CHROOT
761 signal(SIGHUP, check_chroot); 781 signal(SIGHUP, check_chroot);
762#endif 782#endif
763 783
764 /* Turn off rebooting via CTL-ALT-DEL -- we get a 784 /* Turn off rebooting via CTL-ALT-DEL -- we get a
765 * SIGINT on CAD so we can shut things down gracefully... */ 785 * SIGINT on CAD so we can shut things down gracefully... */
766 reboot(RB_DISABLE_CAD); 786 reboot(RB_DISABLE_CAD);
767#endif 787#endif
768 788
769 /* Figure out where the default console should be */ 789 /* Figure out where the default console should be */
770 console_init(); 790 console_init();
771 791
772 /* Close whatever files are open, and reset the console. */ 792 /* Close whatever files are open, and reset the console. */
773 close(0); 793 close(0);
774 close(1); 794 close(1);
775 close(2); 795 close(2);
776 set_term(0); 796 set_term(0);
777 setsid(); 797 setsid();
778 798
779 /* Make sure PATH is set to something sane */ 799 /* Make sure PATH is set to something sane */
780 putenv(_PATH_STDPATH); 800 putenv(_PATH_STDPATH);
781 801
782 /* Hello world */ 802 /* Hello world */
783#ifndef DEBUG_INIT 803#ifndef DEBUG_INIT
784 message(LOG|CONSOLE, 804 message(LOG | CONSOLE,
785 "init started: BusyBox v%s (%s) multi-call binary\r\n", 805 "init started: BusyBox v%s (%s) multi-call binary\r\n",
786 BB_VER, BB_BT); 806 BB_VER, BB_BT);
787#else 807#else
788 message(LOG|CONSOLE, 808 message(LOG | CONSOLE,
789 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n", 809 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n",
790 getpid(), BB_VER, BB_BT); 810 getpid(), BB_VER, BB_BT);
791#endif 811#endif
792 812
793 813
794 /* Mount /proc */ 814 /* Mount /proc */
795 if (mount ("proc", "/proc", "proc", 0, 0) == 0) { 815 if (mount("proc", "/proc", "proc", 0, 0) == 0) {
796 message(LOG|CONSOLE, "Mounting /proc: done.\n"); 816 message(LOG | CONSOLE, "Mounting /proc: done.\n");
797 kernelVersion = get_kernel_revision(); 817 kernelVersion = get_kernel_revision();
798 } else 818 } else
799 message(LOG|CONSOLE, "Mounting /proc: failed!\n"); 819 message(LOG | CONSOLE, "Mounting /proc: failed!\n");
800 820
801 /* Make sure there is enough memory to do something useful. */ 821 /* Make sure there is enough memory to do something useful. */
802 check_memory(); 822 check_memory();
803 823
804 /* Check if we are supposed to be in single user mode */ 824 /* Check if we are supposed to be in single user mode */
805 if ( argc > 1 && (!strcmp(argv[1], "single") || 825 if (argc > 1 && (!strcmp(argv[1], "single") ||
806 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) 826 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
807 { 827 /* Ask first then start a shell on tty2 */
808 /* Ask first then start a shell on tty2 */ 828 if (secondConsole != NULL)
809 if (secondConsole != NULL) 829 new_initAction(ASKFIRST, SHELL, secondConsole);
810 new_initAction( ASKFIRST, SHELL, secondConsole); 830 /* Start a shell on tty1 */
811 /* Start a shell on tty1 */ 831 new_initAction(RESPAWN, SHELL, console);
812 new_initAction( RESPAWN, SHELL, console); 832 } else {
813 } else { 833 /* Not in single user mode -- see what inittab says */
814 /* Not in single user mode -- see what inittab says */ 834
815 835 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
816 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 836 * then parse_inittab() simply adds in some default
817 * then parse_inittab() simply adds in some default 837 * actions(i.e runs INIT_SCRIPT and then starts a pair
818 * actions(i.e runs INIT_SCRIPT and then starts a pair 838 * of "askfirst" shells */
819 * of "askfirst" shells */ 839 parse_inittab();
820 parse_inittab();
821 }
822
823 /* Now run everything that needs to be run */
824
825 /* First run the sysinit command */
826 for( a=initActionList ; a; a=a->nextPtr) {
827 if (a->action == SYSINIT) {
828 waitfor(a->process, a->console, FALSE);
829 /* Now remove the "sysinit" entry from the list */
830 delete_initAction( a);
831 } 840 }
832 } 841
833 /* Next run anything that wants to block */ 842 /* Now run everything that needs to be run */
834 for( a=initActionList ; a; a=a->nextPtr) { 843
835 if (a->action == WAIT) { 844 /* First run the sysinit command */
836 waitfor(a->process, a->console, FALSE); 845 for (a = initActionList; a; a = a->nextPtr) {
837 /* Now remove the "wait" entry from the list */ 846 if (a->action == SYSINIT) {
838 delete_initAction( a); 847 waitfor(a->process, a->console, FALSE);
848 /* Now remove the "sysinit" entry from the list */
849 delete_initAction(a);
850 }
839 } 851 }
840 } 852 /* Next run anything that wants to block */
841 /* Next run anything to be run only once */ 853 for (a = initActionList; a; a = a->nextPtr) {
842 for( a=initActionList ; a; a=a->nextPtr) { 854 if (a->action == WAIT) {
843 if (a->action == ONCE) { 855 waitfor(a->process, a->console, FALSE);
844 run(a->process, a->console, FALSE); 856 /* Now remove the "wait" entry from the list */
845 /* Now remove the "once" entry from the list */ 857 delete_initAction(a);
846 delete_initAction( a); 858 }
847 } 859 }
848 } 860 /* Next run anything to be run only once */
849 /* If there is nothing else to do, stop */ 861 for (a = initActionList; a; a = a->nextPtr) {
850 if (initActionList == NULL) { 862 if (a->action == ONCE) {
851 message(LOG|CONSOLE, "No more tasks for init -- sleeping forever.\n"); 863 run(a->process, a->console, FALSE);
852 while (1) sleep(1); 864 /* Now remove the "once" entry from the list */
853 } 865 delete_initAction(a);
854
855 /* Now run the looping stuff for the rest of forever */
856 while (1) {
857 for( a=initActionList ; a; a=a->nextPtr) {
858 /* Only run stuff with pid==0. If they have
859 * a pid, that means they are still running */
860 if (a->pid == 0) {
861 switch(a->action) {
862 case RESPAWN:
863 /* run the respawn stuff */
864 a->pid = run(a->process, a->console, FALSE);
865 break;
866 case ASKFIRST:
867 /* run the askfirst stuff */
868 a->pid = run(a->process, a->console, TRUE);
869 break;
870 /* silence the compiler's incessant whining */
871 default:
872 break;
873 } 866 }
874 }
875 } 867 }
876 /* Wait for a child process to exit */ 868 /* If there is nothing else to do, stop */
877 wpid = wait(&status); 869 if (initActionList == NULL) {
878 if (wpid > 0 ) { 870 message(LOG | CONSOLE,
879 /* Find out who died and clean up their corpse */ 871 "No more tasks for init -- sleeping forever.\n");
880 for( a=initActionList ; a; a=a->nextPtr) { 872 while (1)
881 if (a->pid==wpid) { 873 sleep(1);
882 a->pid=0; 874 }
883 message(LOG, "Process '%s' (pid %d) exited. Scheduling it for restart.\n", 875
884 a->process, wpid); 876 /* Now run the looping stuff for the rest of forever */
877 while (1) {
878 for (a = initActionList; a; a = a->nextPtr) {
879 /* Only run stuff with pid==0. If they have
880 * a pid, that means they are still running */
881 if (a->pid == 0) {
882 switch (a->action) {
883 case RESPAWN:
884 /* run the respawn stuff */
885 a->pid = run(a->process, a->console, FALSE);
886 break;
887 case ASKFIRST:
888 /* run the askfirst stuff */
889 a->pid = run(a->process, a->console, TRUE);
890 break;
891 /* silence the compiler's incessant whining */
892 default:
893 break;
894 }
895 }
896 }
897 /* Wait for a child process to exit */
898 wpid = wait(&status);
899 if (wpid > 0) {
900 /* Find out who died and clean up their corpse */
901 for (a = initActionList; a; a = a->nextPtr) {
902 if (a->pid == wpid) {
903 a->pid = 0;
904 message(LOG,
905 "Process '%s' (pid %d) exited. Scheduling it for restart.\n",
906 a->process, wpid);
907 }
908 }
885 } 909 }
886 } 910 sleep(1);
887 } 911 }
888 sleep(1);
889 }
890} 912}
891
diff --git a/init/poweroff.c b/init/poweroff.c
index 405ca3fe2..7f9abf14a 100644
--- a/init/poweroff.c
+++ b/init/poweroff.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini poweroff implementation for busybox 3 * Mini poweroff implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int poweroff_main(int argc, char **argv)
27poweroff_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR2)); 30 exit(kill(findInitPid(), SIGUSR2));
31} 31}
diff --git a/init/reboot.c b/init/reboot.c
index 1339a60f4..ef2a848ee 100644
--- a/init/reboot.c
+++ b/init/reboot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini reboot implementation for busybox 3 * Mini reboot implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int reboot_main(int argc, char **argv)
27reboot_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGINT)); 30 exit(kill(findInitPid(), SIGINT));
31} 31}
diff --git a/insmod.c b/insmod.c
index 31cb11261..7cbbed441 100644
--- a/insmod.c
+++ b/insmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini insmod implementation for busybox 3 * Mini insmod implementation for busybox
3 * 4 *
@@ -41,8 +42,7 @@
41 42
42/* Some firendly syscalls to cheer everyone's day... */ 43/* Some firendly syscalls to cheer everyone's day... */
43_syscall2(int, init_module, const char *, name, 44_syscall2(int, init_module, const char *, name,
44 const struct module *, info) 45 const struct module *, info)
45
46#ifndef BB_RMMOD 46#ifndef BB_RMMOD
47_syscall1(int, delete_module, const char *, name) 47_syscall1(int, delete_module, const char *, name)
48#else 48#else
@@ -52,155 +52,159 @@ extern int delete_module(const char *);
52#if defined(__i386__) || defined(__m68k__) || defined(__arm__) 52#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
53/* Jump through hoops to fixup error return codes */ 53/* Jump through hoops to fixup error return codes */
54#define __NR__create_module __NR_create_module 54#define __NR__create_module __NR_create_module
55static inline _syscall2(long, _create_module, const char *, name, size_t, size) 55static inline _syscall2(long, _create_module, const char *, name, size_t,
56 size)
56unsigned long create_module(const char *name, size_t size) 57unsigned long create_module(const char *name, size_t size)
57{ 58{
58 long ret = _create_module(name, size); 59 long ret = _create_module(name, size);
59 if (ret == -1 && errno > 125) { 60
60 ret = -errno; 61 if (ret == -1 && errno > 125) {
61 errno = 0; 62 ret = -errno;
62 } 63 errno = 0;
63 return ret; 64 }
65 return ret;
64} 66}
65#else 67#else
66_syscall2(unsigned long, create_module, const char *, name, size_t, size) 68_syscall2(unsigned long, create_module, const char *, name, size_t, size)
67#endif 69#endif
68
69
70static char m_filename[PATH_MAX + 1] = "\0"; 70static char m_filename[PATH_MAX + 1] = "\0";
71static char m_fullName[PATH_MAX + 1] = "\0"; 71static char m_fullName[PATH_MAX + 1] = "\0";
72static const char insmod_usage[] = 72static const char insmod_usage[] =
73 "insmod [OPTION]... MODULE [symbol=value]...\n\n" 73 "insmod [OPTION]... MODULE [symbol=value]...\n\n"
74 "Loads the specified kernel modules into the kernel.\n\n" 74 "Loads the specified kernel modules into the kernel.\n\n"
75 "Options:\n" 75 "Options:\n"
76 "\t-f\tForce module to load into the wrong kernel version.\n" 76
77 "\t-k\tMake module autoclean-able.\n"; 77 "\t-f\tForce module to load into the wrong kernel version.\n"
78 "\t-k\tMake module autoclean-able.\n";
78 79
79 80
80static int findNamedModule(const char *fileName, struct stat* statbuf) 81static int findNamedModule(const char *fileName, struct stat *statbuf)
81{ 82{
82 if (m_fullName[0]=='\0') 83 if (m_fullName[0] == '\0')
83 return( FALSE); 84 return (FALSE);
84 else { 85 else {
85 char* tmp = strrchr( fileName, '/'); 86 char *tmp = strrchr(fileName, '/');
86 if (tmp == NULL) 87
87 tmp = (char*)fileName; 88 if (tmp == NULL)
88 else 89 tmp = (char *) fileName;
89 tmp++; 90 else
90 if (check_wildcard_match(tmp, m_fullName) == TRUE) { 91 tmp++;
91 /* Stop searching if we find a match */ 92 if (check_wildcard_match(tmp, m_fullName) == TRUE) {
92 memcpy(m_filename, fileName, strlen(fileName)); 93 /* Stop searching if we find a match */
93 return( FALSE); 94 memcpy(m_filename, fileName, strlen(fileName));
95 return (FALSE);
96 }
94 } 97 }
95 } 98 return (TRUE);
96 return( TRUE);
97} 99}
98 100
99 101
100extern int insmod_main(int argc, char **argv) 102extern int insmod_main(int argc, char **argv)
101{ 103{
102 int len; 104 int len;
103 char *tmp; 105 char *tmp;
104 char m_name[PATH_MAX + 1] ="\0"; 106 char m_name[PATH_MAX + 1] = "\0";
105 FILE *fp; 107 FILE *fp;
106 108
107 if (argc<=1) { 109 if (argc <= 1) {
108 usage( insmod_usage);
109 }
110
111 /* Parse any options */
112 while (--argc > 0 && **(++argv) == '-') {
113 while (*(++(*argv))) {
114 switch (**argv) {
115 case 'f':
116 break;
117 case 'k':
118 break;
119 default:
120 usage(insmod_usage); 110 usage(insmod_usage);
121 }
122 } 111 }
123 } 112
124 113 /* Parse any options */
125 if (argc <= 0 ) 114 while (--argc > 0 && **(++argv) == '-') {
126 usage(insmod_usage); 115 while (*(++(*argv))) {
127 116 switch (**argv) {
128 /* Grab the module name */ 117 case 'f':
129 if ((tmp = strrchr(*argv, '/')) != NULL) 118 break;
130 tmp++; 119 case 'k':
131 else 120 break;
132 tmp = *argv; 121 default:
133 len = strlen(tmp); 122 usage(insmod_usage);
134 123 }
135 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') 124 }
136 len -= 2;
137 memcpy(m_name, tmp, len);
138 strcpy(m_fullName, m_name);
139 strcat(m_fullName, ".o");
140
141 /* Get a filedesc for the module */
142 if ((fp = fopen(*argv, "r")) == NULL) {
143 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
144 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
145 findNamedModule, findNamedModule) == FALSE) {
146 if ( m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL)) {
147 perror("No module by that name found in " _PATH_MODULES "\n");
148 exit( FALSE);
149 }
150 } 125 }
151 } else
152 memcpy(m_filename, *argv, strlen(*argv));
153 126
127 if (argc <= 0)
128 usage(insmod_usage);
154 129
155 fprintf(stderr, "m_filename='%s'\n", m_filename); 130 /* Grab the module name */
156 fprintf(stderr, "m_name='%s'\n", m_name); 131 if ((tmp = strrchr(*argv, '/')) != NULL)
132 tmp++;
133 else
134 tmp = *argv;
135 len = strlen(tmp);
136
137 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
138 len -= 2;
139 memcpy(m_name, tmp, len);
140 strcpy(m_fullName, m_name);
141 strcat(m_fullName, ".o");
142
143 /* Get a filedesc for the module */
144 if ((fp = fopen(*argv, "r")) == NULL) {
145 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
146 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
147 findNamedModule, findNamedModule) == FALSE) {
148 if (m_filename[0] == '\0'
149 || ((fp = fopen(m_filename, "r")) == NULL)) {
150 perror("No module by that name found in " _PATH_MODULES
151 "\n");
152 exit(FALSE);
153 }
154 }
155 } else
156 memcpy(m_filename, *argv, strlen(*argv));
157
158
159 fprintf(stderr, "m_filename='%s'\n", m_filename);
160 fprintf(stderr, "m_name='%s'\n", m_name);
161
162
163 /* TODO: do something roughtly like this... */
164#if 0
157 165
166 if ((f = obj_load(fp)) == NULL) {
167 perror("Could not load the module\n");
168 exit(FALSE);
169 }
158 170
159 /* TODO: do something roughtly like this... */ 171 /* Let the module know about the kernel symbols. */
160#if 0 172 add_kernel_symbols(f);
161 173
162 if ((f = obj_load(fp)) == NULL) { 174 if (!create_this_module(f, m_name)) {
163 perror("Could not load the module\n"); 175 perror("Could not create the module\n");
164 exit( FALSE); 176 exit(FALSE);
165 }
166
167 /* Let the module know about the kernel symbols. */
168 add_kernel_symbols(f);
169
170 if (!create_this_module(f, m_name)) {
171 perror("Could not create the module\n");
172 exit( FALSE);
173 }
174
175 if (!obj_check_undefineds(f, quiet)) {
176 perror("Undefined symbols in the module\n");
177 exit( FALSE);
178 }
179 obj_allocate_commons(f);
180
181 /* Perse the module's arguments */
182 while (argc-- >0 && *(argv++) != '\0') {
183 if (!process_module_arguments(f, argc - optind, argv + optind)) {
184 perror("Undefined symbols in the module\n");
185 exit( FALSE);
186 } 177 }
187 }
188 178
189 /* Find current size of the module */ 179 if (!obj_check_undefineds(f, quiet)) {
190 m_size = obj_load_size(f); 180 perror("Undefined symbols in the module\n");
181 exit(FALSE);
182 }
183 obj_allocate_commons(f);
184
185 /* Perse the module's arguments */
186 while (argc-- > 0 && *(argv++) != '\0') {
187 if (!process_module_arguments(f, argc - optind, argv + optind)) {
188 perror("Undefined symbols in the module\n");
189 exit(FALSE);
190 }
191 }
192
193 /* Find current size of the module */
194 m_size = obj_load_size(f);
191 195
192 196
193 errno = 0; 197 errno = 0;
194 m_addr = create_module(m_name, m_size); 198 m_addr = create_module(m_name, m_size);
195 switch (errno) { 199 switch (errno) {
196 /* yada yada */ 200 /* yada yada */
197 default: 201 default:
198 perror("create_module: %m"); 202 perror("create_module: %m");
199 203
200 } 204 }
201 205
202#endif 206#endif
203 207
204 fclose( fp); 208 fclose(fp);
205 exit( TRUE); 209 exit(TRUE);
206} 210}
diff --git a/internal.h b/internal.h
index c3814779b..22f4f2fa1 100644
--- a/internal.h
+++ b/internal.h
@@ -1,4 +1,4 @@
1 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Busybox main internal header file 3 * Busybox main internal header file
4 * 4 *
@@ -218,7 +218,7 @@ static inline int setbit(char * addr,unsigned int nr)
218{ 218{
219 int __res = bit(addr, nr); 219 int __res = bit(addr, nr);
220 addr[nr >> 3] |= (1<<(nr & 7)); 220 addr[nr >> 3] |= (1<<(nr & 7));
221 return __res != 0; \ 221 return __res != 0;
222} 222}
223 223
224static inline int clrbit(char * addr,unsigned int nr) 224static inline int clrbit(char * addr,unsigned int nr)
diff --git a/kill.c b/kill.c
index e72b73493..516621232 100644
--- a/kill.c
+++ b/kill.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini kill implementation for busybox 3 * Mini kill implementation for busybox
3 * 4 *
@@ -29,188 +30,188 @@
29#include <sys/stat.h> 30#include <sys/stat.h>
30#include <unistd.h> 31#include <unistd.h>
31 32
32static const char* kill_usage = "kill [-signal] process-id [process-id ...]\n\n" 33static const char *kill_usage =
33"Send a signal (default is SIGTERM) to the specified process(es).\n\n" 34 "kill [-signal] process-id [process-id ...]\n\n"
34"Options:\n" 35 "Send a signal (default is SIGTERM) to the specified process(es).\n\n"
35"\t-l\tList all signal names and numbers.\n\n"; 36 "Options:\n" "\t-l\tList all signal names and numbers.\n\n";
36 37
37 38
38struct signal_name { 39struct signal_name {
39 const char *name; 40 const char *name;
40 int number; 41 int number;
41}; 42};
42 43
43const struct signal_name signames[] = { 44const struct signal_name signames[] = {
44 {"HUP", SIGHUP}, 45 {"HUP", SIGHUP},
45 {"INT", SIGINT}, 46 {"INT", SIGINT},
46 {"QUIT", SIGQUIT}, 47 {"QUIT", SIGQUIT},
47 {"ILL", SIGILL}, 48 {"ILL", SIGILL},
48 {"TRAP", SIGTRAP}, 49 {"TRAP", SIGTRAP},
49 {"ABRT", SIGABRT}, 50 {"ABRT", SIGABRT},
50#ifndef __alpha__ 51#ifndef __alpha__
51 {"IOT", SIGIOT}, 52 {"IOT", SIGIOT},
52#endif 53#endif
53#if defined(__sparc__) || defined(__alpha__) 54#if defined(__sparc__) || defined(__alpha__)
54 {"EMT", SIGEMT}, 55 {"EMT", SIGEMT},
55#else 56#else
56 {"BUS", SIGBUS}, 57 {"BUS", SIGBUS},
57#endif 58#endif
58 {"FPE", SIGFPE}, 59 {"FPE", SIGFPE},
59 {"KILL", SIGKILL}, 60 {"KILL", SIGKILL},
60#if defined(__sparc__) || defined(__alpha__) 61#if defined(__sparc__) || defined(__alpha__)
61 {"BUS", SIGBUS}, 62 {"BUS", SIGBUS},
62#else 63#else
63 {"USR1", SIGUSR1}, 64 {"USR1", SIGUSR1},
64#endif 65#endif
65 {"SEGV", SIGSEGV}, 66 {"SEGV", SIGSEGV},
66#if defined(__sparc__) || defined(__alpha__) 67#if defined(__sparc__) || defined(__alpha__)
67 {"SYS", SIGSYS}, 68 {"SYS", SIGSYS},
68#else 69#else
69 {"USR2", SIGUSR2}, 70 {"USR2", SIGUSR2},
70#endif 71#endif
71 {"PIPE", SIGPIPE}, 72 {"PIPE", SIGPIPE},
72 {"ALRM", SIGALRM}, 73 {"ALRM", SIGALRM},
73 {"TERM", SIGTERM}, 74 {"TERM", SIGTERM},
74#if defined(__sparc__) || defined(__alpha__) 75#if defined(__sparc__) || defined(__alpha__)
75 {"URG", SIGURG}, 76 {"URG", SIGURG},
76 {"STOP", SIGSTOP}, 77 {"STOP", SIGSTOP},
77 {"TSTP", SIGTSTP}, 78 {"TSTP", SIGTSTP},
78 {"CONT", SIGCONT}, 79 {"CONT", SIGCONT},
79 {"CHLD", SIGCHLD}, 80 {"CHLD", SIGCHLD},
80 {"TTIN", SIGTTIN}, 81 {"TTIN", SIGTTIN},
81 {"TTOU", SIGTTOU}, 82 {"TTOU", SIGTTOU},
82 {"IO", SIGIO}, 83 {"IO", SIGIO},
83# ifndef __alpha__ 84# ifndef __alpha__
84 {"POLL", SIGIO}, 85 {"POLL", SIGIO},
85# endif 86# endif
86 {"XCPU", SIGXCPU}, 87 {"XCPU", SIGXCPU},
87 {"XFSZ", SIGXFSZ}, 88 {"XFSZ", SIGXFSZ},
88 {"VTALRM", SIGVTALRM}, 89 {"VTALRM", SIGVTALRM},
89 {"PROF", SIGPROF}, 90 {"PROF", SIGPROF},
90 {"WINCH", SIGWINCH}, 91 {"WINCH", SIGWINCH},
91# ifdef __alpha__ 92# ifdef __alpha__
92 {"INFO", SIGINFO}, 93 {"INFO", SIGINFO},
93# else 94# else
94 {"LOST", SIGLOST}, 95 {"LOST", SIGLOST},
95# endif 96# endif
96 {"USR1", SIGUSR1}, 97 {"USR1", SIGUSR1},
97 {"USR2", SIGUSR2}, 98 {"USR2", SIGUSR2},
98#else 99#else
99 {"STKFLT", SIGSTKFLT}, 100 {"STKFLT", SIGSTKFLT},
100 {"CHLD", SIGCHLD}, 101 {"CHLD", SIGCHLD},
101 {"CONT", SIGCONT}, 102 {"CONT", SIGCONT},
102 {"STOP", SIGSTOP}, 103 {"STOP", SIGSTOP},
103 {"TSTP", SIGTSTP}, 104 {"TSTP", SIGTSTP},
104 {"TTIN", SIGTTIN}, 105 {"TTIN", SIGTTIN},
105 {"TTOU", SIGTTOU}, 106 {"TTOU", SIGTTOU},
106 {"URG", SIGURG}, 107 {"URG", SIGURG},
107 {"XCPU", SIGXCPU}, 108 {"XCPU", SIGXCPU},
108 {"XFSZ", SIGXFSZ}, 109 {"XFSZ", SIGXFSZ},
109 {"VTALRM", SIGVTALRM}, 110 {"VTALRM", SIGVTALRM},
110 {"PROF", SIGPROF}, 111 {"PROF", SIGPROF},
111 {"WINCH", SIGWINCH}, 112 {"WINCH", SIGWINCH},
112 {"IO", SIGIO}, 113 {"IO", SIGIO},
113 {"POLL", SIGPOLL}, 114 {"POLL", SIGPOLL},
114 {"PWR", SIGPWR}, 115 {"PWR", SIGPWR},
115 {"UNUSED", SIGUNUSED}, 116 {"UNUSED", SIGUNUSED},
116#endif 117#endif
117 {0, 0} 118 {0, 0}
118}; 119};
119 120
120extern int kill_main (int argc, char **argv) 121extern int kill_main(int argc, char **argv)
121{ 122{
122 int sig = SIGTERM; 123 int sig = SIGTERM;
123 124
124 argc--; 125 argc--;
125 argv++; 126 argv++;
126 /* Parse any options */ 127 /* Parse any options */
127 if (argc < 1) 128 if (argc < 1)
128 usage(kill_usage);
129
130 while (argc > 0 && **argv == '-') {
131 while (*++(*argv)) {
132 switch (**argv) {
133 case 'l':
134 {
135 int col=0;
136 const struct signal_name *s = signames;
137
138 while (s->name != 0) {
139 col+=fprintf(stderr, "%2d) %-8s", s->number, (s++)->name);
140 if (col>60) {
141 fprintf(stderr, "\n");
142 col=0;
143 }
144 }
145 fprintf(stderr, "\n\n");
146 exit( TRUE);
147 }
148 break;
149 case '-':
150 usage(kill_usage); 129 usage(kill_usage);
151 default: 130
152 { 131 while (argc > 0 && **argv == '-') {
153 if (isdigit( **argv)) { 132 while (*++(*argv)) {
154 sig = atoi (*argv); 133 switch (**argv) {
155 if (sig < 0 || sig >= NSIG) 134 case 'l':
156 goto end; 135 {
157 else { 136 int col = 0;
158 argc--; 137 const struct signal_name *s = signames;
159 argv++; 138
160 goto do_it_now; 139 while (s->name != 0) {
161 } 140 col +=
162 } 141 fprintf(stderr, "%2d) %-8s", s->number,
163 else { 142 (s++)->name);
164 const struct signal_name *s = signames; 143 if (col > 60) {
165 while (s->name != 0) { 144 fprintf(stderr, "\n");
166 if (strcasecmp (s->name, *argv) == 0) { 145 col = 0;
167 sig = s->number; 146 }
168 argc--; 147 }
169 argv++; 148 fprintf(stderr, "\n\n");
170 goto do_it_now; 149 exit(TRUE);
171 } 150 }
172 s++; 151 break;
152 case '-':
153 usage(kill_usage);
154 default:
155 {
156 if (isdigit(**argv)) {
157 sig = atoi(*argv);
158 if (sig < 0 || sig >= NSIG)
159 goto end;
160 else {
161 argc--;
162 argv++;
163 goto do_it_now;
164 }
165 } else {
166 const struct signal_name *s = signames;
167
168 while (s->name != 0) {
169 if (strcasecmp(s->name, *argv) == 0) {
170 sig = s->number;
171 argc--;
172 argv++;
173 goto do_it_now;
174 }
175 s++;
176 }
177 if (s->name == 0)
178 goto end;
179 }
180 }
173 } 181 }
174 if (s->name == 0) 182 argc--;
175 goto end; 183 argv++;
176 }
177 } 184 }
178 }
179 argc--;
180 argv++;
181 }
182 }
183
184do_it_now:
185
186 while (--argc >= 0) {
187 int pid;
188 struct stat statbuf;
189 char pidpath[20]="/proc/";
190
191 if (! isdigit( **argv)) {
192 fprintf(stderr, "bad PID: %s\n", *argv);
193 exit( FALSE);
194 }
195 pid = atoi (*argv);
196 snprintf(pidpath, 20, "/proc/%s/stat", *argv);
197 if (stat( pidpath, &statbuf)!=0) {
198 fprintf(stderr, "kill: (%d) - No such pid\n", pid);
199 exit( FALSE);
200 } 185 }
201 fprintf(stderr, "sig = %d\n", sig);
202 if (kill (pid, sig) != 0) {
203 perror (*argv);
204 exit ( FALSE);
205 }
206 argv++;
207 }
208 exit ( TRUE);
209 186
187 do_it_now:
210 188
211end: 189 while (--argc >= 0) {
212 fprintf(stderr, "bad signal name: %s\n", *argv); 190 int pid;
213 exit (TRUE); 191 struct stat statbuf;
214} 192 char pidpath[20] = "/proc/";
193
194 if (!isdigit(**argv)) {
195 fprintf(stderr, "bad PID: %s\n", *argv);
196 exit(FALSE);
197 }
198 pid = atoi(*argv);
199 snprintf(pidpath, 20, "/proc/%s/stat", *argv);
200 if (stat(pidpath, &statbuf) != 0) {
201 fprintf(stderr, "kill: (%d) - No such pid\n", pid);
202 exit(FALSE);
203 }
204 fprintf(stderr, "sig = %d\n", sig);
205 if (kill(pid, sig) != 0) {
206 perror(*argv);
207 exit(FALSE);
208 }
209 argv++;
210 }
211 exit(TRUE);
215 212
216 213
214 end:
215 fprintf(stderr, "bad signal name: %s\n", *argv);
216 exit(TRUE);
217}
diff --git a/length.c b/length.c
index 2c83cdfd2..00e5a171b 100644
--- a/length.c
+++ b/length.c
@@ -1,14 +1,14 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
4#include <stdio.h> 5#include <stdio.h>
5 6
6extern int 7extern int length_main(int argc, char **argv)
7length_main(int argc, char * * argv)
8{ 8{
9 if ( argc != 2 || **(argv+1) == '-' ) { 9 if (argc != 2 || **(argv + 1) == '-') {
10 usage("length string\n"); 10 usage("length string\n");
11 } 11 }
12 printf("%d\n", strlen(argv[1])); 12 printf("%d\n", strlen(argv[1]));
13 return( TRUE); 13 return (TRUE);
14} 14}
diff --git a/ln.c b/ln.c
index f20b340ea..bc51cb0d5 100644
--- a/ln.c
+++ b/ln.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini ln implementation for busybox 3 * Mini ln implementation for busybox
3 * 4 *
@@ -30,15 +31,16 @@
30#include <stdio.h> 31#include <stdio.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <errno.h> 33#include <errno.h>
33#include <sys/param.h> /* for PATH_MAX */ 34#include <sys/param.h> /* for PATH_MAX */
34 35
35static const char ln_usage[] = 36static const char ln_usage[] =
36 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n" 37 "ln [OPTION] TARGET... LINK_NAME|DIRECTORY\n\n"
37 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n" 38 "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n\n"
38 "Options:\n" 39 "Options:\n"
39 "\t-s\tmake symbolic links instead of hard links\n" 40 "\t-s\tmake symbolic links instead of hard links\n"
40 "\t-f\tremove existing destination files\n" 41
41 "\t-n\tno dereference symlinks - treat like normal file\n"; 42 "\t-f\tremove existing destination files\n"
43 "\t-n\tno dereference symlinks - treat like normal file\n";
42 44
43static int symlinkFlag = FALSE; 45static int symlinkFlag = FALSE;
44static int removeoldFlag = FALSE; 46static int removeoldFlag = FALSE;
@@ -46,83 +48,83 @@ static int followLinks = TRUE;
46 48
47extern int ln_main(int argc, char **argv) 49extern int ln_main(int argc, char **argv)
48{ 50{
49 char *linkName; 51 char *linkName;
50 int linkIntoDirFlag; 52 int linkIntoDirFlag;
51 53
52 if (argc < 3) { 54 if (argc < 3) {
53 usage (ln_usage); 55 usage(ln_usage);
54 } 56 }
55 argc--;
56 argv++;
57
58 /* Parse any options */
59 while (**argv == '-') {
60 while (*++(*argv))
61 switch (**argv) {
62 case 's':
63 symlinkFlag = TRUE;
64 break;
65 case 'f':
66 removeoldFlag = TRUE;
67 break;
68 case 'n':
69 followLinks = FALSE;
70 break;
71 default:
72 usage (ln_usage);
73 }
74 argc--; 57 argc--;
75 argv++; 58 argv++;
76 }
77
78 linkName = argv[argc - 1];
79
80 if (strlen(linkName) > PATH_MAX) {
81 fprintf(stderr, name_too_long, "ln");
82 exit FALSE;
83 }
84 59
85 linkIntoDirFlag = isDirectory(linkName, TRUE); 60 /* Parse any options */
86 61 while (**argv == '-') {
87 if ((argc > 3) && !linkIntoDirFlag) { 62 while (*++(*argv))
88 fprintf(stderr, not_a_directory, "ln", linkName); 63 switch (**argv) {
89 exit FALSE; 64 case 's':
90 } 65 symlinkFlag = TRUE;
66 break;
67 case 'f':
68 removeoldFlag = TRUE;
69 break;
70 case 'n':
71 followLinks = FALSE;
72 break;
73 default:
74 usage(ln_usage);
75 }
76 argc--;
77 argv++;
78 }
91 79
92 while (argc-- >= 2) { 80 linkName = argv[argc - 1];
93 char srcName[PATH_MAX + 1];
94 int nChars, status;
95 81
96 if (strlen(*argv) > PATH_MAX) { 82 if (strlen(linkName) > PATH_MAX) {
97 fprintf(stderr, name_too_long, "ln"); 83 fprintf(stderr, name_too_long, "ln");
98 exit FALSE; 84 exit FALSE;
99 } 85 }
100 86
101 if (followLinks == FALSE) { 87 linkIntoDirFlag = isDirectory(linkName, TRUE);
102 strcpy(srcName, *argv);
103 } else {
104 /* Warning! This can silently truncate if > PATH_MAX, but
105 I don't think that there can be one > PATH_MAX anyway. */
106 nChars = readlink(*argv, srcName, PATH_MAX);
107 srcName[nChars] = '\0';
108 }
109 88
110 if (removeoldFlag == TRUE) { 89 if ((argc > 3) && !linkIntoDirFlag) {
111 status = ( unlink(linkName) && errno != ENOENT ); 90 fprintf(stderr, not_a_directory, "ln", linkName);
112 if (status != 0) {
113 perror(linkName);
114 exit FALSE; 91 exit FALSE;
115 }
116 } 92 }
117 93
118 if (symlinkFlag == TRUE) 94 while (argc-- >= 2) {
119 status = symlink(*argv, linkName); 95 char srcName[PATH_MAX + 1];
120 else 96 int nChars, status;
121 status = link(*argv, linkName); 97
122 if (status != 0) { 98 if (strlen(*argv) > PATH_MAX) {
123 perror(linkName); 99 fprintf(stderr, name_too_long, "ln");
124 exit FALSE; 100 exit FALSE;
101 }
102
103 if (followLinks == FALSE) {
104 strcpy(srcName, *argv);
105 } else {
106 /* Warning! This can silently truncate if > PATH_MAX, but
107 I don't think that there can be one > PATH_MAX anyway. */
108 nChars = readlink(*argv, srcName, PATH_MAX);
109 srcName[nChars] = '\0';
110 }
111
112 if (removeoldFlag == TRUE) {
113 status = (unlink(linkName) && errno != ENOENT);
114 if (status != 0) {
115 perror(linkName);
116 exit FALSE;
117 }
118 }
119
120 if (symlinkFlag == TRUE)
121 status = symlink(*argv, linkName);
122 else
123 status = link(*argv, linkName);
124 if (status != 0) {
125 perror(linkName);
126 exit FALSE;
127 }
125 } 128 }
126 } 129 exit TRUE;
127 exit TRUE;
128} 130}
diff --git a/loadacm.c b/loadacm.c
index 491bc5ce8..072562f6b 100644
--- a/loadacm.c
+++ b/loadacm.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Derived from 3 * Derived from
3 * mapscrn.c - version 0.92 4 * mapscrn.c - version 0.92
@@ -23,120 +24,115 @@
23typedef unsigned short unicode; 24typedef unsigned short unicode;
24 25
25static long int ctoi(unsigned char *s, int *is_unicode); 26static long int ctoi(unsigned char *s, int *is_unicode);
26int old_screen_map_read_ascii(FILE *fp, unsigned char buf[]); 27int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]);
27int uni_screen_map_read_ascii(FILE *fp, unicode buf[], int* is_unicode); 28int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode);
28unicode utf8_to_ucs2 (char* buf); 29unicode utf8_to_ucs2(char *buf);
29int screen_map_load(int fd, FILE *fp); 30int screen_map_load(int fd, FILE * fp);
30 31
31int loadacm_main(int argc, char **argv) 32int loadacm_main(int argc, char **argv)
32{ 33{
33 int fd; 34 int fd;
34 35
35 fd = open("/dev/tty", O_RDWR); 36 fd = open("/dev/tty", O_RDWR);
36 if (fd < 0) { 37 if (fd < 0) {
37 fprintf(stderr, "Error opening /dev/tty1: %s\n", strerror(errno)); 38 fprintf(stderr, "Error opening /dev/tty1: %s\n", strerror(errno));
38 return 1; 39 return 1;
39 } 40 }
40 41
41 if (screen_map_load(fd, stdin)) 42 if (screen_map_load(fd, stdin)) {
42 { 43 fprintf(stderr, "Error loading acm: %s\n", strerror(errno));
43 fprintf(stderr, "Error loading acm: %s\n", strerror(errno)); 44 return 1;
44 return 1; 45 }
45 } 46
46 47 write(fd, "\033(K", 3);
47 write(fd, "\033(K", 3); 48
48 49 return 0;
49 return 0;
50} 50}
51 51
52int screen_map_load(int fd, FILE *fp) 52int screen_map_load(int fd, FILE * fp)
53{ 53{
54 struct stat stbuf; 54 struct stat stbuf;
55 unicode wbuf[E_TABSZ]; 55 unicode wbuf[E_TABSZ];
56 unsigned char buf[E_TABSZ]; 56 unsigned char buf[E_TABSZ];
57 int parse_failed = 0; 57 int parse_failed = 0;
58 int is_unicode; 58 int is_unicode;
59 59
60 if (fstat(fp->_fileno, &stbuf)) 60 if (fstat(fp->_fileno, &stbuf))
61 perror("Cannot stat map file"), exit(1); 61 perror("Cannot stat map file"), exit(1);
62 62
63 /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */ 63 /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */
64 if (!(parse_failed = (-1 == uni_screen_map_read_ascii(fp,wbuf,&is_unicode))) || 64 if (!
65 (S_ISREG(stbuf.st_mode) && 65 (parse_failed =
66 (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) /* test for binary UTF map by size */ 66 (-1 == uni_screen_map_read_ascii(fp, wbuf, &is_unicode)))
67 { 67|| (S_ISREG(stbuf.st_mode) && (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) { /* test for binary UTF map by size */
68 if (parse_failed) 68 if (parse_failed) {
69 { 69 if (-1 == fseek(fp, 0, SEEK_SET)) {
70 if (-1 == fseek (fp, 0, SEEK_SET)) 70 if (errno == ESPIPE)
71 { 71 fprintf(stderr,
72 if (errno == ESPIPE) 72 "16bit screen-map MUST be a regular file.\n"),
73 fprintf (stderr, "16bit screen-map MUST be a regular file.\n"), exit (1); 73 exit(1);
74 else 74 else
75 perror ("fseek failed reading binary 16bit screen-map"), exit (1); 75 perror("fseek failed reading binary 16bit screen-map"),
76 } 76 exit(1);
77 77 }
78 if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) 78
79 perror("Cannot read [new] map from file"), exit(1); 79 if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1)
80 perror("Cannot read [new] map from file"), exit(1);
80#if 0 81#if 0
81 else 82 else
82 fprintf(stderr, "Input screen-map is binary.\n"); 83 fprintf(stderr, "Input screen-map is binary.\n");
83#endif 84#endif
85 }
86
87 /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */
88 /* same if it was binary, ie. if parse_failed */
89 if (parse_failed || is_unicode) {
90 if (ioctl(fd, PIO_UNISCRNMAP, wbuf))
91 perror("PIO_UNISCRNMAP ioctl"), exit(1);
92 else
93 return 0;
94 }
84 } 95 }
85 96
86 /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */ 97 /* rewind... */
87 /* same if it was binary, ie. if parse_failed */ 98 if (-1 == fseek(fp, 0, SEEK_SET)) {
88 if (parse_failed || is_unicode) 99 if (errno == ESPIPE)
89 { 100 fprintf(stderr,
90 if (ioctl(fd,PIO_UNISCRNMAP,wbuf)) 101 "Assuming 8bit screen-map - MUST be a regular file.\n"),
91 perror("PIO_UNISCRNMAP ioctl"), exit(1); 102 exit(1);
92 else 103 else
93 return 0; 104 perror("fseek failed assuming 8bit screen-map"), exit(1);
94 } 105 }
95 } 106
96 107 /* ... and try an old 8-bit screen-map */
97 /* rewind... */ 108 if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp, buf))) ||
98 if (-1 == fseek (fp, 0, SEEK_SET)) 109 (S_ISREG(stbuf.st_mode) && (stbuf.st_size == E_TABSZ))) { /* test for binary old 8-bit map by size */
99 { 110 if (parse_failed) {
100 if (errno == ESPIPE) 111 if (-1 == fseek(fp, 0, SEEK_SET)) {
101 fprintf (stderr, "Assuming 8bit screen-map - MUST be a regular file.\n"), exit (1); 112 if (errno == ESPIPE)
102 else 113 /* should not - it succedeed above */
103 perror ("fseek failed assuming 8bit screen-map"), exit (1); 114 fprintf(stderr, "fseek() returned ESPIPE !\n"),
104 } 115 exit(1);
105 116 else
106 /* ... and try an old 8-bit screen-map */ 117 perror("fseek for binary 8bit screen-map"), exit(1);
107 if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp,buf))) || 118 }
108 (S_ISREG(stbuf.st_mode) && 119
109 (stbuf.st_size == E_TABSZ))) /* test for binary old 8-bit map by size */ 120 if (fread(buf, E_TABSZ, 1, fp) != 1)
110 { 121 perror("Cannot read [old] map from file"), exit(1);
111 if (parse_failed)
112 {
113 if (-1 == fseek (fp, 0, SEEK_SET))
114 {
115 if (errno == ESPIPE)
116 /* should not - it succedeed above */
117 fprintf (stderr, "fseek() returned ESPIPE !\n"), exit (1);
118 else
119 perror ("fseek for binary 8bit screen-map"), exit (1);
120 }
121
122 if (fread(buf,E_TABSZ,1,fp) != 1)
123 perror("Cannot read [old] map from file"), exit(1);
124#if 0 122#if 0
125 else 123 else
126 fprintf(stderr, "Input screen-map is binary.\n"); 124 fprintf(stderr, "Input screen-map is binary.\n");
127#endif 125#endif
126 }
127
128 if (ioctl(fd, PIO_SCRNMAP, buf))
129 perror("PIO_SCRNMAP ioctl"), exit(1);
130 else
131 return 0;
132 } else {
133 fprintf(stderr, "Error parsing symbolic map\n");
134 exit(1);
128 } 135 }
129
130 if (ioctl(fd,PIO_SCRNMAP,buf))
131 perror("PIO_SCRNMAP ioctl"), exit(1);
132 else
133 return 0;
134 }
135 else
136 {
137 fprintf(stderr, "Error parsing symbolic map\n");
138 exit(1);
139 }
140} 136}
141 137
142 138
@@ -149,116 +145,111 @@ int screen_map_load(int fd, FILE *fp)
149 * 145 *
150 * FIXME: ignores everything after second word 146 * FIXME: ignores everything after second word
151 */ 147 */
152int uni_screen_map_read_ascii(FILE *fp, unicode buf[], int *is_unicode) 148int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode)
153{ 149{
154 char buffer[256]; /* line buffer reading file */ 150 char buffer[256]; /* line buffer reading file */
155 char *p, *q; /* 1st + 2nd words in line */ 151 char *p, *q; /* 1st + 2nd words in line */
156 int in, on; /* the same, as numbers */ 152 int in, on; /* the same, as numbers */
157 int tmp_is_unicode; /* tmp for is_unicode calculation */ 153 int tmp_is_unicode; /* tmp for is_unicode calculation */
158 int i; /* loop index - result holder */ 154 int i; /* loop index - result holder */
159 int ret_code = 0; /* return code */ 155 int ret_code = 0; /* return code */
160 sigset_t sigset, old_sigset; 156 sigset_t sigset, old_sigset;
161 157
162 assert (is_unicode); 158 assert(is_unicode);
163 159
164 *is_unicode = 0; 160 *is_unicode = 0;
165 161
166 /* first 128 codes defaults to ASCII */ 162 /* first 128 codes defaults to ASCII */
167 for (i=0; i<128; i++) buf[i] = i; 163 for (i = 0; i < 128; i++)
168 /* remaining defaults to replacement char (usually E_TABSZ = 256) */ 164 buf[i] = i;
169 for ( ; i<E_TABSZ; i++) buf[i] = 0xfffd; 165 /* remaining defaults to replacement char (usually E_TABSZ = 256) */
170 166 for (; i < E_TABSZ; i++)
171 /* block SIGCHLD */ 167 buf[i] = 0xfffd;
172 sigemptyset (&sigset); 168
173 sigaddset (&sigset, SIGCHLD); 169 /* block SIGCHLD */
174 sigprocmask (SIG_BLOCK, &sigset, &old_sigset); 170 sigemptyset(&sigset);
175 171 sigaddset(&sigset, SIGCHLD);
176 do 172 sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
177 { 173
178 if (NULL == fgets(buffer, sizeof(buffer),fp)) 174 do {
179 { 175 if (NULL == fgets(buffer, sizeof(buffer), fp)) {
180 if (feof (fp)) 176 if (feof(fp))
181 break; 177 break;
182 else 178 else {
183 { 179 perror("uni_screen_map_read_ascii() can't read line");
184 perror ("uni_screen_map_read_ascii() can't read line"); 180 exit(2);
185 exit (2); 181 }
186 } 182 }
187 } 183
188 184 /* get "charset-relative charcode", stripping leading spaces */
189 /* get "charset-relative charcode", stripping leading spaces */ 185 p = strtok(buffer, " \t\n");
190 p = strtok(buffer," \t\n"); 186
191 187 /* skip empty lines and comments */
192 /* skip empty lines and comments */ 188 if (!p || *p == '#')
193 if (!p || *p == '#') 189 continue;
194 continue; 190
195 191 /* get unicode mapping */
196 /* get unicode mapping */ 192 q = strtok(NULL, " \t\n");
197 q = strtok(NULL," \t\n"); 193 if (q) {
198 if (q) 194 in = ctoi(p, NULL);
199 { 195 if (in < 0 || in > 255) {
200 in = ctoi(p, NULL); 196 ret_code = -1;
201 if (in < 0 || in > 255) 197 break;
202 { 198 }
203 ret_code = -1; 199
204 break; 200 on = ctoi(q, &tmp_is_unicode);
205 } 201 if (in < 0 && on > 65535) {
206 202 ret_code = -1;
207 on = ctoi(q, &tmp_is_unicode); 203 break;
208 if (in < 0 && on > 65535) 204 }
209 { 205
210 ret_code = -1; 206 *is_unicode |= tmp_is_unicode;
211 break; 207 buf[in] = on;
212 } 208 } else {
213 209 ret_code = -1;
214 *is_unicode |= tmp_is_unicode; 210 break;
215 buf[in] = on; 211 }
216 } 212 }
217 else 213 while (1); /* terminated by break on feof() */
218 {
219 ret_code = -1;
220 break;
221 }
222 }
223 while (1); /* terminated by break on feof() */
224 214
225 /* restore sig mask */ 215 /* restore sig mask */
226 sigprocmask (SIG_SETMASK, &old_sigset, NULL); 216 sigprocmask(SIG_SETMASK, &old_sigset, NULL);
227 217
228 return ret_code; 218 return ret_code;
229} 219}
230 220
231 221
232int old_screen_map_read_ascii(FILE *fp, unsigned char buf[]) 222int old_screen_map_read_ascii(FILE * fp, unsigned char buf[])
233{ 223{
234 char buffer[256]; 224 char buffer[256];
235 int in, on; 225 int in, on;
236 char *p, *q; 226 char *p, *q;
237 227
238 for (in=0; in<256; in++) buf[in]=in; 228 for (in = 0; in < 256; in++)
239 229 buf[in] = in;
240 while (fgets(buffer,sizeof(buffer)-1,fp)) 230
241 { 231 while (fgets(buffer, sizeof(buffer) - 1, fp)) {
242 p = strtok(buffer," \t\n"); 232 p = strtok(buffer, " \t\n");
243 233
244 if (!p || *p == '#') 234 if (!p || *p == '#')
245 continue; 235 continue;
246 236
247 q = strtok(NULL," \t\n#"); 237 q = strtok(NULL, " \t\n#");
248 if (q) 238 if (q) {
249 { 239 in = ctoi(p, NULL);
250 in = ctoi(p, NULL); 240 if (in < 0 || in > 255)
251 if (in < 0 || in > 255) return -1; 241 return -1;
252 242
253 on = ctoi(q, NULL); 243 on = ctoi(q, NULL);
254 if (in < 0 && on > 255) return -1; 244 if (in < 0 && on > 255)
255 245 return -1;
256 buf[in] = on; 246
247 buf[in] = on;
248 } else
249 return -1;
257 } 250 }
258 else return -1; 251
259 } 252 return (0);
260
261 return(0);
262} 253}
263 254
264 255
@@ -270,172 +261,145 @@ int old_screen_map_read_ascii(FILE *fp, unsigned char buf[])
270 * 261 *
271 * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones. 262 * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones.
272 */ 263 */
273long int ctoi(unsigned char *s, int *is_unicode) 264long int ctoi(unsigned char *s, int *is_unicode)
274{ 265{
275 int i; 266 int i;
276 size_t ls; 267 size_t ls;
277 268
278 ls = strlen(s); 269 ls = strlen(s);
279 if (is_unicode) *is_unicode = 0; 270 if (is_unicode)
280 271 *is_unicode = 0;
281 /* hex-specified UCS2 */ 272
282 if ((strncmp(s,"U+",2) == 0) && 273 /* hex-specified UCS2 */
283 (strspn(s+2,"0123456789abcdefABCDEF") == ls-2)) 274 if ((strncmp(s, "U+", 2) == 0) &&
284 { 275 (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) {
285 sscanf(s+2,"%x",&i); 276 sscanf(s + 2, "%x", &i);
286 if (is_unicode) *is_unicode = 1; 277 if (is_unicode)
287 } 278 *is_unicode = 1;
288 279 }
289 /* hex-specified byte */ 280
290 else if ((ls <= 4) && (strncmp(s,"0x",2) == 0) && 281 /* hex-specified byte */
291 (strspn(s+2,"0123456789abcdefABCDEF") == ls-2)) 282 else if ((ls <= 4) && (strncmp(s, "0x", 2) == 0) &&
292 sscanf(s+2,"%x",&i); 283 (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2))
293 284 sscanf(s + 2, "%x", &i);
294 /* oct-specified number (byte) */ 285
295 else if ((*s == '0') && 286 /* oct-specified number (byte) */
296 (strspn(s,"01234567") == ls)) 287 else if ((*s == '0') && (strspn(s, "01234567") == ls))
297 sscanf(s,"%o",&i); 288 sscanf(s, "%o", &i);
298 289
299 /* dec-specified number (byte) */ 290 /* dec-specified number (byte) */
300 else if (strspn(s,"0123456789") == ls) 291 else if (strspn(s, "0123456789") == ls)
301 sscanf(s,"%d",&i); 292 sscanf(s, "%d", &i);
302 293
303 /* single-byte quoted char */ 294 /* single-byte quoted char */
304 else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\'')) 295 else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\''))
305 i=s[1]; 296 i = s[1];
306 297
307 /* multi-byte UTF8 quoted char */ 298 /* multi-byte UTF8 quoted char */
308 else if ((s[0] == '\'') && (s[ls-1] == '\'')) 299 else if ((s[0] == '\'') && (s[ls - 1] == '\'')) {
309 { 300 s[ls - 1] = 0; /* ensure we'll not "parse UTF too far" */
310 s[ls-1] = 0; /* ensure we'll not "parse UTF too far" */ 301 i = utf8_to_ucs2(s + 1);
311 i = utf8_to_ucs2(s+1); 302 if (is_unicode)
312 if (is_unicode) *is_unicode = 1; 303 *is_unicode = 1;
313 } 304 } else
314 else 305 return (-1);
315 return(-1); 306
316 307 return (i);
317 return(i);
318} 308}
319 309
320 310
321void saveoldmap(int fd, char *omfil) 311void saveoldmap(int fd, char *omfil)
322{ 312{
323 FILE *fp; 313 FILE *fp;
324 char buf[E_TABSZ]; 314 char buf[E_TABSZ];
315
325#ifdef GIO_UNISCRNMAP 316#ifdef GIO_UNISCRNMAP
326 unicode xbuf[E_TABSZ]; 317 unicode xbuf[E_TABSZ];
327 int is_old_map = 0; 318 int is_old_map = 0;
328 319
329 if (ioctl(fd,GIO_UNISCRNMAP,xbuf)) 320 if (ioctl(fd, GIO_UNISCRNMAP, xbuf)) {
330 { 321 perror("GIO_UNISCRNMAP ioctl error");
331 perror("GIO_UNISCRNMAP ioctl error");
332#endif 322#endif
333 if (ioctl(fd,GIO_SCRNMAP,buf)) 323 if (ioctl(fd, GIO_SCRNMAP, buf)) {
334 { 324 perror("GIO_SCRNMAP ioctl error");
335 perror("GIO_SCRNMAP ioctl error"); 325 exit(1);
336 exit(1); 326 } else
337 } 327 is_old_map = 1;
338 else
339 is_old_map = 1;
340#ifdef GIO_UNISCRNMAP 328#ifdef GIO_UNISCRNMAP
341 } 329 }
342#endif 330#endif
343
344 if ((fp = fopen(omfil, "w")) == NULL)
345 {
346 perror(omfil);
347 exit(1);
348 }
349 331
332 if ((fp = fopen(omfil, "w")) == NULL) {
333 perror(omfil);
334 exit(1);
335 }
350#ifdef GIO_UNISCRNMAP 336#ifdef GIO_UNISCRNMAP
351 if (is_old_map) 337 if (is_old_map) {
352 {
353#endif 338#endif
354 if (fwrite(buf,E_TABSZ,1,fp) != 1) 339 if (fwrite(buf, E_TABSZ, 1, fp) != 1) {
355 { 340 perror("Error writing map to file");
356 perror("Error writing map to file"); 341 exit(1);
357 exit(1); 342 }
358 }
359#ifdef GIO_UNISCRNMAP 343#ifdef GIO_UNISCRNMAP
360 } 344 } else if (fwrite(xbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) {
361 else 345 perror("Error writing map to file");
362 if (fwrite(xbuf, sizeof(unicode) * E_TABSZ,1,fp) != 1) 346 exit(1);
363 {
364 perror("Error writing map to file");
365 exit(1);
366 } 347 }
367#endif 348#endif
368 349
369 fclose(fp); 350 fclose(fp);
370} 351}
371 352
372unicode utf8_to_ucs2 (char* buf) 353unicode utf8_to_ucs2(char *buf)
373{ 354{
374 int utf_count = 0; 355 int utf_count = 0;
375 long utf_char; 356 long utf_char;
376 unicode tc; 357 unicode tc;
377 unsigned char c; 358 unsigned char c;
378 359
379 do 360 do {
380 { 361 c = *buf;
381 c = *buf; 362 buf++;
382 buf++; 363
383 364 /* if byte should be part of multi-byte sequence */
384 /* if byte should be part of multi-byte sequence */ 365 if (c & 0x80) {
385 if(c & 0x80) 366 /* if we have already started to parse a UTF8 sequence */
386 { 367 if (utf_count > 0 && (c & 0xc0) == 0x80) {
387 /* if we have already started to parse a UTF8 sequence */ 368 utf_char = (utf_char << 6) | (c & 0x3f);
388 if (utf_count > 0 && (c & 0xc0) == 0x80) 369 utf_count--;
389 { 370 if (utf_count == 0)
390 utf_char = (utf_char << 6) | (c & 0x3f); 371 tc = utf_char;
391 utf_count--; 372 else
392 if (utf_count == 0) 373 continue;
393 tc = utf_char; 374 } else { /* Possibly 1st char of a UTF8 sequence */
394 else 375
395 continue; 376 if ((c & 0xe0) == 0xc0) {
396 } 377 utf_count = 1;
397 else /* Possibly 1st char of a UTF8 sequence */ 378 utf_char = (c & 0x1f);
398 { 379 } else if ((c & 0xf0) == 0xe0) {
399 if ((c & 0xe0) == 0xc0) 380 utf_count = 2;
400 { 381 utf_char = (c & 0x0f);
401 utf_count = 1; 382 } else if ((c & 0xf8) == 0xf0) {
402 utf_char = (c & 0x1f); 383 utf_count = 3;
403 } 384 utf_char = (c & 0x07);
404 else if ((c & 0xf0) == 0xe0) 385 } else if ((c & 0xfc) == 0xf8) {
405 { 386 utf_count = 4;
406 utf_count = 2; 387 utf_char = (c & 0x03);
407 utf_char = (c & 0x0f); 388 } else if ((c & 0xfe) == 0xfc) {
408 } 389 utf_count = 5;
409 else if ((c & 0xf8) == 0xf0) 390 utf_char = (c & 0x01);
410 { 391 } else
411 utf_count = 3; 392 utf_count = 0;
412 utf_char = (c & 0x07); 393 continue;
413 } 394 }
414 else if ((c & 0xfc) == 0xf8) 395 } else { /* not part of multi-byte sequence - treat as ASCII
415 { 396 * this makes incomplete sequences to be ignored
416 utf_count = 4; 397 */
417 utf_char = (c & 0x03); 398 tc = c;
418 } 399 utf_count = 0;
419 else if ((c & 0xfe) == 0xfc) 400 }
420 { 401 }
421 utf_count = 5; 402 while (utf_count);
422 utf_char = (c & 0x01);
423 }
424 else
425 utf_count = 0;
426 continue;
427 }
428 }
429 else /* not part of multi-byte sequence - treat as ASCII
430 * this makes incomplete sequences to be ignored
431 */
432 {
433 tc = c;
434 utf_count = 0;
435 }
436 }
437 while (utf_count);
438
439 return tc;
440}
441 403
404 return tc;
405}
diff --git a/loadfont.c b/loadfont.c
index e44525d9c..64b725610 100644
--- a/loadfont.c
+++ b/loadfont.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * loadfont.c - Eugene Crosser & Andries Brouwer 3 * loadfont.c - Eugene Crosser & Andries Brouwer
3 * 4 *
@@ -30,72 +31,69 @@
30#define PSF_SEPARATOR 0xFFFF 31#define PSF_SEPARATOR 0xFFFF
31 32
32static const char loadfont_usage[] = "loadfont\n" 33static const char loadfont_usage[] = "loadfont\n"
33"\n" 34 "\n" "\tLoad a console font from standard input.\n" "\n";
34"\tLoad a console font from standard input.\n"
35"\n";
36 35
37struct psf_header 36struct psf_header {
38{ 37 unsigned char magic1, magic2; /* Magic number */
39 unsigned char magic1, magic2; /* Magic number */ 38 unsigned char mode; /* PSF font mode */
40 unsigned char mode; /* PSF font mode */ 39 unsigned char charsize; /* Character size */
41 unsigned char charsize; /* Character size */
42}; 40};
43 41
44#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) 42#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
45 43
46static void loadnewfont(int fd); 44static void loadnewfont(int fd);
47 45
48extern int 46extern int loadfont_main(int argc, char **argv)
49loadfont_main(int argc, char **argv)
50{ 47{
51 int fd; 48 int fd;
52 49
53 fd = open("/dev/tty0", O_RDWR); 50 fd = open("/dev/tty0", O_RDWR);
54 if (fd < 0) { 51 if (fd < 0) {
55 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno)); 52 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
56 return 1; 53 return 1;
57 } 54 }
58 loadnewfont(fd); 55 loadnewfont(fd);
59 56
60 return 0; 57 return 0;
61} 58}
62 59
63static void 60static void do_loadfont(int fd, char *inbuf, int unit, int fontsize)
64do_loadfont(int fd, char *inbuf, int unit, int fontsize) { 61{
65 char buf[16384]; 62 char buf[16384];
66 int i; 63 int i;
67 64
68 memset(buf,0,sizeof(buf)); 65 memset(buf, 0, sizeof(buf));
69 66
70 if (unit < 1 || unit > 32) { 67 if (unit < 1 || unit > 32) {
71 fprintf(stderr, "Bad character size %d\n", unit); 68 fprintf(stderr, "Bad character size %d\n", unit);
72 exit(1); 69 exit(1);
73 } 70 }
74 71
75 for (i = 0; i < fontsize; i++) 72 for (i = 0; i < fontsize; i++)
76 memcpy(buf+(32*i), inbuf+(unit*i), unit); 73 memcpy(buf + (32 * i), inbuf + (unit * i), unit);
77 74
78#if defined( PIO_FONTX ) && !defined( __sparc__ ) 75#if defined( PIO_FONTX ) && !defined( __sparc__ )
79 { 76 {
80 struct consolefontdesc cfd; 77 struct consolefontdesc cfd;
81 78
82 cfd.charcount = fontsize; 79 cfd.charcount = fontsize;
83 cfd.charheight = unit; 80 cfd.charheight = unit;
84 cfd.chardata = buf; 81 cfd.chardata = buf;
85 82
86 if (ioctl(fd, PIO_FONTX, &cfd) == 0) 83 if (ioctl(fd, PIO_FONTX, &cfd) == 0)
87 return; /* success */ 84 return; /* success */
88 perror("PIO_FONTX ioctl error (trying PIO_FONT)"); 85 perror("PIO_FONTX ioctl error (trying PIO_FONT)");
89 } 86 }
90#endif 87#endif
91 if (ioctl(fd, PIO_FONT, buf)) { 88 if (ioctl(fd, PIO_FONT, buf)) {
92 perror("PIO_FONT ioctl error"); 89 perror("PIO_FONT ioctl error");
93 exit(1); 90 exit(1);
94 } 91 }
95} 92}
96 93
97static void 94static void
98do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) { 95do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
96{
99 struct unimapinit advice; 97 struct unimapinit advice;
100 struct unimapdesc ud; 98 struct unimapdesc ud;
101 struct unipair *up; 99 struct unipair *up;
@@ -103,23 +101,24 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) {
103 int glyph; 101 int glyph;
104 u_short unicode; 102 u_short unicode;
105 103
106 maxct = tailsz; /* more than enough */ 104 maxct = tailsz; /* more than enough */
107 up = (struct unipair *) malloc(maxct * sizeof(struct unipair)); 105 up = (struct unipair *) malloc(maxct * sizeof(struct unipair));
106
108 if (!up) { 107 if (!up) {
109 fprintf(stderr, "Out of memory?\n"); 108 fprintf(stderr, "Out of memory?\n");
110 exit(1); 109 exit(1);
111 } 110 }
112 for (glyph = 0; glyph < fontsize; glyph++) { 111 for (glyph = 0; glyph < fontsize; glyph++) {
113 while (tailsz >= 2) { 112 while (tailsz >= 2) {
114 unicode = (((u_short) inbuf[1]) << 8) + inbuf[0]; 113 unicode = (((u_short) inbuf[1]) << 8) + inbuf[0];
115 tailsz -= 2; 114 tailsz -= 2;
116 inbuf += 2; 115 inbuf += 2;
117 if (unicode == PSF_SEPARATOR) 116 if (unicode == PSF_SEPARATOR)
118 break; 117 break;
119 up[ct].unicode = unicode; 118 up[ct].unicode = unicode;
120 up[ct].fontpos = glyph; 119 up[ct].fontpos = glyph;
121 ct++; 120 ct++;
122 } 121 }
123 } 122 }
124 123
125 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP 124 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
@@ -128,33 +127,33 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) {
128 advice.advised_hashsize = 0; 127 advice.advised_hashsize = 0;
129 advice.advised_hashstep = 0; 128 advice.advised_hashstep = 0;
130 advice.advised_hashlevel = 0; 129 advice.advised_hashlevel = 0;
131 if(ioctl(fd, PIO_UNIMAPCLR, &advice)) { 130 if (ioctl(fd, PIO_UNIMAPCLR, &advice)) {
132#ifdef ENOIOCTLCMD 131#ifdef ENOIOCTLCMD
133 if (errno == ENOIOCTLCMD) { 132 if (errno == ENOIOCTLCMD) {
134 fprintf(stderr, "It seems this kernel is older than 1.1.92\n"); 133 fprintf(stderr, "It seems this kernel is older than 1.1.92\n");
135 fprintf(stderr, "No Unicode mapping table loaded.\n"); 134 fprintf(stderr, "No Unicode mapping table loaded.\n");
136 } else 135 } else
137#endif 136#endif
138 perror("PIO_UNIMAPCLR"); 137 perror("PIO_UNIMAPCLR");
139 exit(1); 138 exit(1);
140 } 139 }
141 ud.entry_ct = ct; 140 ud.entry_ct = ct;
142 ud.entries = up; 141 ud.entries = up;
143 if(ioctl(fd, PIO_UNIMAP, &ud)) { 142 if (ioctl(fd, PIO_UNIMAP, &ud)) {
144#if 0 143#if 0
145 if (errno == ENOMEM) { 144 if (errno == ENOMEM) {
146 /* change advice parameters */ 145 /* change advice parameters */
147 } 146 }
148#endif 147#endif
149 perror("PIO_UNIMAP"); 148 perror("PIO_UNIMAP");
150 exit(1); 149 exit(1);
151 } 150 }
152} 151}
153 152
154static void 153static void loadnewfont(int fd)
155loadnewfont(int fd) { 154{
156 int unit; 155 int unit;
157 char inbuf[32768]; /* primitive */ 156 char inbuf[32768]; /* primitive */
158 int inputlth, offset; 157 int inputlth, offset;
159 158
160 /* 159 /*
@@ -178,57 +177,58 @@ loadnewfont(int fd) {
178 177
179 /* test for psf first */ 178 /* test for psf first */
180 { 179 {
181 struct psf_header psfhdr; 180 struct psf_header psfhdr;
182 int fontsize; 181 int fontsize;
183 int hastable; 182 int hastable;
184 int head0, head; 183 int head0, head;
185 184
186 if (inputlth < sizeof(struct psf_header)) 185 if (inputlth < sizeof(struct psf_header))
187 goto no_psf; 186 goto no_psf;
188 187
189 psfhdr = * (struct psf_header *) &inbuf[0]; 188 psfhdr = *(struct psf_header *) &inbuf[0];
190 189
191 if (!PSF_MAGIC_OK(psfhdr)) 190 if (!PSF_MAGIC_OK(psfhdr))
192 goto no_psf; 191 goto no_psf;
193 192
194 if (psfhdr.mode > PSF_MAXMODE) { 193 if (psfhdr.mode > PSF_MAXMODE) {
195 fprintf(stderr, "Unsupported psf file mode\n"); 194 fprintf(stderr, "Unsupported psf file mode\n");
196 exit(1); 195 exit(1);
197 } 196 }
198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); 197 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
199#if !defined( PIO_FONTX ) || defined( __sparc__ ) 198#if !defined( PIO_FONTX ) || defined( __sparc__ )
200 if (fontsize != 256) { 199 if (fontsize != 256) {
201 fprintf(stderr, "Only fontsize 256 supported\n"); 200 fprintf(stderr, "Only fontsize 256 supported\n");
202 exit(1); 201 exit(1);
203 } 202 }
204#endif 203#endif
205 hastable = (psfhdr.mode & PSF_MODEHASTAB); 204 hastable = (psfhdr.mode & PSF_MODEHASTAB);
206 unit = psfhdr.charsize; 205 unit = psfhdr.charsize;
207 head0 = sizeof(struct psf_header); 206 head0 = sizeof(struct psf_header);
208 head = head0 + fontsize*unit; 207
209 if (head > inputlth || (!hastable && head != inputlth)) { 208 head = head0 + fontsize * unit;
210 fprintf(stderr, "Input file: bad length\n"); 209 if (head > inputlth || (!hastable && head != inputlth)) {
211 exit(1); 210 fprintf(stderr, "Input file: bad length\n");
212 } 211 exit(1);
213 do_loadfont(fd, inbuf + head0, unit, fontsize); 212 }
214 if (hastable) 213 do_loadfont(fd, inbuf + head0, unit, fontsize);
215 do_loadtable(fd, inbuf + head, inputlth-head, fontsize); 214 if (hastable)
216 return; 215 do_loadtable(fd, inbuf + head, inputlth - head, fontsize);
216 return;
217 } 217 }
218 no_psf: 218 no_psf:
219 219
220 /* file with three code pages? */ 220 /* file with three code pages? */
221 if (inputlth == 9780) { 221 if (inputlth == 9780) {
222 offset = 40; 222 offset = 40;
223 unit = 16; 223 unit = 16;
224 } else { 224 } else {
225 /* bare font */ 225 /* bare font */
226 if (inputlth & 0377) { 226 if (inputlth & 0377) {
227 fprintf(stderr, "Bad input file size\n"); 227 fprintf(stderr, "Bad input file size\n");
228 exit(1); 228 exit(1);
229 } 229 }
230 offset = 0; 230 offset = 0;
231 unit = inputlth/256; 231 unit = inputlth / 256;
232 } 232 }
233 do_loadfont(fd, inbuf+offset, unit, 256); 233 do_loadfont(fd, inbuf + offset, unit, 256);
234} 234}
diff --git a/loadkmap.c b/loadkmap.c
index a228ca460..aa4f6bbc8 100644
--- a/loadkmap.c
+++ b/loadkmap.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini loadkmap implementation for busybox 3 * Mini loadkmap implementation for busybox
3 * 4 *
@@ -29,61 +30,63 @@
29 30
30 31
31static const char loadkmap_usage[] = "loadkmap\n" 32static const char loadkmap_usage[] = "loadkmap\n"
32"\n" 33 "\n"
33"\tLoad a binary keyboard translation table from standard input.\n"
34"\n";
35 34
35 "\tLoad a binary keyboard translation table from standard input.\n"
36 "\n";
36 37
37int
38loadkmap_main(int argc, char * * argv)
39{
40 struct kbentry ke;
41 u_short *ibuff;
42 int i,j,fd,readsz,pos,ibuffsz=NR_KEYS * sizeof(u_short);
43 char flags[MAX_NR_KEYMAPS],magic[]="bkeymap",buff[7];
44 38
45 fd = open("/dev/tty0", O_RDWR); 39int loadkmap_main(int argc, char **argv)
46 if (fd < 0) { 40{
47 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno)); 41 struct kbentry ke;
48 return 1; 42 u_short *ibuff;
49 } 43 int i, j, fd, readsz, pos, ibuffsz = NR_KEYS * sizeof(u_short);
44 char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap", buff[7];
50 45
51 read(0,buff,7); 46 fd = open("/dev/tty0", O_RDWR);
52 if (0 != strncmp(buff,magic,7)) { 47 if (fd < 0) {
53 fprintf(stderr, "This is not a valid binary keymap.\n"); 48 fprintf(stderr, "Error opening /dev/tty0: %s\n", strerror(errno));
54 return 1; 49 return 1;
55 } 50 }
56 51
57 if ( MAX_NR_KEYMAPS != read(0,flags,MAX_NR_KEYMAPS) ) { 52 read(0, buff, 7);
58 fprintf(stderr, "Error reading keymap flags: %s\n", strerror(errno)); 53 if (0 != strncmp(buff, magic, 7)) {
59 return 1; 54 fprintf(stderr, "This is not a valid binary keymap.\n");
60 } 55 return 1;
56 }
61 57
62 ibuff=(u_short *) malloc(ibuffsz); 58 if (MAX_NR_KEYMAPS != read(0, flags, MAX_NR_KEYMAPS)) {
63 if (!ibuff) { 59 fprintf(stderr, "Error reading keymap flags: %s\n",
64 fprintf(stderr, "Out of memory.\n"); 60 strerror(errno));
65 return 1; 61 return 1;
66 } 62 }
63
64 ibuff = (u_short *) malloc(ibuffsz);
65 if (!ibuff) {
66 fprintf(stderr, "Out of memory.\n");
67 return 1;
68 }
67 69
68 for(i=0; i<MAX_NR_KEYMAPS; i++) { 70 for (i = 0; i < MAX_NR_KEYMAPS; i++) {
69 if (flags[i]==1){ 71 if (flags[i] == 1) {
70 pos=0; 72 pos = 0;
71 while (pos < ibuffsz) { 73 while (pos < ibuffsz) {
72 if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) { 74 if ((readsz = read(0, (char *) ibuff + pos, ibuffsz - pos))
73 fprintf(stderr, "Error reading keymap: %s\n", 75 < 0) {
74 strerror(errno)); 76 fprintf(stderr, "Error reading keymap: %s\n",
75 return 1; 77 strerror(errno));
76 } 78 return 1;
77 pos += readsz; 79 }
78 } 80 pos += readsz;
79 for(j=0; j<NR_KEYS; j++) { 81 }
80 ke.kb_index = j; 82 for (j = 0; j < NR_KEYS; j++) {
81 ke.kb_table = i; 83 ke.kb_index = j;
82 ke.kb_value = ibuff[j]; 84 ke.kb_table = i;
83 ioctl(fd, KDSKBENT, &ke); 85 ke.kb_value = ibuff[j];
84 } 86 ioctl(fd, KDSKBENT, &ke);
87 }
88 }
85 } 89 }
86 } 90 close(fd);
87 close (fd); 91 return 0;
88 return 0;
89} 92}
diff --git a/logger.c b/logger.c
index aab95b984..a9e0afcc8 100644
--- a/logger.c
+++ b/logger.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini logger implementation for busybox 3 * Mini logger implementation for busybox
3 * 4 *
@@ -39,21 +40,22 @@
39 */ 40 */
40#include <sys/syslog.h> 41#include <sys/syslog.h>
41typedef struct _code { 42typedef struct _code {
42 char *c_name; 43 char *c_name;
43 int c_val; 44 int c_val;
44} CODE; 45} CODE;
45extern CODE prioritynames[]; 46extern CODE prioritynames[];
46extern CODE facilitynames[]; 47extern CODE facilitynames[];
47#endif 48#endif
48 49
49static const char logger_usage[] = 50static const char logger_usage[] =
50 "logger [OPTION]... [MESSAGE]\n\n" 51 "logger [OPTION]... [MESSAGE]\n\n"
51 "Write MESSAGE to the system log. If MESSAGE is '-', log stdin.\n\n" 52 "Write MESSAGE to the system log. If MESSAGE is '-', log stdin.\n\n"
52 "Options:\n" 53 "Options:\n"
53 "\t-s\tLog to stderr as well as the system log.\n" 54 "\t-s\tLog to stderr as well as the system log.\n"
54 "\t-t\tLog using the specified tag (defaults to user name).\n" 55 "\t-t\tLog using the specified tag (defaults to user name).\n"
55 "\t-p\tEnter the message with the specified priority.\n" 56
56 "\t\tThis may be numerical or a ``facility.level'' pair.\n"; 57 "\t-p\tEnter the message with the specified priority.\n"
58 "\t\tThis may be numerical or a ``facility.level'' pair.\n";
57 59
58 60
59/* Decode a symbolic name to a numeric value 61/* Decode a symbolic name to a numeric value
@@ -61,20 +63,19 @@ static const char logger_usage[] =
61 * Copyright (c) 1983, 1993 63 * Copyright (c) 1983, 1993
62 * The Regents of the University of California. All rights reserved. 64 * The Regents of the University of California. All rights reserved.
63 */ 65 */
64static int 66static int decode(char *name, CODE * codetab)
65decode(char* name, CODE* codetab)
66{ 67{
67 CODE *c; 68 CODE *c;
68 69
69 if (isdigit(*name)) 70 if (isdigit(*name))
70 return (atoi(name)); 71 return (atoi(name));
71 for (c = codetab; c->c_name; c++) { 72 for (c = codetab; c->c_name; c++) {
72 if (!strcasecmp(name, c->c_name)) { 73 if (!strcasecmp(name, c->c_name)) {
73 return (c->c_val); 74 return (c->c_val);
75 }
74 } 76 }
75 }
76 77
77 return (-1); 78 return (-1);
78} 79}
79 80
80/* Decode a symbolic name to a numeric value 81/* Decode a symbolic name to a numeric value
@@ -82,96 +83,94 @@ decode(char* name, CODE* codetab)
82 * Copyright (c) 1983, 1993 83 * Copyright (c) 1983, 1993
83 * The Regents of the University of California. All rights reserved. 84 * The Regents of the University of California. All rights reserved.
84 */ 85 */
85static int 86static int pencode(char *s)
86pencode(char* s)
87{ 87{
88 char *save; 88 char *save;
89 int lev, fac=LOG_USER; 89 int lev, fac = LOG_USER;
90 90
91 for (save = s; *s && *s != '.'; ++s); 91 for (save = s; *s && *s != '.'; ++s);
92 if (*s) { 92 if (*s) {
93 *s = '\0'; 93 *s = '\0';
94 fac = decode(save, facilitynames); 94 fac = decode(save, facilitynames);
95 if (fac < 0) { 95 if (fac < 0) {
96 fprintf(stderr, "unknown facility name: %s\n", save); 96 fprintf(stderr, "unknown facility name: %s\n", save);
97 exit( FALSE); 97 exit(FALSE);
98 }
99 *s++ = '.';
100 } else {
101 s = save;
102 }
103 lev = decode(s, prioritynames);
104 if (lev < 0) {
105 fprintf(stderr, "unknown priority name: %s\n", save);
106 exit(FALSE);
98 } 107 }
99 *s++ = '.'; 108 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
100 }
101 else {
102 s = save;
103 }
104 lev = decode(s, prioritynames);
105 if (lev < 0) {
106 fprintf(stderr, "unknown priority name: %s\n", save);
107 exit( FALSE);
108 }
109 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
110} 109}
111 110
112 111
113extern int logger_main(int argc, char **argv) 112extern int logger_main(int argc, char **argv)
114{ 113{
115 int pri = LOG_USER|LOG_NOTICE; 114 int pri = LOG_USER | LOG_NOTICE;
116 int option = 0; 115 int option = 0;
117 int fromStdinFlag=FALSE; 116 int fromStdinFlag = FALSE;
118 int stopLookingAtMeLikeThat=FALSE; 117 int stopLookingAtMeLikeThat = FALSE;
119 char *message, buf[1024], name[128]; 118 char *message, buf[1024], name[128];
120 119
121 /* Fill out the name string early (may be overwritten later */ 120 /* Fill out the name string early (may be overwritten later */
122 my_getpwuid(name, geteuid()); 121 my_getpwuid(name, geteuid());
123 122
124 /* Parse any options */ 123 /* Parse any options */
125 while (--argc > 0 && **(++argv) == '-') { 124 while (--argc > 0 && **(++argv) == '-') {
126 if (*((*argv)+1) == '\0') { 125 if (*((*argv) + 1) == '\0') {
127 fromStdinFlag=TRUE; 126 fromStdinFlag = TRUE;
128 }
129 stopLookingAtMeLikeThat=FALSE;
130 while (*(++(*argv)) && stopLookingAtMeLikeThat==FALSE) {
131 switch (**argv) {
132 case 's':
133 option |= LOG_PERROR;
134 break;
135 case 'p':
136 if (--argc == 0) {
137 usage(logger_usage);
138 } 127 }
139 pri = pencode(*(++argv)); 128 stopLookingAtMeLikeThat = FALSE;
140 stopLookingAtMeLikeThat=TRUE; 129 while (*(++(*argv)) && stopLookingAtMeLikeThat == FALSE) {
141 break; 130 switch (**argv) {
142 case 't': 131 case 's':
143 if (--argc == 0) { 132 option |= LOG_PERROR;
144 usage(logger_usage); 133 break;
134 case 'p':
135 if (--argc == 0) {
136 usage(logger_usage);
137 }
138 pri = pencode(*(++argv));
139 stopLookingAtMeLikeThat = TRUE;
140 break;
141 case 't':
142 if (--argc == 0) {
143 usage(logger_usage);
144 }
145 strncpy(name, *(++argv), sizeof(name));
146 stopLookingAtMeLikeThat = TRUE;
147 break;
148 default:
149 usage(logger_usage);
150 }
145 } 151 }
146 strncpy(name, *(++argv), sizeof(name));
147 stopLookingAtMeLikeThat=TRUE;
148 break;
149 default:
150 usage(logger_usage);
151 }
152 } 152 }
153 }
154 153
155 if (fromStdinFlag==TRUE) { 154 if (fromStdinFlag == TRUE) {
156 /* read from stdin */ 155 /* read from stdin */
157 int c, i=0; 156 int c, i = 0;
158 while ((c = getc(stdin)) != EOF && i<sizeof(buf)) { 157
159 buf[i++]=c; 158 while ((c = getc(stdin)) != EOF && i < sizeof(buf)) {
160 } 159 buf[i++] = c;
161 message=buf; 160 }
162 } else { 161 message = buf;
163 if (argc>=1) {
164 message = *argv;
165 } else { 162 } else {
166 fprintf(stderr, "No message\n"); 163 if (argc >= 1) {
167 exit( FALSE); 164 message = *argv;
165 } else {
166 fprintf(stderr, "No message\n");
167 exit(FALSE);
168 }
168 } 169 }
169 }
170 170
171 openlog( name, option, (pri | LOG_FACMASK)); 171 openlog(name, option, (pri | LOG_FACMASK));
172 syslog( pri, message); 172 syslog(pri, message);
173 closelog(); 173 closelog();
174 174
175 exit( TRUE); 175 exit(TRUE);
176} 176}
177
diff --git a/logname.c b/logname.c
index 5c8275ab4..182f40ed2 100644
--- a/logname.c
+++ b/logname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini logname implementation for busybox 3 * Mini logname implementation for busybox
3 * 4 *
@@ -23,18 +24,21 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char logname_usage[] = "logname\n\n" 26static const char logname_usage[] = "logname\n\n"
26"Print the name of the current user.\n";
27 27
28extern int logname_main(int argc, char **argv) { 28 "Print the name of the current user.\n";
29
30extern int logname_main(int argc, char **argv)
31{
29 char *cp; 32 char *cp;
30 33
31 if (argc > 1) usage (logname_usage); 34 if (argc > 1)
35 usage(logname_usage);
32 36
33 cp = getlogin (); 37 cp = getlogin();
34 if (cp) { 38 if (cp) {
35 puts (cp); 39 puts(cp);
36 exit (TRUE); 40 exit(TRUE);
37 } 41 }
38 fprintf (stderr, "%s: no login name\n", argv[0]); 42 fprintf(stderr, "%s: no login name\n", argv[0]);
39 exit (FALSE); 43 exit(FALSE);
40} 44}
diff --git a/ls.c b/ls.c
index 450ea1814..f23c1e086 100644
--- a/ls.c
+++ b/ls.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * tiny-ls.c version 0.1.0: A minimalist 'ls' 3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
3 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
@@ -40,18 +41,18 @@
40 * 1. requires lstat (BSD) - how do you do it without? 41 * 1. requires lstat (BSD) - how do you do it without?
41 */ 42 */
42 43
43#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */ 44#define TERMINAL_WIDTH 80 /* use 79 if your terminal has linefold bug */
44#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */ 45#define COLUMN_WIDTH 14 /* default if AUTOWIDTH not defined */
45#define COLUMN_GAP 2 /* includes the file type char, if present */ 46#define COLUMN_GAP 2 /* includes the file type char, if present */
46#define HAS_REWINDDIR 47#define HAS_REWINDDIR
47 48
48/************************************************************************/ 49/************************************************************************/
49 50
50#include "internal.h" 51#include "internal.h"
51#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 52#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
52# include <linux/types.h> 53# include <linux/types.h>
53#else 54#else
54# include <sys/types.h> 55# include <sys/types.h>
55#endif 56#endif
56#include <sys/stat.h> 57#include <sys/stat.h>
57#include <stdio.h> 58#include <stdio.h>
@@ -75,28 +76,28 @@
75#endif 76#endif
76 77
77#define FMT_AUTO 0 78#define FMT_AUTO 0
78#define FMT_LONG 1 /* one record per line, extended info */ 79#define FMT_LONG 1 /* one record per line, extended info */
79#define FMT_SINGLE 2 /* one record per line */ 80#define FMT_SINGLE 2 /* one record per line */
80#define FMT_ROWS 3 /* print across rows */ 81#define FMT_ROWS 3 /* print across rows */
81#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */ 82#define FMT_COLUMNS 3 /* fill columns (same, since we don't sort) */
82 83
83#define TIME_MOD 0 84#define TIME_MOD 0
84#define TIME_CHANGE 1 85#define TIME_CHANGE 1
85#define TIME_ACCESS 2 86#define TIME_ACCESS 2
86 87
87#define DISP_FTYPE 1 /* show character for file type */ 88#define DISP_FTYPE 1 /* show character for file type */
88#define DISP_EXEC 2 /* show '*' if regular executable file */ 89#define DISP_EXEC 2 /* show '*' if regular executable file */
89#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */ 90#define DISP_HIDDEN 4 /* show files starting . (except . and ..) */
90#define DISP_DOT 8 /* show . and .. */ 91#define DISP_DOT 8 /* show . and .. */
91#define DISP_NUMERIC 16 /* numeric uid and gid */ 92#define DISP_NUMERIC 16 /* numeric uid and gid */
92#define DISP_FULLTIME 32 /* show extended time display */ 93#define DISP_FULLTIME 32 /* show extended time display */
93#define DIR_NOLIST 64 /* show directory as itself, not contents */ 94#define DIR_NOLIST 64 /* show directory as itself, not contents */
94#define DISP_DIRNAME 128 /* show directory name (for internal use) */ 95#define DISP_DIRNAME 128 /* show directory name (for internal use) */
95#define DIR_RECURSE 256 /* -R (not yet implemented) */ 96#define DIR_RECURSE 256 /* -R (not yet implemented) */
96 97
97static unsigned char display_fmt = FMT_AUTO; 98static unsigned char display_fmt = FMT_AUTO;
98static unsigned short opts = 0; 99static unsigned short opts = 0;
99static unsigned short column = 0; 100static unsigned short column = 0;
100 101
101#ifdef BB_FEATURE_AUTOWIDTH 102#ifdef BB_FEATURE_AUTOWIDTH
102static unsigned short terminal_width = 0, column_width = 0; 103static unsigned short terminal_width = 0, column_width = 0;
@@ -113,13 +114,14 @@ static unsigned char time_fmt = TIME_MOD;
113 114
114static void writenum(long val, short minwidth) 115static void writenum(long val, short minwidth)
115{ 116{
116 char scratch[128]; 117 char scratch[128];
117 118
118 char *p = scratch + sizeof(scratch); 119 char *p = scratch + sizeof(scratch);
119 short len = 0; 120 short len = 0;
120 short neg = (val < 0); 121 short neg = (val < 0);
121 122
122 if (neg) val = -val; 123 if (neg)
124 val = -val;
123 do 125 do
124 *--p = (val % 10) + '0', len++, val /= 10; 126 *--p = (val % 10) + '0', len++, val /= 10;
125 while (val); 127 while (val);
@@ -142,8 +144,9 @@ static void newline(void)
142static void tab(short col) 144static void tab(short col)
143{ 145{
144 static const char spaces[] = " "; 146 static const char spaces[] = " ";
145 #define nspaces ((sizeof spaces)-1) /* null terminator! */ 147
146 148#define nspaces ((sizeof spaces)-1) /* null terminator! */
149
147 short n = col - column; 150 short n = col - column;
148 151
149 if (n > 0) { 152 if (n > 0) {
@@ -155,7 +158,7 @@ static void tab(short col)
155 /* must be 1...(sizeof spaces) left */ 158 /* must be 1...(sizeof spaces) left */
156 wr(spaces, n); 159 wr(spaces, n);
157 } 160 }
158 #undef nspaces 161#undef nspaces
159} 162}
160 163
161#ifdef BB_FEATURE_LS_FILETYPES 164#ifdef BB_FEATURE_LS_FILETYPES
@@ -163,8 +166,8 @@ static char append_char(mode_t mode)
163{ 166{
164 if (!(opts & DISP_FTYPE)) 167 if (!(opts & DISP_FTYPE))
165 return '\0'; 168 return '\0';
166 if ((opts & DISP_EXEC) && S_ISREG(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH))) 169 if ((opts & DISP_EXEC) && S_ISREG(mode)
167 return '*'; 170 && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*';
168 return APPCHAR(mode); 171 return APPCHAR(mode);
169} 172}
170#endif 173#endif
@@ -176,89 +179,93 @@ static char append_char(mode_t mode)
176 ** 179 **
177 **/ 180 **/
178 181
179static void list_single(const char *name, struct stat *info, const char *fullname) 182static void list_single(const char *name, struct stat *info,
183 const char *fullname)
180{ 184{
181 char scratch[PATH_MAX + 1]; 185 char scratch[PATH_MAX + 1];
182 short len = strlen(name); 186 short len = strlen(name);
187
183#ifdef BB_FEATURE_LS_FILETYPES 188#ifdef BB_FEATURE_LS_FILETYPES
184 char append = append_char(info->st_mode); 189 char append = append_char(info->st_mode);
185#endif 190#endif
186 191
187 if (display_fmt == FMT_LONG) { 192 if (display_fmt == FMT_LONG) {
188 mode_t mode = info->st_mode; 193 mode_t mode = info->st_mode;
194
189 newline(); 195 newline();
190 wr(modeString(mode), 10); 196 wr(modeString(mode), 10);
191 column=10; 197 column = 10;
192 writenum((long)info->st_nlink,(short)5); 198 writenum((long) info->st_nlink, (short) 5);
193 fputs(" ", stdout); 199 fputs(" ", stdout);
194#ifdef BB_FEATURE_LS_USERNAME 200#ifdef BB_FEATURE_LS_USERNAME
195 if (!(opts & DISP_NUMERIC)) { 201 if (!(opts & DISP_NUMERIC)) {
196 memset ( scratch, 0, sizeof (scratch)); 202 memset(scratch, 0, sizeof(scratch));
197 my_getpwuid( scratch, info->st_uid); 203 my_getpwuid(scratch, info->st_uid);
198 if (*scratch) { 204 if (*scratch) {
199 fputs(scratch, stdout); 205 fputs(scratch, stdout);
200 if ( strlen( scratch) <= 8 ) 206 if (strlen(scratch) <= 8)
201 wr(" ", 9-strlen( scratch)); 207 wr(" ", 9 - strlen(scratch));
202 } 208 } else {
203 else { 209 writenum((long) info->st_uid, (short) 8);
204 writenum((long) info->st_uid,(short)8);
205 fputs(" ", stdout); 210 fputs(" ", stdout);
206 } 211 }
207 } else 212 } else
208#endif 213#endif
209 { 214 {
210 writenum((long) info->st_uid,(short)8); 215 writenum((long) info->st_uid, (short) 8);
211 fputs(" ", stdout); 216 fputs(" ", stdout);
212 } 217 }
213#ifdef BB_FEATURE_LS_USERNAME 218#ifdef BB_FEATURE_LS_USERNAME
214 if (!(opts & DISP_NUMERIC)) { 219 if (!(opts & DISP_NUMERIC)) {
215 memset ( scratch, 0, sizeof (scratch)); 220 memset(scratch, 0, sizeof(scratch));
216 my_getgrgid( scratch, info->st_gid); 221 my_getgrgid(scratch, info->st_gid);
217 if (*scratch) { 222 if (*scratch) {
218 fputs(scratch, stdout); 223 fputs(scratch, stdout);
219 if ( strlen( scratch) <= 8 ) 224 if (strlen(scratch) <= 8)
220 wr(" ", 8-strlen( scratch)); 225 wr(" ", 8 - strlen(scratch));
221 } 226 } else
222 else 227 writenum((long) info->st_gid, (short) 8);
223 writenum((long) info->st_gid,(short)8);
224 } else 228 } else
225#endif 229#endif
226 writenum((long) info->st_gid,(short)8); 230 writenum((long) info->st_gid, (short) 8);
227 //tab(26); 231 //tab(26);
228 if (S_ISBLK(mode) || S_ISCHR(mode)) { 232 if (S_ISBLK(mode) || S_ISCHR(mode)) {
229 writenum((long)MAJOR(info->st_rdev),(short)3); 233 writenum((long) MAJOR(info->st_rdev), (short) 3);
230 fputs(", ", stdout); 234 fputs(", ", stdout);
231 writenum((long)MINOR(info->st_rdev),(short)3); 235 writenum((long) MINOR(info->st_rdev), (short) 3);
232 } 236 } else
233 else 237 writenum((long) info->st_size, (short) 8);
234 writenum((long)info->st_size,(short)8);
235 fputs(" ", stdout); 238 fputs(" ", stdout);
236 //tab(32); 239 //tab(32);
237#ifdef BB_FEATURE_LS_TIMESTAMPS 240#ifdef BB_FEATURE_LS_TIMESTAMPS
238 { 241 {
239 time_t cal; 242 time_t cal;
240 char *string; 243 char *string;
241 244
242 switch(time_fmt) { 245 switch (time_fmt) {
243 case TIME_CHANGE: 246 case TIME_CHANGE:
244 cal=info->st_ctime; break; 247 cal = info->st_ctime;
248 break;
245 case TIME_ACCESS: 249 case TIME_ACCESS:
246 cal=info->st_atime; break; 250 cal = info->st_atime;
251 break;
247 default: 252 default:
248 cal=info->st_mtime; break; 253 cal = info->st_mtime;
254 break;
249 } 255 }
250 string=ctime(&cal); 256 string = ctime(&cal);
251 if (opts & DISP_FULLTIME) 257 if (opts & DISP_FULLTIME)
252 wr(string,24); 258 wr(string, 24);
253 else { 259 else {
254 time_t age = time(NULL) - cal; 260 time_t age = time(NULL) - cal;
255 wr(string+4,7); /* mmm_dd_ */ 261
256 if(age < 3600L*24*365/2 && age > -15*60) 262 wr(string + 4, 7); /* mmm_dd_ */
263 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60)
257 /* hh:mm if less than 6 months old */ 264 /* hh:mm if less than 6 months old */
258 wr(string+11,5); 265 wr(string + 11, 5);
259 else 266 else
260 /* _yyyy otherwise */ 267 /* _yyyy otherwise */
261 wr(string+19,5); 268 wr(string + 19, 5);
262 } 269 }
263 wr(" ", 1); 270 wr(" ", 1);
264 } 271 }
@@ -269,7 +276,8 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
269 if (S_ISLNK(mode)) { 276 if (S_ISLNK(mode)) {
270 wr(" -> ", 4); 277 wr(" -> ", 4);
271 len = readlink(fullname, scratch, sizeof scratch); 278 len = readlink(fullname, scratch, sizeof scratch);
272 if (len > 0) fwrite(scratch, 1, len, stdout); 279 if (len > 0)
280 fwrite(scratch, 1, len, stdout);
273#ifdef BB_FEATURE_LS_FILETYPES 281#ifdef BB_FEATURE_LS_FILETYPES
274 /* show type of destination */ 282 /* show type of destination */
275 if (opts & DISP_FTYPE) { 283 if (opts & DISP_FTYPE) {
@@ -287,18 +295,17 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
287#endif 295#endif
288 } else { 296 } else {
289 static short nexttab = 0; 297 static short nexttab = 0;
290 298
291 /* sort out column alignment */ 299 /* sort out column alignment */
292 if (column == 0) 300 if (column == 0); /* nothing to do */
293 ; /* nothing to do */
294 else if (display_fmt == FMT_SINGLE) 301 else if (display_fmt == FMT_SINGLE)
295 newline(); 302 newline();
296 else { 303 else {
297 if (nexttab + column_width > terminal_width 304 if (nexttab + column_width > terminal_width
298#ifndef BB_FEATURE_AUTOWIDTH 305#ifndef BB_FEATURE_AUTOWIDTH
299 || nexttab + len >= terminal_width 306 || nexttab + len >= terminal_width
300#endif 307#endif
301 ) 308 )
302 newline(); 309 newline();
303 else 310 else
304 tab(nexttab); 311 tab(nexttab);
@@ -336,32 +343,33 @@ static int list_item(const char *name)
336 struct stat info; 343 struct stat info;
337 DIR *dir; 344 DIR *dir;
338 struct dirent *entry; 345 struct dirent *entry;
339 char fullname[MAXNAMLEN+1], *fnend; 346 char fullname[MAXNAMLEN + 1], *fnend;
340 347
341 if (lstat(name, &info)) 348 if (lstat(name, &info))
342 goto listerr; 349 goto listerr;
343 350
344 if (!S_ISDIR(info.st_mode) || 351 if (!S_ISDIR(info.st_mode) || (opts & DIR_NOLIST)) {
345 (opts & DIR_NOLIST)) {
346 list_single(name, &info, name); 352 list_single(name, &info, name);
347 return 0; 353 return 0;
348 } 354 }
349 355
350 /* Otherwise, it's a directory we want to list the contents of */ 356 /* Otherwise, it's a directory we want to list the contents of */
351 357
352 if (opts & DISP_DIRNAME) { /* identify the directory */ 358 if (opts & DISP_DIRNAME) { /* identify the directory */
353 if (column) 359 if (column)
354 wr("\n\n", 2), column = 0; 360 wr("\n\n", 2), column = 0;
355 wr(name, strlen(name)); 361 wr(name, strlen(name));
356 wr(":\n", 2); 362 wr(":\n", 2);
357 } 363 }
358 364
359 dir = opendir(name); 365 dir = opendir(name);
360 if (!dir) goto listerr; 366 if (!dir)
367 goto listerr;
361#ifdef BB_FEATURE_AUTOWIDTH 368#ifdef BB_FEATURE_AUTOWIDTH
362 column_width = 0; 369 column_width = 0;
363 while ((entry = readdir(dir)) != NULL) { 370 while ((entry = readdir(dir)) != NULL) {
364 short w = strlen(entry->d_name); 371 short w = strlen(entry->d_name);
372
365 if (column_width < w) 373 if (column_width < w)
366 column_width = w; 374 column_width = w;
367 } 375 }
@@ -370,39 +378,40 @@ static int list_item(const char *name)
370#else 378#else
371 closedir(dir); 379 closedir(dir);
372 dir = opendir(name); 380 dir = opendir(name);
373 if (!dir) goto listerr; 381 if (!dir)
382 goto listerr;
374#endif 383#endif
375#endif 384#endif
376 385
377 /* List the contents */ 386 /* List the contents */
378 387
379 strcpy(fullname,name); /* *** ignore '.' by itself */ 388 strcpy(fullname, name); /* *** ignore '.' by itself */
380 fnend=fullname+strlen(fullname); 389 fnend = fullname + strlen(fullname);
381 if (fnend[-1] != '/') 390 if (fnend[-1] != '/')
382 *fnend++ = '/'; 391 *fnend++ = '/';
383 392
384 while ((entry = readdir(dir)) != NULL) { 393 while ((entry = readdir(dir)) != NULL) {
385 const char *en=entry->d_name; 394 const char *en = entry->d_name;
395
386 if (en[0] == '.') { 396 if (en[0] == '.') {
387 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */ 397 if (!en[1] || (en[1] == '.' && !en[2])) { /* . or .. */
388 if (!(opts & DISP_DOT)) 398 if (!(opts & DISP_DOT))
389 continue; 399 continue;
390 } 400 } else if (!(opts & DISP_HIDDEN))
391 else if (!(opts & DISP_HIDDEN))
392 continue; 401 continue;
393 } 402 }
394 /* FIXME: avoid stat if not required */ 403 /* FIXME: avoid stat if not required */
395 strcpy(fnend, entry->d_name); 404 strcpy(fnend, entry->d_name);
396 if (lstat(fullname, &info)) 405 if (lstat(fullname, &info))
397 goto direrr; /* (shouldn't fail) */ 406 goto direrr; /* (shouldn't fail) */
398 list_single(entry->d_name, &info, fullname); 407 list_single(entry->d_name, &info, fullname);
399 } 408 }
400 closedir(dir); 409 closedir(dir);
401 return 0; 410 return 0;
402 411
403direrr: 412 direrr:
404 closedir(dir); 413 closedir(dir);
405listerr: 414 listerr:
406 newline(); 415 newline();
407 perror(name); 416 perror(name);
408 return 1; 417 return 1;
@@ -432,50 +441,79 @@ static const char ls_usage[] = "ls [-1a"
432#endif 441#endif
433 "] [filenames...]\n"; 442 "] [filenames...]\n";
434 443
435extern int 444extern int ls_main(int argc, char **argv)
436ls_main(int argc, char * * argv)
437{ 445{
438 int argi=1, i; 446 int argi = 1, i;
439 447
440 /* process options */ 448 /* process options */
441 while (argi < argc && argv[argi][0] == '-') { 449 while (argi < argc && argv[argi][0] == '-') {
442 const char *p = &argv[argi][1]; 450 const char *p = &argv[argi][1];
443 451
444 if (!*p) goto print_usage_message; /* "-" by itself not allowed */ 452 if (!*p)
453 goto print_usage_message; /* "-" by itself not allowed */
445 if (*p == '-') { 454 if (*p == '-') {
446 if (!p[1]) { /* "--" forces end of options */ 455 if (!p[1]) { /* "--" forces end of options */
447 argi++; 456 argi++;
448 break; 457 break;
449 } 458 }
450 /* it's a long option name - we don't support them */ 459 /* it's a long option name - we don't support them */
451 goto print_usage_message; 460 goto print_usage_message;
452 } 461 }
453 462
454 while (*p) 463 while (*p)
455 switch (*p++) { 464 switch (*p++) {
456 case 'l': display_fmt = FMT_LONG; break; 465 case 'l':
457 case '1': display_fmt = FMT_SINGLE; break; 466 display_fmt = FMT_LONG;
458 case 'x': display_fmt = FMT_ROWS; break; 467 break;
459 case 'C': display_fmt = FMT_COLUMNS; break; 468 case '1':
469 display_fmt = FMT_SINGLE;
470 break;
471 case 'x':
472 display_fmt = FMT_ROWS;
473 break;
474 case 'C':
475 display_fmt = FMT_COLUMNS;
476 break;
460#ifdef BB_FEATURE_LS_FILETYPES 477#ifdef BB_FEATURE_LS_FILETYPES
461 case 'p': opts |= DISP_FTYPE; break; 478 case 'p':
462 case 'F': opts |= DISP_FTYPE|DISP_EXEC; break; 479 opts |= DISP_FTYPE;
480 break;
481 case 'F':
482 opts |= DISP_FTYPE | DISP_EXEC;
483 break;
463#endif 484#endif
464 case 'A': opts |= DISP_HIDDEN; break; 485 case 'A':
465 case 'a': opts |= DISP_HIDDEN|DISP_DOT; break; 486 opts |= DISP_HIDDEN;
466 case 'n': opts |= DISP_NUMERIC; break; 487 break;
467 case 'd': opts |= DIR_NOLIST; break; 488 case 'a':
489 opts |= DISP_HIDDEN | DISP_DOT;
490 break;
491 case 'n':
492 opts |= DISP_NUMERIC;
493 break;
494 case 'd':
495 opts |= DIR_NOLIST;
496 break;
468#ifdef FEATURE_RECURSIVE 497#ifdef FEATURE_RECURSIVE
469 case 'R': opts |= DIR_RECURSE; break; 498 case 'R':
499 opts |= DIR_RECURSE;
500 break;
470#endif 501#endif
471#ifdef BB_FEATURE_LS_TIMESTAMPS 502#ifdef BB_FEATURE_LS_TIMESTAMPS
472 case 'u': time_fmt = TIME_ACCESS; break; 503 case 'u':
473 case 'c': time_fmt = TIME_CHANGE; break; 504 time_fmt = TIME_ACCESS;
474 case 'e': opts |= DISP_FULLTIME; break; 505 break;
506 case 'c':
507 time_fmt = TIME_CHANGE;
508 break;
509 case 'e':
510 opts |= DISP_FULLTIME;
511 break;
475#endif 512#endif
476 default: goto print_usage_message; 513 default:
514 goto print_usage_message;
477 } 515 }
478 516
479 argi++; 517 argi++;
480 } 518 }
481 519
@@ -483,29 +521,30 @@ ls_main(int argc, char * * argv)
483 if (display_fmt == FMT_AUTO) 521 if (display_fmt == FMT_AUTO)
484 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE; 522 display_fmt = isatty(fileno(stdout)) ? FMT_COLUMNS : FMT_SINGLE;
485 if (argi < argc - 1) 523 if (argi < argc - 1)
486 opts |= DISP_DIRNAME; /* 2 or more items? label directories */ 524 opts |= DISP_DIRNAME; /* 2 or more items? label directories */
487#ifdef BB_FEATURE_AUTOWIDTH 525#ifdef BB_FEATURE_AUTOWIDTH
488 /* could add a -w option and/or TIOCGWINSZ call */ 526 /* could add a -w option and/or TIOCGWINSZ call */
489 if (terminal_width < 1) terminal_width = TERMINAL_WIDTH; 527 if (terminal_width < 1)
490 528 terminal_width = TERMINAL_WIDTH;
529
491 for (i = argi; i < argc; i++) { 530 for (i = argi; i < argc; i++) {
492 int len = strlen(argv[i]); 531 int len = strlen(argv[i]);
532
493 if (column_width < len) 533 if (column_width < len)
494 column_width = len; 534 column_width = len;
495 } 535 }
496#endif 536#endif
497 537
498 /* process files specified, or current directory if none */ 538 /* process files specified, or current directory if none */
499 i=0; 539 i = 0;
500 if (argi == argc) 540 if (argi == argc)
501 i = list_item("."); 541 i = list_item(".");
502 while (argi < argc) 542 while (argi < argc)
503 i |= list_item(argv[argi++]); 543 i |= list_item(argv[argi++]);
504 newline(); 544 newline();
505 exit( i); 545 exit(i);
506 546
507print_usage_message: 547 print_usage_message:
508 usage (ls_usage); 548 usage(ls_usage);
509 exit( FALSE); 549 exit(FALSE);
510} 550}
511
diff --git a/lsmod.c b/lsmod.c
index 1696f756e..d9c40eaaf 100644
--- a/lsmod.c
+++ b/lsmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini lsmod implementation for busybox 3 * Mini lsmod implementation for busybox
3 * 4 *
@@ -30,6 +31,7 @@
30 31
31extern int lsmod_main(int argc, char **argv) 32extern int lsmod_main(int argc, char **argv)
32{ 33{
33 char* cmd[] = { "cat", "/proc/modules", "\0" }; 34 char *cmd[] = { "cat", "/proc/modules", "\0" };
34 exit(cat_main( 3, cmd)); 35
36 exit(cat_main(3, cmd));
35} 37}
diff --git a/makedevs.c b/makedevs.c
index f7fbeb2fe..5948bacc8 100644
--- a/makedevs.c
+++ b/makedevs.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> 3 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
3 * 4 *
@@ -5,7 +6,7 @@
5 * Make ranges of device files quickly. 6 * Make ranges of device files quickly.
6 * known bugs: can't deal with alpha ranges 7 * known bugs: can't deal with alpha ranges
7 */ 8 */
8 9
9#include "internal.h" 10#include "internal.h"
10#include <stdio.h> 11#include <stdio.h>
11#include <stdlib.h> 12#include <stdlib.h>
@@ -15,60 +16,64 @@
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/stat.h> 17#include <sys/stat.h>
17 18
18static const char makedevs_usage[] = 19static const char makedevs_usage[] =
19"makedevs 0.01 -- Create an entire range of device files\n\n" 20 "makedevs 0.01 -- Create an entire range of device files\n\n"
20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" 21 "\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; 22
23 "\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
22 24
23int 25int makedevs_main(int argc, char **argv)
24makedevs_main(int argc, char * * argv)
25{ 26{
26 27
27const char *basedev = argv[1]; 28 const char *basedev = argv[1];
28const char *type = argv[2]; 29 const char *type = argv[2];
29int major = atoi(argv[3]); 30 int major = atoi(argv[3]);
30int Sminor = atoi(argv[4]); 31 int Sminor = atoi(argv[4]);
31int S = atoi(argv[5]); 32 int S = atoi(argv[5]);
32int E = atoi(argv[6]); 33 int E = atoi(argv[6]);
33int sbase = argc == 8 ? 1 : 0; 34 int sbase = argc == 8 ? 1 : 0;
34 35
35mode_t mode = 0; 36 mode_t mode = 0;
36dev_t dev = 0; 37 dev_t dev = 0;
37char devname[255]; 38 char devname[255];
38char buf[255]; 39 char buf[255];
39 40
40 switch (type[0]) { 41 switch (type[0]) {
41 case 'c': 42 case 'c':
42 mode = S_IFCHR; break; 43 mode = S_IFCHR;
43 case 'b': 44 break;
44 mode = S_IFBLK; break; 45 case 'b':
45 case 'f': 46 mode = S_IFBLK;
46 mode = S_IFIFO; break; 47 break;
47 default: 48 case 'f':
48 usage( makedevs_usage); 49 mode = S_IFIFO;
49 } 50 break;
50 mode |= 0660; 51 default:
51 52 usage(makedevs_usage);
52 while ( S <= E ) { 53 }
53 54 mode |= 0660;
55
56 while (S <= E) {
57
54 if (type[0] != 'f') 58 if (type[0] != 'f')
55 dev = (major << 8) | Sminor; 59 dev = (major << 8) | Sminor;
56 strcpy(devname, basedev); 60 strcpy(devname, basedev);
57 61
58 if (sbase == 0) { 62 if (sbase == 0) {
59 sprintf(buf, "%d", S); 63 sprintf(buf, "%d", S);
60 strcat(devname, buf); 64 strcat(devname, buf);
61 } else { 65 } else {
62 sbase = 0; 66 sbase = 0;
63 } 67 }
64 68
65 if (mknod (devname, mode, dev)) 69 if (mknod(devname, mode, dev))
66 printf("Failed to create: %s\n", devname); 70 printf("Failed to create: %s\n", devname);
67 71
68 S++; Sminor++; 72 S++;
73 Sminor++;
69 } 74 }
70 75
71return 0; 76 return 0;
72} 77}
73 78
74/* 79/*
diff --git a/math.c b/math.c
index 1f6d093b9..75b4cdeb5 100644
--- a/math.c
+++ b/math.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -8,126 +9,114 @@
8 9
9static const char math_usage[] = "math expression ..."; 10static const char math_usage[] = "math expression ...";
10 11
11static double stack[100]; 12static double stack[100];
12static unsigned int pointer; 13static unsigned int pointer;
13 14
14static void 15static void push(double a)
15push(double a)
16{ 16{
17 if ( pointer >= (sizeof(stack) / sizeof(*stack)) ) { 17 if (pointer >= (sizeof(stack) / sizeof(*stack))) {
18 fprintf(stderr, "math: stack overflow\n"); 18 fprintf(stderr, "math: stack overflow\n");
19 exit(-1); 19 exit(-1);
20 } 20 } else
21 else
22 stack[pointer++] = a; 21 stack[pointer++] = a;
23} 22}
24 23
25static double 24static double pop()
26pop()
27{ 25{
28 if ( pointer == 0 ) { 26 if (pointer == 0) {
29 fprintf(stderr, "math: stack underflow\n"); 27 fprintf(stderr, "math: stack underflow\n");
30 exit(-1); 28 exit(-1);
31 } 29 }
32 return stack[--pointer]; 30 return stack[--pointer];
33} 31}
34 32
35static void 33static void add()
36add()
37{ 34{
38 push(pop() + pop()); 35 push(pop() + pop());
39} 36}
40 37
41static void 38static void sub()
42sub()
43{ 39{
44 double subtrahend = pop(); 40 double subtrahend = pop();
45 41
46 push(pop() - subtrahend); 42 push(pop() - subtrahend);
47} 43}
48 44
49static void 45static void mul()
50mul()
51{ 46{
52 push(pop() * pop()); 47 push(pop() * pop());
53} 48}
54 49
55static void 50static void divide()
56divide()
57{ 51{
58 double divisor = pop(); 52 double divisor = pop();
53
59 push(pop() / divisor); 54 push(pop() / divisor);
60} 55}
61 56
62static void 57static void and()
63and()
64{ 58{
65 push((unsigned int)pop() & (unsigned int)pop()); 59 push((unsigned int) pop() & (unsigned int) pop());
66} 60}
67 61
68static void 62static void or()
69or()
70{ 63{
71 push((unsigned int)pop() | (unsigned int)pop()); 64 push((unsigned int) pop() | (unsigned int) pop());
72} 65}
73 66
74static void 67static void eor()
75eor()
76{ 68{
77 push((unsigned int)pop() ^ (unsigned int)pop()); 69 push((unsigned int) pop() ^ (unsigned int) pop());
78} 70}
79 71
80static void 72static void not()
81not()
82{ 73{
83 push(~(unsigned int)pop()); 74 push(~(unsigned int) pop());
84} 75}
85 76
86static void 77static void print()
87print()
88{ 78{
89 printf("%g\n", pop()); 79 printf("%g\n", pop());
90} 80}
91 81
92struct op { 82struct op {
93 const char * name; 83 const char *name;
94 void (*function)(); 84 void (*function) ();
95}; 85};
96 86
97static const struct op operators[] = { 87static const struct op operators[] = {
98 { "add", add }, 88 {"add", add},
99 { "and", and }, 89 {"and", and},
100 { "div", divide }, 90 {"div", divide},
101 { "eor", eor }, 91 {"eor", eor},
102 { "mul", mul }, 92 {"mul", mul},
103 { "not", not }, 93 {"not", not},
104 { "or", or }, 94 {"or", or},
105 { "sub", sub }, 95 {"sub", sub},
106 { 0, 0 } 96 {0, 0}
107}; 97};
108 98
109static void 99static void stack_machine(const char *argument)
110stack_machine(const char * argument)
111{ 100{
112 char * endPointer = 0; 101 char *endPointer = 0;
113 double d; 102 double d;
114 const struct op * o = operators; 103 const struct op *o = operators;
115 104
116 if ( argument == 0 ) { 105 if (argument == 0) {
117 print(); 106 print();
118 return; 107 return;
119 } 108 }
120 109
121 d = strtod(argument, &endPointer); 110 d = strtod(argument, &endPointer);
122 111
123 if ( endPointer != argument ) { 112 if (endPointer != argument) {
124 push(d); 113 push(d);
125 return; 114 return;
126 } 115 }
127 116
128 while ( o->name != 0 ) { 117 while (o->name != 0) {
129 if ( strcmp(o->name, argument) == 0 ) { 118 if (strcmp(o->name, argument) == 0) {
130 (*(o->function))(); 119 (*(o->function)) ();
131 return; 120 return;
132 } 121 }
133 o++; 122 o++;
@@ -136,10 +125,9 @@ stack_machine(const char * argument)
136 exit(-1); 125 exit(-1);
137} 126}
138 127
139int 128int math_main(int argc, char **argv)
140math_main(int argc, char * * argv)
141{ 129{
142 while ( argc >= 2 ) { 130 while (argc >= 2) {
143 stack_machine(argv[1]); 131 stack_machine(argv[1]);
144 argv++; 132 argv++;
145 argc--; 133 argc--;
diff --git a/messages.c b/messages.c
index bfbf3175b..265c5ade8 100644
--- a/messages.c
+++ b/messages.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Copyright (C) 2000 by BitterSweet Enterprises, LLC. 3 * Copyright (C) 2000 by BitterSweet Enterprises, LLC.
3 * Written by Karl M. Hegbloom <karlheg@debian.org> 4 * Written by Karl M. Hegbloom <karlheg@debian.org>
@@ -40,25 +41,19 @@
40#if defined bb_need_name_too_long || ! defined BB_DECLARE_EXTERN 41#if defined bb_need_name_too_long || ! defined BB_DECLARE_EXTERN
41BB_DEF_MESSAGE(name_too_long, "%s: file name too long\n") 42BB_DEF_MESSAGE(name_too_long, "%s: file name too long\n")
42#endif 43#endif
43
44#if defined bb_need_omitting_directory || ! defined BB_DECLARE_EXTERN 44#if defined bb_need_omitting_directory || ! defined BB_DECLARE_EXTERN
45BB_DEF_MESSAGE(omitting_directory, "%s: %s: omitting directory\n") 45 BB_DEF_MESSAGE(omitting_directory, "%s: %s: omitting directory\n")
46#endif 46#endif
47
48#if defined bb_need_not_a_directory || ! defined BB_DECLARE_EXTERN 47#if defined bb_need_not_a_directory || ! defined BB_DECLARE_EXTERN
49BB_DEF_MESSAGE(not_a_directory, "%s: %s: not a directory\n") 48 BB_DEF_MESSAGE(not_a_directory, "%s: %s: not a directory\n")
50#endif 49#endif
51
52#if defined bb_need_memory_exhausted || ! defined BB_DECLARE_EXTERN 50#if defined bb_need_memory_exhausted || ! defined BB_DECLARE_EXTERN
53BB_DEF_MESSAGE(memory_exhausted, "%s: memory exhausted\n") 51 BB_DEF_MESSAGE(memory_exhausted, "%s: memory exhausted\n")
54#endif 52#endif
55
56#if defined bb_need_invalid_date || ! defined BB_DECLARE_EXTERN 53#if defined bb_need_invalid_date || ! defined BB_DECLARE_EXTERN
57BB_DEF_MESSAGE(invalid_date, "%s: invalid date `%s'\n") 54 BB_DEF_MESSAGE(invalid_date, "%s: invalid date `%s'\n")
58#endif 55#endif
59
60#if defined bb_need_invalid_option || ! defined BB_DECLARE_EXTERN 56#if defined bb_need_invalid_option || ! defined BB_DECLARE_EXTERN
61BB_DEF_MESSAGE(invalid_option, "%s: invalid option -- %c\n") 57 BB_DEF_MESSAGE(invalid_option, "%s: invalid option -- %c\n")
62#endif 58#endif
63 59#endif /* _BB_MESSAGES_C */
64#endif /* _BB_MESSAGES_C */
diff --git a/miscutils/dutmp.c b/miscutils/dutmp.c
index a9e879daf..45eab8ae7 100644
--- a/miscutils/dutmp.c
+++ b/miscutils/dutmp.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> 3 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
3 * 4 *
@@ -15,37 +16,38 @@
15#include <utmp.h> 16#include <utmp.h>
16 17
17static const char dutmp_usage[] = "dutmp\n" 18static const char dutmp_usage[] = "dutmp\n"
18 "\n" 19 "\n"
19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20 "\tdutmp /var/run/utmp\n";
21 20
22extern int dutmp_main (int argc, char **argv) 21 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
22 "\tdutmp /var/run/utmp\n";
23
24extern int dutmp_main(int argc, char **argv)
23{ 25{
24 26
25 FILE *f = stdin; 27 FILE *f = stdin;
26 struct utmp ut; 28 struct utmp ut;
27 29
28 if ((argc < 2) || (**(argv + 1) == '-')) { 30 if ((argc < 2) || (**(argv + 1) == '-')) {
29 usage( dutmp_usage); 31 usage(dutmp_usage);
30 } 32 }
31 33
32 if ( **(++argv) == 0 ) { 34 if (**(++argv) == 0) {
33 f = fopen (*(++argv), "r"); 35 f = fopen(*(++argv), "r");
34 if (f < 0 ) { 36 if (f < 0) {
35 perror (*argv); 37 perror(*argv);
36 exit (FALSE); 38 exit(FALSE);
37 } 39 }
38 } 40 }
39 41
40 while (fread (&ut, 1, sizeof (struct utmp), f)) { 42 while (fread(&ut, 1, sizeof(struct utmp), f)) {
41 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n", 43 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
42 printf ("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n", 44 printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
43 ut.ut_type, ut.ut_pid, ut.ut_line, 45 ut.ut_type, ut.ut_pid, ut.ut_line,
44 ut.ut_id, ut.ut_user, ut.ut_host, 46 ut.ut_id, ut.ut_user, ut.ut_host,
45 ut.ut_exit.e_termination, ut.ut_exit.e_exit, 47 ut.ut_exit.e_termination, ut.ut_exit.e_exit,
46 ut.ut_session, 48 ut.ut_session,
47 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr); 49 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr);
48 } 50 }
49 51
50 exit (TRUE); 52 exit(TRUE);
51} 53}
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c
index f7fbeb2fe..5948bacc8 100644
--- a/miscutils/makedevs.c
+++ b/miscutils/makedevs.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> 3 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
3 * 4 *
@@ -5,7 +6,7 @@
5 * Make ranges of device files quickly. 6 * Make ranges of device files quickly.
6 * known bugs: can't deal with alpha ranges 7 * known bugs: can't deal with alpha ranges
7 */ 8 */
8 9
9#include "internal.h" 10#include "internal.h"
10#include <stdio.h> 11#include <stdio.h>
11#include <stdlib.h> 12#include <stdlib.h>
@@ -15,60 +16,64 @@
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/stat.h> 17#include <sys/stat.h>
17 18
18static const char makedevs_usage[] = 19static const char makedevs_usage[] =
19"makedevs 0.01 -- Create an entire range of device files\n\n" 20 "makedevs 0.01 -- Create an entire range of device files\n\n"
20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" 21 "\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; 22
23 "\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
22 24
23int 25int makedevs_main(int argc, char **argv)
24makedevs_main(int argc, char * * argv)
25{ 26{
26 27
27const char *basedev = argv[1]; 28 const char *basedev = argv[1];
28const char *type = argv[2]; 29 const char *type = argv[2];
29int major = atoi(argv[3]); 30 int major = atoi(argv[3]);
30int Sminor = atoi(argv[4]); 31 int Sminor = atoi(argv[4]);
31int S = atoi(argv[5]); 32 int S = atoi(argv[5]);
32int E = atoi(argv[6]); 33 int E = atoi(argv[6]);
33int sbase = argc == 8 ? 1 : 0; 34 int sbase = argc == 8 ? 1 : 0;
34 35
35mode_t mode = 0; 36 mode_t mode = 0;
36dev_t dev = 0; 37 dev_t dev = 0;
37char devname[255]; 38 char devname[255];
38char buf[255]; 39 char buf[255];
39 40
40 switch (type[0]) { 41 switch (type[0]) {
41 case 'c': 42 case 'c':
42 mode = S_IFCHR; break; 43 mode = S_IFCHR;
43 case 'b': 44 break;
44 mode = S_IFBLK; break; 45 case 'b':
45 case 'f': 46 mode = S_IFBLK;
46 mode = S_IFIFO; break; 47 break;
47 default: 48 case 'f':
48 usage( makedevs_usage); 49 mode = S_IFIFO;
49 } 50 break;
50 mode |= 0660; 51 default:
51 52 usage(makedevs_usage);
52 while ( S <= E ) { 53 }
53 54 mode |= 0660;
55
56 while (S <= E) {
57
54 if (type[0] != 'f') 58 if (type[0] != 'f')
55 dev = (major << 8) | Sminor; 59 dev = (major << 8) | Sminor;
56 strcpy(devname, basedev); 60 strcpy(devname, basedev);
57 61
58 if (sbase == 0) { 62 if (sbase == 0) {
59 sprintf(buf, "%d", S); 63 sprintf(buf, "%d", S);
60 strcat(devname, buf); 64 strcat(devname, buf);
61 } else { 65 } else {
62 sbase = 0; 66 sbase = 0;
63 } 67 }
64 68
65 if (mknod (devname, mode, dev)) 69 if (mknod(devname, mode, dev))
66 printf("Failed to create: %s\n", devname); 70 printf("Failed to create: %s\n", devname);
67 71
68 S++; Sminor++; 72 S++;
73 Sminor++;
69 } 74 }
70 75
71return 0; 76 return 0;
72} 77}
73 78
74/* 79/*
diff --git a/miscutils/mt.c b/miscutils/mt.c
index 7168ef7ac..9791b64b2 100644
--- a/miscutils/mt.c
+++ b/miscutils/mt.c
@@ -1,97 +1,97 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <sys/mtio.h> 4#include <sys/mtio.h>
4#include <sys/fcntl.h> 5#include <sys/fcntl.h>
5 6
6static const char mt_usage[] = "mt [-f device] opcode value\n"; 7static const char mt_usage[] = "mt [-f device] opcode value\n";
7 8
8struct mt_opcodes { 9struct mt_opcodes {
9 char * name; 10 char *name;
10 short value; 11 short value;
11}; 12};
12 13
13/* missing: eod/seod, stoptions, stwrthreshold, densities */ 14/* missing: eod/seod, stoptions, stwrthreshold, densities */
14static const struct mt_opcodes opcodes[] = { 15static const struct mt_opcodes opcodes[] = {
15 { "bsf", MTBSF }, 16 {"bsf", MTBSF},
16 { "bsfm", MTBSFM }, 17 {"bsfm", MTBSFM},
17 { "bsr", MTBSR }, 18 {"bsr", MTBSR},
18 { "bss", MTBSS }, 19 {"bss", MTBSS},
19 { "datacompression", MTCOMPRESSION }, 20 {"datacompression", MTCOMPRESSION},
20 { "eom", MTEOM }, 21 {"eom", MTEOM},
21 { "erase", MTERASE }, 22 {"erase", MTERASE},
22 { "fsf", MTFSF }, 23 {"fsf", MTFSF},
23 { "fsfm", MTFSFM }, 24 {"fsfm", MTFSFM},
24 { "fsr", MTFSR }, 25 {"fsr", MTFSR},
25 { "fss", MTFSS }, 26 {"fss", MTFSS},
26 { "load", MTLOAD }, 27 {"load", MTLOAD},
27 { "lock", MTLOCK }, 28 {"lock", MTLOCK},
28 { "mkpart", MTMKPART }, 29 {"mkpart", MTMKPART},
29 { "nop", MTNOP }, 30 {"nop", MTNOP},
30 { "offline",MTOFFL }, 31 {"offline", MTOFFL},
31 { "rewoffline",MTOFFL }, 32 {"rewoffline", MTOFFL},
32 { "ras1", MTRAS1 }, 33 {"ras1", MTRAS1},
33 { "ras2", MTRAS2 }, 34 {"ras2", MTRAS2},
34 { "ras3", MTRAS3 }, 35 {"ras3", MTRAS3},
35 { "reset", MTRESET }, 36 {"reset", MTRESET},
36 { "retension", MTRETEN }, 37 {"retension", MTRETEN},
37 { "rew", MTREW }, 38 {"rew", MTREW},
38 { "seek", MTSEEK }, 39 {"seek", MTSEEK},
39 { "setblk", MTSETBLK }, 40 {"setblk", MTSETBLK},
40 { "setdensity", MTSETDENSITY }, 41 {"setdensity", MTSETDENSITY},
41 { "drvbuffer", MTSETDRVBUFFER }, 42 {"drvbuffer", MTSETDRVBUFFER},
42 { "setpart", MTSETPART }, 43 {"setpart", MTSETPART},
43 { "tell", MTTELL }, 44 {"tell", MTTELL},
44 { "wset", MTWSM }, 45 {"wset", MTWSM},
45 { "unload", MTUNLOAD }, 46 {"unload", MTUNLOAD},
46 { "unlock", MTUNLOCK }, 47 {"unlock", MTUNLOCK},
47 { "eof", MTWEOF }, 48 {"eof", MTWEOF},
48 { "weof", MTWEOF }, 49 {"weof", MTWEOF},
49 { 0, 0 } 50 {0, 0}
50}; 51};
51 52
52extern int 53extern int mt_main(int argc, char **argv)
53mt_main(int argc, char** argv)
54{ 54{
55 const char * file = "/dev/tape"; 55 const char *file = "/dev/tape";
56 const struct mt_opcodes * code = opcodes; 56 const struct mt_opcodes *code = opcodes;
57 struct mtop op; 57 struct mtop op;
58 int fd; 58 int fd;
59 59
60 if ( strcmp(argv[1], "-f") == 0 ) { 60 if (strcmp(argv[1], "-f") == 0) {
61 if ( argc < 4 ) { 61 if (argc < 4) {
62 usage (mt_usage); 62 usage(mt_usage);
63 } 63 }
64 file = argv[2]; 64 file = argv[2];
65 argv += 2; 65 argv += 2;
66 argc -= 2; 66 argc -= 2;
67 } 67 }
68 68
69 while ( code->name != 0 ) { 69 while (code->name != 0) {
70 if ( strcmp(code->name, argv[1]) == 0 ) 70 if (strcmp(code->name, argv[1]) == 0)
71 break; 71 break;
72 code++; 72 code++;
73 } 73 }
74 74
75 if ( code->name == 0 ) { 75 if (code->name == 0) {
76 fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]); 76 fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
77 return( FALSE); 77 return (FALSE);
78 } 78 }
79 79
80 op.mt_op = code->value; 80 op.mt_op = code->value;
81 if ( argc >= 3 ) 81 if (argc >= 3)
82 op.mt_count = atoi(argv[2]); 82 op.mt_count = atoi(argv[2]);
83 else 83 else
84 op.mt_count = 1; /* One, not zero, right? */ 84 op.mt_count = 1; /* One, not zero, right? */
85 85
86 if ( (fd = open(file, O_RDONLY, 0)) < 0 ) { 86 if ((fd = open(file, O_RDONLY, 0)) < 0) {
87 perror(file); 87 perror(file);
88 return( FALSE); 88 return (FALSE);
89 } 89 }
90 90
91 if ( ioctl(fd, MTIOCTOP, &op) != 0 ) { 91 if (ioctl(fd, MTIOCTOP, &op) != 0) {
92 perror(file); 92 perror(file);
93 return( FALSE); 93 return (FALSE);
94 } 94 }
95 95
96 return( TRUE); 96 return (TRUE);
97} 97}
diff --git a/miscutils/update.c b/miscutils/update.c
index 5a7c755ff..fef188bba 100644
--- a/miscutils/update.c
+++ b/miscutils/update.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini update implementation for busybox 3 * Mini update implementation for busybox
3 * 4 *
@@ -27,20 +28,19 @@
27#include <sys/kdaemon.h> 28#include <sys/kdaemon.h>
28#else 29#else
29_syscall2(int, bdflush, int, func, int, data); 30_syscall2(int, bdflush, int, func, int, data);
30#endif /* __GLIBC__ */ 31#endif /* __GLIBC__ */
31 32
32extern int 33extern int update_main(int argc, char **argv)
33update_main(int argc, char** argv)
34{ 34{
35 /* 35 /*
36 * Update is actually two daemons, bdflush and update. 36 * Update is actually two daemons, bdflush and update.
37 */ 37 */
38 int pid; 38 int pid;
39 39
40 pid = fork(); 40 pid = fork();
41 if ( pid < 0 ) 41 if (pid < 0)
42 return pid; 42 return pid;
43 else if ( pid == 0 ) { 43 else if (pid == 0) {
44 /* 44 /*
45 * This is no longer necessary since 1.3.5x, but it will harmlessly 45 * This is no longer necessary since 1.3.5x, but it will harmlessly
46 * exit if that is the case. 46 * exit if that is the case.
@@ -52,11 +52,11 @@ update_main(int argc, char** argv)
52 _exit(0); 52 _exit(0);
53 } 53 }
54 pid = fork(); 54 pid = fork();
55 if ( pid < 0 ) 55 if (pid < 0)
56 return pid; 56 return pid;
57 else if ( pid == 0 ) { 57 else if (pid == 0) {
58 argv[0] = "update"; 58 argv[0] = "update";
59 for ( ; ; ) { 59 for (;;) {
60 sync(); 60 sync();
61 sleep(30); 61 sleep(30);
62 } 62 }
diff --git a/mkdir.c b/mkdir.c
index 8e3f51bfb..70fdbdfb5 100644
--- a/mkdir.c
+++ b/mkdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkdir implementation for busybox 3 * Mini mkdir implementation for busybox
3 * 4 *
@@ -28,14 +29,15 @@
28 29
29#include <stdio.h> 30#include <stdio.h>
30#include <errno.h> 31#include <errno.h>
31#include <sys/param.h> /* for PATH_MAX */ 32#include <sys/param.h> /* for PATH_MAX */
32 33
33static const char mkdir_usage[] = 34static const char mkdir_usage[] =
34"mkdir [OPTION] DIRECTORY...\n\n" 35 "mkdir [OPTION] DIRECTORY...\n\n"
35"Create the DIRECTORY(ies), if they do not already exist\n\n" 36 "Create the DIRECTORY(ies), if they do not already exist\n\n"
36"Options:\n" 37 "Options:\n"
37"\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" 38
38"\t-p\tno error if existing, make parent directories as needed\n"; 39 "\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n"
40 "\t-p\tno error if existing, make parent directories as needed\n";
39 41
40 42
41static int parentFlag = FALSE; 43static int parentFlag = FALSE;
@@ -44,71 +46,70 @@ static mode_t mode = 0777;
44 46
45extern int mkdir_main(int argc, char **argv) 47extern int mkdir_main(int argc, char **argv)
46{ 48{
47 int i = FALSE; 49 int i = FALSE;
48 argc--;
49 argv++;
50 50
51 /* Parse any options */
52 while (argc > 0 && **argv == '-') {
53 while (i == FALSE && *++(*argv)) {
54 switch (**argv) {
55 case 'm':
56 if (--argc == 0)
57 usage( mkdir_usage);
58 /* Find the specified modes */
59 mode = 0;
60 if (parse_mode(*(++argv), &mode) == FALSE ) {
61 fprintf(stderr, "Unknown mode: %s\n", *argv);
62 exit FALSE;
63 }
64 /* Set the umask for this process so it doesn't
65 * screw up whatever the user just entered. */
66 umask(0);
67 i = TRUE;
68 break;
69 case 'p':
70 parentFlag = TRUE;
71 break;
72 default:
73 usage( mkdir_usage);
74 }
75 }
76 argc--; 51 argc--;
77 argv++; 52 argv++;
78 }
79
80 if (argc < 1) {
81 usage( mkdir_usage);
82 }
83 53
84 while (argc > 0) { 54 /* Parse any options */
85 int status; 55 while (argc > 0 && **argv == '-') {
86 struct stat statBuf; 56 while (i == FALSE && *++(*argv)) {
87 char buf[PATH_MAX + 1]; 57 switch (**argv) {
88 if (strlen(*argv) > PATH_MAX - 1) { 58 case 'm':
89 fprintf(stderr, name_too_long, "mkdir"); 59 if (--argc == 0)
90 exit FALSE; 60 usage(mkdir_usage);
91 } 61 /* Find the specified modes */
92 strcpy (buf, *argv); 62 mode = 0;
93 status = stat(buf, &statBuf); 63 if (parse_mode(*(++argv), &mode) == FALSE) {
94 if (parentFlag == FALSE && status != -1 && errno != ENOENT) { 64 fprintf(stderr, "Unknown mode: %s\n", *argv);
95 fprintf(stderr, "%s: File exists\n", buf); 65 exit FALSE;
96 exit FALSE; 66 }
97 } 67 /* Set the umask for this process so it doesn't
98 if (parentFlag == TRUE) { 68 * screw up whatever the user just entered. */
99 strcat( buf, "/"); 69 umask(0);
100 createPath(buf, mode); 70 i = TRUE;
71 break;
72 case 'p':
73 parentFlag = TRUE;
74 break;
75 default:
76 usage(mkdir_usage);
77 }
78 }
79 argc--;
80 argv++;
101 } 81 }
102 else { 82
103 if (mkdir (buf, mode) != 0 && parentFlag == FALSE) { 83 if (argc < 1) {
104 perror(buf); 84 usage(mkdir_usage);
105 exit FALSE;
106 }
107 } 85 }
108 argc--;
109 argv++;
110 }
111 exit TRUE;
112}
113 86
87 while (argc > 0) {
88 int status;
89 struct stat statBuf;
90 char buf[PATH_MAX + 1];
114 91
92 if (strlen(*argv) > PATH_MAX - 1) {
93 fprintf(stderr, name_too_long, "mkdir");
94 exit FALSE;
95 }
96 strcpy(buf, *argv);
97 status = stat(buf, &statBuf);
98 if (parentFlag == FALSE && status != -1 && errno != ENOENT) {
99 fprintf(stderr, "%s: File exists\n", buf);
100 exit FALSE;
101 }
102 if (parentFlag == TRUE) {
103 strcat(buf, "/");
104 createPath(buf, mode);
105 } else {
106 if (mkdir(buf, mode) != 0 && parentFlag == FALSE) {
107 perror(buf);
108 exit FALSE;
109 }
110 }
111 argc--;
112 argv++;
113 }
114 exit TRUE;
115}
diff --git a/mkfifo.c b/mkfifo.c
index 676592ac7..c74402d4c 100644
--- a/mkfifo.c
+++ b/mkfifo.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mkfifo implementation for busybox 3 * Mini mkfifo implementation for busybox
3 * 4 *
@@ -26,36 +27,43 @@
26#include <errno.h> 27#include <errno.h>
27 28
28static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n" 29static const char mkfifo_usage[] = "mkfifo [OPTIONS] name\n\n"
29"Create the named fifo\n\n" 30 "Create the named fifo\n\n"
30"Options:\n" 31
31"\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n"; 32 "Options:\n"
33 "\t-m\tcreate the fifo with the specified mode; default = a=rw-umask\n";
32 34
33extern int mkfifo_main(int argc, char **argv) 35extern int mkfifo_main(int argc, char **argv)
34{ 36{
35 char *thisarg; 37 char *thisarg;
36 mode_t mode = 0666; 38 mode_t mode = 0666;
37 argc--; 39
38 argv++; 40 argc--;
41 argv++;
39 42
40 /* Parse any options */ 43 /* Parse any options */
41 while (argc > 1) { 44 while (argc > 1) {
42 if (**argv != '-') usage(mkfifo_usage); 45 if (**argv != '-')
43 thisarg = *argv; thisarg++; 46 usage(mkfifo_usage);
44 switch (*thisarg) { 47 thisarg = *argv;
45 case 'm': 48 thisarg++;
46 argc--; argv++; 49 switch (*thisarg) {
47 parse_mode(*argv, &mode); 50 case 'm':
48 break; 51 argc--;
49 default: 52 argv++;
50 usage (mkfifo_usage); 53 parse_mode(*argv, &mode);
51 } 54 break;
52 argc--; argv++; 55 default:
53 } 56 usage(mkfifo_usage);
54 if (argc < 1) usage (mkfifo_usage); 57 }
55 if (mkfifo(*argv, mode) < 0) { 58 argc--;
56 perror("mkfifo"); 59 argv++;
57 exit(255); 60 }
58 } else { 61 if (argc < 1)
59 exit(TRUE); 62 usage(mkfifo_usage);
60 } 63 if (mkfifo(*argv, mode) < 0) {
64 perror("mkfifo");
65 exit(255);
66 } else {
67 exit(TRUE);
68 }
61} 69}
diff --git a/mkfs_minix.c b/mkfs_minix.c
index b90d3a700..4435cb64a 100644
--- a/mkfs_minix.c
+++ b/mkfs_minix.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * mkfs.c - make a linux (minix) file-system. 3 * mkfs.c - make a linux (minix) file-system.
3 * 4 *
@@ -107,27 +108,30 @@
107 108
108#define BITS_PER_BLOCK (BLOCK_SIZE<<3) 109#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
109 110
110static char * program_name = "mkfs"; 111static char *program_name = "mkfs";
111static char * device_name = NULL; 112static char *device_name = NULL;
112static int DEV = -1; 113static int DEV = -1;
113static long BLOCKS = 0; 114static long BLOCKS = 0;
114static int check = 0; 115static int check = 0;
115static int badblocks = 0; 116static int badblocks = 0;
116static int namelen = 30; /* default (changed to 30, per Linus's 117static int namelen = 30; /* default (changed to 30, per Linus's
117 suggestion, Sun Nov 21 08:05:07 1993) */ 118
119 suggestion, Sun Nov 21 08:05:07 1993) */
118static int dirsize = 32; 120static int dirsize = 32;
119static int magic = MINIX_SUPER_MAGIC2; 121static int magic = MINIX_SUPER_MAGIC2;
120static int version2 = 0; 122static int version2 = 0;
121 123
122static char root_block[BLOCK_SIZE] = "\0"; 124static char root_block[BLOCK_SIZE] = "\0";
123 125
124static char * inode_buffer = NULL; 126static char *inode_buffer = NULL;
127
125#define Inode (((struct minix_inode *) inode_buffer)-1) 128#define Inode (((struct minix_inode *) inode_buffer)-1)
126#ifdef HAVE_MINIX2 129#ifdef HAVE_MINIX2
127#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 130#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
128#endif 131#endif
129static char super_block_buffer[BLOCK_SIZE]; 132static char super_block_buffer[BLOCK_SIZE];
130static char boot_block_buffer[512]; 133static char boot_block_buffer[512];
134
131#define Super (*(struct minix_super_block *)super_block_buffer) 135#define Super (*(struct minix_super_block *)super_block_buffer)
132#define INODES ((unsigned long)Super.s_ninodes) 136#define INODES ((unsigned long)Super.s_ninodes)
133#ifdef HAVE_MINIX2 137#ifdef HAVE_MINIX2
@@ -164,21 +168,28 @@ static unsigned long req_nr_inodes = 0;
164 * to compile this under minix, volatile gives a warning, as 168 * to compile this under minix, volatile gives a warning, as
165 * exit() isn't defined as volatile under minix. 169 * exit() isn't defined as volatile under minix.
166 */ 170 */
167static volatile void die(char *str) { 171static volatile void die(char *str)
172{
168 fprintf(stderr, "%s: %s\n", program_name, str); 173 fprintf(stderr, "%s: %s\n", program_name, str);
169 exit(8); 174 exit(8);
170} 175}
171 176
172static volatile void show_usage() 177static volatile void show_usage()
173{ 178{
174 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 179 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
175 fprintf(stderr, "Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n\n", program_name); 180 BB_VER, BB_BT);
181 fprintf(stderr,
182 "Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n\n",
183 program_name);
176 fprintf(stderr, "Make a MINIX filesystem.\n\n"); 184 fprintf(stderr, "Make a MINIX filesystem.\n\n");
177 fprintf(stderr, "OPTIONS:\n"); 185 fprintf(stderr, "OPTIONS:\n");
178 fprintf(stderr, "\t-c\t\tCheck the device for bad blocks\n"); 186 fprintf(stderr, "\t-c\t\tCheck the device for bad blocks\n");
179 fprintf(stderr, "\t-n [14|30]\tSpecify the maximum length of filenames\n"); 187 fprintf(stderr,
180 fprintf(stderr, "\t-i\t\tSpecify the number of inodes for the filesystem\n"); 188 "\t-n [14|30]\tSpecify the maximum length of filenames\n");
181 fprintf(stderr, "\t-l FILENAME\tRead the bad blocks list from FILENAME\n"); 189 fprintf(stderr,
190 "\t-i\t\tSpecify the number of inodes for the filesystem\n");
191 fprintf(stderr,
192 "\t-l FILENAME\tRead the bad blocks list from FILENAME\n");
182 fprintf(stderr, "\t-v\t\tMake a Minix version 2 filesystem\n\n"); 193 fprintf(stderr, "\t-v\t\tMake a Minix version 2 filesystem\n\n");
183 exit(16); 194 exit(16);
184} 195}
@@ -190,56 +201,55 @@ static volatile void show_usage()
190 */ 201 */
191static void check_mount(void) 202static void check_mount(void)
192{ 203{
193 FILE * f; 204 FILE *f;
194 struct mntent * mnt; 205 struct mntent *mnt;
195 206
196 if ((f = setmntent (MOUNTED, "r")) == NULL) 207 if ((f = setmntent(MOUNTED, "r")) == NULL)
197 return; 208 return;
198 while ((mnt = getmntent (f)) != NULL) 209 while ((mnt = getmntent(f)) != NULL)
199 if (strcmp (device_name, mnt->mnt_fsname) == 0) 210 if (strcmp(device_name, mnt->mnt_fsname) == 0)
200 break; 211 break;
201 endmntent (f); 212 endmntent(f);
202 if (!mnt) 213 if (!mnt)
203 return; 214 return;
204 215
205 die("%s is mounted; will not make a filesystem here!"); 216 die("%s is mounted; will not make a filesystem here!");
206} 217}
207 218
208static long valid_offset (int fd, int offset) 219static long valid_offset(int fd, int offset)
209{ 220{
210 char ch; 221 char ch;
211 222
212 if (lseek (fd, offset, 0) < 0) 223 if (lseek(fd, offset, 0) < 0)
213 return 0; 224 return 0;
214 if (read (fd, &ch, 1) < 1) 225 if (read(fd, &ch, 1) < 1)
215 return 0; 226 return 0;
216 return 1; 227 return 1;
217} 228}
218 229
219static int count_blocks (int fd) 230static int count_blocks(int fd)
220{ 231{
221 int high, low; 232 int high, low;
222 233
223 low = 0; 234 low = 0;
224 for (high = 1; valid_offset (fd, high); high *= 2) 235 for (high = 1; valid_offset(fd, high); high *= 2)
225 low = high; 236 low = high;
226 while (low < high - 1) 237 while (low < high - 1) {
227 {
228 const int mid = (low + high) / 2; 238 const int mid = (low + high) / 2;
229 239
230 if (valid_offset (fd, mid)) 240 if (valid_offset(fd, mid))
231 low = mid; 241 low = mid;
232 else 242 else
233 high = mid; 243 high = mid;
234 } 244 }
235 valid_offset (fd, 0); 245 valid_offset(fd, 0);
236 return (low + 1); 246 return (low + 1);
237} 247}
238 248
239static int get_size(const char *file) 249static int get_size(const char *file)
240{ 250{
241 int fd; 251 int fd;
242 long size; 252 long size;
243 253
244 fd = open(file, O_RDWR); 254 fd = open(file, O_RDWR);
245 if (fd < 0) { 255 if (fd < 0) {
@@ -250,7 +260,7 @@ static int get_size(const char *file)
250 close(fd); 260 close(fd);
251 return (size * 512); 261 return (size * 512);
252 } 262 }
253 263
254 size = count_blocks(fd); 264 size = count_blocks(fd);
255 close(fd); 265 close(fd);
256 return size; 266 return size;
@@ -270,18 +280,18 @@ static void write_tables(void)
270 die("seek failed in write_tables"); 280 die("seek failed in write_tables");
271 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) 281 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
272 die("unable to write super-block"); 282 die("unable to write super-block");
273 if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE)) 283 if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE))
274 die("unable to write inode map"); 284 die("unable to write inode map");
275 if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE)) 285 if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE))
276 die("unable to write zone map"); 286 die("unable to write zone map");
277 if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE)) 287 if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE))
278 die("unable to write inodes"); 288 die("unable to write inodes");
279 289
280} 290}
281 291
282static void write_block(int blk, char * buffer) 292static void write_block(int blk, char *buffer)
283{ 293{
284 if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET)) 294 if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET))
285 die("seek failed in write_block"); 295 die("seek failed in write_block");
286 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) 296 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
287 die("write failed in write_block"); 297 die("write failed in write_block");
@@ -291,10 +301,10 @@ static int get_free_block(void)
291{ 301{
292 int blk; 302 int blk;
293 303
294 if (used_good_blocks+1 >= MAX_GOOD_BLOCKS) 304 if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
295 die("too many bad blocks"); 305 die("too many bad blocks");
296 if (used_good_blocks) 306 if (used_good_blocks)
297 blk = good_blocks_table[used_good_blocks-1]+1; 307 blk = good_blocks_table[used_good_blocks - 1] + 1;
298 else 308 else
299 blk = FIRSTZONE; 309 blk = FIRSTZONE;
300 while (blk < ZONES && zone_in_use(blk)) 310 while (blk < ZONES && zone_in_use(blk))
@@ -310,14 +320,14 @@ static void mark_good_blocks(void)
310{ 320{
311 int blk; 321 int blk;
312 322
313 for (blk=0 ; blk < used_good_blocks ; blk++) 323 for (blk = 0; blk < used_good_blocks; blk++)
314 mark_zone(good_blocks_table[blk]); 324 mark_zone(good_blocks_table[blk]);
315} 325}
316 326
317inline int next(int zone) 327inline int next(int zone)
318{ 328{
319 if (!zone) 329 if (!zone)
320 zone = FIRSTZONE-1; 330 zone = FIRSTZONE - 1;
321 while (++zone < ZONES) 331 while (++zone < ZONES)
322 if (zone_in_use(zone)) 332 if (zone_in_use(zone))
323 return zone; 333 return zone;
@@ -326,11 +336,11 @@ inline int next(int zone)
326 336
327static void make_bad_inode(void) 337static void make_bad_inode(void)
328{ 338{
329 struct minix_inode * inode = &Inode[MINIX_BAD_INO]; 339 struct minix_inode *inode = &Inode[MINIX_BAD_INO];
330 int i,j,zone; 340 int i, j, zone;
331 int ind=0,dind=0; 341 int ind = 0, dind = 0;
332 unsigned short ind_block[BLOCK_SIZE>>1]; 342 unsigned short ind_block[BLOCK_SIZE >> 1];
333 unsigned short dind_block[BLOCK_SIZE>>1]; 343 unsigned short dind_block[BLOCK_SIZE >> 1];
334 344
335#define NEXT_BAD (zone = next(zone)) 345#define NEXT_BAD (zone = next(zone))
336 346
@@ -340,34 +350,34 @@ static void make_bad_inode(void)
340 inode->i_nlinks = 1; 350 inode->i_nlinks = 1;
341 inode->i_time = time(NULL); 351 inode->i_time = time(NULL);
342 inode->i_mode = S_IFREG + 0000; 352 inode->i_mode = S_IFREG + 0000;
343 inode->i_size = badblocks*BLOCK_SIZE; 353 inode->i_size = badblocks * BLOCK_SIZE;
344 zone = next(0); 354 zone = next(0);
345 for (i=0 ; i<7 ; i++) { 355 for (i = 0; i < 7; i++) {
346 inode->i_zone[i] = zone; 356 inode->i_zone[i] = zone;
347 if (!NEXT_BAD) 357 if (!NEXT_BAD)
348 goto end_bad; 358 goto end_bad;
349 } 359 }
350 inode->i_zone[7] = ind = get_free_block(); 360 inode->i_zone[7] = ind = get_free_block();
351 memset(ind_block,0,BLOCK_SIZE); 361 memset(ind_block, 0, BLOCK_SIZE);
352 for (i=0 ; i<512 ; i++) { 362 for (i = 0; i < 512; i++) {
353 ind_block[i] = zone; 363 ind_block[i] = zone;
354 if (!NEXT_BAD) 364 if (!NEXT_BAD)
355 goto end_bad; 365 goto end_bad;
356 } 366 }
357 inode->i_zone[8] = dind = get_free_block(); 367 inode->i_zone[8] = dind = get_free_block();
358 memset(dind_block,0,BLOCK_SIZE); 368 memset(dind_block, 0, BLOCK_SIZE);
359 for (i=0 ; i<512 ; i++) { 369 for (i = 0; i < 512; i++) {
360 write_block(ind,(char *) ind_block); 370 write_block(ind, (char *) ind_block);
361 dind_block[i] = ind = get_free_block(); 371 dind_block[i] = ind = get_free_block();
362 memset(ind_block,0,BLOCK_SIZE); 372 memset(ind_block, 0, BLOCK_SIZE);
363 for (j=0 ; j<512 ; j++) { 373 for (j = 0; j < 512; j++) {
364 ind_block[j] = zone; 374 ind_block[j] = zone;
365 if (!NEXT_BAD) 375 if (!NEXT_BAD)
366 goto end_bad; 376 goto end_bad;
367 } 377 }
368 } 378 }
369 die("too many bad blocks"); 379 die("too many bad blocks");
370end_bad: 380 end_bad:
371 if (ind) 381 if (ind)
372 write_block(ind, (char *) ind_block); 382 write_block(ind, (char *) ind_block);
373 if (dind) 383 if (dind)
@@ -375,8 +385,7 @@ end_bad:
375} 385}
376 386
377#ifdef HAVE_MINIX2 387#ifdef HAVE_MINIX2
378static void 388static void make_bad_inode2(void)
379make_bad_inode2 (void)
380{ 389{
381 struct minix2_inode *inode = &Inode2[MINIX_BAD_INO]; 390 struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
382 int i, j, zone; 391 int i, j, zone;
@@ -386,30 +395,30 @@ make_bad_inode2 (void)
386 395
387 if (!badblocks) 396 if (!badblocks)
388 return; 397 return;
389 mark_inode (MINIX_BAD_INO); 398 mark_inode(MINIX_BAD_INO);
390 inode->i_nlinks = 1; 399 inode->i_nlinks = 1;
391 inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL); 400 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
392 inode->i_mode = S_IFREG + 0000; 401 inode->i_mode = S_IFREG + 0000;
393 inode->i_size = badblocks * BLOCK_SIZE; 402 inode->i_size = badblocks * BLOCK_SIZE;
394 zone = next (0); 403 zone = next(0);
395 for (i = 0; i < 7; i++) { 404 for (i = 0; i < 7; i++) {
396 inode->i_zone[i] = zone; 405 inode->i_zone[i] = zone;
397 if (!NEXT_BAD) 406 if (!NEXT_BAD)
398 goto end_bad; 407 goto end_bad;
399 } 408 }
400 inode->i_zone[7] = ind = get_free_block (); 409 inode->i_zone[7] = ind = get_free_block();
401 memset (ind_block, 0, BLOCK_SIZE); 410 memset(ind_block, 0, BLOCK_SIZE);
402 for (i = 0; i < 256; i++) { 411 for (i = 0; i < 256; i++) {
403 ind_block[i] = zone; 412 ind_block[i] = zone;
404 if (!NEXT_BAD) 413 if (!NEXT_BAD)
405 goto end_bad; 414 goto end_bad;
406 } 415 }
407 inode->i_zone[8] = dind = get_free_block (); 416 inode->i_zone[8] = dind = get_free_block();
408 memset (dind_block, 0, BLOCK_SIZE); 417 memset(dind_block, 0, BLOCK_SIZE);
409 for (i = 0; i < 256; i++) { 418 for (i = 0; i < 256; i++) {
410 write_block (ind, (char *) ind_block); 419 write_block(ind, (char *) ind_block);
411 dind_block[i] = ind = get_free_block (); 420 dind_block[i] = ind = get_free_block();
412 memset (ind_block, 0, BLOCK_SIZE); 421 memset(ind_block, 0, BLOCK_SIZE);
413 for (j = 0; j < 256; j++) { 422 for (j = 0; j < 256; j++) {
414 ind_block[j] = zone; 423 ind_block[j] = zone;
415 if (!NEXT_BAD) 424 if (!NEXT_BAD)
@@ -417,47 +426,46 @@ make_bad_inode2 (void)
417 } 426 }
418 } 427 }
419 /* Could make triple indirect block here */ 428 /* Could make triple indirect block here */
420 die ("too many bad blocks"); 429 die("too many bad blocks");
421 end_bad: 430 end_bad:
422 if (ind) 431 if (ind)
423 write_block (ind, (char *) ind_block); 432 write_block(ind, (char *) ind_block);
424 if (dind) 433 if (dind)
425 write_block (dind, (char *) dind_block); 434 write_block(dind, (char *) dind_block);
426} 435}
427#endif 436#endif
428 437
429static void make_root_inode(void) 438static void make_root_inode(void)
430{ 439{
431 struct minix_inode * inode = &Inode[MINIX_ROOT_INO]; 440 struct minix_inode *inode = &Inode[MINIX_ROOT_INO];
432 441
433 mark_inode(MINIX_ROOT_INO); 442 mark_inode(MINIX_ROOT_INO);
434 inode->i_zone[0] = get_free_block(); 443 inode->i_zone[0] = get_free_block();
435 inode->i_nlinks = 2; 444 inode->i_nlinks = 2;
436 inode->i_time = time(NULL); 445 inode->i_time = time(NULL);
437 if (badblocks) 446 if (badblocks)
438 inode->i_size = 3*dirsize; 447 inode->i_size = 3 * dirsize;
439 else { 448 else {
440 root_block[2*dirsize] = '\0'; 449 root_block[2 * dirsize] = '\0';
441 root_block[2*dirsize+1] = '\0'; 450 root_block[2 * dirsize + 1] = '\0';
442 inode->i_size = 2*dirsize; 451 inode->i_size = 2 * dirsize;
443 } 452 }
444 inode->i_mode = S_IFDIR + 0755; 453 inode->i_mode = S_IFDIR + 0755;
445 inode->i_uid = getuid(); 454 inode->i_uid = getuid();
446 if (inode->i_uid) 455 if (inode->i_uid)
447 inode->i_gid = getgid(); 456 inode->i_gid = getgid();
448 write_block(inode->i_zone[0],root_block); 457 write_block(inode->i_zone[0], root_block);
449} 458}
450 459
451#ifdef HAVE_MINIX2 460#ifdef HAVE_MINIX2
452static void 461static void make_root_inode2(void)
453make_root_inode2 (void)
454{ 462{
455 struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO]; 463 struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO];
456 464
457 mark_inode (MINIX_ROOT_INO); 465 mark_inode(MINIX_ROOT_INO);
458 inode->i_zone[0] = get_free_block (); 466 inode->i_zone[0] = get_free_block();
459 inode->i_nlinks = 2; 467 inode->i_nlinks = 2;
460 inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL); 468 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
461 if (badblocks) 469 if (badblocks)
462 inode->i_size = 3 * dirsize; 470 inode->i_size = 3 * dirsize;
463 else { 471 else {
@@ -469,7 +477,7 @@ make_root_inode2 (void)
469 inode->i_uid = getuid(); 477 inode->i_uid = getuid();
470 if (inode->i_uid) 478 if (inode->i_uid)
471 inode->i_gid = getgid(); 479 inode->i_gid = getgid();
472 write_block (inode->i_zone[0], root_block); 480 write_block(inode->i_zone[0], root_block);
473} 481}
474#endif 482#endif
475 483
@@ -478,34 +486,38 @@ static void setup_tables(void)
478 int i; 486 int i;
479 unsigned long inodes; 487 unsigned long inodes;
480 488
481 memset(super_block_buffer,0,BLOCK_SIZE); 489 memset(super_block_buffer, 0, BLOCK_SIZE);
482 memset(boot_block_buffer,0,512); 490 memset(boot_block_buffer, 0, 512);
483 MAGIC = magic; 491 MAGIC = magic;
484 ZONESIZE = 0; 492 ZONESIZE = 0;
485 MAXSIZE = version2 ? 0x7fffffff : (7+512+512*512)*1024; 493 MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
486 ZONES = BLOCKS; 494 ZONES = BLOCKS;
487/* some magic nrs: 1 inode / 3 blocks */ 495/* some magic nrs: 1 inode / 3 blocks */
488 if ( req_nr_inodes == 0 ) 496 if (req_nr_inodes == 0)
489 inodes = BLOCKS/3; 497 inodes = BLOCKS / 3;
490 else 498 else
491 inodes = req_nr_inodes; 499 inodes = req_nr_inodes;
492 /* Round up inode count to fill block size */ 500 /* Round up inode count to fill block size */
493#ifdef HAVE_MINIX2 501#ifdef HAVE_MINIX2
494 if (version2) 502 if (version2)
495 inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & 503 inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
496 ~(MINIX2_INODES_PER_BLOCK - 1)); 504 ~(MINIX2_INODES_PER_BLOCK - 1));
497 else 505 else
498#endif 506#endif
499 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & 507 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
500 ~(MINIX_INODES_PER_BLOCK - 1)); 508 ~(MINIX_INODES_PER_BLOCK - 1));
501 if (inodes > 65535) 509 if (inodes > 65535)
502 inodes = 65535; 510 inodes = 65535;
503 INODES = inodes; 511 INODES = inodes;
504 IMAPS = UPPER(INODES + 1,BITS_PER_BLOCK); 512 IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK);
505 ZMAPS = 0; 513 ZMAPS = 0;
506 i=0; 514 i = 0;
507 while (ZMAPS != UPPER(BLOCKS - (2+IMAPS+ZMAPS+INODE_BLOCKS) + 1,BITS_PER_BLOCK) && i<1000) { 515 while (ZMAPS !=
508 ZMAPS = UPPER(BLOCKS - (2+IMAPS+ZMAPS+INODE_BLOCKS) + 1,BITS_PER_BLOCK); 516 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
517 BITS_PER_BLOCK) && i < 1000) {
518 ZMAPS =
519 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
520 BITS_PER_BLOCK);
509 i++; 521 i++;
510 } 522 }
511 /* Real bad hack but overwise mkfs.minix can be thrown 523 /* Real bad hack but overwise mkfs.minix can be thrown
@@ -514,50 +526,51 @@ static void setup_tables(void)
514 * dd if=/dev/zero of=test.fs count=10 bs=1024 526 * dd if=/dev/zero of=test.fs count=10 bs=1024
515 * /sbin/mkfs.minix -i 200 test.fs 527 * /sbin/mkfs.minix -i 200 test.fs
516 * */ 528 * */
517 if (i>=999) { 529 if (i >= 999) {
518 die ("unable to allocate buffers for maps"); 530 die("unable to allocate buffers for maps");
519 } 531 }
520 FIRSTZONE = NORM_FIRSTZONE; 532 FIRSTZONE = NORM_FIRSTZONE;
521 inode_map = malloc(IMAPS * BLOCK_SIZE); 533 inode_map = malloc(IMAPS * BLOCK_SIZE);
522 zone_map = malloc(ZMAPS * BLOCK_SIZE); 534 zone_map = malloc(ZMAPS * BLOCK_SIZE);
523 if (!inode_map || !zone_map) 535 if (!inode_map || !zone_map)
524 die("unable to allocate buffers for maps"); 536 die("unable to allocate buffers for maps");
525 memset(inode_map,0xff,IMAPS * BLOCK_SIZE); 537 memset(inode_map, 0xff, IMAPS * BLOCK_SIZE);
526 memset(zone_map,0xff,ZMAPS * BLOCK_SIZE); 538 memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE);
527 for (i = FIRSTZONE ; i<ZONES ; i++) 539 for (i = FIRSTZONE; i < ZONES; i++)
528 unmark_zone(i); 540 unmark_zone(i);
529 for (i = MINIX_ROOT_INO ; i<=INODES ; i++) 541 for (i = MINIX_ROOT_INO; i <= INODES; i++)
530 unmark_inode(i); 542 unmark_inode(i);
531 inode_buffer = malloc(INODE_BUFFER_SIZE); 543 inode_buffer = malloc(INODE_BUFFER_SIZE);
532 if (!inode_buffer) 544 if (!inode_buffer)
533 die("unable to allocate buffer for inodes"); 545 die("unable to allocate buffer for inodes");
534 memset(inode_buffer,0,INODE_BUFFER_SIZE); 546 memset(inode_buffer, 0, INODE_BUFFER_SIZE);
535 printf("%ld inodes\n",INODES); 547 printf("%ld inodes\n", INODES);
536 printf("%ld blocks\n",ZONES); 548 printf("%ld blocks\n", ZONES);
537 printf("Firstdatazone=%ld (%ld)\n",FIRSTZONE,NORM_FIRSTZONE); 549 printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE);
538 printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); 550 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
539 printf("Maxsize=%ld\n\n",MAXSIZE); 551 printf("Maxsize=%ld\n\n", MAXSIZE);
540} 552}
541 553
542/* 554/*
543 * Perform a test of a block; return the number of 555 * Perform a test of a block; return the number of
544 * blocks readable/writeable. 556 * blocks readable/writeable.
545 */ 557 */
546long do_check(char * buffer, int try, unsigned int current_block) 558long do_check(char *buffer, int try, unsigned int current_block)
547{ 559{
548 long got; 560 long got;
549 561
550 /* Seek to the correct loc. */ 562 /* Seek to the correct loc. */
551 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != 563 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
552 current_block * BLOCK_SIZE ) { 564 current_block * BLOCK_SIZE) {
553 die("seek failed during testing of blocks"); 565 die("seek failed during testing of blocks");
554 } 566 }
555 567
556 568
557 /* Try the read */ 569 /* Try the read */
558 got = read(DEV, buffer, try * BLOCK_SIZE); 570 got = read(DEV, buffer, try * BLOCK_SIZE);
559 if (got < 0) got = 0; 571 if (got < 0)
560 if (got & (BLOCK_SIZE - 1 )) { 572 got = 0;
573 if (got & (BLOCK_SIZE - 1)) {
561 printf("Weird values in do_check: probably bugs\n"); 574 printf("Weird values in do_check: probably bugs\n");
562 } 575 }
563 got /= BLOCK_SIZE; 576 got /= BLOCK_SIZE;
@@ -570,7 +583,7 @@ static void alarm_intr(int alnum)
570{ 583{
571 if (currently_testing >= ZONES) 584 if (currently_testing >= ZONES)
572 return; 585 return;
573 signal(SIGALRM,alarm_intr); 586 signal(SIGALRM, alarm_intr);
574 alarm(5); 587 alarm(5);
575 if (!currently_testing) 588 if (!currently_testing)
576 return; 589 return;
@@ -580,19 +593,19 @@ static void alarm_intr(int alnum)
580 593
581static void check_blocks(void) 594static void check_blocks(void)
582{ 595{
583 int try,got; 596 int try, got;
584 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 597 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
585 598
586 currently_testing=0; 599 currently_testing = 0;
587 signal(SIGALRM,alarm_intr); 600 signal(SIGALRM, alarm_intr);
588 alarm(5); 601 alarm(5);
589 while (currently_testing < ZONES) { 602 while (currently_testing < ZONES) {
590 if (lseek(DEV,currently_testing*BLOCK_SIZE,SEEK_SET) != 603 if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) !=
591 currently_testing*BLOCK_SIZE) 604 currently_testing * BLOCK_SIZE)
592 die("seek failed in check_blocks"); 605 die("seek failed in check_blocks");
593 try = TEST_BUFFER_BLOCKS; 606 try = TEST_BUFFER_BLOCKS;
594 if (currently_testing + try > ZONES) 607 if (currently_testing + try > ZONES)
595 try = ZONES-currently_testing; 608 try = ZONES - currently_testing;
596 got = do_check(buffer, try, currently_testing); 609 got = do_check(buffer, try, currently_testing);
597 currently_testing += got; 610 currently_testing += got;
598 if (got == try) 611 if (got == try)
@@ -613,139 +626,141 @@ static void get_list_blocks(filename)
613char *filename; 626char *filename;
614 627
615{ 628{
616 FILE *listfile; 629 FILE *listfile;
617 unsigned long blockno; 630 unsigned long blockno;
618 631
619 listfile=fopen(filename,"r"); 632 listfile = fopen(filename, "r");
620 if(listfile == (FILE *)NULL) { 633 if (listfile == (FILE *) NULL) {
621 die("can't open file of bad blocks"); 634 die("can't open file of bad blocks");
622 } 635 }
623 while(!feof(listfile)) { 636 while (!feof(listfile)) {
624 fscanf(listfile,"%ld\n", &blockno); 637 fscanf(listfile, "%ld\n", &blockno);
625 mark_zone(blockno); 638 mark_zone(blockno);
626 badblocks++; 639 badblocks++;
627 } 640 }
628 if(badblocks > 1) 641 if (badblocks > 1)
629 printf("%d bad blocks\n", badblocks); 642 printf("%d bad blocks\n", badblocks);
630 else if (badblocks == 1) 643 else if (badblocks == 1)
631 printf("one bad block\n"); 644 printf("one bad block\n");
632} 645}
633 646
634extern int 647extern int mkfs_minix_main(int argc, char **argv)
635mkfs_minix_main(int argc, char ** argv)
636{ 648{
637 int i; 649 int i;
638 char * tmp; 650 char *tmp;
639 struct stat statbuf; 651 struct stat statbuf;
640 char * listfile = NULL; 652 char *listfile = NULL;
641 653
642 if (argc && *argv) 654 if (argc && *argv)
643 program_name = *argv; 655 program_name = *argv;
644 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 656 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
645 die("bad inode size"); 657 die("bad inode size");
646#ifdef HAVE_MINIX2 658#ifdef HAVE_MINIX2
647 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 659 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
648 die("bad inode size"); 660 die("bad inode size");
649#endif 661#endif
650 opterr = 0; 662 opterr = 0;
651 while ((i = getopt(argc, argv, "ci:l:n:v")) != EOF) 663 while ((i = getopt(argc, argv, "ci:l:n:v")) != EOF)
652 switch (i) { 664 switch (i) {
653 case 'c': 665 case 'c':
654 check=1; break; 666 check = 1;
655 case 'i': 667 break;
656 req_nr_inodes = (unsigned long) atol(optarg); 668 case 'i':
657 break; 669 req_nr_inodes = (unsigned long) atol(optarg);
658 case 'l': 670 break;
659 listfile = optarg; break; 671 case 'l':
660 case 'n': 672 listfile = optarg;
661 i = strtoul(optarg,&tmp,0); 673 break;
662 if (*tmp) 674 case 'n':
663 show_usage(); 675 i = strtoul(optarg, &tmp, 0);
664 if (i == 14) 676 if (*tmp)
665 magic = MINIX_SUPER_MAGIC; 677 show_usage();
666 else if (i == 30) 678 if (i == 14)
667 magic = MINIX_SUPER_MAGIC2; 679 magic = MINIX_SUPER_MAGIC;
668 else 680 else if (i == 30)
669 show_usage(); 681 magic = MINIX_SUPER_MAGIC2;
670 namelen = i; 682 else
671 dirsize = i+2; 683 show_usage();
672 break; 684 namelen = i;
673 case 'v': 685 dirsize = i + 2;
686 break;
687 case 'v':
674#ifdef HAVE_MINIX2 688#ifdef HAVE_MINIX2
675 version2 = 1; 689 version2 = 1;
676#else 690#else
677 fprintf(stderr,"%s: not compiled with minix v2 support\n",program_name,device_name); 691 fprintf(stderr, "%s: not compiled with minix v2 support\n",
678 exit(-1); 692 program_name, device_name);
693 exit(-1);
679#endif 694#endif
680 break; 695 break;
681 default: 696 default:
682 show_usage(); 697 show_usage();
683 } 698 }
684 argc -= optind; 699 argc -= optind;
685 argv += optind; 700 argv += optind;
686 if (argc > 0 && !device_name) { 701 if (argc > 0 && !device_name) {
687 device_name = argv[0]; 702 device_name = argv[0];
688 argc--; 703 argc--;
689 argv++; 704 argv++;
690 } 705 }
691 if (argc > 0) { 706 if (argc > 0) {
692 BLOCKS = strtol(argv[0],&tmp,0); 707 BLOCKS = strtol(argv[0], &tmp, 0);
693 if (*tmp) { 708 if (*tmp) {
694 printf("strtol error: number of blocks not specified"); 709 printf("strtol error: number of blocks not specified");
695 show_usage(); 710 show_usage();
696 } 711 }
697 } 712 }
698 713
699 if (device_name && !BLOCKS) 714 if (device_name && !BLOCKS)
700 BLOCKS = get_size (device_name) / 1024; 715 BLOCKS = get_size(device_name) / 1024;
701 if (!device_name || BLOCKS<10) { 716 if (!device_name || BLOCKS < 10) {
702 show_usage(); 717 show_usage();
703 } 718 }
704#ifdef HAVE_MINIX2 719#ifdef HAVE_MINIX2
705 if (version2) { 720 if (version2) {
706 if (namelen == 14) 721 if (namelen == 14)
707 magic = MINIX2_SUPER_MAGIC; 722 magic = MINIX2_SUPER_MAGIC;
708 else 723 else
709 magic = MINIX2_SUPER_MAGIC2; 724 magic = MINIX2_SUPER_MAGIC2;
710 } else 725 } else
711#endif 726#endif
712 if (BLOCKS > 65535) 727 if (BLOCKS > 65535)
713 BLOCKS = 65535; 728 BLOCKS = 65535;
714 check_mount(); /* is it already mounted? */ 729 check_mount(); /* is it already mounted? */
715 tmp = root_block; 730 tmp = root_block;
716 *(short *)tmp = 1; 731 *(short *) tmp = 1;
717 strcpy(tmp+2,"."); 732 strcpy(tmp + 2, ".");
718 tmp += dirsize; 733 tmp += dirsize;
719 *(short *)tmp = 1; 734 *(short *) tmp = 1;
720 strcpy(tmp+2,".."); 735 strcpy(tmp + 2, "..");
721 tmp += dirsize; 736 tmp += dirsize;
722 *(short *)tmp = 2; 737 *(short *) tmp = 2;
723 strcpy(tmp+2,".badblocks"); 738 strcpy(tmp + 2, ".badblocks");
724 DEV = open(device_name,O_RDWR ); 739 DEV = open(device_name, O_RDWR);
725 if (DEV<0) 740 if (DEV < 0)
726 die("unable to open %s"); 741 die("unable to open %s");
727 if (fstat(DEV,&statbuf)<0) 742 if (fstat(DEV, &statbuf) < 0)
728 die("unable to stat %s"); 743 die("unable to stat %s");
729 if (!S_ISBLK(statbuf.st_mode)) 744 if (!S_ISBLK(statbuf.st_mode))
730 check=0; 745 check = 0;
731 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 746 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
732 die("will not try to make filesystem on '%s'"); 747 die("will not try to make filesystem on '%s'");
733 setup_tables(); 748 setup_tables();
734 if (check) 749 if (check)
735 check_blocks(); 750 check_blocks();
736 else if (listfile) 751 else if (listfile)
737 get_list_blocks(listfile); 752 get_list_blocks(listfile);
738#ifdef HAVE_MINIX2 753#ifdef HAVE_MINIX2
739 if (version2) { 754 if (version2) {
740 make_root_inode2 (); 755 make_root_inode2();
741 make_bad_inode2 (); 756 make_bad_inode2();
742 } else 757 } else
743#endif 758#endif
744 { 759 {
745 make_root_inode(); 760 make_root_inode();
746 make_bad_inode(); 761 make_bad_inode();
747 } 762 }
748 mark_good_blocks(); 763 mark_good_blocks();
749 write_tables(); 764 write_tables();
750 return 0; 765 return 0;
751} 766}
diff --git a/mknod.c b/mknod.c
index 5822cd3ad..b11a81f2a 100644
--- a/mknod.c
+++ b/mknod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mknod implementation for busybox 3 * Mini mknod implementation for busybox
3 * 4 *
@@ -28,22 +29,22 @@
28#include <unistd.h> 29#include <unistd.h>
29 30
30static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n" 31static const char mknod_usage[] = "mknod NAME TYPE MAJOR MINOR\n\n"
31"Make block or character special files.\n\n" 32 "Make block or character special files.\n\n"
32"TYPEs include:\n" 33 "TYPEs include:\n"
33"\tb:\tMake a block (buffered) device.\n" 34 "\tb:\tMake a block (buffered) device.\n"
34"\tc or u:\tMake a character (un-buffered) device.\n"
35"\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
36 35
37int 36 "\tc or u:\tMake a character (un-buffered) device.\n"
38mknod_main(int argc, char** argv) 37 "\tp:\tMake a named pipe. Major and minor are ignored for named pipes.\n";
38
39int mknod_main(int argc, char **argv)
39{ 40{
40 mode_t mode = 0; 41 mode_t mode = 0;
41 dev_t dev = 0; 42 dev_t dev = 0;
42 43
43 if ( argc != 5 || **(argv+1) == '-' ) { 44 if (argc != 5 || **(argv + 1) == '-') {
44 usage (mknod_usage); 45 usage(mknod_usage);
45 } 46 }
46 switch(argv[2][0]) { 47 switch (argv[2][0]) {
47 case 'c': 48 case 'c':
48 case 'u': 49 case 'u':
49 mode = S_IFCHR; 50 mode = S_IFCHR;
@@ -55,21 +56,21 @@ mknod_main(int argc, char** argv)
55 mode = S_IFIFO; 56 mode = S_IFIFO;
56 break; 57 break;
57 default: 58 default:
58 usage (mknod_usage); 59 usage(mknod_usage);
59 } 60 }
60 61
61 if ( mode == S_IFCHR || mode == S_IFBLK ) { 62 if (mode == S_IFCHR || mode == S_IFBLK) {
62 dev = (atoi(argv[3]) << 8) | atoi(argv[4]); 63 dev = (atoi(argv[3]) << 8) | atoi(argv[4]);
63 if ( argc != 5 ) { 64 if (argc != 5) {
64 usage (mknod_usage); 65 usage(mknod_usage);
65 } 66 }
66 } 67 }
67 68
68 mode |= 0666; 69 mode |= 0666;
69 70
70 if ( mknod(argv[1], mode, dev) != 0 ) { 71 if (mknod(argv[1], mode, dev) != 0) {
71 perror(argv[1]); 72 perror(argv[1]);
72 return( FALSE); 73 return (FALSE);
73 } 74 }
74 return( TRUE); 75 return (TRUE);
75} 76}
diff --git a/mkswap.c b/mkswap.c
index 601188f86..130d24162 100644
--- a/mkswap.c
+++ b/mkswap.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * mkswap.c - set up a linux swap device 3 * mkswap.c - set up a linux swap device
3 * 4 *
@@ -40,20 +41,21 @@
40#include <string.h> 41#include <string.h>
41#include <fcntl.h> 42#include <fcntl.h>
42#include <stdlib.h> 43#include <stdlib.h>
43#include <sys/ioctl.h> /* for _IO */ 44#include <sys/ioctl.h> /* for _IO */
44#include <sys/utsname.h> 45#include <sys/utsname.h>
45#include <sys/stat.h> 46#include <sys/stat.h>
46#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ 47#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
47 /* we also get PAGE_SIZE via getpagesize() */ 48 /* we also get PAGE_SIZE via getpagesize() */
48 49
49 50
50static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n\n" 51static const char mkswap_usage[] =
51"Prepare a disk partition to be used as a swap partition.\n\n" 52 "mkswap [-c] [-v0|-v1] device [block-count]\n\n"
52"Options:\n" 53 "Prepare a disk partition to be used as a swap partition.\n\n"
53"\t-c\t\tCheck for read-ability.\n" 54 "Options:\n" "\t-c\t\tCheck for read-ability.\n"
54"\t-v0\t\tMake version 0 swap [max 128 Megs].\n" 55 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
55"\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n" 56 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
56"\tblock-count\tNumber of block to use (default is entire partition).\n"; 57
58 "\tblock-count\tNumber of block to use (default is entire partition).\n";
57 59
58 60
59#ifndef _IO 61#ifndef _IO
@@ -64,8 +66,8 @@ static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n
64#define BLKGETSIZE _IO(0x12,96) 66#define BLKGETSIZE _IO(0x12,96)
65#endif 67#endif
66 68
67static char * program_name = "mkswap"; 69static char *program_name = "mkswap";
68static char * device_name = NULL; 70static char *device_name = NULL;
69static int DEV = -1; 71static int DEV = -1;
70static long PAGES = 0; 72static long PAGES = 0;
71static int check = 0; 73static int check = 0;
@@ -74,8 +76,8 @@ static int version = -1;
74 76
75#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) 77#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
76 78
77static int 79static int linux_version_code(void)
78linux_version_code(void) { 80{
79 struct utsname my_utsname; 81 struct utsname my_utsname;
80 int p, q, r; 82 int p, q, r;
81 83
@@ -83,7 +85,7 @@ linux_version_code(void) {
83 p = atoi(strtok(my_utsname.release, ".")); 85 p = atoi(strtok(my_utsname.release, "."));
84 q = atoi(strtok(NULL, ".")); 86 q = atoi(strtok(NULL, "."));
85 r = atoi(strtok(NULL, ".")); 87 r = atoi(strtok(NULL, "."));
86 return MAKE_VERSION(p,q,r); 88 return MAKE_VERSION(p, q, r);
87 } 89 }
88 return 0; 90 return 0;
89} 91}
@@ -98,7 +100,7 @@ static int pagesize;
98static int *signature_page; 100static int *signature_page;
99 101
100struct swap_header_v1 { 102struct swap_header_v1 {
101 char bootbits[1024]; /* Space for disklabel etc. */ 103 char bootbits[1024]; /* Space for disklabel etc. */
102 unsigned int version; 104 unsigned int version;
103 unsigned int last_page; 105 unsigned int last_page;
104 unsigned int nr_badpages; 106 unsigned int nr_badpages;
@@ -106,8 +108,8 @@ struct swap_header_v1 {
106 unsigned int badpages[1]; 108 unsigned int badpages[1];
107} *p; 109} *p;
108 110
109static void 111static void init_signature_page()
110init_signature_page() { 112{
111 pagesize = getpagesize(); 113 pagesize = getpagesize();
112 114
113#ifdef PAGE_SIZE 115#ifdef PAGE_SIZE
@@ -115,15 +117,15 @@ init_signature_page() {
115 fprintf(stderr, "Assuming pages of size %d\n", pagesize); 117 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
116#endif 118#endif
117 signature_page = (int *) malloc(pagesize); 119 signature_page = (int *) malloc(pagesize);
118 memset(signature_page,0,pagesize); 120 memset(signature_page, 0, pagesize);
119 p = (struct swap_header_v1 *) signature_page; 121 p = (struct swap_header_v1 *) signature_page;
120} 122}
121 123
122static void 124static void write_signature(char *sig)
123write_signature(char *sig) { 125{
124 char *sp = (char *) signature_page; 126 char *sp = (char *) signature_page;
125 127
126 strncpy(sp+pagesize-10, sig, 10); 128 strncpy(sp + pagesize - 10, sig, 10);
127} 129}
128 130
129#define V0_MAX_PAGES (8 * (pagesize - 10)) 131#define V0_MAX_PAGES (8 * (pagesize - 10))
@@ -172,42 +174,46 @@ It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
172 174
173#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) 175#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
174 176
175static void bit_set (unsigned int *addr, unsigned int nr) 177static void bit_set(unsigned int *addr, unsigned int nr)
176{ 178{
177 unsigned int r, m; 179 unsigned int r, m;
178 180
179 addr += nr / (8 * sizeof(int)); 181 addr += nr / (8 * sizeof(int));
182
180 r = *addr; 183 r = *addr;
181 m = 1 << (nr & (8 * sizeof(int) - 1)); 184 m = 1 << (nr & (8 * sizeof(int) - 1));
185
182 *addr = r | m; 186 *addr = r | m;
183} 187}
184 188
185static int bit_test_and_clear (unsigned int *addr, unsigned int nr) 189static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
186{ 190{
187 unsigned int r, m; 191 unsigned int r, m;
188 192
189 addr += nr / (8 * sizeof(int)); 193 addr += nr / (8 * sizeof(int));
194
190 r = *addr; 195 r = *addr;
191 m = 1 << (nr & (8 * sizeof(int) - 1)); 196 m = 1 << (nr & (8 * sizeof(int) - 1));
197
192 *addr = r & ~m; 198 *addr = r & ~m;
193 return (r & m) != 0; 199 return (r & m) != 0;
194} 200}
195 201
196 202
197void 203void die(const char *str)
198die(const char *str) { 204{
199 fprintf(stderr, "%s: %s\n", program_name, str); 205 fprintf(stderr, "%s: %s\n", program_name, str);
200 exit( FALSE); 206 exit(FALSE);
201} 207}
202 208
203void 209void page_ok(int page)
204page_ok(int page) { 210{
205 if (version==0) 211 if (version == 0)
206 bit_set(signature_page, page); 212 bit_set(signature_page, page);
207} 213}
208 214
209void 215void page_bad(int page)
210page_bad(int page) { 216{
211 if (version == 0) 217 if (version == 0)
212 bit_test_and_clear(signature_page, page); 218 bit_test_and_clear(signature_page, page);
213 else { 219 else {
@@ -218,8 +224,8 @@ page_bad(int page) {
218 badpages++; 224 badpages++;
219} 225}
220 226
221void 227void check_blocks(void)
222check_blocks(void) { 228{
223 unsigned int current_page; 229 unsigned int current_page;
224 int do_seek = 1; 230 int do_seek = 1;
225 char *buffer; 231 char *buffer;
@@ -233,8 +239,8 @@ check_blocks(void) {
233 page_ok(current_page++); 239 page_ok(current_page++);
234 continue; 240 continue;
235 } 241 }
236 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != 242 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
237 current_page*pagesize) 243 current_page * pagesize)
238 die("seek failed in check_blocks"); 244 die("seek failed in check_blocks");
239 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { 245 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
240 page_bad(current_page++); 246 page_bad(current_page++);
@@ -248,30 +254,28 @@ check_blocks(void) {
248 printf("%d bad pages\n", badpages); 254 printf("%d bad pages\n", badpages);
249} 255}
250 256
251static long valid_offset (int fd, int offset) 257static long valid_offset(int fd, int offset)
252{ 258{
253 char ch; 259 char ch;
254 260
255 if (lseek (fd, offset, 0) < 0) 261 if (lseek(fd, offset, 0) < 0)
256 return 0; 262 return 0;
257 if (read (fd, &ch, 1) < 1) 263 if (read(fd, &ch, 1) < 1)
258 return 0; 264 return 0;
259 return 1; 265 return 1;
260} 266}
261 267
262static int 268static int find_size(int fd)
263find_size (int fd)
264{ 269{
265 unsigned int high, low; 270 unsigned int high, low;
266 271
267 low = 0; 272 low = 0;
268 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2) 273 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
269 low = high; 274 low = high;
270 while (low < high - 1) 275 while (low < high - 1) {
271 {
272 const int mid = (low + high) / 2; 276 const int mid = (low + high) / 2;
273 277
274 if (valid_offset (fd, mid)) 278 if (valid_offset(fd, mid))
275 low = mid; 279 low = mid;
276 else 280 else
277 high = mid; 281 high = mid;
@@ -280,11 +284,10 @@ find_size (int fd)
280} 284}
281 285
282/* return size in pages, to avoid integer overflow */ 286/* return size in pages, to avoid integer overflow */
283static long 287static long get_size(const char *file)
284get_size(const char *file)
285{ 288{
286 int fd; 289 int fd;
287 long size; 290 long size;
288 291
289 fd = open(file, O_RDONLY); 292 fd = open(file, O_RDONLY);
290 if (fd < 0) { 293 if (fd < 0) {
@@ -292,7 +295,8 @@ get_size(const char *file)
292 exit(1); 295 exit(1);
293 } 296 }
294 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 297 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
295 int sectors_per_page = pagesize/512; 298 int sectors_per_page = pagesize / 512;
299
296 size /= sectors_per_page; 300 size /= sectors_per_page;
297 } else { 301 } else {
298 size = find_size(fd) / pagesize; 302 size = find_size(fd) / pagesize;
@@ -301,9 +305,9 @@ get_size(const char *file)
301 return size; 305 return size;
302} 306}
303 307
304int mkswap_main(int argc, char ** argv) 308int mkswap_main(int argc, char **argv)
305{ 309{
306 char * tmp; 310 char *tmp;
307 struct stat statbuf; 311 struct stat statbuf;
308 int sz; 312 int sz;
309 int maxpages; 313 int maxpages;
@@ -314,56 +318,56 @@ int mkswap_main(int argc, char ** argv)
314 if (argc && *argv) 318 if (argc && *argv)
315 program_name = *argv; 319 program_name = *argv;
316 320
317 init_signature_page(); /* get pagesize */ 321 init_signature_page(); /* get pagesize */
318 322
319 while (argc-- > 1) { 323 while (argc-- > 1) {
320 argv++; 324 argv++;
321 if (argv[0][0] != '-') { 325 if (argv[0][0] != '-') {
322 if (device_name) { 326 if (device_name) {
323 int blocks_per_page = pagesize/1024; 327 int blocks_per_page = pagesize / 1024;
324 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; 328
329 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
325 if (*tmp) 330 if (*tmp)
326 usage( mkswap_usage); 331 usage(mkswap_usage);
327 } else 332 } else
328 device_name = argv[0]; 333 device_name = argv[0];
329 } else { 334 } else {
330 switch (argv[0][1]) { 335 switch (argv[0][1]) {
331 case 'c': 336 case 'c':
332 check=1; 337 check = 1;
333 break; 338 break;
334 case 'f': 339 case 'f':
335 force=1; 340 force = 1;
336 break; 341 break;
337 case 'v': 342 case 'v':
338 version=atoi(argv[0]+2); 343 version = atoi(argv[0] + 2);
339 break; 344 break;
340 default: 345 default:
341 usage( mkswap_usage); 346 usage(mkswap_usage);
342 } 347 }
343 } 348 }
344 } 349 }
345 if (!device_name) { 350 if (!device_name) {
346 fprintf(stderr, 351 fprintf(stderr,
347 "%s: error: Nowhere to set up swap on?\n", 352 "%s: error: Nowhere to set up swap on?\n", program_name);
348 program_name); 353 usage(mkswap_usage);
349 usage( mkswap_usage);
350 } 354 }
351 sz = get_size(device_name); 355 sz = get_size(device_name);
352 if (!PAGES) { 356 if (!PAGES) {
353 PAGES = sz; 357 PAGES = sz;
354 } else if (PAGES > sz && !force) { 358 } else if (PAGES > sz && !force) {
355 fprintf(stderr, 359 fprintf(stderr,
356 "%s: error: " 360 "%s: error: "
357 "size %ld is larger than device size %d\n", 361 "size %ld is larger than device size %d\n",
358 program_name, 362 program_name,
359 PAGES*(pagesize/1024), sz*(pagesize/1024)); 363 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
360 exit( FALSE); 364 exit(FALSE);
361 } 365 }
362 366
363 if (version == -1) { 367 if (version == -1) {
364 if (PAGES <= V0_MAX_PAGES) 368 if (PAGES <= V0_MAX_PAGES)
365 version = 0; 369 version = 0;
366 else if (linux_version_code() < MAKE_VERSION(2,1,117)) 370 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
367 version = 0; 371 version = 0;
368 else if (pagesize < 2048) 372 else if (pagesize < 2048)
369 version = 0; 373 version = 0;
@@ -372,21 +376,21 @@ int mkswap_main(int argc, char ** argv)
372 } 376 }
373 if (version != 0 && version != 1) { 377 if (version != 0 && version != 1) {
374 fprintf(stderr, "%s: error: unknown version %d\n", 378 fprintf(stderr, "%s: error: unknown version %d\n",
375 program_name, version); 379 program_name, version);
376 usage( mkswap_usage); 380 usage(mkswap_usage);
377 } 381 }
378 if (PAGES < 10) { 382 if (PAGES < 10) {
379 fprintf(stderr, 383 fprintf(stderr,
380 "%s: error: swap area needs to be at least %ldkB\n", 384 "%s: error: swap area needs to be at least %ldkB\n",
381 program_name, (long)(10 * pagesize / 1024)); 385 program_name, (long) (10 * pagesize / 1024));
382 usage( mkswap_usage); 386 usage(mkswap_usage);
383 } 387 }
384#if 0 388#if 0
385 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); 389 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
386#else 390#else
387 if (!version) 391 if (!version)
388 maxpages = V0_MAX_PAGES; 392 maxpages = V0_MAX_PAGES;
389 else if (linux_version_code() >= MAKE_VERSION(2,2,1)) 393 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
390 maxpages = V1_MAX_PAGES; 394 maxpages = V1_MAX_PAGES;
391 else { 395 else {
392 maxpages = V1_OLD_MAX_PAGES; 396 maxpages = V1_OLD_MAX_PAGES;
@@ -397,29 +401,29 @@ int mkswap_main(int argc, char ** argv)
397 if (PAGES > maxpages) { 401 if (PAGES > maxpages) {
398 PAGES = maxpages; 402 PAGES = maxpages;
399 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", 403 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
400 program_name, PAGES * pagesize / 1024); 404 program_name, PAGES * pagesize / 1024);
401 } 405 }
402 406
403 DEV = open(device_name,O_RDWR); 407 DEV = open(device_name, O_RDWR);
404 if (DEV < 0 || fstat(DEV, &statbuf) < 0) { 408 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
405 perror(device_name); 409 perror(device_name);
406 exit( FALSE); 410 exit(FALSE);
407 } 411 }
408 if (!S_ISBLK(statbuf.st_mode)) 412 if (!S_ISBLK(statbuf.st_mode))
409 check=0; 413 check = 0;
410 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 414 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
411 die("Will not try to make swapdevice on '%s'"); 415 die("Will not try to make swapdevice on '%s'");
412 416
413#ifdef __sparc__ 417#ifdef __sparc__
414 if (!force && version == 0) { 418 if (!force && version == 0) {
415 /* Don't overwrite partition table unless forced */ 419 /* Don't overwrite partition table unless forced */
416 unsigned char *buffer = (unsigned char *)signature_page; 420 unsigned char *buffer = (unsigned char *) signature_page;
417 unsigned short *q, sum; 421 unsigned short *q, sum;
418 422
419 if (read(DEV, buffer, 512) != 512) 423 if (read(DEV, buffer, 512) != 512)
420 die("fatal: first page unreadable"); 424 die("fatal: first page unreadable");
421 if (buffer[508] == 0xDA && buffer[509] == 0xBE) { 425 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
422 q = (unsigned short *)(buffer + 510); 426 q = (unsigned short *) (buffer + 510);
423 for (sum = 0; q >= (unsigned short *) buffer;) 427 for (sum = 0; q >= (unsigned short *) buffer;)
424 sum ^= *q--; 428 sum ^= *q--;
425 if (!sum) { 429 if (!sum) {
@@ -427,9 +431,8 @@ int mkswap_main(int argc, char ** argv)
427%s: Device '%s' contains a valid Sun disklabel.\n\ 431%s: Device '%s' contains a valid Sun disklabel.\n\
428This probably means creating v0 swap would destroy your partition table\n\ 432This probably means creating v0 swap would destroy your partition table\n\
429No swap created. If you really want to create swap v0 on that device, use\n\ 433No swap created. If you really want to create swap v0 on that device, use\n\
430the -f option to force it.\n", 434the -f option to force it.\n", program_name, device_name);
431 program_name, device_name); 435 exit(FALSE);
432 exit( FALSE);
433 } 436 }
434 } 437 }
435 } 438 }
@@ -437,11 +440,11 @@ the -f option to force it.\n",
437 440
438 if (version == 0 || check) 441 if (version == 0 || check)
439 check_blocks(); 442 check_blocks();
440 if (version == 0 && !bit_test_and_clear(signature_page,0)) 443 if (version == 0 && !bit_test_and_clear(signature_page, 0))
441 die("fatal: first page unreadable"); 444 die("fatal: first page unreadable");
442 if (version == 1) { 445 if (version == 1) {
443 p->version = version; 446 p->version = version;
444 p->last_page = PAGES-1; 447 p->last_page = PAGES - 1;
445 p->nr_badpages = badpages; 448 p->nr_badpages = badpages;
446 } 449 }
447 450
@@ -449,14 +452,14 @@ the -f option to force it.\n",
449 if (goodpages <= 0) 452 if (goodpages <= 0)
450 die("Unable to set up swap-space: unreadable"); 453 die("Unable to set up swap-space: unreadable");
451 printf("Setting up swapspace version %d, size = %ld bytes\n", 454 printf("Setting up swapspace version %d, size = %ld bytes\n",
452 version, (long)(goodpages*pagesize)); 455 version, (long) (goodpages * pagesize));
453 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); 456 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
454 457
455 offset = ((version == 0) ? 0 : 1024); 458 offset = ((version == 0) ? 0 : 1024);
456 if (lseek(DEV, offset, SEEK_SET) != offset) 459 if (lseek(DEV, offset, SEEK_SET) != offset)
457 die("unable to rewind swap-device"); 460 die("unable to rewind swap-device");
458 if (write(DEV,(char*)signature_page+offset, pagesize-offset) 461 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
459 != pagesize-offset) 462 != pagesize - offset)
460 die("unable to write signature page"); 463 die("unable to write signature page");
461 464
462 /* 465 /*
@@ -464,6 +467,6 @@ the -f option to force it.\n",
464 * is not actually on disk. (This is a kernel bug.) 467 * is not actually on disk. (This is a kernel bug.)
465 */ 468 */
466 if (fsync(DEV)) 469 if (fsync(DEV))
467 die("fsync failed"); 470 die("fsync failed");
468 exit ( TRUE); 471 exit(TRUE);
469} 472}
diff --git a/mnc.c b/mnc.c
index 81dfd2529..54cfdc602 100644
--- a/mnc.c
+++ b/mnc.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* mnc: mini-netcat - built from the ground up for LRP 2/* mnc: mini-netcat - built from the ground up for LRP
2 Copyright (C) 1998 Charles P. Wright 3 Copyright (C) 1998 Charles P. Wright
3 4
@@ -39,101 +40,92 @@
39 40
40#define BUFSIZE 100 41#define BUFSIZE 100
41 42
42static const char mnc_usage[] = 43static const char mnc_usage[] =
43"mnc [IP] [port]\n\n"
44"mini-netcat opens a pipe to IP:port\n";
45 44
46int 45 "mnc [IP] [port]\n\n" "mini-netcat opens a pipe to IP:port\n";
47mnc_main(int argc, char **argv) 46
47int mnc_main(int argc, char **argv)
48{ 48{
49 int sfd; 49 int sfd;
50 int result; 50 int result;
51 int len; 51 int len;
52 char ch[BUFSIZE]; 52 char ch[BUFSIZE];
53 53
54 struct sockaddr_in address; 54 struct sockaddr_in address;
55 struct hostent *hostinfo; 55 struct hostent *hostinfo;
56 56
57 fd_set readfds, testfds; 57 fd_set readfds, testfds;
58 58
59 if (argc<=1 || **(argv+1) == '-' ) { 59 if (argc <= 1 || **(argv + 1) == '-') {
60 usage( mnc_usage); 60 usage(mnc_usage);
61 } 61 }
62 argc--; 62 argc--;
63 argv++; 63 argv++;
64 64
65 sfd = socket(AF_INET, SOCK_STREAM, 0); 65 sfd = socket(AF_INET, SOCK_STREAM, 0);
66 66
67 hostinfo = (struct hostent *) gethostbyname(*argv); 67 hostinfo = (struct hostent *) gethostbyname(*argv);
68 68
69 if (!hostinfo) 69 if (!hostinfo) {
70 { 70 exit(1);
71 exit(1); 71 }
72 }
73 72
74 address.sin_family = AF_INET; 73 address.sin_family = AF_INET;
75 address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; 74 address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
76 address.sin_port = htons(atoi(*(++argv))); 75 address.sin_port = htons(atoi(*(++argv)));
77 76
78 len = sizeof(address); 77 len = sizeof(address);
79 78
80 result = connect(sfd, (struct sockaddr *)&address, len); 79 result = connect(sfd, (struct sockaddr *) &address, len);
81 80
82 if (result < 0) 81 if (result < 0) {
83 { 82 exit(2);
84 exit(2); 83 }
85 }
86 84
87 FD_ZERO(&readfds); 85 FD_ZERO(&readfds);
88 FD_SET(sfd, &readfds); 86 FD_SET(sfd, &readfds);
89 FD_SET(fileno(stdin), &readfds); 87 FD_SET(fileno(stdin), &readfds);
90 88
91 while(1) 89 while (1) {
92 { 90 int fd;
93 int fd;
94 int ofd; 91 int ofd;
95 int nread; 92 int nread;
96 93
97 testfds = readfds; 94 testfds = readfds;
98 95
99 result = select(FD_SETSIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) 0); 96 result =
97 select(FD_SETSIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL,
98 (struct timeval *) 0);
100 99
101 if(result < 1) 100 if (result < 1) {
102 { 101 exit(3);
103 exit(3); 102 }
104 }
105 103
106 for(fd = 0; fd < FD_SETSIZE; fd++) 104 for (fd = 0; fd < FD_SETSIZE; fd++) {
107 { 105 if (FD_ISSET(fd, &testfds)) {
108 if(FD_ISSET(fd,&testfds))
109 {
110 int trn = 0; 106 int trn = 0;
111 int rn; 107 int rn;
112 108
113 ioctl(fd, FIONREAD, &nread); 109 ioctl(fd, FIONREAD, &nread);
114 110
115 if(fd == sfd) 111 if (fd == sfd) {
116 { 112 if (nread == 0)
117 if (nread == 0) 113 exit(0);
118 exit(0);
119 ofd = fileno(stdout); 114 ofd = fileno(stdout);
120 } 115 } else {
121 else
122 {
123 ofd = sfd; 116 ofd = sfd;
124 } 117 }
125 118
126 119
127 120
128 do 121 do {
129 {
130 rn = (BUFSIZE < nread - trn) ? BUFSIZE : nread - trn; 122 rn = (BUFSIZE < nread - trn) ? BUFSIZE : nread - trn;
131 trn += rn; 123 trn += rn;
132 read(fd, ch, rn); 124 read(fd, ch, rn);
133 write(ofd, ch, rn); 125 write(ofd, ch, rn);
134 } 126 }
135 while (trn < nread); 127 while (trn < nread);
136 } 128 }
137 } 129 }
138 } 130 }
139} 131}
diff --git a/modutils/insmod.c b/modutils/insmod.c
index 31cb11261..7cbbed441 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini insmod implementation for busybox 3 * Mini insmod implementation for busybox
3 * 4 *
@@ -41,8 +42,7 @@
41 42
42/* Some firendly syscalls to cheer everyone's day... */ 43/* Some firendly syscalls to cheer everyone's day... */
43_syscall2(int, init_module, const char *, name, 44_syscall2(int, init_module, const char *, name,
44 const struct module *, info) 45 const struct module *, info)
45
46#ifndef BB_RMMOD 46#ifndef BB_RMMOD
47_syscall1(int, delete_module, const char *, name) 47_syscall1(int, delete_module, const char *, name)
48#else 48#else
@@ -52,155 +52,159 @@ extern int delete_module(const char *);
52#if defined(__i386__) || defined(__m68k__) || defined(__arm__) 52#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
53/* Jump through hoops to fixup error return codes */ 53/* Jump through hoops to fixup error return codes */
54#define __NR__create_module __NR_create_module 54#define __NR__create_module __NR_create_module
55static inline _syscall2(long, _create_module, const char *, name, size_t, size) 55static inline _syscall2(long, _create_module, const char *, name, size_t,
56 size)
56unsigned long create_module(const char *name, size_t size) 57unsigned long create_module(const char *name, size_t size)
57{ 58{
58 long ret = _create_module(name, size); 59 long ret = _create_module(name, size);
59 if (ret == -1 && errno > 125) { 60
60 ret = -errno; 61 if (ret == -1 && errno > 125) {
61 errno = 0; 62 ret = -errno;
62 } 63 errno = 0;
63 return ret; 64 }
65 return ret;
64} 66}
65#else 67#else
66_syscall2(unsigned long, create_module, const char *, name, size_t, size) 68_syscall2(unsigned long, create_module, const char *, name, size_t, size)
67#endif 69#endif
68
69
70static char m_filename[PATH_MAX + 1] = "\0"; 70static char m_filename[PATH_MAX + 1] = "\0";
71static char m_fullName[PATH_MAX + 1] = "\0"; 71static char m_fullName[PATH_MAX + 1] = "\0";
72static const char insmod_usage[] = 72static const char insmod_usage[] =
73 "insmod [OPTION]... MODULE [symbol=value]...\n\n" 73 "insmod [OPTION]... MODULE [symbol=value]...\n\n"
74 "Loads the specified kernel modules into the kernel.\n\n" 74 "Loads the specified kernel modules into the kernel.\n\n"
75 "Options:\n" 75 "Options:\n"
76 "\t-f\tForce module to load into the wrong kernel version.\n" 76
77 "\t-k\tMake module autoclean-able.\n"; 77 "\t-f\tForce module to load into the wrong kernel version.\n"
78 "\t-k\tMake module autoclean-able.\n";
78 79
79 80
80static int findNamedModule(const char *fileName, struct stat* statbuf) 81static int findNamedModule(const char *fileName, struct stat *statbuf)
81{ 82{
82 if (m_fullName[0]=='\0') 83 if (m_fullName[0] == '\0')
83 return( FALSE); 84 return (FALSE);
84 else { 85 else {
85 char* tmp = strrchr( fileName, '/'); 86 char *tmp = strrchr(fileName, '/');
86 if (tmp == NULL) 87
87 tmp = (char*)fileName; 88 if (tmp == NULL)
88 else 89 tmp = (char *) fileName;
89 tmp++; 90 else
90 if (check_wildcard_match(tmp, m_fullName) == TRUE) { 91 tmp++;
91 /* Stop searching if we find a match */ 92 if (check_wildcard_match(tmp, m_fullName) == TRUE) {
92 memcpy(m_filename, fileName, strlen(fileName)); 93 /* Stop searching if we find a match */
93 return( FALSE); 94 memcpy(m_filename, fileName, strlen(fileName));
95 return (FALSE);
96 }
94 } 97 }
95 } 98 return (TRUE);
96 return( TRUE);
97} 99}
98 100
99 101
100extern int insmod_main(int argc, char **argv) 102extern int insmod_main(int argc, char **argv)
101{ 103{
102 int len; 104 int len;
103 char *tmp; 105 char *tmp;
104 char m_name[PATH_MAX + 1] ="\0"; 106 char m_name[PATH_MAX + 1] = "\0";
105 FILE *fp; 107 FILE *fp;
106 108
107 if (argc<=1) { 109 if (argc <= 1) {
108 usage( insmod_usage);
109 }
110
111 /* Parse any options */
112 while (--argc > 0 && **(++argv) == '-') {
113 while (*(++(*argv))) {
114 switch (**argv) {
115 case 'f':
116 break;
117 case 'k':
118 break;
119 default:
120 usage(insmod_usage); 110 usage(insmod_usage);
121 }
122 } 111 }
123 } 112
124 113 /* Parse any options */
125 if (argc <= 0 ) 114 while (--argc > 0 && **(++argv) == '-') {
126 usage(insmod_usage); 115 while (*(++(*argv))) {
127 116 switch (**argv) {
128 /* Grab the module name */ 117 case 'f':
129 if ((tmp = strrchr(*argv, '/')) != NULL) 118 break;
130 tmp++; 119 case 'k':
131 else 120 break;
132 tmp = *argv; 121 default:
133 len = strlen(tmp); 122 usage(insmod_usage);
134 123 }
135 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') 124 }
136 len -= 2;
137 memcpy(m_name, tmp, len);
138 strcpy(m_fullName, m_name);
139 strcat(m_fullName, ".o");
140
141 /* Get a filedesc for the module */
142 if ((fp = fopen(*argv, "r")) == NULL) {
143 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
144 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
145 findNamedModule, findNamedModule) == FALSE) {
146 if ( m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL)) {
147 perror("No module by that name found in " _PATH_MODULES "\n");
148 exit( FALSE);
149 }
150 } 125 }
151 } else
152 memcpy(m_filename, *argv, strlen(*argv));
153 126
127 if (argc <= 0)
128 usage(insmod_usage);
154 129
155 fprintf(stderr, "m_filename='%s'\n", m_filename); 130 /* Grab the module name */
156 fprintf(stderr, "m_name='%s'\n", m_name); 131 if ((tmp = strrchr(*argv, '/')) != NULL)
132 tmp++;
133 else
134 tmp = *argv;
135 len = strlen(tmp);
136
137 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
138 len -= 2;
139 memcpy(m_name, tmp, len);
140 strcpy(m_fullName, m_name);
141 strcat(m_fullName, ".o");
142
143 /* Get a filedesc for the module */
144 if ((fp = fopen(*argv, "r")) == NULL) {
145 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
146 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
147 findNamedModule, findNamedModule) == FALSE) {
148 if (m_filename[0] == '\0'
149 || ((fp = fopen(m_filename, "r")) == NULL)) {
150 perror("No module by that name found in " _PATH_MODULES
151 "\n");
152 exit(FALSE);
153 }
154 }
155 } else
156 memcpy(m_filename, *argv, strlen(*argv));
157
158
159 fprintf(stderr, "m_filename='%s'\n", m_filename);
160 fprintf(stderr, "m_name='%s'\n", m_name);
161
162
163 /* TODO: do something roughtly like this... */
164#if 0
157 165
166 if ((f = obj_load(fp)) == NULL) {
167 perror("Could not load the module\n");
168 exit(FALSE);
169 }
158 170
159 /* TODO: do something roughtly like this... */ 171 /* Let the module know about the kernel symbols. */
160#if 0 172 add_kernel_symbols(f);
161 173
162 if ((f = obj_load(fp)) == NULL) { 174 if (!create_this_module(f, m_name)) {
163 perror("Could not load the module\n"); 175 perror("Could not create the module\n");
164 exit( FALSE); 176 exit(FALSE);
165 }
166
167 /* Let the module know about the kernel symbols. */
168 add_kernel_symbols(f);
169
170 if (!create_this_module(f, m_name)) {
171 perror("Could not create the module\n");
172 exit( FALSE);
173 }
174
175 if (!obj_check_undefineds(f, quiet)) {
176 perror("Undefined symbols in the module\n");
177 exit( FALSE);
178 }
179 obj_allocate_commons(f);
180
181 /* Perse the module's arguments */
182 while (argc-- >0 && *(argv++) != '\0') {
183 if (!process_module_arguments(f, argc - optind, argv + optind)) {
184 perror("Undefined symbols in the module\n");
185 exit( FALSE);
186 } 177 }
187 }
188 178
189 /* Find current size of the module */ 179 if (!obj_check_undefineds(f, quiet)) {
190 m_size = obj_load_size(f); 180 perror("Undefined symbols in the module\n");
181 exit(FALSE);
182 }
183 obj_allocate_commons(f);
184
185 /* Perse the module's arguments */
186 while (argc-- > 0 && *(argv++) != '\0') {
187 if (!process_module_arguments(f, argc - optind, argv + optind)) {
188 perror("Undefined symbols in the module\n");
189 exit(FALSE);
190 }
191 }
192
193 /* Find current size of the module */
194 m_size = obj_load_size(f);
191 195
192 196
193 errno = 0; 197 errno = 0;
194 m_addr = create_module(m_name, m_size); 198 m_addr = create_module(m_name, m_size);
195 switch (errno) { 199 switch (errno) {
196 /* yada yada */ 200 /* yada yada */
197 default: 201 default:
198 perror("create_module: %m"); 202 perror("create_module: %m");
199 203
200 } 204 }
201 205
202#endif 206#endif
203 207
204 fclose( fp); 208 fclose(fp);
205 exit( TRUE); 209 exit(TRUE);
206} 210}
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index 1696f756e..d9c40eaaf 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini lsmod implementation for busybox 3 * Mini lsmod implementation for busybox
3 * 4 *
@@ -30,6 +31,7 @@
30 31
31extern int lsmod_main(int argc, char **argv) 32extern int lsmod_main(int argc, char **argv)
32{ 33{
33 char* cmd[] = { "cat", "/proc/modules", "\0" }; 34 char *cmd[] = { "cat", "/proc/modules", "\0" };
34 exit(cat_main( 3, cmd)); 35
36 exit(cat_main(3, cmd));
35} 37}
diff --git a/modutils/rmmod.c b/modutils/rmmod.c
index 6b15b48bb..a0db4ae5c 100644
--- a/modutils/rmmod.c
+++ b/modutils/rmmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rmmod implementation for busybox 3 * Mini rmmod implementation for busybox
3 * 4 *
@@ -33,41 +34,41 @@ _syscall1(int, delete_module, const char *, name)
33 34
34 35
35static const char rmmod_usage[] = 36static const char rmmod_usage[] =
36 "rmmod [OPTION]... [MODULE]...\n\n" 37 "rmmod [OPTION]... [MODULE]...\n\n"
37 "Unloads the specified kernel modules from the kernel.\n\n" 38 "Unloads the specified kernel modules from the kernel.\n\n"
38 "Options:\n" 39
39 "\t-a\tTry to remove all unused kernel modules.\n"; 40 "Options:\n" "\t-a\tTry to remove all unused kernel modules.\n";
40 41
41 42
42 43
43extern int rmmod_main(int argc, char **argv) 44extern int rmmod_main(int argc, char **argv)
44{ 45{
45 if (argc<=1) { 46 if (argc <= 1) {
46 usage(rmmod_usage); 47 usage(rmmod_usage);
47 } 48 }
48 49
49 /* Parse any options */ 50 /* Parse any options */
50 while (--argc > 0 && **(++argv) == '-') { 51 while (--argc > 0 && **(++argv) == '-') {
51 while (*(++(*argv))) { 52 while (*(++(*argv))) {
52 switch (**argv) { 53 switch (**argv) {
53 case 'a': 54 case 'a':
54 /* Unload _all_ unused modules via NULL delete_module() call */ 55 /* Unload _all_ unused modules via NULL delete_module() call */
55 if (delete_module(NULL)) { 56 if (delete_module(NULL)) {
56 perror("rmmod"); 57 perror("rmmod");
57 exit( FALSE); 58 exit(FALSE);
59 }
60 exit(TRUE);
61 default:
62 usage(rmmod_usage);
63 }
58 } 64 }
59 exit( TRUE);
60 default:
61 usage(rmmod_usage);
62 }
63 } 65 }
64 }
65 66
66 while (argc-- > 0 ) { 67 while (argc-- > 0) {
67 if (delete_module(*argv) < 0) { 68 if (delete_module(*argv) < 0) {
68 perror(*argv); 69 perror(*argv);
70 }
71 argv++;
69 } 72 }
70 argv++; 73 exit(TRUE);
71 }
72 exit( TRUE);
73} 74}
diff --git a/more.c b/more.c
index 821427dda..d5711aa2f 100644
--- a/more.c
+++ b/more.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini more implementation for busybox 3 * Mini more implementation for busybox
3 * 4 *
@@ -45,19 +46,20 @@ static const char more_usage[] = "more [file ...]\n";
45# define stty(fd,argp) tcsetattr(fd,TCSANOW,argp) 46# define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
46#endif 47#endif
47 48
48 FILE *cin; 49FILE *cin;
49 struct termios initial_settings, new_settings; 50struct termios initial_settings, new_settings;
50 51
51 void gotsig(int sig) { 52void gotsig(int sig)
52 stty(fileno(cin), &initial_settings); 53{
53 fprintf(stdout, "\n"); 54 stty(fileno(cin), &initial_settings);
54 exit( TRUE); 55 fprintf(stdout, "\n");
55 } 56 exit(TRUE);
57}
56#endif 58#endif
57 59
58 60
59 61
60#define TERMINAL_WIDTH 79 /* not 80 in case terminal has linefold bug */ 62#define TERMINAL_WIDTH 79 /* not 80 in case terminal has linefold bug */
61#define TERMINAL_HEIGHT 24 63#define TERMINAL_HEIGHT 24
62 64
63 65
@@ -72,118 +74,121 @@ static int terminal_width = 0, terminal_height = 0;
72 74
73extern int more_main(int argc, char **argv) 75extern int more_main(int argc, char **argv)
74{ 76{
75 int c, lines=0, input=0; 77 int c, lines = 0, input = 0;
76 int next_page=0; 78 int next_page = 0;
77 struct stat st; 79 struct stat st;
78 FILE *file; 80 FILE *file;
81
79#ifdef BB_FEATURE_AUTOWIDTH 82#ifdef BB_FEATURE_AUTOWIDTH
80 struct winsize win = {0,0}; 83 struct winsize win = { 0, 0 };
81#endif 84#endif
82 85
83 argc--; 86 argc--;
84 argv++; 87 argv++;
85
86 if ( argc > 0 && (strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0) ) {
87 usage (more_usage);
88 }
89 do {
90 if (argc==0) {
91 file = stdin;
92 }
93 else
94 file = fopen(*argv, "r");
95 88
96 if (file == NULL) { 89 if (argc > 0
97 perror(*argv); 90 && (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0)) {
98 exit(FALSE); 91 usage(more_usage);
99 } 92 }
100 fstat(fileno(file), &st); 93 do {
94 if (argc == 0) {
95 file = stdin;
96 } else
97 file = fopen(*argv, "r");
98
99 if (file == NULL) {
100 perror(*argv);
101 exit(FALSE);
102 }
103 fstat(fileno(file), &st);
101 104
102#ifdef BB_FEATURE_USE_TERMIOS 105#ifdef BB_FEATURE_USE_TERMIOS
103 cin = fopen("/dev/tty", "r"); 106 cin = fopen("/dev/tty", "r");
104 if (!cin) 107 if (!cin)
105 cin = fopen("/dev/console", "r"); 108 cin = fopen("/dev/console", "r");
106#ifdef USE_OLD_TERMIO 109#ifdef USE_OLD_TERMIO
107 ioctl(fileno(cin),TCGETA,&initial_settings); 110 ioctl(fileno(cin), TCGETA, &initial_settings);
108#else 111#else
109 tcgetattr(fileno(cin),&initial_settings); 112 tcgetattr(fileno(cin), &initial_settings);
110#endif 113#endif
111 new_settings = initial_settings; 114 new_settings = initial_settings;
112 new_settings.c_lflag &= ~ICANON; 115 new_settings.c_lflag &= ~ICANON;
113 new_settings.c_lflag &= ~ECHO; 116 new_settings.c_lflag &= ~ECHO;
114 stty(fileno(cin), &new_settings); 117 stty(fileno(cin), &new_settings);
115 118
116#ifdef BB_FEATURE_AUTOWIDTH 119#ifdef BB_FEATURE_AUTOWIDTH
117 ioctl(fileno(stdout), TIOCGWINSZ, &win); 120 ioctl(fileno(stdout), TIOCGWINSZ, &win);
118 if (win.ws_row > 4) 121 if (win.ws_row > 4)
119 terminal_height = win.ws_row - 2; 122 terminal_height = win.ws_row - 2;
120 if (win.ws_col > 0) 123 if (win.ws_col > 0)
121 terminal_width = win.ws_col - 1; 124 terminal_width = win.ws_col - 1;
122#endif 125#endif
123 126
124 (void) signal(SIGINT, gotsig); 127 (void) signal(SIGINT, gotsig);
125 (void) signal(SIGQUIT, gotsig); 128 (void) signal(SIGQUIT, gotsig);
126 (void) signal(SIGTERM, gotsig); 129 (void) signal(SIGTERM, gotsig);
127 130
128#endif 131#endif
129 while ((c = getc(file)) != EOF) { 132 while ((c = getc(file)) != EOF) {
130 if ( next_page ) { 133 if (next_page) {
131 int len=0; 134 int len = 0;
132 next_page = 0; 135
133 lines=0; 136 next_page = 0;
134 len = fprintf(stdout, "--More-- "); 137 lines = 0;
135 if (file != stdin) { 138 len = fprintf(stdout, "--More-- ");
136 len += fprintf(stdout, "(%d%% of %ld bytes)", 139 if (file != stdin) {
137 (int) (100*( (double) ftell(file) / (double) st.st_size )), 140 len += fprintf(stdout, "(%d%% of %ld bytes)",
138 st.st_size); 141 (int) (100 *
139 } 142 ((double) ftell(file) /
140 len += fprintf(stdout, "%s", 143 (double) st.st_size)),
144 st.st_size);
145 }
146 len += fprintf(stdout, "%s",
141#ifdef BB_FEATURE_USE_TERMIOS 147#ifdef BB_FEATURE_USE_TERMIOS
142 "" 148 ""
143#else 149#else
144 "\n" 150 "\n"
145#endif 151#endif
146 ); 152 );
147 153
148 fflush(stdout); 154 fflush(stdout);
149 input = getc( cin); 155 input = getc(cin);
150 156
151#ifdef BB_FEATURE_USE_TERMIOS 157#ifdef BB_FEATURE_USE_TERMIOS
152 /* Erase the "More" message */ 158 /* Erase the "More" message */
153 while(--len >= 0) 159 while (--len >= 0)
154 putc('\b', stdout); 160 putc('\b', stdout);
155 while(++len <= terminal_width) 161 while (++len <= terminal_width)
156 putc(' ', stdout); 162 putc(' ', stdout);
157 while(--len >= 0) 163 while (--len >= 0)
158 putc('\b', stdout); 164 putc('\b', stdout);
159 fflush(stdout); 165 fflush(stdout);
160#endif 166#endif
161 167
162 } 168 }
163 if (c == '\n' ) { 169 if (c == '\n') {
164 switch(input) { 170 switch (input) {
165 case 'q': 171 case 'q':
166 goto end; 172 goto end;
167 case '\n': 173 case '\n':
168 /* increment by just one line if we are at 174 /* increment by just one line if we are at
169 * the end of this line*/ 175 * the end of this line*/
170 next_page = 1; 176 next_page = 1;
171 break; 177 break;
178 }
179 if (++lines == terminal_height)
180 next_page = 1;
181 }
182 putc(c, stdout);
172 } 183 }
173 if ( ++lines == terminal_height ) 184 fclose(file);
174 next_page = 1; 185 fflush(stdout);
175 }
176 putc(c, stdout);
177 }
178 fclose(file);
179 fflush(stdout);
180 186
181 argv++; 187 argv++;
182 } while (--argc > 0); 188 } while (--argc > 0);
183end: 189 end:
184#ifdef BB_FEATURE_USE_TERMIOS 190#ifdef BB_FEATURE_USE_TERMIOS
185 gotsig(0); 191 gotsig(0);
186#endif 192#endif
187 exit(TRUE); 193 exit(TRUE);
188} 194}
189
diff --git a/mount.c b/mount.c
index 4c9e77be0..c3e3bbd75 100644
--- a/mount.c
+++ b/mount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mount implementation for busybox 3 * Mini mount implementation for busybox
3 * 4 *
@@ -55,357 +56,371 @@
55static int use_loop = 0; 56static int use_loop = 0;
56#endif 57#endif
57 58
58extern const char mtab_file[]; /* Defined in utility.c */ 59extern const char mtab_file[]; /* Defined in utility.c */
59 60
60static const char mount_usage[] = "\tmount [flags]\n" 61static const char mount_usage[] = "\tmount [flags]\n"
61 "\tmount [flags] device directory [-o options,more-options]\n" 62 "\tmount [flags] device directory [-o options,more-options]\n"
62 "\n" 63 "\n" "Flags:\n" "\t-a:\tMount all file systems in fstab.\n"
63 "Flags:\n"
64 "\t-a:\tMount all file systems in fstab.\n"
65#ifdef BB_MTAB 64#ifdef BB_MTAB
66 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" 65 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n"
67 "\t-n:\tDon't write a mount table entry.\n" 66 "\t-n:\tDon't write a mount table entry.\n"
68#endif 67#endif
69 "\t-o option:\tOne of many filesystem options, listed below.\n" 68 "\t-o option:\tOne of many filesystem options, listed below.\n"
70 "\t-r:\tMount the filesystem read-only.\n" 69 "\t-r:\tMount the filesystem read-only.\n"
71 "\t-t filesystem-type:\tSpecify the filesystem type.\n" 70 "\t-t filesystem-type:\tSpecify the filesystem type.\n"
72 "\t-w:\tMount for reading and writing (default).\n" 71 "\t-w:\tMount for reading and writing (default).\n"
73 "\n" 72 "\n"
74 "Options for use with the \"-o\" flag:\n" 73 "Options for use with the \"-o\" flag:\n"
75 "\tasync / sync:\tWrites are asynchronous / synchronous.\n" 74 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
76 "\tdev / nodev:\tAllow use of special device files / disallow them.\n" 75 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
77 "\texec / noexec:\tAllow use of executable files / disallow them.\n" 76 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
78#if defined BB_FEATURE_MOUNT_LOOP 77#if defined BB_FEATURE_MOUNT_LOOP
79 "\tloop: Mounts a file via loop device.\n" 78 "\tloop: Mounts a file via loop device.\n"
80#endif 79#endif
81 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" 80 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
82 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" 81 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
83 "\tro / rw: Mount for read-only / read-write.\n" 82 "\tro / rw: Mount for read-only / read-write.\n"
84 "\t" 83 "\t"
85 "There are EVEN MORE flags that are specific to each filesystem.\n" 84
86 "You'll have to see the written documentation for those.\n"; 85 "There are EVEN MORE flags that are specific to each filesystem.\n"
86 "You'll have to see the written documentation for those.\n";
87 87
88 88
89struct mount_options { 89struct mount_options {
90 const char *name; 90 const char *name;
91 unsigned long and; 91 unsigned long and;
92 unsigned long or; 92 unsigned long or;
93}; 93};
94 94
95static const struct mount_options mount_options[] = { 95static const struct mount_options mount_options[] = {
96 {"async", ~MS_SYNCHRONOUS, 0}, 96 {"async", ~MS_SYNCHRONOUS, 0},
97 {"defaults", ~0, 0}, 97 {"defaults", ~0, 0},
98 {"dev", ~MS_NODEV, 0}, 98 {"dev", ~MS_NODEV, 0},
99 {"exec", ~MS_NOEXEC, 0}, 99 {"exec", ~MS_NOEXEC, 0},
100 {"nodev", ~0, MS_NODEV}, 100 {"nodev", ~0, MS_NODEV},
101 {"noexec", ~0, MS_NOEXEC}, 101 {"noexec", ~0, MS_NOEXEC},
102 {"nosuid", ~0, MS_NOSUID}, 102 {"nosuid", ~0, MS_NOSUID},
103 {"remount", ~0, MS_REMOUNT}, 103 {"remount", ~0, MS_REMOUNT},
104 {"ro", ~0, MS_RDONLY}, 104 {"ro", ~0, MS_RDONLY},
105 {"rw", ~MS_RDONLY, 0}, 105 {"rw", ~MS_RDONLY, 0},
106 {"suid", ~MS_NOSUID, 0}, 106 {"suid", ~MS_NOSUID, 0},
107 {"sync", ~0, MS_SYNCHRONOUS}, 107 {"sync", ~0, MS_SYNCHRONOUS},
108 {0, 0, 0} 108 {0, 0, 0}
109}; 109};
110 110
111static int 111static int
112do_mount(char* specialfile, char* dir, char* filesystemtype, 112do_mount(char *specialfile, char *dir, char *filesystemtype,
113 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts) 113 long flags, void *string_flags, int useMtab, int fakeIt,
114 char *mtab_opts)
114{ 115{
115 int status=0; 116 int status = 0;
116 117
117#if defined BB_MTAB 118#if defined BB_MTAB
118 if (fakeIt==FALSE) 119 if (fakeIt == FALSE)
119#endif 120#endif
120 { 121 {
121#if defined BB_FEATURE_MOUNT_LOOP 122#if defined BB_FEATURE_MOUNT_LOOP
122 if (use_loop) { 123 if (use_loop) {
123 int loro = flags & MS_RDONLY; 124 int loro = flags & MS_RDONLY;
124 char *lofile = specialfile; 125 char *lofile = specialfile;
125 specialfile = find_unused_loop_device(); 126
126 if (specialfile == NULL) { 127 specialfile = find_unused_loop_device();
127 fprintf(stderr, "Could not find a spare loop device\n"); 128 if (specialfile == NULL) {
128 return( FALSE); 129 fprintf(stderr, "Could not find a spare loop device\n");
129 } 130 return (FALSE);
130 if (set_loop (specialfile, lofile, 0, &loro)) { 131 }
131 fprintf(stderr, "Could not setup loop device\n"); 132 if (set_loop(specialfile, lofile, 0, &loro)) {
132 return( FALSE); 133 fprintf(stderr, "Could not setup loop device\n");
133 } 134 return (FALSE);
134 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ 135 }
135 fprintf(stderr, "WARNING: loop device is read-only\n"); 136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
136 flags &= ~MS_RDONLY; 137 fprintf(stderr, "WARNING: loop device is read-only\n");
137 } 138 flags &= ~MS_RDONLY;
138 } 139 }
140 }
139#endif 141#endif
140 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 142 status =
141 } 143 mount(specialfile, dir, filesystemtype, flags, string_flags);
144 }
142 145
143 146
144 /* If the mount was sucessful, do anything needed, then return TRUE */ 147 /* If the mount was sucessful, do anything needed, then return TRUE */
145 if (status == 0) { 148 if (status == 0) {
146 149
147#if defined BB_MTAB 150#if defined BB_MTAB
148 if (useMtab==TRUE) { 151 if (useMtab == TRUE) {
149 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 152 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
150 } 153 }
151#endif 154#endif
152 return( TRUE); 155 return (TRUE);
153 } 156 }
154 157
155 /* Bummer. mount failed. Clean up */ 158 /* Bummer. mount failed. Clean up */
156#if defined BB_FEATURE_MOUNT_LOOP 159#if defined BB_FEATURE_MOUNT_LOOP
157 if (specialfile != NULL) { 160 if (specialfile != NULL) {
158 del_loop(specialfile); 161 del_loop(specialfile);
159 } 162 }
160#endif 163#endif
161 return( FALSE); 164 return (FALSE);
162} 165}
163 166
164 167
165 168
166#if defined BB_MTAB 169#if defined BB_MTAB
167#define whine_if_fstab_is_missing() {} 170#define whine_if_fstab_is_missing() {}
168#else 171#else
169extern void whine_if_fstab_is_missing() 172extern void whine_if_fstab_is_missing()
170{ 173{
171 struct stat statBuf; 174 struct stat statBuf;
172 if (stat("/etc/fstab", &statBuf) < 0) 175
173 fprintf(stderr, "/etc/fstab file missing -- install one to name /dev/root.\n\n"); 176 if (stat("/etc/fstab", &statBuf) < 0)
177 fprintf(stderr,
178 "/etc/fstab file missing -- install one to name /dev/root.\n\n");
174} 179}
175#endif 180#endif
176 181
177 182
178/* Seperate standard mount options from the nonstandard string options */ 183/* Seperate standard mount options from the nonstandard string options */
179static void 184static void
180parse_mount_options ( char *options, unsigned long *flags, char *strflags) 185parse_mount_options(char *options, unsigned long *flags, char *strflags)
181{ 186{
182 while (options) { 187 while (options) {
183 int gotone=FALSE; 188 int gotone = FALSE;
184 char *comma = strchr (options, ','); 189 char *comma = strchr(options, ',');
185 const struct mount_options* f = mount_options; 190 const struct mount_options *f = mount_options;
186 if (comma) 191
187 *comma = '\0'; 192 if (comma)
188 193 *comma = '\0';
189 while (f->name != 0) { 194
190 if (strcasecmp (f->name, options) == 0) { 195 while (f->name != 0) {
191 196 if (strcasecmp(f->name, options) == 0) {
192 *flags &= f->and; 197
193 *flags |= f->or; 198 *flags &= f->and;
194 gotone=TRUE; 199 *flags |= f->or;
195 break; 200 gotone = TRUE;
196 } 201 break;
197 f++; 202 }
198 } 203 f++;
204 }
199#if defined BB_FEATURE_MOUNT_LOOP 205#if defined BB_FEATURE_MOUNT_LOOP
200 if (gotone==FALSE && !strcasecmp ("loop", options)) { /* loop device support */ 206 if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */
201 use_loop = 1; 207 use_loop = 1;
202 gotone=TRUE; 208 gotone = TRUE;
203 } 209 }
204#endif 210#endif
205 if (*strflags && strflags!= '\0' && gotone==FALSE) { 211 if (*strflags && strflags != '\0' && gotone == FALSE) {
206 char *temp=strflags; 212 char *temp = strflags;
207 temp += strlen (strflags); 213
208 *temp++ = ','; 214 temp += strlen(strflags);
209 *temp++ = '\0'; 215 *temp++ = ',';
210 } 216 *temp++ = '\0';
211 if (gotone==FALSE) 217 }
212 strcat (strflags, options); 218 if (gotone == FALSE)
213 if (comma) { 219 strcat(strflags, options);
214 *comma = ','; 220 if (comma) {
215 options = ++comma; 221 *comma = ',';
216 } else { 222 options = ++comma;
217 break; 223 } else {
224 break;
225 }
218 } 226 }
219 }
220} 227}
221 228
222int 229int
223mount_one(char *blockDevice, char *directory, char *filesystemType, 230mount_one(char *blockDevice, char *directory, char *filesystemType,
224 unsigned long flags, char *string_flags, int useMtab, int fakeIt, char *mtab_opts) 231 unsigned long flags, char *string_flags, int useMtab, int fakeIt,
232 char *mtab_opts)
225{ 233{
226 int status = 0; 234 int status = 0;
227 235
228 char buf[255]; 236 char buf[255];
229 237
230#if defined BB_FEATURE_USE_PROCFS 238#if defined BB_FEATURE_USE_PROCFS
231 if (strcmp(filesystemType, "auto") == 0) { 239 if (strcmp(filesystemType, "auto") == 0) {
232 FILE *f = fopen ("/proc/filesystems", "r"); 240 FILE *f = fopen("/proc/filesystems", "r");
233 241
234 if (f == NULL) 242 if (f == NULL)
235 return( FALSE); 243 return (FALSE);
236 244
237 while (fgets (buf, sizeof (buf), f) != NULL) { 245 while (fgets(buf, sizeof(buf), f) != NULL) {
238 filesystemType = buf; 246 filesystemType = buf;
239 if (*filesystemType == '\t') { // Not a nodev filesystem 247 if (*filesystemType == '\t') { // Not a nodev filesystem
240 248
241 // Add NULL termination to each line 249 // Add NULL termination to each line
242 while (*filesystemType && *filesystemType != '\n') 250 while (*filesystemType && *filesystemType != '\n')
243 filesystemType++; 251 filesystemType++;
244 *filesystemType = '\0'; 252 *filesystemType = '\0';
245 253
246 filesystemType = buf; 254 filesystemType = buf;
247 filesystemType++; // hop past tab 255 filesystemType++; // hop past tab
248 256
249 status = do_mount (blockDevice, directory, filesystemType, 257 status = do_mount(blockDevice, directory, filesystemType,
250 flags | MS_MGC_VAL, string_flags, useMtab, 258 flags | MS_MGC_VAL, string_flags,
251 fakeIt, mtab_opts); 259 useMtab, fakeIt, mtab_opts);
252 if (status == TRUE) 260 if (status == TRUE)
253 break; 261 break;
254 } 262 }
255 } 263 }
256 fclose (f); 264 fclose(f);
257 } else 265 } else
258#endif 266#endif
259 { 267 {
260 status = do_mount (blockDevice, directory, filesystemType, 268 status = do_mount(blockDevice, directory, filesystemType,
261 flags | MS_MGC_VAL, string_flags, useMtab, 269 flags | MS_MGC_VAL, string_flags, useMtab,
262 fakeIt, mtab_opts); 270 fakeIt, mtab_opts);
263 } 271 }
264 272
265 if (status==FALSE) { 273 if (status == FALSE) {
266 fprintf (stderr, "Mounting %s on %s failed: %s\n", 274 fprintf(stderr, "Mounting %s on %s failed: %s\n",
267 blockDevice, directory, strerror(errno)); 275 blockDevice, directory, strerror(errno));
268 return (FALSE); 276 return (FALSE);
269 } 277 }
270 return (TRUE); 278 return (TRUE);
271} 279}
272 280
273extern int mount_main (int argc, char **argv) 281extern int mount_main(int argc, char **argv)
274{ 282{
275 char string_flags_buf[1024]=""; 283 char string_flags_buf[1024] = "";
276 char *string_flags = string_flags_buf; 284 char *string_flags = string_flags_buf;
277 char *extra_opts = string_flags_buf; 285 char *extra_opts = string_flags_buf;
278 unsigned long flags = 0; 286 unsigned long flags = 0;
279 char *filesystemType = "auto"; 287 char *filesystemType = "auto";
280 char *device = NULL; 288 char *device = NULL;
281 char *directory = NULL; 289 char *directory = NULL;
282 int all = FALSE; 290 int all = FALSE;
283 int fakeIt = FALSE; 291 int fakeIt = FALSE;
284 int useMtab = TRUE; 292 int useMtab = TRUE;
285 int i; 293 int i;
286 294
287 /* Only compiled in if BB_MTAB is not defined */ 295 /* Only compiled in if BB_MTAB is not defined */
288 whine_if_fstab_is_missing(); 296 whine_if_fstab_is_missing();
289 297
290 if (argc == 1) { 298 if (argc == 1) {
291 FILE *mountTable = setmntent (mtab_file, "r"); 299 FILE *mountTable = setmntent(mtab_file, "r");
292 if (mountTable) { 300
293 struct mntent *m; 301 if (mountTable) {
294 while ((m = getmntent (mountTable)) != 0) { 302 struct mntent *m;
295 struct fstab* fstabItem; 303
296 char *blockDevice = m->mnt_fsname; 304 while ((m = getmntent(mountTable)) != 0) {
297 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */ 305 struct fstab *fstabItem;
298 if (strcmp (blockDevice, "/dev/root") == 0) { 306 char *blockDevice = m->mnt_fsname;
299 fstabItem = getfsfile ("/"); 307
300 if (fstabItem != NULL) 308 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
301 blockDevice = fstabItem->fs_spec; 309 if (strcmp(blockDevice, "/dev/root") == 0) {
310 fstabItem = getfsfile("/");
311 if (fstabItem != NULL)
312 blockDevice = fstabItem->fs_spec;
313 }
314 printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
315 m->mnt_type, m->mnt_opts);
316 }
317 endmntent(mountTable);
318 } else {
319 perror(mtab_file);
302 } 320 }
303 printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, 321 exit(TRUE);
304 m->mnt_type, m->mnt_opts);
305 }
306 endmntent (mountTable);
307 } else {
308 perror(mtab_file);
309 } 322 }
310 exit( TRUE); 323
311 } 324
312 325 /* Parse options */
313 326 i = --argc;
314 /* Parse options */ 327 argv++;
315 i = --argc; 328 while (i > 0 && **argv) {
316 argv++; 329 if (**argv == '-') {
317 while (i > 0 && **argv) { 330 char *opt = *argv;
318 if (**argv == '-') { 331
319 char *opt = *argv; 332 while (i > 0 && *++opt)
320 while (i>0 && *++opt) switch (*opt) { 333 switch (*opt) {
321 case 'o': 334 case 'o':
322 if (--i == 0) { 335 if (--i == 0) {
323 goto goodbye; 336 goto goodbye;
324 } 337 }
325 parse_mount_options (*(++argv), &flags, string_flags); 338 parse_mount_options(*(++argv), &flags, string_flags);
326 break; 339 break;
327 case 'r': 340 case 'r':
328 flags |= MS_RDONLY; 341 flags |= MS_RDONLY;
329 break; 342 break;
330 case 't': 343 case 't':
331 if (--i == 0) { 344 if (--i == 0) {
332 goto goodbye; 345 goto goodbye;
333 } 346 }
334 filesystemType = *(++argv); 347 filesystemType = *(++argv);
335 break; 348 break;
336 case 'w': 349 case 'w':
337 flags &= ~MS_RDONLY; 350 flags &= ~MS_RDONLY;
338 break; 351 break;
339 case 'a': 352 case 'a':
340 all = TRUE; 353 all = TRUE;
341 break; 354 break;
342#ifdef BB_MTAB 355#ifdef BB_MTAB
343 case 'f': 356 case 'f':
344 fakeIt = TRUE; 357 fakeIt = TRUE;
345 break; 358 break;
346 case 'n': 359 case 'n':
347 useMtab = FALSE; 360 useMtab = FALSE;
348 break; 361 break;
349#endif 362#endif
350 case 'v': 363 case 'v':
351 case 'h': 364 case 'h':
352 case '-': 365 case '-':
353 goto goodbye; 366 goto goodbye;
354 } 367 }
355 } else { 368 } else {
356 if (device == NULL) 369 if (device == NULL)
357 device = *argv; 370 device = *argv;
358 else if (directory == NULL) 371 else if (directory == NULL)
359 directory = *argv; 372 directory = *argv;
360 else { 373 else {
361 goto goodbye; 374 goto goodbye;
362 } 375 }
376 }
377 i--;
378 argv++;
363 } 379 }
364 i--;
365 argv++;
366 }
367 380
368 if (all == TRUE) { 381 if (all == TRUE) {
369 struct mntent *m; 382 struct mntent *m;
370 FILE *f = setmntent ("/etc/fstab", "r"); 383 FILE *f = setmntent("/etc/fstab", "r");
371 384
372 if (f == NULL) { 385 if (f == NULL) {
373 perror("/etc/fstab"); 386 perror("/etc/fstab");
374 exit( FALSE); 387 exit(FALSE);
375 } 388 }
376 while ((m = getmntent (f)) != NULL) { 389 while ((m = getmntent(f)) != NULL) {
377 // If the file system isn't noauto, and isn't mounted on /, 390 // If the file system isn't noauto, and isn't mounted on /,
378 // and isn't swap or nfs, then mount it 391 // and isn't swap or nfs, then mount it
379 if ((!strstr (m->mnt_opts, "noauto")) && 392 if ((!strstr(m->mnt_opts, "noauto")) &&
380 (m->mnt_dir[1] != '\0') && 393 (m->mnt_dir[1] != '\0') &&
381 (!strstr (m->mnt_type, "swap")) && 394 (!strstr(m->mnt_type, "swap")) &&
382 (!strstr (m->mnt_type, "nfs"))) 395 (!strstr(m->mnt_type, "nfs"))) {
383 { 396 flags = 0;
384 flags = 0; 397 *string_flags = '\0';
385 *string_flags = '\0'; 398 parse_mount_options(m->mnt_opts, &flags, string_flags);
386 parse_mount_options(m->mnt_opts, &flags, string_flags); 399 mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
387 mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, 400 flags, string_flags, useMtab, fakeIt,
388 flags, string_flags, useMtab, fakeIt, extra_opts); 401 extra_opts);
389 } 402 }
390 } 403 }
391 endmntent (f); 404 endmntent(f);
392 } else { 405 } else {
393 if (device && directory) { 406 if (device && directory) {
394#ifdef BB_NFSMOUNT 407#ifdef BB_NFSMOUNT
395 if (strcmp(filesystemType, "nfs") == 0) { 408 if (strcmp(filesystemType, "nfs") == 0) {
396 if (nfsmount(device, directory, &flags, &extra_opts, &string_flags, 1) != 0) 409 if (nfsmount
397 exit(FALSE); 410 (device, directory, &flags, &extra_opts, &string_flags,
398 } 411 1) != 0)
412 exit(FALSE);
413 }
399#endif 414#endif
400 exit (mount_one (device, directory, filesystemType, 415 exit(mount_one(device, directory, filesystemType,
401 flags, string_flags, useMtab, fakeIt, extra_opts)); 416 flags, string_flags, useMtab, fakeIt,
402 } else { 417 extra_opts));
403 goto goodbye; 418 } else {
419 goto goodbye;
420 }
404 } 421 }
405 } 422 exit(TRUE);
406 exit( TRUE);
407 423
408goodbye: 424 goodbye:
409 usage( mount_usage); 425 usage(mount_usage);
410} 426}
411
diff --git a/mt.c b/mt.c
index 7168ef7ac..9791b64b2 100644
--- a/mt.c
+++ b/mt.c
@@ -1,97 +1,97 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <sys/mtio.h> 4#include <sys/mtio.h>
4#include <sys/fcntl.h> 5#include <sys/fcntl.h>
5 6
6static const char mt_usage[] = "mt [-f device] opcode value\n"; 7static const char mt_usage[] = "mt [-f device] opcode value\n";
7 8
8struct mt_opcodes { 9struct mt_opcodes {
9 char * name; 10 char *name;
10 short value; 11 short value;
11}; 12};
12 13
13/* missing: eod/seod, stoptions, stwrthreshold, densities */ 14/* missing: eod/seod, stoptions, stwrthreshold, densities */
14static const struct mt_opcodes opcodes[] = { 15static const struct mt_opcodes opcodes[] = {
15 { "bsf", MTBSF }, 16 {"bsf", MTBSF},
16 { "bsfm", MTBSFM }, 17 {"bsfm", MTBSFM},
17 { "bsr", MTBSR }, 18 {"bsr", MTBSR},
18 { "bss", MTBSS }, 19 {"bss", MTBSS},
19 { "datacompression", MTCOMPRESSION }, 20 {"datacompression", MTCOMPRESSION},
20 { "eom", MTEOM }, 21 {"eom", MTEOM},
21 { "erase", MTERASE }, 22 {"erase", MTERASE},
22 { "fsf", MTFSF }, 23 {"fsf", MTFSF},
23 { "fsfm", MTFSFM }, 24 {"fsfm", MTFSFM},
24 { "fsr", MTFSR }, 25 {"fsr", MTFSR},
25 { "fss", MTFSS }, 26 {"fss", MTFSS},
26 { "load", MTLOAD }, 27 {"load", MTLOAD},
27 { "lock", MTLOCK }, 28 {"lock", MTLOCK},
28 { "mkpart", MTMKPART }, 29 {"mkpart", MTMKPART},
29 { "nop", MTNOP }, 30 {"nop", MTNOP},
30 { "offline",MTOFFL }, 31 {"offline", MTOFFL},
31 { "rewoffline",MTOFFL }, 32 {"rewoffline", MTOFFL},
32 { "ras1", MTRAS1 }, 33 {"ras1", MTRAS1},
33 { "ras2", MTRAS2 }, 34 {"ras2", MTRAS2},
34 { "ras3", MTRAS3 }, 35 {"ras3", MTRAS3},
35 { "reset", MTRESET }, 36 {"reset", MTRESET},
36 { "retension", MTRETEN }, 37 {"retension", MTRETEN},
37 { "rew", MTREW }, 38 {"rew", MTREW},
38 { "seek", MTSEEK }, 39 {"seek", MTSEEK},
39 { "setblk", MTSETBLK }, 40 {"setblk", MTSETBLK},
40 { "setdensity", MTSETDENSITY }, 41 {"setdensity", MTSETDENSITY},
41 { "drvbuffer", MTSETDRVBUFFER }, 42 {"drvbuffer", MTSETDRVBUFFER},
42 { "setpart", MTSETPART }, 43 {"setpart", MTSETPART},
43 { "tell", MTTELL }, 44 {"tell", MTTELL},
44 { "wset", MTWSM }, 45 {"wset", MTWSM},
45 { "unload", MTUNLOAD }, 46 {"unload", MTUNLOAD},
46 { "unlock", MTUNLOCK }, 47 {"unlock", MTUNLOCK},
47 { "eof", MTWEOF }, 48 {"eof", MTWEOF},
48 { "weof", MTWEOF }, 49 {"weof", MTWEOF},
49 { 0, 0 } 50 {0, 0}
50}; 51};
51 52
52extern int 53extern int mt_main(int argc, char **argv)
53mt_main(int argc, char** argv)
54{ 54{
55 const char * file = "/dev/tape"; 55 const char *file = "/dev/tape";
56 const struct mt_opcodes * code = opcodes; 56 const struct mt_opcodes *code = opcodes;
57 struct mtop op; 57 struct mtop op;
58 int fd; 58 int fd;
59 59
60 if ( strcmp(argv[1], "-f") == 0 ) { 60 if (strcmp(argv[1], "-f") == 0) {
61 if ( argc < 4 ) { 61 if (argc < 4) {
62 usage (mt_usage); 62 usage(mt_usage);
63 } 63 }
64 file = argv[2]; 64 file = argv[2];
65 argv += 2; 65 argv += 2;
66 argc -= 2; 66 argc -= 2;
67 } 67 }
68 68
69 while ( code->name != 0 ) { 69 while (code->name != 0) {
70 if ( strcmp(code->name, argv[1]) == 0 ) 70 if (strcmp(code->name, argv[1]) == 0)
71 break; 71 break;
72 code++; 72 code++;
73 } 73 }
74 74
75 if ( code->name == 0 ) { 75 if (code->name == 0) {
76 fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]); 76 fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
77 return( FALSE); 77 return (FALSE);
78 } 78 }
79 79
80 op.mt_op = code->value; 80 op.mt_op = code->value;
81 if ( argc >= 3 ) 81 if (argc >= 3)
82 op.mt_count = atoi(argv[2]); 82 op.mt_count = atoi(argv[2]);
83 else 83 else
84 op.mt_count = 1; /* One, not zero, right? */ 84 op.mt_count = 1; /* One, not zero, right? */
85 85
86 if ( (fd = open(file, O_RDONLY, 0)) < 0 ) { 86 if ((fd = open(file, O_RDONLY, 0)) < 0) {
87 perror(file); 87 perror(file);
88 return( FALSE); 88 return (FALSE);
89 } 89 }
90 90
91 if ( ioctl(fd, MTIOCTOP, &op) != 0 ) { 91 if (ioctl(fd, MTIOCTOP, &op) != 0) {
92 perror(file); 92 perror(file);
93 return( FALSE); 93 return (FALSE);
94 } 94 }
95 95
96 return( TRUE); 96 return (TRUE);
97} 97}
diff --git a/mtab.c b/mtab.c
index 41d88184b..27489cfd4 100644
--- a/mtab.c
+++ b/mtab.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2#include <stdlib.h> 3#include <stdlib.h>
3#include <unistd.h> 4#include <unistd.h>
@@ -8,29 +9,29 @@
8#include <fstab.h> 9#include <fstab.h>
9#include <sys/mount.h> 10#include <sys/mount.h>
10 11
11extern const char mtab_file[]; /* Defined in utility.c */ 12extern const char mtab_file[]; /* Defined in utility.c */
12 13
13 14
14void erase_mtab(const char * name) 15void erase_mtab(const char *name)
15{ 16{
16 struct mntent entries[20]; 17 struct mntent entries[20];
17 int count = 0; 18 int count = 0;
18 FILE *mountTable = setmntent(mtab_file, "r"); 19 FILE *mountTable = setmntent(mtab_file, "r");
19 struct mntent * m; 20 struct mntent *m;
20 21
21 /* Check if reading the mtab file failed */ 22 /* Check if reading the mtab file failed */
22 if ( mountTable == 0 23 if (mountTable == 0
23#if ! defined BB_FEATURE_USE_PROCFS 24#if ! defined BB_FEATURE_USE_PROCFS
24 ) { 25 ) {
25#else 26#else
26 /* Bummer. fall back on trying the /proc filesystem */ 27 /* Bummer. fall back on trying the /proc filesystem */
27 && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) { 28 && (mountTable = setmntent("/proc/mounts", "r")) == 0) {
28#endif 29#endif
29 perror(mtab_file); 30 perror(mtab_file);
30 return; 31 return;
31 } 32 }
32 33
33 while ( (m = getmntent(mountTable)) != 0 ) { 34 while ((m = getmntent(mountTable)) != 0) {
34 entries[count].mnt_fsname = strdup(m->mnt_fsname); 35 entries[count].mnt_fsname = strdup(m->mnt_fsname);
35 entries[count].mnt_dir = strdup(m->mnt_dir); 36 entries[count].mnt_dir = strdup(m->mnt_dir);
36 entries[count].mnt_type = strdup(m->mnt_type); 37 entries[count].mnt_type = strdup(m->mnt_type);
@@ -40,64 +41,63 @@ void erase_mtab(const char * name)
40 count++; 41 count++;
41 } 42 }
42 endmntent(mountTable); 43 endmntent(mountTable);
43 if ( (mountTable = setmntent(mtab_file, "w")) ) { 44 if ((mountTable = setmntent(mtab_file, "w"))) {
44 int i; 45 int i;
45 for ( i = 0; i < count; i++ ) {
46 int result = ( strcmp(entries[i].mnt_fsname, name) == 0
47 || strcmp(entries[i].mnt_dir, name) == 0 );
48 46
49 if ( result ) 47 for (i = 0; i < count; i++) {
48 int result = (strcmp(entries[i].mnt_fsname, name) == 0
49 || strcmp(entries[i].mnt_dir, name) == 0);
50
51 if (result)
50 continue; 52 continue;
51 else 53 else
52 addmntent(mountTable, &entries[i]); 54 addmntent(mountTable, &entries[i]);
53 } 55 }
54 endmntent(mountTable); 56 endmntent(mountTable);
55 } 57 } else if (errno != EROFS)
56 else if ( errno != EROFS )
57 perror(mtab_file); 58 perror(mtab_file);
58} 59}
59 60
60void write_mtab(char* blockDevice, char* directory, 61void write_mtab(char *blockDevice, char *directory,
61 char* filesystemType, long flags, char* string_flags) 62 char *filesystemType, long flags, char *string_flags)
62{ 63{
63 FILE *mountTable = setmntent(mtab_file, "a+"); 64 FILE *mountTable = setmntent(mtab_file, "a+");
64 struct mntent m; 65 struct mntent m;
65 66
66 if ( mountTable == 0 ) { 67 if (mountTable == 0) {
67 perror(mtab_file); 68 perror(mtab_file);
68 return; 69 return;
69 } 70 }
70 if (mountTable) { 71 if (mountTable) {
71 int length = strlen(directory); 72 int length = strlen(directory);
72 73
73 if ( length > 1 && directory[length - 1] == '/' ) 74 if (length > 1 && directory[length - 1] == '/')
74 directory[length - 1] = '\0'; 75 directory[length - 1] = '\0';
75 76
76#ifdef BB_FEATURE_USE_PROCFS 77#ifdef BB_FEATURE_USE_PROCFS
77 if ( filesystemType == 0 ) { 78 if (filesystemType == 0) {
78 struct mntent *p = findMountPoint(blockDevice, "/proc/mounts"); 79 struct mntent *p = findMountPoint(blockDevice, "/proc/mounts");
79 80
80 if ( p && p->mnt_type ) 81 if (p && p->mnt_type)
81 filesystemType = p->mnt_type; 82 filesystemType = p->mnt_type;
82 } 83 }
83#endif 84#endif
84 m.mnt_fsname = blockDevice; 85 m.mnt_fsname = blockDevice;
85 m.mnt_dir = directory; 86 m.mnt_dir = directory;
86 m.mnt_type = filesystemType ? filesystemType : "default"; 87 m.mnt_type = filesystemType ? filesystemType : "default";
87 88
88 if (*string_flags) { 89 if (*string_flags) {
89 m.mnt_opts = string_flags; 90 m.mnt_opts = string_flags;
90 } else { 91 } else {
91 if ( (flags | MS_RDONLY) == flags ) 92 if ((flags | MS_RDONLY) == flags)
92 m.mnt_opts = "ro"; 93 m.mnt_opts = "ro";
93 else 94 else
94 m.mnt_opts = "rw"; 95 m.mnt_opts = "rw";
95 } 96 }
96
97 m.mnt_freq = 0;
98 m.mnt_passno = 0;
99 addmntent(mountTable, &m);
100 endmntent(mountTable);
101 }
102}
103 97
98 m.mnt_freq = 0;
99 m.mnt_passno = 0;
100 addmntent(mountTable, &m);
101 endmntent(mountTable);
102 }
103}
diff --git a/networking/hostname.c b/networking/hostname.c
index 68a560950..8cc334da0 100644
--- a/networking/hostname.c
+++ b/networking/hostname.c
@@ -1,5 +1,6 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * $Id: hostname.c,v 1.6 2000/02/07 05:29:42 erik Exp $ 3 * $Id: hostname.c,v 1.7 2000/02/08 19:58:47 erik Exp $
3 * Mini hostname implementation for busybox 4 * Mini hostname implementation for busybox
4 * 5 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -29,110 +30,116 @@
29#include <unistd.h> 30#include <unistd.h>
30#include <stdio.h> 31#include <stdio.h>
31 32
32static const char* hostname_usage = 33static const char *hostname_usage =
33"hostname [OPTION] {hostname | -F file}\n\n" 34 "hostname [OPTION] {hostname | -F file}\n\n"
34"Get or set the hostname or DNS domain name. If a hostname is given\n" 35 "Get or set the hostname or DNS domain name. If a hostname is given\n"
35"(or a file with the -F parameter), the host name will be set.\n\n" 36 "(or a file with the -F parameter), the host name will be set.\n\n"
36"Options:\n" 37 "Options:\n"
37"\t-s\t\tShort\n" 38 "\t-s\t\tShort\n"
38"\t-i\t\tAddresses for the hostname\n" 39
39"\t-d\t\tDNS domain name\n" 40 "\t-i\t\tAddresses for the hostname\n"
40"\t-F FILE\t\tUse the contents of FILE to specify the hostname\n"; 41 "\t-d\t\tDNS domain name\n"
42 "\t-F FILE\t\tUse the contents of FILE to specify the hostname\n";
41 43
42 44
43void do_sethostname(char *s, int isfile) 45void do_sethostname(char *s, int isfile)
44{ 46{
45 FILE *f; 47 FILE *f;
46 char buf[255]; 48 char buf[255];
47 49
48 if (!s) return; 50 if (!s)
49 if (!isfile) { 51 return;
50 if (sethostname(s, strlen(s)) < 0) { 52 if (!isfile) {
51 if (errno == EPERM) 53 if (sethostname(s, strlen(s)) < 0) {
52 fprintf(stderr, "hostname: you must be root to change the hostname\n"); 54 if (errno == EPERM)
53 else 55 fprintf(stderr,
54 perror("sethostname"); 56 "hostname: you must be root to change the hostname\n");
55 exit(1); 57 else
56 } 58 perror("sethostname");
57 } else { 59 exit(1);
58 if ((f = fopen(s, "r")) == NULL) { 60 }
59 perror(s);
60 exit(1);
61 } else { 61 } else {
62 fgets(buf, 255, f); 62 if ((f = fopen(s, "r")) == NULL) {
63 fclose(f); 63 perror(s);
64 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; 64 exit(1);
65 if (sethostname(buf, strlen(buf)) < 0) { 65 } else {
66 perror("sethostname"); 66 fgets(buf, 255, f);
67 exit(1); 67 fclose(f);
68 } 68 if (buf[strlen(buf) - 1] == '\n')
69 buf[strlen(buf) - 1] = 0;
70 if (sethostname(buf, strlen(buf)) < 0) {
71 perror("sethostname");
72 exit(1);
73 }
74 }
69 } 75 }
70 }
71} 76}
72 77
73int hostname_main(int argc, char **argv) 78int hostname_main(int argc, char **argv)
74{ 79{
75 int opt_short = 0; 80 int opt_short = 0;
76 int opt_domain = 0; 81 int opt_domain = 0;
77 int opt_ip = 0; 82 int opt_ip = 0;
78 struct hostent *h; 83 struct hostent *h;
79 char *filename = NULL; 84 char *filename = NULL;
80 char buf[255]; 85 char buf[255];
81 char *s = NULL; 86 char *s = NULL;
82
83 if (argc < 1) usage(hostname_usage);
84 87
85 while (--argc > 0 && **(++argv) == '-') { 88 if (argc < 1)
86 while (*(++(*argv))) {
87 switch (**argv) {
88 case 's':
89 opt_short = 1;
90 break;
91 case 'i':
92 opt_ip = 1;
93 break;
94 case 'd':
95 opt_domain = 1;
96 break;
97 case 'F':
98 filename = optarg;
99 if (--argc == 0) {
100 usage(hostname_usage);
101 }
102 filename = *(++argv);
103 break;
104 default:
105 usage(hostname_usage); 89 usage(hostname_usage);
106 } 90
107 if (filename!=NULL) 91 while (--argc > 0 && **(++argv) == '-') {
108 break; 92 while (*(++(*argv))) {
93 switch (**argv) {
94 case 's':
95 opt_short = 1;
96 break;
97 case 'i':
98 opt_ip = 1;
99 break;
100 case 'd':
101 opt_domain = 1;
102 break;
103 case 'F':
104 filename = optarg;
105 if (--argc == 0) {
106 usage(hostname_usage);
107 }
108 filename = *(++argv);
109 break;
110 default:
111 usage(hostname_usage);
112 }
113 if (filename != NULL)
114 break;
115 }
109 } 116 }
110 }
111 117
112 if (argc >= 1) { 118 if (argc >= 1) {
113 do_sethostname(*argv, 0); 119 do_sethostname(*argv, 0);
114 } else if (filename!=NULL) { 120 } else if (filename != NULL) {
115 do_sethostname(filename, 1); 121 do_sethostname(filename, 1);
116 } else { 122 } else {
117 gethostname(buf, 255); 123 gethostname(buf, 255);
118 if (opt_short) { 124 if (opt_short) {
119 s = strchr(buf, '.'); 125 s = strchr(buf, '.');
120 if (!s) s = buf; *s = 0; 126 if (!s)
121 printf("%s\n", buf); 127 s = buf;
122 } else if (opt_domain) { 128 *s = 0;
123 s = strchr(buf, '.'); 129 printf("%s\n", buf);
124 printf("%s\n", (s ? s+1 : "")); 130 } else if (opt_domain) {
125 } else if (opt_ip) { 131 s = strchr(buf, '.');
126 h = gethostbyname(buf); 132 printf("%s\n", (s ? s + 1 : ""));
127 if (!h) { 133 } else if (opt_ip) {
128 printf("Host not found\n"); 134 h = gethostbyname(buf);
129 exit(1); 135 if (!h) {
130 } 136 printf("Host not found\n");
131 printf("%s\n", inet_ntoa(*(struct in_addr *)(h->h_addr))); 137 exit(1);
132 } else { 138 }
133 printf("%s\n", buf); 139 printf("%s\n", inet_ntoa(*(struct in_addr *) (h->h_addr)));
134 } 140 } else {
135 } 141 printf("%s\n", buf);
136 exit( 0); 142 }
143 }
144 exit(0);
137} 145}
138
diff --git a/networking/nslookup.c b/networking/nslookup.c
index 969d0b19b..ffa720174 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini nslookup implementation for busybox 3 * Mini nslookup implementation for busybox
3 * 4 *
@@ -41,148 +42,136 @@
41 | + find out how the real nslookup gets the default name server 42 | + find out how the real nslookup gets the default name server
42 */ 43 */
43 44
44static const char nslookup_usage[] = 45static const char nslookup_usage[] = "nslookup [HOST]\n\n";
45 "nslookup [HOST]\n\n"
46;
47 46
48 47
49/* I have to see how the real nslookup does this. 48/* I have to see how the real nslookup does this.
50 * I could dig through /etc/resolv.conf, but is there a 49 * I could dig through /etc/resolv.conf, but is there a
51 * better (programatic) way? 50 * better (programatic) way?
52 */ 51 */
53static void 52static void server_fprint(FILE * dst)
54server_fprint(FILE *dst)
55{ 53{
56 fprintf(dst, "Server: %s\n", "something"); 54 fprintf(dst, "Server: %s\n", "something");
57 fprintf(dst, "Address: %s\n\n", "something"); 55 fprintf(dst, "Address: %s\n\n", "something");
58} 56}
59 57
60/* only works for IPv4 */ 58/* only works for IPv4 */
61static int 59static int addr_fprint(char *addr, FILE * dst)
62addr_fprint(char *addr, FILE *dst)
63{ 60{
64 uint8_t split[4]; 61 uint8_t split[4];
65 uint32_t ip; 62 uint32_t ip;
66 uint32_t *x = (uint32_t *) addr; 63 uint32_t *x = (uint32_t *) addr;
67 64
68 ip = ntohl(*x); 65 ip = ntohl(*x);
69 split[0] = (ip & 0xff000000) >> 24; 66 split[0] = (ip & 0xff000000) >> 24;
70 split[1] = (ip & 0x00ff0000) >> 16; 67 split[1] = (ip & 0x00ff0000) >> 16;
71 split[2] = (ip & 0x0000ff00) >> 8; 68 split[2] = (ip & 0x0000ff00) >> 8;
72 split[3] = (ip & 0x000000ff); 69 split[3] = (ip & 0x000000ff);
73 fprintf ( 70 fprintf(dst, "%d.%d.%d.%d", split[0], split[1], split[2], split[3]
74 dst, "%d.%d.%d.%d", 71 );
75 split[0], split[1], split[2], split[3] 72 return 0;
76 );
77 return 0;
78} 73}
79 74
80/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+ 75/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+
81 * into a uint32_t 76 * into a uint32_t
82 */ 77 */
83static uint32_t 78static uint32_t str_to_addr(const char *addr)
84str_to_addr(const char *addr)
85{ 79{
86 uint32_t split[4]; 80 uint32_t split[4];
87 uint32_t ip; 81 uint32_t ip;
88 82
89 sscanf(addr, "%d.%d.%d.%d", 83 sscanf(addr, "%d.%d.%d.%d",
90 &split[0], &split[1], &split[2], &split[3]); 84 &split[0], &split[1], &split[2], &split[3]);
91 85
92 /* assuming sscanf worked */ 86 /* assuming sscanf worked */
93 ip = (split[0] << 24) | 87 ip = (split[0] << 24) |
94 (split[1] << 16) | 88 (split[1] << 16) | (split[2] << 8) | (split[3]);
95 (split[2] << 8) |
96 (split[3]);
97 89
98 return htonl(ip); 90 return htonl(ip);
99} 91}
100 92
101/* takes the NULL-terminated array h_addr_list, and 93/* takes the NULL-terminated array h_addr_list, and
102 * prints its contents appropriately 94 * prints its contents appropriately
103 */ 95 */
104static int 96static int addr_list_fprint(char **h_addr_list, FILE * dst)
105addr_list_fprint(char **h_addr_list, FILE *dst)
106{ 97{
107 int i, j; 98 int i, j;
108 char *addr_string = (h_addr_list[1]) 99 char *addr_string = (h_addr_list[1])
109 ? "Addresses" 100 ? "Addresses" : "Address";
110 : "Address"; 101
111 102 fprintf(dst, "%s: ", addr_string);
112 fprintf(dst, "%s: ", addr_string); 103 for (i = 0, j = 0; h_addr_list[i]; i++, j++) {
113 for (i = 0, j = 0; h_addr_list[i]; i++, j++) { 104 addr_fprint(h_addr_list[i], dst);
114 addr_fprint(h_addr_list[i], dst); 105
115 106 /* real nslookup does this */
116 /* real nslookup does this */ 107 if (j == 4) {
117 if (j == 4) { 108 if (h_addr_list[i + 1]) {
118 if (h_addr_list[i+1]) { 109 fprintf(dst, "\n ");
119 fprintf(dst, "\n "); 110 }
120 } 111 j = 0;
121 j = 0; 112 } else {
122 } else { 113 if (h_addr_list[i + 1]) {
123 if (h_addr_list[i+1]) { 114 fprintf(dst, ", ");
124 fprintf(dst, ", "); 115 }
125 } 116 }
126 }
127 117
128 } 118 }
129 fprintf(dst,"\n"); 119 fprintf(dst, "\n");
130 return 0; 120 return 0;
131} 121}
132 122
133/* gethostbyaddr wrapper */ 123/* gethostbyaddr wrapper */
134static struct hostent * 124static struct hostent *gethostbyaddr_wrapper(const char *address)
135gethostbyaddr_wrapper(const char *address)
136{ 125{
137 struct in_addr addr; 126 struct in_addr addr;
138 127
139 addr.s_addr = str_to_addr(address); 128 addr.s_addr = str_to_addr(address);
140 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */ 129 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */
141} 130}
142 131
143/* print the results as nslookup would */ 132/* print the results as nslookup would */
144static struct hostent * 133static struct hostent *hostent_fprint(struct hostent *host, FILE * dst)
145hostent_fprint(struct hostent *host, FILE *dst)
146{ 134{
147 if (host) { 135 if (host) {
148 fprintf(dst, "Name: %s\n", host->h_name); 136 fprintf(dst, "Name: %s\n", host->h_name);
149 addr_list_fprint(host->h_addr_list, dst); 137 addr_list_fprint(host->h_addr_list, dst);
150 } else { 138 } else {
151 fprintf(dst, "*** %s\n", hstrerror(h_errno)); 139 fprintf(dst, "*** %s\n", hstrerror(h_errno));
152 } 140 }
153 return host; 141 return host;
154} 142}
155 143
156 144
157/* naive function to check whether char *s is an ip address */ 145/* naive function to check whether char *s is an ip address */
158static int 146static int is_ip_address(const char *s)
159is_ip_address(const char *s)
160{ 147{
161 while (*s) { 148 while (*s) {
162 if ((isdigit(*s)) || (*s == '.')) { s++; continue; } 149 if ((isdigit(*s)) || (*s == '.')) {
163 return 0; 150 s++;
164 } 151 continue;
165 return 1; 152 }
153 return 0;
154 }
155 return 1;
166} 156}
167 157
168/* ________________________________________________________________________ */ 158/* ________________________________________________________________________ */
169int 159int nslookup_main(int argc, char **argv)
170nslookup_main(int argc, char **argv)
171{ 160{
172 struct hostent *host; 161 struct hostent *host;
173 162
174 if (argc < 2) { 163 if (argc < 2) {
175 usage(nslookup_usage); 164 usage(nslookup_usage);
176 } 165 }
177 166
178 server_fprint(stdout); 167 server_fprint(stdout);
179 if (is_ip_address(argv[1])) { 168 if (is_ip_address(argv[1])) {
180 host = gethostbyaddr_wrapper(argv[1]); 169 host = gethostbyaddr_wrapper(argv[1]);
181 } else { 170 } else {
182 host = gethostbyname(argv[1]); 171 host = gethostbyname(argv[1]);
183 } 172 }
184 hostent_fprint(host, stdout); 173 hostent_fprint(host, stdout);
185 return 0; 174 return 0;
186} 175}
187 176
188/* $Id: nslookup.c,v 1.3 2000/02/07 05:29:42 erik Exp $ */ 177/* $Id: nslookup.c,v 1.4 2000/02/08 19:58:47 erik Exp $ */
diff --git a/networking/ping.c b/networking/ping.c
index 3ffbdc553..c9cf5ffb4 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -1,5 +1,6 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * $Id: ping.c,v 1.10 2000/02/07 05:29:42 erik Exp $ 3 * $Id: ping.c,v 1.11 2000/02/08 19:58:47 erik Exp $
3 * Mini ping implementation for busybox 4 * Mini ping implementation for busybox
4 * 5 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -53,7 +54,7 @@
53#define MAXPACKET 65468 54#define MAXPACKET 65468
54#define MAX_DUP_CHK (8 * 128) 55#define MAX_DUP_CHK (8 * 128)
55#define MAXWAIT 10 56#define MAXWAIT 10
56#define PINGINTERVAL 1 /* second */ 57#define PINGINTERVAL 1 /* second */
57 58
58#define O_QUIET (1 << 0) 59#define O_QUIET (1 << 0)
59 60
@@ -66,118 +67,124 @@
66/* common routines */ 67/* common routines */
67static int in_cksum(unsigned short *buf, int sz) 68static int in_cksum(unsigned short *buf, int sz)
68{ 69{
69 int nleft = sz; 70 int nleft = sz;
70 int sum = 0; 71 int sum = 0;
71 unsigned short *w = buf; 72 unsigned short *w = buf;
72 unsigned short ans = 0; 73 unsigned short ans = 0;
73 74
74 while (nleft > 1) { 75 while (nleft > 1) {
75 sum += *w++; 76 sum += *w++;
76 nleft -= 2; 77 nleft -= 2;
77 } 78 }
78 79
79 if (nleft == 1) { 80 if (nleft == 1) {
80 *(unsigned char *)(&ans) = *(unsigned char *)w; 81 *(unsigned char *) (&ans) = *(unsigned char *) w;
81 sum += ans; 82 sum += ans;
82 } 83 }
83 84
84 sum = (sum >> 16) + (sum & 0xFFFF); 85 sum = (sum >> 16) + (sum & 0xFFFF);
85 sum += (sum >> 16); 86 sum += (sum >> 16);
86 ans = ~sum; 87 ans = ~sum;
87 return(ans); 88 return (ans);
88} 89}
89 90
90/* simple version */ 91/* simple version */
91#ifdef BB_SIMPLE_PING 92#ifdef BB_SIMPLE_PING
92static const char* ping_usage = "ping host\n\n"; 93static const char *ping_usage = "ping host\n\n";
93 94
94static char* hostname = NULL; 95static char *hostname = NULL;
95 96
96static void noresp(int ign) 97static void noresp(int ign)
97{ 98{
98 printf("No response from %s\n", hostname); 99 printf("No response from %s\n", hostname);
99 exit(0); 100 exit(0);
100} 101}
101 102
102static int ping(const char *host) 103static int ping(const char *host)
103{ 104{
104 struct hostent *h; 105 struct hostent *h;
105 struct sockaddr_in pingaddr; 106 struct sockaddr_in pingaddr;
106 struct icmp *pkt; 107 struct icmp *pkt;
107 int pingsock, c; 108 int pingsock, c;
108 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 109 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
109 110
110 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { /* 1 == ICMP */ 111 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { /* 1 == ICMP */
111 perror("ping"); 112 perror("ping");
112 exit(1); 113 exit(1);
113 } 114 }
114 115
115 /* drop root privs if running setuid */ 116 /* drop root privs if running setuid */
116 setuid(getuid()); 117 setuid(getuid());
117 118
118 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 119 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
119 pingaddr.sin_family = AF_INET; 120
120 if (!(h = gethostbyname(host))) { 121 pingaddr.sin_family = AF_INET;
121 fprintf(stderr, "ping: unknown host %s\n", host); 122 if (!(h = gethostbyname(host))) {
122 exit(1); 123 fprintf(stderr, "ping: unknown host %s\n", host);
123 } 124 exit(1);
124 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); 125 }
125 hostname = h->h_name; 126 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
126 127 hostname = h->h_name;
127 pkt = (struct icmp *)packet; 128
128 memset(pkt, 0, sizeof(packet)); 129 pkt = (struct icmp *) packet;
129 pkt->icmp_type = ICMP_ECHO; 130 memset(pkt, 0, sizeof(packet));
130 pkt->icmp_cksum = in_cksum((unsigned short *)pkt, sizeof(packet)); 131 pkt->icmp_type = ICMP_ECHO;
131 132 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
132 c = sendto(pingsock, packet, sizeof(packet), 0, 133
133 (struct sockaddr *)&pingaddr, sizeof(struct sockaddr_in)); 134 c = sendto(pingsock, packet, sizeof(packet), 0,
134 135 (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
135 if (c < 0 || c != sizeof(packet)) { 136
136 if (c < 0) perror("ping"); 137 if (c < 0 || c != sizeof(packet)) {
137 fprintf(stderr, "ping: write incomplete\n"); 138 if (c < 0)
138 exit(1); 139 perror("ping");
139 } 140 fprintf(stderr, "ping: write incomplete\n");
140 141 exit(1);
141 signal(SIGALRM, noresp); 142 }
142 alarm(5); /* give the host 5000ms to respond */ 143
143 /* listen for replies */ 144 signal(SIGALRM, noresp);
144 while (1) { 145 alarm(5); /* give the host 5000ms to respond */
145 struct sockaddr_in from; 146 /* listen for replies */
146 size_t fromlen = sizeof(from); 147 while (1) {
147 148 struct sockaddr_in from;
148 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0, 149 size_t fromlen = sizeof(from);
149 (struct sockaddr *)&from, &fromlen)) < 0) { 150
150 if (errno == EINTR) continue; 151 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
151 perror("ping"); 152 (struct sockaddr *) &from, &fromlen)) < 0) {
152 continue; 153 if (errno == EINTR)
154 continue;
155 perror("ping");
156 continue;
157 }
158 if (c >= 76) { /* ip + icmp */
159 struct iphdr *iphdr = (struct iphdr *) packet;
160
161 pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); /* skip ip hdr */
162 if (pkt->icmp_type == ICMP_ECHOREPLY)
163 break;
164 }
153 } 165 }
154 if (c >= 76) { /* ip + icmp */ 166 printf("%s is alive!\n", hostname);
155 struct iphdr *iphdr = (struct iphdr *)packet; 167 return (TRUE);
156 pkt = (struct icmp *)(packet + (iphdr->ihl << 2)); /* skip ip hdr */
157 if (pkt->icmp_type == ICMP_ECHOREPLY) break;
158 }
159 }
160 printf("%s is alive!\n", hostname);
161 return(TRUE);
162} 168}
163 169
164extern int ping_main(int argc, char **argv) 170extern int ping_main(int argc, char **argv)
165{ 171{
166 argc--; 172 argc--;
167 argv++; 173 argv++;
168 if (argc < 1) usage(ping_usage); 174 if (argc < 1)
169 ping(*argv); 175 usage(ping_usage);
170 exit(TRUE); 176 ping(*argv);
177 exit(TRUE);
171} 178}
172 179
173#else 180#else
174/* full(er) version */ 181/* full(er) version */
175static const char* ping_usage = "ping [OPTION]... host\n\n" 182static const char *ping_usage = "ping [OPTION]... host\n\n"
176"Send ICMP ECHO_REQUEST packets to network hosts.\n\n" 183 "Send ICMP ECHO_REQUEST packets to network hosts.\n\n"
177"Options:\n" 184 "Options:\n"
178"\t-q\t\tQuiet mode, only displays output at start" 185 "\t-q\t\tQuiet mode, only displays output at start"
179"\t\t\tand when finished.\n" 186
180"\t-c COUNT\tSend only COUNT pings.\n"; 187 "\t\t\tand when finished.\n" "\t-c COUNT\tSend only COUNT pings.\n";
181 188
182static char *hostname = NULL; 189static char *hostname = NULL;
183static struct sockaddr_in pingaddr; 190static struct sockaddr_in pingaddr;
@@ -196,224 +203,247 @@ static void ping(char *);
196 203
197/**************************************************************************/ 204/**************************************************************************/
198 205
199static void pingstats(int ign) { 206static void pingstats(int ign)
200 signal(SIGINT, SIG_IGN); 207{
201 208 signal(SIGINT, SIG_IGN);
202 printf("\n--- %s ping statistics ---\n", hostname); 209
203 printf("%ld packets transmitted, ", ntransmitted); 210 printf("\n--- %s ping statistics ---\n", hostname);
204 printf("%ld packets received, ", nreceived); 211 printf("%ld packets transmitted, ", ntransmitted);
205 if (nrepeats) 212 printf("%ld packets received, ", nreceived);
206 printf("%ld duplicates, ", nrepeats); 213 if (nrepeats)
207 if (ntransmitted) 214 printf("%ld duplicates, ", nrepeats);
208 printf("%ld%% packet loss\n", 215 if (ntransmitted)
209 (ntransmitted - nreceived)*100/ntransmitted); 216 printf("%ld%% packet loss\n",
210 if (nreceived) 217 (ntransmitted - nreceived) * 100 / ntransmitted);
211 printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n", 218 if (nreceived)
212 tmin/10, tmin%10, 219 printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n",
213 (tsum/(nreceived+nrepeats))/10, 220 tmin / 10, tmin % 10,
214 (tsum/(nreceived+nrepeats))%10, 221 (tsum / (nreceived + nrepeats)) / 10,
215 tmax/10, tmax%10); 222 (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10);
216 exit(0); 223 exit(0);
217} 224}
218 225
219static void sendping(int ign) 226static void sendping(int ign)
220{ 227{
221 struct icmp *pkt; 228 struct icmp *pkt;
222 int i; 229 int i;
223 char packet[DEFDATALEN + 8]; 230 char packet[DEFDATALEN + 8];
224 231
225 pkt = (struct icmp *)packet; 232 pkt = (struct icmp *) packet;
226 233
227 pkt->icmp_type = ICMP_ECHO; 234 pkt->icmp_type = ICMP_ECHO;
228 pkt->icmp_code = 0; 235 pkt->icmp_code = 0;
229 pkt->icmp_cksum = 0; 236 pkt->icmp_cksum = 0;
230 pkt->icmp_seq = ntransmitted++; 237 pkt->icmp_seq = ntransmitted++;
231 pkt->icmp_id = myid; 238 pkt->icmp_id = myid;
232 CLR(pkt->icmp_seq % MAX_DUP_CHK); 239 CLR(pkt->icmp_seq % MAX_DUP_CHK);
233 240
234 gettimeofday((struct timeval *)&packet[8], NULL); 241 gettimeofday((struct timeval *) &packet[8], NULL);
235 pkt->icmp_cksum = in_cksum((unsigned short *)pkt, sizeof(packet)); 242 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
236 243
237 i = sendto(pingsock, packet, sizeof(packet), 0, 244 i = sendto(pingsock, packet, sizeof(packet), 0,
238 (struct sockaddr *)&pingaddr, sizeof(struct sockaddr_in)); 245 (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
239 246
240 if (i < 0 || i != sizeof(packet)) { 247 if (i < 0 || i != sizeof(packet)) {
241 if (i < 0) perror("ping"); 248 if (i < 0)
242 fprintf(stderr, "ping wrote %d chars; %d expected\n", i, sizeof(packet)); 249 perror("ping");
243 exit(1); 250 fprintf(stderr, "ping wrote %d chars; %d expected\n", i,
244 } 251 sizeof(packet));
245 252 exit(1);
246 signal(SIGALRM, sendping); 253 }
247 if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ 254
248 alarm(PINGINTERVAL); 255 signal(SIGALRM, sendping);
249 } else { /* done, wait for the last ping to come back */ 256 if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */
250 /* todo, don't necessarily need to wait so long... */ 257 alarm(PINGINTERVAL);
251 signal(SIGALRM, pingstats); 258 } else { /* done, wait for the last ping to come back */
252 alarm(MAXWAIT); 259 /* todo, don't necessarily need to wait so long... */
253 } 260 signal(SIGALRM, pingstats);
261 alarm(MAXWAIT);
262 }
254} 263}
255 264
256static void unpack(char *buf, int sz, struct sockaddr_in *from) 265static void unpack(char *buf, int sz, struct sockaddr_in *from)
257{ 266{
258 struct icmp *icmppkt; 267 struct icmp *icmppkt;
259 struct iphdr *iphdr; 268 struct iphdr *iphdr;
260 struct timeval tv, *tp; 269 struct timeval tv, *tp;
261 int hlen, dupflag; 270 int hlen, dupflag;
262 unsigned long triptime; 271 unsigned long triptime;
263 272
264 gettimeofday(&tv, NULL); 273 gettimeofday(&tv, NULL);
265 274
266 /* check IP header */ 275 /* check IP header */
267 iphdr = (struct iphdr *)buf; 276 iphdr = (struct iphdr *) buf;
268 hlen = iphdr->ihl << 2; 277 hlen = iphdr->ihl << 2;
269 /* discard if too short */ 278 /* discard if too short */
270 if (sz < (DEFDATALEN + ICMP_MINLEN)) return; 279 if (sz < (DEFDATALEN + ICMP_MINLEN))
271 280 return;
272 sz -= hlen; 281
273 icmppkt = (struct icmp *)(buf + hlen); 282 sz -= hlen;
274 283 icmppkt = (struct icmp *) (buf + hlen);
275 if (icmppkt->icmp_type == ICMP_ECHOREPLY) { 284
276 if (icmppkt->icmp_id != myid) return; /* not our ping */ 285 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
277 ++nreceived; 286 if (icmppkt->icmp_id != myid)
278 tp = (struct timeval *)icmppkt->icmp_data; 287 return; /* not our ping */
279 288 ++nreceived;
280 if ((tv.tv_usec -= tp->tv_usec) < 0) { 289 tp = (struct timeval *) icmppkt->icmp_data;
281 --tv.tv_sec; 290
282 tv.tv_usec += 1000000; 291 if ((tv.tv_usec -= tp->tv_usec) < 0) {
283 } 292 --tv.tv_sec;
284 tv.tv_sec -= tp->tv_sec; 293 tv.tv_usec += 1000000;
285 294 }
286 triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); 295 tv.tv_sec -= tp->tv_sec;
287 tsum += triptime; 296
288 if (triptime < tmin) tmin = triptime; 297 triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100);
289 if (triptime > tmax) tmax = triptime; 298 tsum += triptime;
290 299 if (triptime < tmin)
291 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) { 300 tmin = triptime;
292 ++nrepeats; 301 if (triptime > tmax)
293 --nreceived; 302 tmax = triptime;
294 dupflag = 1; 303
304 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) {
305 ++nrepeats;
306 --nreceived;
307 dupflag = 1;
308 } else {
309 SET(icmppkt->icmp_seq % MAX_DUP_CHK);
310 dupflag = 0;
311 }
312
313 if (options & O_QUIET)
314 return;
315
316 printf("%d bytes from %s: icmp_seq=%u", sz,
317 inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
318 icmppkt->icmp_seq);
319 printf(" ttl=%d", iphdr->ttl);
320 printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);
321 if (dupflag)
322 printf(" (DUP!)");
323 printf("\n");
295 } else { 324 } else {
296 SET(icmppkt->icmp_seq % MAX_DUP_CHK); 325 fprintf(stderr,
297 dupflag = 0; 326 "Warning: unknown ICMP packet received (not echo-reply)\n");
298 } 327 }
299
300 if (options & O_QUIET) return;
301
302 printf("%d bytes from %s: icmp_seq=%u", sz,
303 inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
304 icmppkt->icmp_seq);
305 printf(" ttl=%d", iphdr->ttl);
306 printf(" time=%lu.%lu ms", triptime/10, triptime%10);
307 if (dupflag) printf(" (DUP!)");
308 printf("\n");
309 } else {
310 fprintf(stderr, "Warning: unknown ICMP packet received (not echo-reply)\n");
311 }
312} 328}
313 329
314static void ping(char *host) 330static void ping(char *host)
315{ 331{
316 struct protoent *proto; 332 struct protoent *proto;
317 struct hostent *h; 333 struct hostent *h;
318 char buf[MAXHOSTNAMELEN]; 334 char buf[MAXHOSTNAMELEN];
319 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 335 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
320 int sockopt; 336 int sockopt;
321 337
322 proto = getprotobyname("icmp"); 338 proto = getprotobyname("icmp");
323 /* if getprotobyname failed, just silently force 339 /* if getprotobyname failed, just silently force
324 * proto->p_proto to have the correct value for "icmp" */ 340 * proto->p_proto to have the correct value for "icmp" */
325 if ((pingsock = socket(AF_INET, SOCK_RAW, 341 if ((pingsock = socket(AF_INET, SOCK_RAW,
326 (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */ 342 (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */
327 if (errno == EPERM) { 343 if (errno == EPERM) {
328 fprintf(stderr, "ping: permission denied. (are you root?)\n"); 344 fprintf(stderr, "ping: permission denied. (are you root?)\n");
329 } else { 345 } else {
330 perror("ping"); 346 perror("ping");
347 }
348 exit(1);
331 } 349 }
332 exit(1); 350
333 } 351 /* drop root privs if running setuid */
334 352 setuid(getuid());
335 /* drop root privs if running setuid */ 353
336 setuid(getuid()); 354 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
337 355
338 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 356 pingaddr.sin_family = AF_INET;
339 pingaddr.sin_family = AF_INET; 357 if (!(h = gethostbyname(host))) {
340 if (!(h = gethostbyname(host))) { 358 fprintf(stderr, "ping: unknown host %s\n", host);
341 fprintf(stderr, "ping: unknown host %s\n", host); 359 exit(1);
342 exit(1); 360 }
343 } 361
344 362 if (h->h_addrtype != AF_INET) {
345 if (h->h_addrtype != AF_INET) { 363 fprintf(stderr,
346 fprintf(stderr, "ping: unknown address type; only AF_INET is currently supported.\n"); 364 "ping: unknown address type; only AF_INET is currently supported.\n");
347 exit(1); 365 exit(1);
348 }
349
350 pingaddr.sin_family = AF_INET; /* h->h_addrtype */
351 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
352 strncpy(buf, h->h_name, sizeof(buf)-1);
353 hostname = buf;
354
355 /* enable broadcast pings */
356 sockopt = 1;
357 setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *)&sockopt, sizeof(sockopt));
358
359 /* set recv buf for broadcast pings */
360 sockopt = 48 * 1024;
361 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockopt, sizeof(sockopt));
362
363 printf("PING %s (%s): %d data bytes\n",
364 hostname, inet_ntoa(*(struct in_addr *)&pingaddr.sin_addr.s_addr),
365 DEFDATALEN);
366
367 signal(SIGINT, pingstats);
368
369 /* start the ping's going ... */
370 sendping(0);
371
372 /* listen for replies */
373 while (1) {
374 struct sockaddr_in from;
375 size_t fromlen = sizeof(from);
376 int c;
377
378 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
379 (struct sockaddr *)&from, &fromlen)) < 0) {
380 if (errno == EINTR) continue;
381 perror("ping");
382 continue;
383 } 366 }
384 unpack(packet, c, &from); 367
385 if (pingcount > 0 && nreceived >= pingcount) break; 368 pingaddr.sin_family = AF_INET; /* h->h_addrtype */
386 } 369 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
387 pingstats(0); 370 strncpy(buf, h->h_name, sizeof(buf) - 1);
371 hostname = buf;
372
373 /* enable broadcast pings */
374 sockopt = 1;
375 setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
376 sizeof(sockopt));
377
378 /* set recv buf for broadcast pings */
379 sockopt = 48 * 1024;
380 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
381 sizeof(sockopt));
382
383 printf("PING %s (%s): %d data bytes\n",
384 hostname,
385 inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr),
386 DEFDATALEN);
387
388 signal(SIGINT, pingstats);
389
390 /* start the ping's going ... */
391 sendping(0);
392
393 /* listen for replies */
394 while (1) {
395 struct sockaddr_in from;
396 size_t fromlen = sizeof(from);
397 int c;
398
399 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
400 (struct sockaddr *) &from, &fromlen)) < 0) {
401 if (errno == EINTR)
402 continue;
403 perror("ping");
404 continue;
405 }
406 unpack(packet, c, &from);
407 if (pingcount > 0 && nreceived >= pingcount)
408 break;
409 }
410 pingstats(0);
388} 411}
389 412
390extern int ping_main(int argc, char **argv) 413extern int ping_main(int argc, char **argv)
391{ 414{
392 char *thisarg; 415 char *thisarg;
393 416
394 argc--; 417 argc--;
395 argv++; 418 argv++;
396 options = 0; 419 options = 0;
397 /* Parse any options */ 420 /* Parse any options */
398 while (argc > 1) { 421 while (argc > 1) {
399 if (**argv != '-') usage(ping_usage); 422 if (**argv != '-')
400 thisarg = *argv; thisarg++; 423 usage(ping_usage);
401 switch (*thisarg) { 424 thisarg = *argv;
402 case 'q': options |= O_QUIET; break; 425 thisarg++;
403 case 'c': 426 switch (*thisarg) {
404 argc--; argv++; 427 case 'q':
405 pingcount = atoi(*argv); 428 options |= O_QUIET;
406 break; 429 break;
407 default: 430 case 'c':
408 usage(ping_usage); 431 argc--;
409 } 432 argv++;
410 argc--; argv++; 433 pingcount = atoi(*argv);
411 } 434 break;
412 if (argc < 1) usage(ping_usage); 435 default:
413 436 usage(ping_usage);
414 myid = getpid() & 0xFFFF; 437 }
415 ping(*argv); 438 argc--;
416 exit(TRUE); 439 argv++;
440 }
441 if (argc < 1)
442 usage(ping_usage);
443
444 myid = getpid() & 0xFFFF;
445 ping(*argv);
446 exit(TRUE);
417} 447}
418#endif 448#endif
419 449
diff --git a/nfsmount.c b/nfsmount.c
index f2bd2f49c..03ce58447 100644
--- a/nfsmount.c
+++ b/nfsmount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * nfsmount.c -- Linux NFS mount 3 * nfsmount.c -- Linux NFS mount
3 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> 4 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
@@ -53,7 +54,7 @@
53 54
54#define _ 55#define _
55#define HAVE_inet_aton 56#define HAVE_inet_aton
56#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 57#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
57#define sloppy 0 58#define sloppy 0
58#define EX_FAIL 1 59#define EX_FAIL 1
59#define EX_BG 1 60#define EX_BG 1
@@ -65,8 +66,8 @@ static char *nfs_strerror(int stat);
65 66
66#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) 67#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
67 68
68static int 69static int linux_version_code(void)
69linux_version_code(void) { 70{
70 struct utsname my_utsname; 71 struct utsname my_utsname;
71 int p, q, r; 72 int p, q, r;
72 73
@@ -74,7 +75,7 @@ linux_version_code(void) {
74 p = atoi(strtok(my_utsname.release, ".")); 75 p = atoi(strtok(my_utsname.release, "."));
75 q = atoi(strtok(NULL, ".")); 76 q = atoi(strtok(NULL, "."));
76 r = atoi(strtok(NULL, ".")); 77 r = atoi(strtok(NULL, "."));
77 return MAKE_VERSION(p,q,r); 78 return MAKE_VERSION(p, q, r);
78 } 79 }
79 return 0; 80 return 0;
80} 81}
@@ -95,22 +96,22 @@ static int nfs_mount_version = NFS_MOUNT_VERSION;
95 * NFS_MOUNT_VERSION: these nfsmount sources at compile time 96 * NFS_MOUNT_VERSION: these nfsmount sources at compile time
96 * nfs_mount_version: version this source and running kernel can handle 97 * nfs_mount_version: version this source and running kernel can handle
97 */ 98 */
98static void 99static void find_kernel_nfs_mount_version(void)
99find_kernel_nfs_mount_version(void) { 100{
100 int kernel_version = linux_version_code(); 101 int kernel_version = linux_version_code();
101 102
102 if (kernel_version) { 103 if (kernel_version) {
103 if (kernel_version < MAKE_VERSION(2,1,32)) 104 if (kernel_version < MAKE_VERSION(2, 1, 32))
104 nfs_mount_version = 1; 105 nfs_mount_version = 1;
105 else 106 else
106 nfs_mount_version = 3; 107 nfs_mount_version = 3;
107 } 108 }
108 if (nfs_mount_version > NFS_MOUNT_VERSION) 109 if (nfs_mount_version > NFS_MOUNT_VERSION)
109 nfs_mount_version = NFS_MOUNT_VERSION; 110 nfs_mount_version = NFS_MOUNT_VERSION;
110} 111}
111 112
112int nfsmount(const char *spec, const char *node, unsigned long *flags, 113int nfsmount(const char *spec, const char *node, unsigned long *flags,
113 char **extra_opts, char **mount_opts, int running_bg) 114 char **extra_opts, char **mount_opts, int running_bg)
114{ 115{
115 static char *prev_bg_host; 116 static char *prev_bg_host;
116 char hostdir[1024]; 117 char hostdir[1024];
@@ -118,7 +119,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
118 char *hostname; 119 char *hostname;
119 char *dirname; 120 char *dirname;
120 char *old_opts; 121 char *old_opts;
121 char *mounthost=NULL; 122 char *mounthost = NULL;
122 char new_opts[1024]; 123 char new_opts[1024];
123 fhandle root_fhandle; 124 fhandle root_fhandle;
124 struct timeval total_timeout; 125 struct timeval total_timeout;
@@ -161,7 +162,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
161 mclient = NULL; 162 mclient = NULL;
162 if (strlen(spec) >= sizeof(hostdir)) { 163 if (strlen(spec) >= sizeof(hostdir)) {
163 fprintf(stderr, _("mount: " 164 fprintf(stderr, _("mount: "
164 "excessively long host:dir argument\n")); 165 "excessively long host:dir argument\n"));
165 goto fail; 166 goto fail;
166 } 167 }
167 strcpy(hostdir, spec); 168 strcpy(hostdir, spec);
@@ -174,11 +175,11 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
174 if ((s = strchr(hostdir, ','))) { 175 if ((s = strchr(hostdir, ','))) {
175 *s = '\0'; 176 *s = '\0';
176 fprintf(stderr, _("mount: warning: " 177 fprintf(stderr, _("mount: warning: "
177 "multiple hostnames not supported\n")); 178 "multiple hostnames not supported\n"));
178 } 179 }
179 } else { 180 } else {
180 fprintf(stderr, _("mount: " 181 fprintf(stderr, _("mount: "
181 "directory to mount not in host:dir format\n")); 182 "directory to mount not in host:dir format\n"));
182 goto fail; 183 goto fail;
183 } 184 }
184 185
@@ -189,20 +190,18 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
189 { 190 {
190 if ((hp = gethostbyname(hostname)) == NULL) { 191 if ((hp = gethostbyname(hostname)) == NULL) {
191 fprintf(stderr, _("mount: can't get address for %s\n"), 192 fprintf(stderr, _("mount: can't get address for %s\n"),
192 hostname); 193 hostname);
193 goto fail; 194 goto fail;
194 } else { 195 } else {
195 if (hp->h_length > sizeof(struct in_addr)) { 196 if (hp->h_length > sizeof(struct in_addr)) {
196 fprintf(stderr, 197 fprintf(stderr, _("mount: got bad hp->h_length\n"));
197 _("mount: got bad hp->h_length\n"));
198 hp->h_length = sizeof(struct in_addr); 198 hp->h_length = sizeof(struct in_addr);
199 } 199 }
200 memcpy(&server_addr.sin_addr, 200 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
201 hp->h_addr, hp->h_length);
202 } 201 }
203 } 202 }
204 203
205 memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); 204 memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr));
206 205
207 /* add IP address to mtab options for use when unmounting */ 206 /* add IP address to mtab options for use when unmounting */
208 207
@@ -211,12 +210,10 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
211 if (!old_opts) 210 if (!old_opts)
212 old_opts = ""; 211 old_opts = "";
213 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { 212 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
214 fprintf(stderr, _("mount: " 213 fprintf(stderr, _("mount: " "excessively long option argument\n"));
215 "excessively long option argument\n"));
216 goto fail; 214 goto fail;
217 } 215 }
218 sprintf(new_opts, "%s%saddr=%s", 216 sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s);
219 old_opts, *old_opts ? "," : "", s);
220 *extra_opts = xstrdup(new_opts); 217 *extra_opts = xstrdup(new_opts);
221 218
222 /* Set default options. 219 /* Set default options.
@@ -224,13 +221,13 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
224 * let the kernel decide. 221 * let the kernel decide.
225 * timeo is filled in after we know whether it'll be TCP or UDP. */ 222 * timeo is filled in after we know whether it'll be TCP or UDP. */
226 memset(&data, 0, sizeof(data)); 223 memset(&data, 0, sizeof(data));
227 data.retrans = 3; 224 data.retrans = 3;
228 data.acregmin = 3; 225 data.acregmin = 3;
229 data.acregmax = 60; 226 data.acregmax = 60;
230 data.acdirmin = 30; 227 data.acdirmin = 30;
231 data.acdirmax = 60; 228 data.acdirmax = 60;
232#if NFS_MOUNT_VERSION >= 2 229#if NFS_MOUNT_VERSION >= 2
233 data.namlen = NAME_MAX; 230 data.namlen = NAME_MAX;
234#endif 231#endif
235 232
236 bg = 0; 233 bg = 0;
@@ -240,7 +237,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
240 nocto = 0; 237 nocto = 0;
241 nolock = 0; 238 nolock = 0;
242 noac = 0; 239 noac = 0;
243 retry = 10000; /* 10000 minutes ~ 1 week */ 240 retry = 10000; /* 10000 minutes ~ 1 week */
244 tcp = 0; 241 tcp = 0;
245 242
246 mountprog = MOUNTPROG; 243 mountprog = MOUNTPROG;
@@ -254,7 +251,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
254 251
255 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { 252 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
256 if ((opteq = strchr(opt, '='))) { 253 if ((opteq = strchr(opt, '='))) {
257 val = atoi(opteq + 1); 254 val = atoi(opteq + 1);
258 *opteq = '\0'; 255 *opteq = '\0';
259 if (!strcmp(opt, "rsize")) 256 if (!strcmp(opt, "rsize"))
260 data.rsize = val; 257 data.rsize = val;
@@ -277,29 +274,27 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
277 data.acregmax = val; 274 data.acregmax = val;
278 data.acdirmin = val; 275 data.acdirmin = val;
279 data.acdirmax = val; 276 data.acdirmax = val;
280 } 277 } else if (!strcmp(opt, "retry"))
281 else if (!strcmp(opt, "retry"))
282 retry = val; 278 retry = val;
283 else if (!strcmp(opt, "port")) 279 else if (!strcmp(opt, "port"))
284 port = val; 280 port = val;
285 else if (!strcmp(opt, "mountport")) 281 else if (!strcmp(opt, "mountport"))
286 mountport = val; 282 mountport = val;
287 else if (!strcmp(opt, "mounthost")) 283 else if (!strcmp(opt, "mounthost"))
288 mounthost=xstrndup(opteq+1, 284 mounthost = xstrndup(opteq + 1,
289 strcspn(opteq+1," \t\n\r,")); 285 strcspn(opteq + 1, " \t\n\r,"));
290 else if (!strcmp(opt, "mountprog")) 286 else if (!strcmp(opt, "mountprog"))
291 mountprog = val; 287 mountprog = val;
292 else if (!strcmp(opt, "mountvers")) 288 else if (!strcmp(opt, "mountvers"))
293 mountvers = val; 289 mountvers = val;
294 else if (!strcmp(opt, "nfsprog")) 290 else if (!strcmp(opt, "nfsprog"))
295 nfsprog = val; 291 nfsprog = val;
296 else if (!strcmp(opt, "nfsvers") || 292 else if (!strcmp(opt, "nfsvers") || !strcmp(opt, "vers"))
297 !strcmp(opt, "vers"))
298 nfsvers = val; 293 nfsvers = val;
299 else if (!strcmp(opt, "proto")) { 294 else if (!strcmp(opt, "proto")) {
300 if (!strncmp(opteq+1, "tcp", 3)) 295 if (!strncmp(opteq + 1, "tcp", 3))
301 tcp = 1; 296 tcp = 1;
302 else if (!strncmp(opteq+1, "udp", 3)) 297 else if (!strncmp(opteq + 1, "udp", 3))
303 tcp = 0; 298 tcp = 0;
304 else 299 else
305 printf(_("Warning: Unrecognized proto= option.\n")); 300 printf(_("Warning: Unrecognized proto= option.\n"));
@@ -309,24 +304,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
309 data.namlen = val; 304 data.namlen = val;
310 else 305 else
311#endif 306#endif
312 printf(_("Warning: Option namlen is not supported.\n")); 307 printf(_
308 ("Warning: Option namlen is not supported.\n"));
313 } else if (!strcmp(opt, "addr")) 309 } else if (!strcmp(opt, "addr"))
314 /* ignore */; 310 /* ignore */ ;
315 else { 311 else {
316 printf(_("unknown nfs mount parameter: " 312 printf(_("unknown nfs mount parameter: "
317 "%s=%d\n"), opt, val); 313 "%s=%d\n"), opt, val);
318 goto fail; 314 goto fail;
319 } 315 }
320 } 316 } else {
321 else {
322 val = 1; 317 val = 1;
323 if (!strncmp(opt, "no", 2)) { 318 if (!strncmp(opt, "no", 2)) {
324 val = 0; 319 val = 0;
325 opt += 2; 320 opt += 2;
326 } 321 }
327 if (!strcmp(opt, "bg")) 322 if (!strcmp(opt, "bg"))
328 bg = val; 323 bg = val;
329 else if (!strcmp(opt, "fg")) 324 else if (!strcmp(opt, "fg"))
330 bg = !val; 325 bg = !val;
331 else if (!strcmp(opt, "soft")) 326 else if (!strcmp(opt, "soft"))
332 soft = val; 327 soft = val;
@@ -348,11 +343,12 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
348 if (nfs_mount_version >= 3) 343 if (nfs_mount_version >= 3)
349 nolock = !val; 344 nolock = !val;
350 else 345 else
351 printf(_("Warning: option nolock is not supported.\n")); 346 printf(_
347 ("Warning: option nolock is not supported.\n"));
352 } else { 348 } else {
353 if (!sloppy) { 349 if (!sloppy) {
354 printf(_("unknown nfs mount option: " 350 printf(_("unknown nfs mount option: "
355 "%s%s\n"), val ? "" : "no", opt); 351 "%s%s\n"), val ? "" : "no", opt);
356 goto fail; 352 goto fail;
357 } 353 }
358 } 354 }
@@ -378,22 +374,21 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
378 374
379#ifdef NFS_MOUNT_DEBUG 375#ifdef NFS_MOUNT_DEBUG
380 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", 376 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
381 data.rsize, data.wsize, data.timeo, data.retrans); 377 data.rsize, data.wsize, data.timeo, data.retrans);
382 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", 378 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
383 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); 379 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
384 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", 380 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
385 port, bg, retry, data.flags); 381 port, bg, retry, data.flags);
386 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", 382 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
387 mountprog, mountvers, nfsprog, nfsvers); 383 mountprog, mountvers, nfsprog, nfsvers);
388 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", 384 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
389 (data.flags & NFS_MOUNT_SOFT) != 0, 385 (data.flags & NFS_MOUNT_SOFT) != 0,
390 (data.flags & NFS_MOUNT_INTR) != 0, 386 (data.flags & NFS_MOUNT_INTR) != 0,
391 (data.flags & NFS_MOUNT_POSIX) != 0, 387 (data.flags & NFS_MOUNT_POSIX) != 0,
392 (data.flags & NFS_MOUNT_NOCTO) != 0, 388 (data.flags & NFS_MOUNT_NOCTO) != 0,
393 (data.flags & NFS_MOUNT_NOAC) != 0); 389 (data.flags & NFS_MOUNT_NOAC) != 0);
394#if NFS_MOUNT_VERSION >= 2 390#if NFS_MOUNT_VERSION >= 2
395 printf("tcp = %d\n", 391 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0);
396 (data.flags & NFS_MOUNT_TCP) != 0);
397#endif 392#endif
398#endif 393#endif
399 394
@@ -409,7 +404,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
409 * give up immediately, to avoid the initial timeout. 404 * give up immediately, to avoid the initial timeout.
410 */ 405 */
411 if (bg && !running_bg && 406 if (bg && !running_bg &&
412 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { 407 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
413 if (retry > 0) 408 if (retry > 0)
414 retval = EX_BG; 409 retval = EX_BG;
415 return retval; 410 return retval;
@@ -418,25 +413,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
418 /* create mount deamon client */ 413 /* create mount deamon client */
419 /* See if the nfs host = mount host. */ 414 /* See if the nfs host = mount host. */
420 if (mounthost) { 415 if (mounthost) {
421 if (mounthost[0] >= '0' && mounthost[0] <= '9') { 416 if (mounthost[0] >= '0' && mounthost[0] <= '9') {
422 mount_server_addr.sin_family = AF_INET; 417 mount_server_addr.sin_family = AF_INET;
423 mount_server_addr.sin_addr.s_addr = inet_addr(hostname); 418 mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
424 } else { 419 } else {
425 if ((hp = gethostbyname(mounthost)) == NULL) { 420 if ((hp = gethostbyname(mounthost)) == NULL) {
426 fprintf(stderr, _("mount: can't get address for %s\n"), 421 fprintf(stderr, _("mount: can't get address for %s\n"),
427 hostname); 422 hostname);
428 goto fail; 423 goto fail;
429 } else { 424 } else {
430 if (hp->h_length > sizeof(struct in_addr)) { 425 if (hp->h_length > sizeof(struct in_addr)) {
431 fprintf(stderr, 426 fprintf(stderr, _("mount: got bad hp->h_length?\n"));
432 _("mount: got bad hp->h_length?\n")); 427 hp->h_length = sizeof(struct in_addr);
433 hp->h_length = sizeof(struct in_addr); 428 }
434 } 429 mount_server_addr.sin_family = AF_INET;
435 mount_server_addr.sin_family = AF_INET; 430 memcpy(&mount_server_addr.sin_addr,
436 memcpy(&mount_server_addr.sin_addr, 431 hp->h_addr, hp->h_length);
437 hp->h_addr, hp->h_length); 432 }
438 } 433 }
439 }
440 } 434 }
441 435
442 /* 436 /*
@@ -466,7 +460,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
466 for (;;) { 460 for (;;) {
467 if (bg && stat(node, &statbuf) == -1) { 461 if (bg && stat(node, &statbuf) == -1) {
468 if (running_bg) { 462 if (running_bg) {
469 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ 463 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */
470 val *= 2; 464 val *= 2;
471 if (val > 30) 465 if (val > 30)
472 val = 30; 466 val = 30;
@@ -480,24 +474,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
480 mount_server_addr.sin_port = htons(mountport); 474 mount_server_addr.sin_port = htons(mountport);
481 msock = RPC_ANYSOCK; 475 msock = RPC_ANYSOCK;
482 mclient = clnttcp_create(&mount_server_addr, 476 mclient = clnttcp_create(&mount_server_addr,
483 mountprog, mountvers, 477 mountprog, mountvers, &msock, 0, 0);
484 &msock, 0, 0);
485 478
486 /* if this fails, contact the mount daemon via UDP */ 479 /* if this fails, contact the mount daemon via UDP */
487 if (!mclient) { 480 if (!mclient) {
488 mount_server_addr.sin_port = htons(mountport); 481 mount_server_addr.sin_port = htons(mountport);
489 msock = RPC_ANYSOCK; 482 msock = RPC_ANYSOCK;
490 mclient = clntudp_create(&mount_server_addr, 483 mclient = clntudp_create(&mount_server_addr,
491 mountprog, mountvers, 484 mountprog, mountvers,
492 retry_timeout, &msock); 485 retry_timeout, &msock);
493 } 486 }
494 if (mclient) { 487 if (mclient) {
495 /* try to mount hostname:dirname */ 488 /* try to mount hostname:dirname */
496 mclient->cl_auth = authunix_create_default(); 489 mclient->cl_auth = authunix_create_default();
497 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, 490 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
498 (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, 491 (xdrproc_t) xdr_dirpath,
499 (xdrproc_t) xdr_fhstatus, (caddr_t) &status, 492 (caddr_t) & dirname,
500 total_timeout); 493 (xdrproc_t) xdr_fhstatus,
494 (caddr_t) & status, total_timeout);
501 if (clnt_stat == RPC_SUCCESS) 495 if (clnt_stat == RPC_SUCCESS)
502 break; /* we're done */ 496 break; /* we're done */
503 if (errno != ECONNREFUSED) { 497 if (errno != ECONNREFUSED) {
@@ -517,7 +511,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
517 prevt = t; 511 prevt = t;
518 } 512 }
519 if (!bg) 513 if (!bg)
520 goto fail; 514 goto fail;
521 if (!running_bg) { 515 if (!running_bg) {
522 prev_bg_host = xstrdup(hostname); 516 prev_bg_host = xstrdup(hostname);
523 if (retry > 0) 517 if (retry > 0)
@@ -531,18 +525,18 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
531 525
532 if (status.fhs_status != 0) { 526 if (status.fhs_status != 0) {
533 fprintf(stderr, 527 fprintf(stderr,
534 _("mount: %s:%s failed, reason given by server: %s\n"), 528 _("mount: %s:%s failed, reason given by server: %s\n"),
535 hostname, dirname, nfs_strerror(status.fhs_status)); 529 hostname, dirname, nfs_strerror(status.fhs_status));
536 goto fail; 530 goto fail;
537 } 531 }
538 memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, 532 memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle,
539 sizeof (root_fhandle)); 533 sizeof(root_fhandle));
540 534
541 /* create nfs socket for kernel */ 535 /* create nfs socket for kernel */
542 536
543 if (tcp) { 537 if (tcp) {
544 if (nfs_mount_version < 3) { 538 if (nfs_mount_version < 3) {
545 printf(_("NFS over TCP is not supported.\n")); 539 printf(_("NFS over TCP is not supported.\n"));
546 goto fail; 540 goto fail;
547 } 541 }
548 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 542 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -559,7 +553,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
559 if (port == 0) { 553 if (port == 0) {
560 server_addr.sin_port = PMAPPORT; 554 server_addr.sin_port = PMAPPORT;
561 port = pmap_getport(&server_addr, nfsprog, nfsvers, 555 port = pmap_getport(&server_addr, nfsprog, nfsvers,
562 tcp ? IPPROTO_TCP : IPPROTO_UDP); 556 tcp ? IPPROTO_TCP : IPPROTO_UDP);
563 if (port == 0) 557 if (port == 0)
564 port = NFS_PORT; 558 port = NFS_PORT;
565#ifdef NFS_MOUNT_DEBUG 559#ifdef NFS_MOUNT_DEBUG
@@ -571,14 +565,14 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
571 printf(_("using port %d for nfs deamon\n"), port); 565 printf(_("using port %d for nfs deamon\n"), port);
572#endif 566#endif
573 server_addr.sin_port = htons(port); 567 server_addr.sin_port = htons(port);
574 /* 568 /*
575 * connect() the socket for kernels 1.3.10 and below only, 569 * connect() the socket for kernels 1.3.10 and below only,
576 * to avoid problems with multihomed hosts. 570 * to avoid problems with multihomed hosts.
577 * --Swen 571 * --Swen
578 */ 572 */
579 if (linux_version_code() <= 66314 573 if (linux_version_code() <= 66314
580 && connect(fsock, (struct sockaddr *) &server_addr, 574 && connect(fsock, (struct sockaddr *) &server_addr,
581 sizeof (server_addr)) < 0) { 575 sizeof(server_addr)) < 0) {
582 perror(_("nfs connect")); 576 perror(_("nfs connect"));
583 goto fail; 577 goto fail;
584 } 578 }
@@ -587,7 +581,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
587 581
588 data.fd = fsock; 582 data.fd = fsock;
589 memcpy((char *) &data.root, (char *) &root_fhandle, 583 memcpy((char *) &data.root, (char *) &root_fhandle,
590 sizeof (root_fhandle)); 584 sizeof(root_fhandle));
591 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); 585 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
592 strncpy(data.hostname, hostname, sizeof(data.hostname)); 586 strncpy(data.hostname, hostname, sizeof(data.hostname));
593 587
@@ -600,7 +594,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
600 594
601 /* abort */ 595 /* abort */
602 596
603fail: 597 fail:
604 if (msock != -1) { 598 if (msock != -1) {
605 if (mclient) { 599 if (mclient) {
606 auth_destroy(mclient->cl_auth); 600 auth_destroy(mclient->cl_auth);
@@ -611,7 +605,7 @@ fail:
611 if (fsock != -1) 605 if (fsock != -1)
612 close(fsock); 606 close(fsock);
613 return retval; 607 return retval;
614} 608}
615 609
616/* 610/*
617 * We need to translate between nfs status return values and 611 * We need to translate between nfs status return values and
@@ -630,33 +624,37 @@ static struct {
630 enum nfs_stat stat; 624 enum nfs_stat stat;
631 int errnum; 625 int errnum;
632} nfs_errtbl[] = { 626} nfs_errtbl[] = {
633 { NFS_OK, 0 }, 627 {
634 { NFSERR_PERM, EPERM }, 628 NFS_OK, 0}, {
635 { NFSERR_NOENT, ENOENT }, 629 NFSERR_PERM, EPERM}, {
636 { NFSERR_IO, EIO }, 630 NFSERR_NOENT, ENOENT}, {
637 { NFSERR_NXIO, ENXIO }, 631 NFSERR_IO, EIO}, {
638 { NFSERR_ACCES, EACCES }, 632 NFSERR_NXIO, ENXIO}, {
639 { NFSERR_EXIST, EEXIST }, 633 NFSERR_ACCES, EACCES}, {
640 { NFSERR_NODEV, ENODEV }, 634 NFSERR_EXIST, EEXIST}, {
641 { NFSERR_NOTDIR, ENOTDIR }, 635 NFSERR_NODEV, ENODEV}, {
642 { NFSERR_ISDIR, EISDIR }, 636 NFSERR_NOTDIR, ENOTDIR}, {
637 NFSERR_ISDIR, EISDIR},
643#ifdef NFSERR_INVAL 638#ifdef NFSERR_INVAL
644 { NFSERR_INVAL, EINVAL }, /* that Sun forgot */ 639 {
640 NFSERR_INVAL, EINVAL}, /* that Sun forgot */
645#endif 641#endif
646 { NFSERR_FBIG, EFBIG }, 642 {
647 { NFSERR_NOSPC, ENOSPC }, 643 NFSERR_FBIG, EFBIG}, {
648 { NFSERR_ROFS, EROFS }, 644 NFSERR_NOSPC, ENOSPC}, {
649 { NFSERR_NAMETOOLONG, ENAMETOOLONG }, 645 NFSERR_ROFS, EROFS}, {
650 { NFSERR_NOTEMPTY, ENOTEMPTY }, 646 NFSERR_NAMETOOLONG, ENAMETOOLONG}, {
651 { NFSERR_DQUOT, EDQUOT }, 647 NFSERR_NOTEMPTY, ENOTEMPTY}, {
652 { NFSERR_STALE, ESTALE }, 648 NFSERR_DQUOT, EDQUOT}, {
649 NFSERR_STALE, ESTALE},
653#ifdef EWFLUSH 650#ifdef EWFLUSH
654 { NFSERR_WFLUSH, EWFLUSH }, 651 {
652 NFSERR_WFLUSH, EWFLUSH},
655#endif 653#endif
656 /* Throw in some NFSv3 values for even more fun (HP returns these) */ 654 /* Throw in some NFSv3 values for even more fun (HP returns these) */
657 { 71, EREMOTE }, 655 {
658 656 71, EREMOTE}, {
659 { -1, EIO } 657 -1, EIO}
660}; 658};
661 659
662static char *nfs_strerror(int stat) 660static char *nfs_strerror(int stat)
@@ -673,33 +671,32 @@ static char *nfs_strerror(int stat)
673} 671}
674 672
675#if 0 673#if 0
676int 674int my_getport(struct in_addr server, struct timeval *timeo, ...)
677my_getport(struct in_addr server, struct timeval *timeo, ...)
678{ 675{
679 struct sockaddr_in sin; 676 struct sockaddr_in sin;
680 struct pmap pmap; 677 struct pmap pmap;
681 CLIENT *clnt; 678 CLIENT *clnt;
682 int sock = RPC_ANYSOCK, port; 679 int sock = RPC_ANYSOCK, port;
683 680
684 pmap.pm_prog = prog; 681 pmap.pm_prog = prog;
685 pmap.pm_vers = vers; 682 pmap.pm_vers = vers;
686 pmap.pm_prot = prot; 683 pmap.pm_prot = prot;
687 pmap.pm_port = 0; 684 pmap.pm_port = 0;
688 sin.sin_family = AF_INET; 685 sin.sin_family = AF_INET;
689 sin.sin_addr = server; 686 sin.sin_addr = server;
690 sin.sin_port = htons(111); 687 sin.sin_port = htons(111);
691 clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock); 688 clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock);
692 status = clnt_call(clnt, PMAP_GETPORT, 689 status = clnt_call(clnt, PMAP_GETPORT,
693 &pmap, (xdrproc_t) xdr_pmap, 690 &pmap, (xdrproc_t) xdr_pmap,
694 &port, (xdrproc_t) xdr_uint); 691 &port, (xdrproc_t) xdr_uint);
695 if (status != SUCCESS) { 692 if (status != SUCCESS) {
696 /* natter */ 693 /* natter */
697 port = 0; 694 port = 0;
698 } 695 }
699 696
700 clnt_destroy(clnt); 697 clnt_destroy(clnt);
701 close(sock); 698 close(sock);
702 return port; 699 return port;
703} 700}
704#endif 701#endif
705 702
@@ -756,28 +753,26 @@ my_getport(struct in_addr server, struct timeval *timeo, ...)
756 753
757/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ 754/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
758 755
759bool_t 756bool_t xdr_fhandle(XDR * xdrs, fhandle objp)
760xdr_fhandle(XDR *xdrs, fhandle objp)
761{ 757{
762 758
763 if (!xdr_opaque(xdrs, objp, FHSIZE)) { 759 if (!xdr_opaque(xdrs, objp, FHSIZE)) {
764 return (FALSE); 760 return (FALSE);
765 } 761 }
766 return (TRUE); 762 return (TRUE);
767} 763}
768 764
769bool_t 765bool_t xdr_fhstatus(XDR * xdrs, fhstatus * objp)
770xdr_fhstatus(XDR *xdrs, fhstatus *objp)
771{ 766{
772 767
773 if (!xdr_u_int(xdrs, &objp->fhs_status)) { 768 if (!xdr_u_int(xdrs, &objp->fhs_status)) {
774 return (FALSE); 769 return (FALSE);
775 } 770 }
776 switch (objp->fhs_status) { 771 switch (objp->fhs_status) {
777 case 0: 772 case 0:
778 if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) { 773 if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
779 return (FALSE); 774 return (FALSE);
780 } 775 }
781 break; 776 break;
782 default: 777 default:
783 break; 778 break;
@@ -785,245 +780,246 @@ xdr_fhstatus(XDR *xdrs, fhstatus *objp)
785 return (TRUE); 780 return (TRUE);
786} 781}
787 782
788bool_t 783bool_t xdr_dirpath(XDR * xdrs, dirpath * objp)
789xdr_dirpath(XDR *xdrs, dirpath *objp)
790{ 784{
791 785
792 if (!xdr_string(xdrs, objp, MNTPATHLEN)) { 786 if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
793 return (FALSE); 787 return (FALSE);
794 } 788 }
795 return (TRUE); 789 return (TRUE);
796} 790}
797 791
798bool_t 792bool_t xdr_name(XDR * xdrs, name * objp)
799xdr_name(XDR *xdrs, name *objp)
800{ 793{
801 794
802 if (!xdr_string(xdrs, objp, MNTNAMLEN)) { 795 if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
803 return (FALSE); 796 return (FALSE);
804 } 797 }
805 return (TRUE); 798 return (TRUE);
806} 799}
807 800
808bool_t 801bool_t xdr_mountlist(XDR * xdrs, mountlist * objp)
809xdr_mountlist(XDR *xdrs, mountlist *objp)
810{ 802{
811 803
812 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) { 804 if (!xdr_pointer
813 return (FALSE); 805 (xdrs, (char **) objp, sizeof(struct mountbody),
814 } 806 (xdrproc_t) xdr_mountbody)) {
807 return (FALSE);
808 }
815 return (TRUE); 809 return (TRUE);
816} 810}
817 811
818bool_t 812bool_t xdr_mountbody(XDR * xdrs, mountbody * objp)
819xdr_mountbody(XDR *xdrs, mountbody *objp)
820{ 813{
821 814
822 if (!xdr_name(xdrs, &objp->ml_hostname)) { 815 if (!xdr_name(xdrs, &objp->ml_hostname)) {
823 return (FALSE); 816 return (FALSE);
824 } 817 }
825 if (!xdr_dirpath(xdrs, &objp->ml_directory)) { 818 if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
826 return (FALSE); 819 return (FALSE);
827 } 820 }
828 if (!xdr_mountlist(xdrs, &objp->ml_next)) { 821 if (!xdr_mountlist(xdrs, &objp->ml_next)) {
829 return (FALSE); 822 return (FALSE);
830 } 823 }
831 return (TRUE); 824 return (TRUE);
832} 825}
833 826
834bool_t 827bool_t xdr_groups(XDR * xdrs, groups * objp)
835xdr_groups(XDR *xdrs, groups *objp)
836{ 828{
837 829
838 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) { 830 if (!xdr_pointer
839 return (FALSE); 831 (xdrs, (char **) objp, sizeof(struct groupnode),
840 } 832 (xdrproc_t) xdr_groupnode)) {
833 return (FALSE);
834 }
841 return (TRUE); 835 return (TRUE);
842} 836}
843 837
844bool_t 838bool_t xdr_groupnode(XDR * xdrs, groupnode * objp)
845xdr_groupnode(XDR *xdrs, groupnode *objp)
846{ 839{
847 840
848 if (!xdr_name(xdrs, &objp->gr_name)) { 841 if (!xdr_name(xdrs, &objp->gr_name)) {
849 return (FALSE); 842 return (FALSE);
850 } 843 }
851 if (!xdr_groups(xdrs, &objp->gr_next)) { 844 if (!xdr_groups(xdrs, &objp->gr_next)) {
852 return (FALSE); 845 return (FALSE);
853 } 846 }
854 return (TRUE); 847 return (TRUE);
855} 848}
856 849
857bool_t 850bool_t xdr_exports(XDR * xdrs, exports * objp)
858xdr_exports(XDR *xdrs, exports *objp)
859{ 851{
860 852
861 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) { 853 if (!xdr_pointer
862 return (FALSE); 854 (xdrs, (char **) objp, sizeof(struct exportnode),
863 } 855 (xdrproc_t) xdr_exportnode)) {
856 return (FALSE);
857 }
864 return (TRUE); 858 return (TRUE);
865} 859}
866 860
867bool_t 861bool_t xdr_exportnode(XDR * xdrs, exportnode * objp)
868xdr_exportnode(XDR *xdrs, exportnode *objp)
869{ 862{
870 863
871 if (!xdr_dirpath(xdrs, &objp->ex_dir)) { 864 if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
872 return (FALSE); 865 return (FALSE);
873 } 866 }
874 if (!xdr_groups(xdrs, &objp->ex_groups)) { 867 if (!xdr_groups(xdrs, &objp->ex_groups)) {
875 return (FALSE); 868 return (FALSE);
876 } 869 }
877 if (!xdr_exports(xdrs, &objp->ex_next)) { 870 if (!xdr_exports(xdrs, &objp->ex_next)) {
878 return (FALSE); 871 return (FALSE);
879 } 872 }
880 return (TRUE); 873 return (TRUE);
881} 874}
882 875
883bool_t 876bool_t xdr_ppathcnf(XDR * xdrs, ppathcnf * objp)
884xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
885{ 877{
886 878
887 register long *buf; 879 register long *buf;
888 880
889 int i; 881 int i;
890 882
891 if (xdrs->x_op == XDR_ENCODE) { 883 if (xdrs->x_op == XDR_ENCODE) {
892 buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); 884 buf = (long *) XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
893 if (buf == NULL) {
894 if (!xdr_int(xdrs, &objp->pc_link_max)) {
895 return (FALSE);
896 }
897 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
898 return (FALSE);
899 }
900 if (!xdr_short(xdrs, &objp->pc_max_input)) {
901 return (FALSE);
902 }
903 if (!xdr_short(xdrs, &objp->pc_name_max)) {
904 return (FALSE);
905 }
906 if (!xdr_short(xdrs, &objp->pc_path_max)) {
907 return (FALSE);
908 }
909 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
910 return (FALSE);
911 }
912
913 }
914 else {
915 IXDR_PUT_LONG(buf,objp->pc_link_max);
916 IXDR_PUT_SHORT(buf,objp->pc_max_canon);
917 IXDR_PUT_SHORT(buf,objp->pc_max_input);
918 IXDR_PUT_SHORT(buf,objp->pc_name_max);
919 IXDR_PUT_SHORT(buf,objp->pc_path_max);
920 IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
921 }
922 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
923 return (FALSE);
924 }
925 if (!xdr_char(xdrs, &objp->pc_xxx)) {
926 return (FALSE);
927 }
928 buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
929 if (buf == NULL) { 885 if (buf == NULL) {
930 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 886 if (!xdr_int(xdrs, &objp->pc_link_max)) {
931 return (FALSE); 887 return (FALSE);
932 } 888 }
933 889 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
934 } 890 return (FALSE);
935 else { 891 }
936 { register short *genp; 892 if (!xdr_short(xdrs, &objp->pc_max_input)) {
937 for ( i = 0,genp=objp->pc_mask; 893 return (FALSE);
938 i < 2; i++){ 894 }
939 IXDR_PUT_SHORT(buf,*genp++); 895 if (!xdr_short(xdrs, &objp->pc_name_max)) {
940 } 896 return (FALSE);
941 }; 897 }
942 } 898 if (!xdr_short(xdrs, &objp->pc_path_max)) {
943 899 return (FALSE);
944 return (TRUE); 900 }
901 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
902 return (FALSE);
903 }
904
905 } else {
906 IXDR_PUT_LONG(buf, objp->pc_link_max);
907 IXDR_PUT_SHORT(buf, objp->pc_max_canon);
908 IXDR_PUT_SHORT(buf, objp->pc_max_input);
909 IXDR_PUT_SHORT(buf, objp->pc_name_max);
910 IXDR_PUT_SHORT(buf, objp->pc_path_max);
911 IXDR_PUT_SHORT(buf, objp->pc_pipe_buf);
912 }
913 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
914 return (FALSE);
915 }
916 if (!xdr_char(xdrs, &objp->pc_xxx)) {
917 return (FALSE);
918 }
919 buf = (long *) XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
920 if (buf == NULL) {
921 if (!xdr_vector
922 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
923 (xdrproc_t) xdr_short)) {
924 return (FALSE);
925 }
926
927 } else {
928 {
929 register short *genp;
930
931 for (i = 0, genp = objp->pc_mask; i < 2; i++) {
932 IXDR_PUT_SHORT(buf, *genp++);
933 }
934 };
935 }
936
937 return (TRUE);
945 } else if (xdrs->x_op == XDR_DECODE) { 938 } else if (xdrs->x_op == XDR_DECODE) {
946 buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); 939 buf = (long *) XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
947 if (buf == NULL) { 940 if (buf == NULL) {
948 if (!xdr_int(xdrs, &objp->pc_link_max)) { 941 if (!xdr_int(xdrs, &objp->pc_link_max)) {
949 return (FALSE); 942 return (FALSE);
950 } 943 }
951 if (!xdr_short(xdrs, &objp->pc_max_canon)) { 944 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
952 return (FALSE); 945 return (FALSE);
953 } 946 }
954 if (!xdr_short(xdrs, &objp->pc_max_input)) { 947 if (!xdr_short(xdrs, &objp->pc_max_input)) {
955 return (FALSE); 948 return (FALSE);
956 } 949 }
957 if (!xdr_short(xdrs, &objp->pc_name_max)) { 950 if (!xdr_short(xdrs, &objp->pc_name_max)) {
958 return (FALSE); 951 return (FALSE);
959 } 952 }
960 if (!xdr_short(xdrs, &objp->pc_path_max)) { 953 if (!xdr_short(xdrs, &objp->pc_path_max)) {
961 return (FALSE); 954 return (FALSE);
962 } 955 }
963 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { 956 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
964 return (FALSE); 957 return (FALSE);
965 } 958 }
966 959
967 } 960 } else {
968 else { 961 objp->pc_link_max = IXDR_GET_LONG(buf);
969 objp->pc_link_max = IXDR_GET_LONG(buf); 962 objp->pc_max_canon = IXDR_GET_SHORT(buf);
970 objp->pc_max_canon = IXDR_GET_SHORT(buf); 963 objp->pc_max_input = IXDR_GET_SHORT(buf);
971 objp->pc_max_input = IXDR_GET_SHORT(buf); 964 objp->pc_name_max = IXDR_GET_SHORT(buf);
972 objp->pc_name_max = IXDR_GET_SHORT(buf); 965 objp->pc_path_max = IXDR_GET_SHORT(buf);
973 objp->pc_path_max = IXDR_GET_SHORT(buf); 966 objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
974 objp->pc_pipe_buf = IXDR_GET_SHORT(buf); 967 }
975 } 968 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
976 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { 969 return (FALSE);
977 return (FALSE); 970 }
978 } 971 if (!xdr_char(xdrs, &objp->pc_xxx)) {
979 if (!xdr_char(xdrs, &objp->pc_xxx)) { 972 return (FALSE);
980 return (FALSE); 973 }
981 } 974 buf = (long *) XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
982 buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
983 if (buf == NULL) { 975 if (buf == NULL) {
984 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 976 if (!xdr_vector
985 return (FALSE); 977 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
986 } 978 (xdrproc_t) xdr_short)) {
987 979 return (FALSE);
988 } 980 }
989 else { 981
990 { register short *genp; 982 } else {
991 for ( i = 0,genp=objp->pc_mask; 983 {
992 i < 2; i++){ 984 register short *genp;
993 *genp++ = IXDR_GET_SHORT(buf); 985
994 } 986 for (i = 0, genp = objp->pc_mask; i < 2; i++) {
995 }; 987 *genp++ = IXDR_GET_SHORT(buf);
996 } 988 }
997 return(TRUE); 989 };
990 }
991 return (TRUE);
998 } 992 }
999 993
1000 if (!xdr_int(xdrs, &objp->pc_link_max)) { 994 if (!xdr_int(xdrs, &objp->pc_link_max)) {
1001 return (FALSE); 995 return (FALSE);
1002 } 996 }
1003 if (!xdr_short(xdrs, &objp->pc_max_canon)) { 997 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
1004 return (FALSE); 998 return (FALSE);
1005 } 999 }
1006 if (!xdr_short(xdrs, &objp->pc_max_input)) { 1000 if (!xdr_short(xdrs, &objp->pc_max_input)) {
1007 return (FALSE); 1001 return (FALSE);
1008 } 1002 }
1009 if (!xdr_short(xdrs, &objp->pc_name_max)) { 1003 if (!xdr_short(xdrs, &objp->pc_name_max)) {
1010 return (FALSE); 1004 return (FALSE);
1011 } 1005 }
1012 if (!xdr_short(xdrs, &objp->pc_path_max)) { 1006 if (!xdr_short(xdrs, &objp->pc_path_max)) {
1013 return (FALSE); 1007 return (FALSE);
1014 } 1008 }
1015 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { 1009 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
1016 return (FALSE); 1010 return (FALSE);
1017 } 1011 }
1018 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { 1012 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
1019 return (FALSE); 1013 return (FALSE);
1020 } 1014 }
1021 if (!xdr_char(xdrs, &objp->pc_xxx)) { 1015 if (!xdr_char(xdrs, &objp->pc_xxx)) {
1022 return (FALSE); 1016 return (FALSE);
1023 } 1017 }
1024 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 1018 if (!xdr_vector
1025 return (FALSE); 1019 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
1026 } 1020 (xdrproc_t) xdr_short)) {
1021 return (FALSE);
1022 }
1027 return (TRUE); 1023 return (TRUE);
1028} 1024}
1029 1025
@@ -1063,247 +1059,232 @@ xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
1063 1059
1064/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ 1060/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
1065 1061
1066#include <string.h> /* for memset() */ 1062#include <string.h> /* for memset() */
1067 1063
1068/* Default timeout can be changed using clnt_control() */ 1064/* Default timeout can be changed using clnt_control() */
1069static struct timeval TIMEOUT = { 25, 0 }; 1065static struct timeval TIMEOUT = { 25, 0 };
1070 1066
1071void * 1067void *mountproc_null_1(argp, clnt)
1072mountproc_null_1(argp, clnt) 1068void *argp;
1073 void *argp; 1069CLIENT *clnt;
1074 CLIENT *clnt;
1075{ 1070{
1076 static char clnt_res; 1071 static char clnt_res;
1077 1072
1078 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1073 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1079 if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1074 if (clnt_call
1075 (clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp,
1076 (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1080 return (NULL); 1077 return (NULL);
1081 } 1078 }
1082 return ((void *)&clnt_res); 1079 return ((void *) &clnt_res);
1083} 1080}
1084 1081
1085fhstatus * 1082fhstatus *mountproc_mnt_1(argp, clnt)
1086mountproc_mnt_1(argp, clnt) 1083dirpath *argp;
1087 dirpath *argp; 1084CLIENT *clnt;
1088 CLIENT *clnt;
1089{ 1085{
1090 static fhstatus clnt_res; 1086 static fhstatus clnt_res;
1091 1087
1092 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1088 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1093 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, 1089 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1094 (caddr_t) argp, (xdrproc_t) xdr_fhstatus, 1090 (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1095 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1091 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1096 return (NULL); 1092 return (NULL);
1097 } 1093 }
1098 return (&clnt_res); 1094 return (&clnt_res);
1099} 1095}
1100 1096
1101mountlist * 1097mountlist *mountproc_dump_1(argp, clnt)
1102mountproc_dump_1(argp, clnt) 1098void *argp;
1103 void *argp; 1099CLIENT *clnt;
1104 CLIENT *clnt;
1105{ 1100{
1106 static mountlist clnt_res; 1101 static mountlist clnt_res;
1107 1102
1108 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1103 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1109 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, 1104 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void,
1110 (caddr_t) argp, (xdrproc_t) xdr_mountlist, 1105 (caddr_t) argp, (xdrproc_t) xdr_mountlist,
1111 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1106 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1112 return (NULL); 1107 return (NULL);
1113 } 1108 }
1114 return (&clnt_res); 1109 return (&clnt_res);
1115} 1110}
1116 1111
1117void * 1112void *mountproc_umnt_1(argp, clnt)
1118mountproc_umnt_1(argp, clnt) 1113dirpath *argp;
1119 dirpath *argp; 1114CLIENT *clnt;
1120 CLIENT *clnt;
1121{ 1115{
1122 static char clnt_res; 1116 static char clnt_res;
1123 1117
1124 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1118 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1125 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, 1119 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1126 (caddr_t) argp, (xdrproc_t) xdr_void, 1120 (caddr_t) argp, (xdrproc_t) xdr_void,
1127 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1121 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1128 return (NULL); 1122 return (NULL);
1129 } 1123 }
1130 return ((void *)&clnt_res); 1124 return ((void *) &clnt_res);
1131} 1125}
1132 1126
1133void * 1127void *mountproc_umntall_1(argp, clnt)
1134mountproc_umntall_1(argp, clnt) 1128void *argp;
1135 void *argp; 1129CLIENT *clnt;
1136 CLIENT *clnt;
1137{ 1130{
1138 static char clnt_res; 1131 static char clnt_res;
1139 1132
1140 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1133 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1141 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, 1134 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1142 (caddr_t) argp, (xdrproc_t) xdr_void, 1135 (caddr_t) argp, (xdrproc_t) xdr_void,
1143 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1136 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1144 return (NULL); 1137 return (NULL);
1145 } 1138 }
1146 return ((void *)&clnt_res); 1139 return ((void *) &clnt_res);
1147} 1140}
1148 1141
1149exports * 1142exports *mountproc_export_1(argp, clnt)
1150mountproc_export_1(argp, clnt) 1143void *argp;
1151 void *argp; 1144CLIENT *clnt;
1152 CLIENT *clnt;
1153{ 1145{
1154 static exports clnt_res; 1146 static exports clnt_res;
1155 1147
1156 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1148 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1157 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, 1149 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1158 (caddr_t) argp, (xdrproc_t) xdr_exports, 1150 (caddr_t) argp, (xdrproc_t) xdr_exports,
1159 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1151 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1160 return (NULL); 1152 return (NULL);
1161 } 1153 }
1162 return (&clnt_res); 1154 return (&clnt_res);
1163} 1155}
1164 1156
1165exports * 1157exports *mountproc_exportall_1(argp, clnt)
1166mountproc_exportall_1(argp, clnt) 1158void *argp;
1167 void *argp; 1159CLIENT *clnt;
1168 CLIENT *clnt;
1169{ 1160{
1170 static exports clnt_res; 1161 static exports clnt_res;
1171 1162
1172 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1163 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1173 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, 1164 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void,
1174 (caddr_t) argp, (xdrproc_t) xdr_exports, 1165 (caddr_t) argp, (xdrproc_t) xdr_exports,
1175 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1166 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1176 return (NULL); 1167 return (NULL);
1177 } 1168 }
1178 return (&clnt_res); 1169 return (&clnt_res);
1179} 1170}
1180 1171
1181void * 1172void *mountproc_null_2(argp, clnt)
1182mountproc_null_2(argp, clnt) 1173void *argp;
1183 void *argp; 1174CLIENT *clnt;
1184 CLIENT *clnt;
1185{ 1175{
1186 static char clnt_res; 1176 static char clnt_res;
1187 1177
1188 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1178 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1189 if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1179 if (clnt_call
1180 (clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp,
1181 (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1190 return (NULL); 1182 return (NULL);
1191 } 1183 }
1192 return ((void *)&clnt_res); 1184 return ((void *) &clnt_res);
1193} 1185}
1194 1186
1195fhstatus * 1187fhstatus *mountproc_mnt_2(argp, clnt)
1196mountproc_mnt_2(argp, clnt) 1188dirpath *argp;
1197 dirpath *argp; 1189CLIENT *clnt;
1198 CLIENT *clnt;
1199{ 1190{
1200 static fhstatus clnt_res; 1191 static fhstatus clnt_res;
1201 1192
1202 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1193 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1203 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, 1194 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1204 (caddr_t) argp, (xdrproc_t) xdr_fhstatus, 1195 (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1205 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1196 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1206 return (NULL); 1197 return (NULL);
1207 } 1198 }
1208 return (&clnt_res); 1199 return (&clnt_res);
1209} 1200}
1210 1201
1211mountlist * 1202mountlist *mountproc_dump_2(argp, clnt)
1212mountproc_dump_2(argp, clnt) 1203void *argp;
1213 void *argp; 1204CLIENT *clnt;
1214 CLIENT *clnt;
1215{ 1205{
1216 static mountlist clnt_res; 1206 static mountlist clnt_res;
1217 1207
1218 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1208 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1219 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, 1209 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp,
1220 (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res, 1210 (xdrproc_t) xdr_mountlist, (caddr_t) & clnt_res,
1221 TIMEOUT) != RPC_SUCCESS) { 1211 TIMEOUT) != RPC_SUCCESS) {
1222 return (NULL); 1212 return (NULL);
1223 } 1213 }
1224 return (&clnt_res); 1214 return (&clnt_res);
1225} 1215}
1226 1216
1227void * 1217void *mountproc_umnt_2(argp, clnt)
1228mountproc_umnt_2(argp, clnt) 1218dirpath *argp;
1229 dirpath *argp; 1219CLIENT *clnt;
1230 CLIENT *clnt;
1231{ 1220{
1232 static char clnt_res; 1221 static char clnt_res;
1233 1222
1234 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1223 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1235 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, 1224 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1236 (caddr_t) argp, (xdrproc_t) xdr_void, 1225 (caddr_t) argp, (xdrproc_t) xdr_void,
1237 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1226 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1238 return (NULL); 1227 return (NULL);
1239 } 1228 }
1240 return ((void *)&clnt_res); 1229 return ((void *) &clnt_res);
1241} 1230}
1242 1231
1243void * 1232void *mountproc_umntall_2(argp, clnt)
1244mountproc_umntall_2(argp, clnt) 1233void *argp;
1245 void *argp; 1234CLIENT *clnt;
1246 CLIENT *clnt;
1247{ 1235{
1248 static char clnt_res; 1236 static char clnt_res;
1249 1237
1250 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1238 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1251 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, 1239 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1252 (caddr_t) argp, (xdrproc_t) xdr_void, 1240 (caddr_t) argp, (xdrproc_t) xdr_void,
1253 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1241 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1254 return (NULL); 1242 return (NULL);
1255 } 1243 }
1256 return ((void *)&clnt_res); 1244 return ((void *) &clnt_res);
1257} 1245}
1258 1246
1259exports * 1247exports *mountproc_export_2(argp, clnt)
1260mountproc_export_2(argp, clnt) 1248void *argp;
1261 void *argp; 1249CLIENT *clnt;
1262 CLIENT *clnt;
1263{ 1250{
1264 static exports clnt_res; 1251 static exports clnt_res;
1265 1252
1266 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1253 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1267 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, 1254 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1268 argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, 1255 argp, (xdrproc_t) xdr_exports, (caddr_t) & clnt_res,
1269 TIMEOUT) != RPC_SUCCESS) { 1256 TIMEOUT) != RPC_SUCCESS) {
1270 return (NULL); 1257 return (NULL);
1271 } 1258 }
1272 return (&clnt_res); 1259 return (&clnt_res);
1273} 1260}
1274 1261
1275exports * 1262exports *mountproc_exportall_2(argp, clnt)
1276mountproc_exportall_2(argp, clnt) 1263void *argp;
1277 void *argp; 1264CLIENT *clnt;
1278 CLIENT *clnt;
1279{ 1265{
1280 static exports clnt_res; 1266 static exports clnt_res;
1281 1267
1282 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1268 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1283 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, 1269 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp,
1284 (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, 1270 (xdrproc_t) xdr_exports, (caddr_t) & clnt_res,
1285 TIMEOUT) != RPC_SUCCESS) { 1271 TIMEOUT) != RPC_SUCCESS) {
1286 return (NULL); 1272 return (NULL);
1287 } 1273 }
1288 return (&clnt_res); 1274 return (&clnt_res);
1289} 1275}
1290 1276
1291ppathcnf * 1277ppathcnf *mountproc_pathconf_2(argp, clnt)
1292mountproc_pathconf_2(argp, clnt) 1278dirpath *argp;
1293 dirpath *argp; 1279CLIENT *clnt;
1294 CLIENT *clnt;
1295{ 1280{
1296 static ppathcnf clnt_res; 1281 static ppathcnf clnt_res;
1297 1282
1298 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1283 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1299 if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, 1284 if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath,
1300 (caddr_t) argp, (xdrproc_t) xdr_ppathcnf, 1285 (caddr_t) argp, (xdrproc_t) xdr_ppathcnf,
1301 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1286 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1302 return (NULL); 1287 return (NULL);
1303 } 1288 }
1304 return (&clnt_res); 1289 return (&clnt_res);
1305} 1290}
1306
1307
1308
1309
diff --git a/nfsmount.h b/nfsmount.h
index 73c71fc68..64ac617c0 100644
--- a/nfsmount.h
+++ b/nfsmount.h
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Please do not edit this file. 3 * Please do not edit this file.
3 * It was generated using rpcgen. 4 * It was generated using rpcgen.
diff --git a/nslookup.c b/nslookup.c
index 969d0b19b..ffa720174 100644
--- a/nslookup.c
+++ b/nslookup.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini nslookup implementation for busybox 3 * Mini nslookup implementation for busybox
3 * 4 *
@@ -41,148 +42,136 @@
41 | + find out how the real nslookup gets the default name server 42 | + find out how the real nslookup gets the default name server
42 */ 43 */
43 44
44static const char nslookup_usage[] = 45static const char nslookup_usage[] = "nslookup [HOST]\n\n";
45 "nslookup [HOST]\n\n"
46;
47 46
48 47
49/* I have to see how the real nslookup does this. 48/* I have to see how the real nslookup does this.
50 * I could dig through /etc/resolv.conf, but is there a 49 * I could dig through /etc/resolv.conf, but is there a
51 * better (programatic) way? 50 * better (programatic) way?
52 */ 51 */
53static void 52static void server_fprint(FILE * dst)
54server_fprint(FILE *dst)
55{ 53{
56 fprintf(dst, "Server: %s\n", "something"); 54 fprintf(dst, "Server: %s\n", "something");
57 fprintf(dst, "Address: %s\n\n", "something"); 55 fprintf(dst, "Address: %s\n\n", "something");
58} 56}
59 57
60/* only works for IPv4 */ 58/* only works for IPv4 */
61static int 59static int addr_fprint(char *addr, FILE * dst)
62addr_fprint(char *addr, FILE *dst)
63{ 60{
64 uint8_t split[4]; 61 uint8_t split[4];
65 uint32_t ip; 62 uint32_t ip;
66 uint32_t *x = (uint32_t *) addr; 63 uint32_t *x = (uint32_t *) addr;
67 64
68 ip = ntohl(*x); 65 ip = ntohl(*x);
69 split[0] = (ip & 0xff000000) >> 24; 66 split[0] = (ip & 0xff000000) >> 24;
70 split[1] = (ip & 0x00ff0000) >> 16; 67 split[1] = (ip & 0x00ff0000) >> 16;
71 split[2] = (ip & 0x0000ff00) >> 8; 68 split[2] = (ip & 0x0000ff00) >> 8;
72 split[3] = (ip & 0x000000ff); 69 split[3] = (ip & 0x000000ff);
73 fprintf ( 70 fprintf(dst, "%d.%d.%d.%d", split[0], split[1], split[2], split[3]
74 dst, "%d.%d.%d.%d", 71 );
75 split[0], split[1], split[2], split[3] 72 return 0;
76 );
77 return 0;
78} 73}
79 74
80/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+ 75/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+
81 * into a uint32_t 76 * into a uint32_t
82 */ 77 */
83static uint32_t 78static uint32_t str_to_addr(const char *addr)
84str_to_addr(const char *addr)
85{ 79{
86 uint32_t split[4]; 80 uint32_t split[4];
87 uint32_t ip; 81 uint32_t ip;
88 82
89 sscanf(addr, "%d.%d.%d.%d", 83 sscanf(addr, "%d.%d.%d.%d",
90 &split[0], &split[1], &split[2], &split[3]); 84 &split[0], &split[1], &split[2], &split[3]);
91 85
92 /* assuming sscanf worked */ 86 /* assuming sscanf worked */
93 ip = (split[0] << 24) | 87 ip = (split[0] << 24) |
94 (split[1] << 16) | 88 (split[1] << 16) | (split[2] << 8) | (split[3]);
95 (split[2] << 8) |
96 (split[3]);
97 89
98 return htonl(ip); 90 return htonl(ip);
99} 91}
100 92
101/* takes the NULL-terminated array h_addr_list, and 93/* takes the NULL-terminated array h_addr_list, and
102 * prints its contents appropriately 94 * prints its contents appropriately
103 */ 95 */
104static int 96static int addr_list_fprint(char **h_addr_list, FILE * dst)
105addr_list_fprint(char **h_addr_list, FILE *dst)
106{ 97{
107 int i, j; 98 int i, j;
108 char *addr_string = (h_addr_list[1]) 99 char *addr_string = (h_addr_list[1])
109 ? "Addresses" 100 ? "Addresses" : "Address";
110 : "Address"; 101
111 102 fprintf(dst, "%s: ", addr_string);
112 fprintf(dst, "%s: ", addr_string); 103 for (i = 0, j = 0; h_addr_list[i]; i++, j++) {
113 for (i = 0, j = 0; h_addr_list[i]; i++, j++) { 104 addr_fprint(h_addr_list[i], dst);
114 addr_fprint(h_addr_list[i], dst); 105
115 106 /* real nslookup does this */
116 /* real nslookup does this */ 107 if (j == 4) {
117 if (j == 4) { 108 if (h_addr_list[i + 1]) {
118 if (h_addr_list[i+1]) { 109 fprintf(dst, "\n ");
119 fprintf(dst, "\n "); 110 }
120 } 111 j = 0;
121 j = 0; 112 } else {
122 } else { 113 if (h_addr_list[i + 1]) {
123 if (h_addr_list[i+1]) { 114 fprintf(dst, ", ");
124 fprintf(dst, ", "); 115 }
125 } 116 }
126 }
127 117
128 } 118 }
129 fprintf(dst,"\n"); 119 fprintf(dst, "\n");
130 return 0; 120 return 0;
131} 121}
132 122
133/* gethostbyaddr wrapper */ 123/* gethostbyaddr wrapper */
134static struct hostent * 124static struct hostent *gethostbyaddr_wrapper(const char *address)
135gethostbyaddr_wrapper(const char *address)
136{ 125{
137 struct in_addr addr; 126 struct in_addr addr;
138 127
139 addr.s_addr = str_to_addr(address); 128 addr.s_addr = str_to_addr(address);
140 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */ 129 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */
141} 130}
142 131
143/* print the results as nslookup would */ 132/* print the results as nslookup would */
144static struct hostent * 133static struct hostent *hostent_fprint(struct hostent *host, FILE * dst)
145hostent_fprint(struct hostent *host, FILE *dst)
146{ 134{
147 if (host) { 135 if (host) {
148 fprintf(dst, "Name: %s\n", host->h_name); 136 fprintf(dst, "Name: %s\n", host->h_name);
149 addr_list_fprint(host->h_addr_list, dst); 137 addr_list_fprint(host->h_addr_list, dst);
150 } else { 138 } else {
151 fprintf(dst, "*** %s\n", hstrerror(h_errno)); 139 fprintf(dst, "*** %s\n", hstrerror(h_errno));
152 } 140 }
153 return host; 141 return host;
154} 142}
155 143
156 144
157/* naive function to check whether char *s is an ip address */ 145/* naive function to check whether char *s is an ip address */
158static int 146static int is_ip_address(const char *s)
159is_ip_address(const char *s)
160{ 147{
161 while (*s) { 148 while (*s) {
162 if ((isdigit(*s)) || (*s == '.')) { s++; continue; } 149 if ((isdigit(*s)) || (*s == '.')) {
163 return 0; 150 s++;
164 } 151 continue;
165 return 1; 152 }
153 return 0;
154 }
155 return 1;
166} 156}
167 157
168/* ________________________________________________________________________ */ 158/* ________________________________________________________________________ */
169int 159int nslookup_main(int argc, char **argv)
170nslookup_main(int argc, char **argv)
171{ 160{
172 struct hostent *host; 161 struct hostent *host;
173 162
174 if (argc < 2) { 163 if (argc < 2) {
175 usage(nslookup_usage); 164 usage(nslookup_usage);
176 } 165 }
177 166
178 server_fprint(stdout); 167 server_fprint(stdout);
179 if (is_ip_address(argv[1])) { 168 if (is_ip_address(argv[1])) {
180 host = gethostbyaddr_wrapper(argv[1]); 169 host = gethostbyaddr_wrapper(argv[1]);
181 } else { 170 } else {
182 host = gethostbyname(argv[1]); 171 host = gethostbyname(argv[1]);
183 } 172 }
184 hostent_fprint(host, stdout); 173 hostent_fprint(host, stdout);
185 return 0; 174 return 0;
186} 175}
187 176
188/* $Id: nslookup.c,v 1.3 2000/02/07 05:29:42 erik Exp $ */ 177/* $Id: nslookup.c,v 1.4 2000/02/08 19:58:47 erik Exp $ */
diff --git a/ping.c b/ping.c
index 3ffbdc553..c9cf5ffb4 100644
--- a/ping.c
+++ b/ping.c
@@ -1,5 +1,6 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * $Id: ping.c,v 1.10 2000/02/07 05:29:42 erik Exp $ 3 * $Id: ping.c,v 1.11 2000/02/08 19:58:47 erik Exp $
3 * Mini ping implementation for busybox 4 * Mini ping implementation for busybox
4 * 5 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -53,7 +54,7 @@
53#define MAXPACKET 65468 54#define MAXPACKET 65468
54#define MAX_DUP_CHK (8 * 128) 55#define MAX_DUP_CHK (8 * 128)
55#define MAXWAIT 10 56#define MAXWAIT 10
56#define PINGINTERVAL 1 /* second */ 57#define PINGINTERVAL 1 /* second */
57 58
58#define O_QUIET (1 << 0) 59#define O_QUIET (1 << 0)
59 60
@@ -66,118 +67,124 @@
66/* common routines */ 67/* common routines */
67static int in_cksum(unsigned short *buf, int sz) 68static int in_cksum(unsigned short *buf, int sz)
68{ 69{
69 int nleft = sz; 70 int nleft = sz;
70 int sum = 0; 71 int sum = 0;
71 unsigned short *w = buf; 72 unsigned short *w = buf;
72 unsigned short ans = 0; 73 unsigned short ans = 0;
73 74
74 while (nleft > 1) { 75 while (nleft > 1) {
75 sum += *w++; 76 sum += *w++;
76 nleft -= 2; 77 nleft -= 2;
77 } 78 }
78 79
79 if (nleft == 1) { 80 if (nleft == 1) {
80 *(unsigned char *)(&ans) = *(unsigned char *)w; 81 *(unsigned char *) (&ans) = *(unsigned char *) w;
81 sum += ans; 82 sum += ans;
82 } 83 }
83 84
84 sum = (sum >> 16) + (sum & 0xFFFF); 85 sum = (sum >> 16) + (sum & 0xFFFF);
85 sum += (sum >> 16); 86 sum += (sum >> 16);
86 ans = ~sum; 87 ans = ~sum;
87 return(ans); 88 return (ans);
88} 89}
89 90
90/* simple version */ 91/* simple version */
91#ifdef BB_SIMPLE_PING 92#ifdef BB_SIMPLE_PING
92static const char* ping_usage = "ping host\n\n"; 93static const char *ping_usage = "ping host\n\n";
93 94
94static char* hostname = NULL; 95static char *hostname = NULL;
95 96
96static void noresp(int ign) 97static void noresp(int ign)
97{ 98{
98 printf("No response from %s\n", hostname); 99 printf("No response from %s\n", hostname);
99 exit(0); 100 exit(0);
100} 101}
101 102
102static int ping(const char *host) 103static int ping(const char *host)
103{ 104{
104 struct hostent *h; 105 struct hostent *h;
105 struct sockaddr_in pingaddr; 106 struct sockaddr_in pingaddr;
106 struct icmp *pkt; 107 struct icmp *pkt;
107 int pingsock, c; 108 int pingsock, c;
108 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 109 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
109 110
110 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { /* 1 == ICMP */ 111 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { /* 1 == ICMP */
111 perror("ping"); 112 perror("ping");
112 exit(1); 113 exit(1);
113 } 114 }
114 115
115 /* drop root privs if running setuid */ 116 /* drop root privs if running setuid */
116 setuid(getuid()); 117 setuid(getuid());
117 118
118 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 119 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
119 pingaddr.sin_family = AF_INET; 120
120 if (!(h = gethostbyname(host))) { 121 pingaddr.sin_family = AF_INET;
121 fprintf(stderr, "ping: unknown host %s\n", host); 122 if (!(h = gethostbyname(host))) {
122 exit(1); 123 fprintf(stderr, "ping: unknown host %s\n", host);
123 } 124 exit(1);
124 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); 125 }
125 hostname = h->h_name; 126 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
126 127 hostname = h->h_name;
127 pkt = (struct icmp *)packet; 128
128 memset(pkt, 0, sizeof(packet)); 129 pkt = (struct icmp *) packet;
129 pkt->icmp_type = ICMP_ECHO; 130 memset(pkt, 0, sizeof(packet));
130 pkt->icmp_cksum = in_cksum((unsigned short *)pkt, sizeof(packet)); 131 pkt->icmp_type = ICMP_ECHO;
131 132 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
132 c = sendto(pingsock, packet, sizeof(packet), 0, 133
133 (struct sockaddr *)&pingaddr, sizeof(struct sockaddr_in)); 134 c = sendto(pingsock, packet, sizeof(packet), 0,
134 135 (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
135 if (c < 0 || c != sizeof(packet)) { 136
136 if (c < 0) perror("ping"); 137 if (c < 0 || c != sizeof(packet)) {
137 fprintf(stderr, "ping: write incomplete\n"); 138 if (c < 0)
138 exit(1); 139 perror("ping");
139 } 140 fprintf(stderr, "ping: write incomplete\n");
140 141 exit(1);
141 signal(SIGALRM, noresp); 142 }
142 alarm(5); /* give the host 5000ms to respond */ 143
143 /* listen for replies */ 144 signal(SIGALRM, noresp);
144 while (1) { 145 alarm(5); /* give the host 5000ms to respond */
145 struct sockaddr_in from; 146 /* listen for replies */
146 size_t fromlen = sizeof(from); 147 while (1) {
147 148 struct sockaddr_in from;
148 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0, 149 size_t fromlen = sizeof(from);
149 (struct sockaddr *)&from, &fromlen)) < 0) { 150
150 if (errno == EINTR) continue; 151 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
151 perror("ping"); 152 (struct sockaddr *) &from, &fromlen)) < 0) {
152 continue; 153 if (errno == EINTR)
154 continue;
155 perror("ping");
156 continue;
157 }
158 if (c >= 76) { /* ip + icmp */
159 struct iphdr *iphdr = (struct iphdr *) packet;
160
161 pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); /* skip ip hdr */
162 if (pkt->icmp_type == ICMP_ECHOREPLY)
163 break;
164 }
153 } 165 }
154 if (c >= 76) { /* ip + icmp */ 166 printf("%s is alive!\n", hostname);
155 struct iphdr *iphdr = (struct iphdr *)packet; 167 return (TRUE);
156 pkt = (struct icmp *)(packet + (iphdr->ihl << 2)); /* skip ip hdr */
157 if (pkt->icmp_type == ICMP_ECHOREPLY) break;
158 }
159 }
160 printf("%s is alive!\n", hostname);
161 return(TRUE);
162} 168}
163 169
164extern int ping_main(int argc, char **argv) 170extern int ping_main(int argc, char **argv)
165{ 171{
166 argc--; 172 argc--;
167 argv++; 173 argv++;
168 if (argc < 1) usage(ping_usage); 174 if (argc < 1)
169 ping(*argv); 175 usage(ping_usage);
170 exit(TRUE); 176 ping(*argv);
177 exit(TRUE);
171} 178}
172 179
173#else 180#else
174/* full(er) version */ 181/* full(er) version */
175static const char* ping_usage = "ping [OPTION]... host\n\n" 182static const char *ping_usage = "ping [OPTION]... host\n\n"
176"Send ICMP ECHO_REQUEST packets to network hosts.\n\n" 183 "Send ICMP ECHO_REQUEST packets to network hosts.\n\n"
177"Options:\n" 184 "Options:\n"
178"\t-q\t\tQuiet mode, only displays output at start" 185 "\t-q\t\tQuiet mode, only displays output at start"
179"\t\t\tand when finished.\n" 186
180"\t-c COUNT\tSend only COUNT pings.\n"; 187 "\t\t\tand when finished.\n" "\t-c COUNT\tSend only COUNT pings.\n";
181 188
182static char *hostname = NULL; 189static char *hostname = NULL;
183static struct sockaddr_in pingaddr; 190static struct sockaddr_in pingaddr;
@@ -196,224 +203,247 @@ static void ping(char *);
196 203
197/**************************************************************************/ 204/**************************************************************************/
198 205
199static void pingstats(int ign) { 206static void pingstats(int ign)
200 signal(SIGINT, SIG_IGN); 207{
201 208 signal(SIGINT, SIG_IGN);
202 printf("\n--- %s ping statistics ---\n", hostname); 209
203 printf("%ld packets transmitted, ", ntransmitted); 210 printf("\n--- %s ping statistics ---\n", hostname);
204 printf("%ld packets received, ", nreceived); 211 printf("%ld packets transmitted, ", ntransmitted);
205 if (nrepeats) 212 printf("%ld packets received, ", nreceived);
206 printf("%ld duplicates, ", nrepeats); 213 if (nrepeats)
207 if (ntransmitted) 214 printf("%ld duplicates, ", nrepeats);
208 printf("%ld%% packet loss\n", 215 if (ntransmitted)
209 (ntransmitted - nreceived)*100/ntransmitted); 216 printf("%ld%% packet loss\n",
210 if (nreceived) 217 (ntransmitted - nreceived) * 100 / ntransmitted);
211 printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n", 218 if (nreceived)
212 tmin/10, tmin%10, 219 printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n",
213 (tsum/(nreceived+nrepeats))/10, 220 tmin / 10, tmin % 10,
214 (tsum/(nreceived+nrepeats))%10, 221 (tsum / (nreceived + nrepeats)) / 10,
215 tmax/10, tmax%10); 222 (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10);
216 exit(0); 223 exit(0);
217} 224}
218 225
219static void sendping(int ign) 226static void sendping(int ign)
220{ 227{
221 struct icmp *pkt; 228 struct icmp *pkt;
222 int i; 229 int i;
223 char packet[DEFDATALEN + 8]; 230 char packet[DEFDATALEN + 8];
224 231
225 pkt = (struct icmp *)packet; 232 pkt = (struct icmp *) packet;
226 233
227 pkt->icmp_type = ICMP_ECHO; 234 pkt->icmp_type = ICMP_ECHO;
228 pkt->icmp_code = 0; 235 pkt->icmp_code = 0;
229 pkt->icmp_cksum = 0; 236 pkt->icmp_cksum = 0;
230 pkt->icmp_seq = ntransmitted++; 237 pkt->icmp_seq = ntransmitted++;
231 pkt->icmp_id = myid; 238 pkt->icmp_id = myid;
232 CLR(pkt->icmp_seq % MAX_DUP_CHK); 239 CLR(pkt->icmp_seq % MAX_DUP_CHK);
233 240
234 gettimeofday((struct timeval *)&packet[8], NULL); 241 gettimeofday((struct timeval *) &packet[8], NULL);
235 pkt->icmp_cksum = in_cksum((unsigned short *)pkt, sizeof(packet)); 242 pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
236 243
237 i = sendto(pingsock, packet, sizeof(packet), 0, 244 i = sendto(pingsock, packet, sizeof(packet), 0,
238 (struct sockaddr *)&pingaddr, sizeof(struct sockaddr_in)); 245 (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
239 246
240 if (i < 0 || i != sizeof(packet)) { 247 if (i < 0 || i != sizeof(packet)) {
241 if (i < 0) perror("ping"); 248 if (i < 0)
242 fprintf(stderr, "ping wrote %d chars; %d expected\n", i, sizeof(packet)); 249 perror("ping");
243 exit(1); 250 fprintf(stderr, "ping wrote %d chars; %d expected\n", i,
244 } 251 sizeof(packet));
245 252 exit(1);
246 signal(SIGALRM, sendping); 253 }
247 if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ 254
248 alarm(PINGINTERVAL); 255 signal(SIGALRM, sendping);
249 } else { /* done, wait for the last ping to come back */ 256 if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */
250 /* todo, don't necessarily need to wait so long... */ 257 alarm(PINGINTERVAL);
251 signal(SIGALRM, pingstats); 258 } else { /* done, wait for the last ping to come back */
252 alarm(MAXWAIT); 259 /* todo, don't necessarily need to wait so long... */
253 } 260 signal(SIGALRM, pingstats);
261 alarm(MAXWAIT);
262 }
254} 263}
255 264
256static void unpack(char *buf, int sz, struct sockaddr_in *from) 265static void unpack(char *buf, int sz, struct sockaddr_in *from)
257{ 266{
258 struct icmp *icmppkt; 267 struct icmp *icmppkt;
259 struct iphdr *iphdr; 268 struct iphdr *iphdr;
260 struct timeval tv, *tp; 269 struct timeval tv, *tp;
261 int hlen, dupflag; 270 int hlen, dupflag;
262 unsigned long triptime; 271 unsigned long triptime;
263 272
264 gettimeofday(&tv, NULL); 273 gettimeofday(&tv, NULL);
265 274
266 /* check IP header */ 275 /* check IP header */
267 iphdr = (struct iphdr *)buf; 276 iphdr = (struct iphdr *) buf;
268 hlen = iphdr->ihl << 2; 277 hlen = iphdr->ihl << 2;
269 /* discard if too short */ 278 /* discard if too short */
270 if (sz < (DEFDATALEN + ICMP_MINLEN)) return; 279 if (sz < (DEFDATALEN + ICMP_MINLEN))
271 280 return;
272 sz -= hlen; 281
273 icmppkt = (struct icmp *)(buf + hlen); 282 sz -= hlen;
274 283 icmppkt = (struct icmp *) (buf + hlen);
275 if (icmppkt->icmp_type == ICMP_ECHOREPLY) { 284
276 if (icmppkt->icmp_id != myid) return; /* not our ping */ 285 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
277 ++nreceived; 286 if (icmppkt->icmp_id != myid)
278 tp = (struct timeval *)icmppkt->icmp_data; 287 return; /* not our ping */
279 288 ++nreceived;
280 if ((tv.tv_usec -= tp->tv_usec) < 0) { 289 tp = (struct timeval *) icmppkt->icmp_data;
281 --tv.tv_sec; 290
282 tv.tv_usec += 1000000; 291 if ((tv.tv_usec -= tp->tv_usec) < 0) {
283 } 292 --tv.tv_sec;
284 tv.tv_sec -= tp->tv_sec; 293 tv.tv_usec += 1000000;
285 294 }
286 triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); 295 tv.tv_sec -= tp->tv_sec;
287 tsum += triptime; 296
288 if (triptime < tmin) tmin = triptime; 297 triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100);
289 if (triptime > tmax) tmax = triptime; 298 tsum += triptime;
290 299 if (triptime < tmin)
291 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) { 300 tmin = triptime;
292 ++nrepeats; 301 if (triptime > tmax)
293 --nreceived; 302 tmax = triptime;
294 dupflag = 1; 303
304 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) {
305 ++nrepeats;
306 --nreceived;
307 dupflag = 1;
308 } else {
309 SET(icmppkt->icmp_seq % MAX_DUP_CHK);
310 dupflag = 0;
311 }
312
313 if (options & O_QUIET)
314 return;
315
316 printf("%d bytes from %s: icmp_seq=%u", sz,
317 inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
318 icmppkt->icmp_seq);
319 printf(" ttl=%d", iphdr->ttl);
320 printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);
321 if (dupflag)
322 printf(" (DUP!)");
323 printf("\n");
295 } else { 324 } else {
296 SET(icmppkt->icmp_seq % MAX_DUP_CHK); 325 fprintf(stderr,
297 dupflag = 0; 326 "Warning: unknown ICMP packet received (not echo-reply)\n");
298 } 327 }
299
300 if (options & O_QUIET) return;
301
302 printf("%d bytes from %s: icmp_seq=%u", sz,
303 inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
304 icmppkt->icmp_seq);
305 printf(" ttl=%d", iphdr->ttl);
306 printf(" time=%lu.%lu ms", triptime/10, triptime%10);
307 if (dupflag) printf(" (DUP!)");
308 printf("\n");
309 } else {
310 fprintf(stderr, "Warning: unknown ICMP packet received (not echo-reply)\n");
311 }
312} 328}
313 329
314static void ping(char *host) 330static void ping(char *host)
315{ 331{
316 struct protoent *proto; 332 struct protoent *proto;
317 struct hostent *h; 333 struct hostent *h;
318 char buf[MAXHOSTNAMELEN]; 334 char buf[MAXHOSTNAMELEN];
319 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 335 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
320 int sockopt; 336 int sockopt;
321 337
322 proto = getprotobyname("icmp"); 338 proto = getprotobyname("icmp");
323 /* if getprotobyname failed, just silently force 339 /* if getprotobyname failed, just silently force
324 * proto->p_proto to have the correct value for "icmp" */ 340 * proto->p_proto to have the correct value for "icmp" */
325 if ((pingsock = socket(AF_INET, SOCK_RAW, 341 if ((pingsock = socket(AF_INET, SOCK_RAW,
326 (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */ 342 (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */
327 if (errno == EPERM) { 343 if (errno == EPERM) {
328 fprintf(stderr, "ping: permission denied. (are you root?)\n"); 344 fprintf(stderr, "ping: permission denied. (are you root?)\n");
329 } else { 345 } else {
330 perror("ping"); 346 perror("ping");
347 }
348 exit(1);
331 } 349 }
332 exit(1); 350
333 } 351 /* drop root privs if running setuid */
334 352 setuid(getuid());
335 /* drop root privs if running setuid */ 353
336 setuid(getuid()); 354 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
337 355
338 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 356 pingaddr.sin_family = AF_INET;
339 pingaddr.sin_family = AF_INET; 357 if (!(h = gethostbyname(host))) {
340 if (!(h = gethostbyname(host))) { 358 fprintf(stderr, "ping: unknown host %s\n", host);
341 fprintf(stderr, "ping: unknown host %s\n", host); 359 exit(1);
342 exit(1); 360 }
343 } 361
344 362 if (h->h_addrtype != AF_INET) {
345 if (h->h_addrtype != AF_INET) { 363 fprintf(stderr,
346 fprintf(stderr, "ping: unknown address type; only AF_INET is currently supported.\n"); 364 "ping: unknown address type; only AF_INET is currently supported.\n");
347 exit(1); 365 exit(1);
348 }
349
350 pingaddr.sin_family = AF_INET; /* h->h_addrtype */
351 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
352 strncpy(buf, h->h_name, sizeof(buf)-1);
353 hostname = buf;
354
355 /* enable broadcast pings */
356 sockopt = 1;
357 setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *)&sockopt, sizeof(sockopt));
358
359 /* set recv buf for broadcast pings */
360 sockopt = 48 * 1024;
361 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockopt, sizeof(sockopt));
362
363 printf("PING %s (%s): %d data bytes\n",
364 hostname, inet_ntoa(*(struct in_addr *)&pingaddr.sin_addr.s_addr),
365 DEFDATALEN);
366
367 signal(SIGINT, pingstats);
368
369 /* start the ping's going ... */
370 sendping(0);
371
372 /* listen for replies */
373 while (1) {
374 struct sockaddr_in from;
375 size_t fromlen = sizeof(from);
376 int c;
377
378 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
379 (struct sockaddr *)&from, &fromlen)) < 0) {
380 if (errno == EINTR) continue;
381 perror("ping");
382 continue;
383 } 366 }
384 unpack(packet, c, &from); 367
385 if (pingcount > 0 && nreceived >= pingcount) break; 368 pingaddr.sin_family = AF_INET; /* h->h_addrtype */
386 } 369 memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
387 pingstats(0); 370 strncpy(buf, h->h_name, sizeof(buf) - 1);
371 hostname = buf;
372
373 /* enable broadcast pings */
374 sockopt = 1;
375 setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
376 sizeof(sockopt));
377
378 /* set recv buf for broadcast pings */
379 sockopt = 48 * 1024;
380 setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
381 sizeof(sockopt));
382
383 printf("PING %s (%s): %d data bytes\n",
384 hostname,
385 inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr),
386 DEFDATALEN);
387
388 signal(SIGINT, pingstats);
389
390 /* start the ping's going ... */
391 sendping(0);
392
393 /* listen for replies */
394 while (1) {
395 struct sockaddr_in from;
396 size_t fromlen = sizeof(from);
397 int c;
398
399 if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
400 (struct sockaddr *) &from, &fromlen)) < 0) {
401 if (errno == EINTR)
402 continue;
403 perror("ping");
404 continue;
405 }
406 unpack(packet, c, &from);
407 if (pingcount > 0 && nreceived >= pingcount)
408 break;
409 }
410 pingstats(0);
388} 411}
389 412
390extern int ping_main(int argc, char **argv) 413extern int ping_main(int argc, char **argv)
391{ 414{
392 char *thisarg; 415 char *thisarg;
393 416
394 argc--; 417 argc--;
395 argv++; 418 argv++;
396 options = 0; 419 options = 0;
397 /* Parse any options */ 420 /* Parse any options */
398 while (argc > 1) { 421 while (argc > 1) {
399 if (**argv != '-') usage(ping_usage); 422 if (**argv != '-')
400 thisarg = *argv; thisarg++; 423 usage(ping_usage);
401 switch (*thisarg) { 424 thisarg = *argv;
402 case 'q': options |= O_QUIET; break; 425 thisarg++;
403 case 'c': 426 switch (*thisarg) {
404 argc--; argv++; 427 case 'q':
405 pingcount = atoi(*argv); 428 options |= O_QUIET;
406 break; 429 break;
407 default: 430 case 'c':
408 usage(ping_usage); 431 argc--;
409 } 432 argv++;
410 argc--; argv++; 433 pingcount = atoi(*argv);
411 } 434 break;
412 if (argc < 1) usage(ping_usage); 435 default:
413 436 usage(ping_usage);
414 myid = getpid() & 0xFFFF; 437 }
415 ping(*argv); 438 argc--;
416 exit(TRUE); 439 argv++;
440 }
441 if (argc < 1)
442 usage(ping_usage);
443
444 myid = getpid() & 0xFFFF;
445 ping(*argv);
446 exit(TRUE);
417} 447}
418#endif 448#endif
419 449
diff --git a/poweroff.c b/poweroff.c
index 405ca3fe2..7f9abf14a 100644
--- a/poweroff.c
+++ b/poweroff.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini poweroff implementation for busybox 3 * Mini poweroff implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int poweroff_main(int argc, char **argv)
27poweroff_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR2)); 30 exit(kill(findInitPid(), SIGUSR2));
31} 31}
diff --git a/printf.c b/printf.c
index 5fd5ea303..41ab2e442 100644
--- a/printf.c
+++ b/printf.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* printf - format and print data 2/* printf - format and print data
2 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. 3 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3 4
@@ -42,7 +43,7 @@
42 to convert all of the given arguments. 43 to convert all of the given arguments.
43 44
44 David MacKenzie <djm@gnu.ai.mit.edu> */ 45 David MacKenzie <djm@gnu.ai.mit.edu> */
45 46
46 47
47// 19990508 Busy Boxed! Dave Cinege 48// 19990508 Busy Boxed! Dave Cinege
48 49
@@ -84,11 +85,11 @@
84#if !defined(S_ISSOCK) && defined(S_IFSOCK) 85#if !defined(S_ISSOCK) && defined(S_IFSOCK)
85# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 86# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
86#endif 87#endif
87#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ 88#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
88# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) 89# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
89# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) 90# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
90#endif 91#endif
91#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ 92#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
92# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) 93# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
93#endif 94#endif
94 95
@@ -121,407 +122,358 @@
121#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') 122#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
122#define octtobin(c) ((c) - '0') 123#define octtobin(c) ((c) - '0')
123 124
124static double xstrtod __P ((char *s)); 125static double xstrtod __P((char *s));
125static int print_esc __P ((char *escstart)); 126static int print_esc __P((char *escstart));
126static int print_formatted __P ((char *format, int argc, char **argv)); 127static int print_formatted __P((char *format, int argc, char **argv));
127static long xstrtol __P ((char *s)); 128static long xstrtol __P((char *s));
128static unsigned long xstrtoul __P ((char *s)); 129static unsigned long xstrtoul __P((char *s));
129static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument)); 130static void print_direc
130static void print_esc_char __P ((int c)); 131__P(
131static void print_esc_string __P ((char *str)); 132
132static void verify __P ((char *s, char *end)); 133 (char *start, size_t length, int field_width, int precision,
134 char *argument));
135static void print_esc_char __P((int c));
136static void print_esc_string __P((char *str));
137static void verify __P((char *s, char *end));
133 138
134/* The value to return to the calling program. */ 139/* The value to return to the calling program. */
135static int exit_status; 140static int exit_status;
136 141
137static const char printf_usage[] = "printf format [argument...]\n"; 142static const char printf_usage[] = "printf format [argument...]\n";
138 143
139int 144int printf_main(int argc, char **argv)
140printf_main(int argc, char** argv)
141{ 145{
142 char *format; 146 char *format;
143 int args_used; 147 int args_used;
144 148
145 exit_status = 0; 149 exit_status = 0;
146 if ( argc <= 1 || **(argv+1) == '-' ) { 150 if (argc <= 1 || **(argv + 1) == '-') {
147 usage (printf_usage); 151 usage(printf_usage);
148 } 152 }
149 153
150 format = argv[1]; 154 format = argv[1];
151 argc -= 2; 155 argc -= 2;
152 argv += 2; 156 argv += 2;
153 157
154 do 158 do {
155 { 159 args_used = print_formatted(format, argc, argv);
156 args_used = print_formatted (format, argc, argv); 160 argc -= args_used;
157 argc -= args_used; 161 argv += args_used;
158 argv += args_used; 162 }
159 } 163 while (args_used > 0 && argc > 0);
160 while (args_used > 0 && argc > 0);
161 164
162/* 165/*
163 if (argc > 0) 166 if (argc > 0)
164 fprintf(stderr, "excess args ignored"); 167 fprintf(stderr, "excess args ignored");
165*/ 168*/
166 169
167 exit (exit_status); 170 exit(exit_status);
168} 171}
169 172
170/* Print the text in FORMAT, using ARGV (with ARGC elements) for 173/* Print the text in FORMAT, using ARGV (with ARGC elements) for
171 arguments to any `%' directives. 174 arguments to any `%' directives.
172 Return the number of elements of ARGV used. */ 175 Return the number of elements of ARGV used. */
173 176
174static int 177static int print_formatted(char *format, int argc, char **argv)
175print_formatted (char *format, int argc, char **argv)
176{ 178{
177 int save_argc = argc; /* Preserve original value. */ 179 int save_argc = argc; /* Preserve original value. */
178 char *f; /* Pointer into `format'. */ 180 char *f; /* Pointer into `format'. */
179 char *direc_start; /* Start of % directive. */ 181 char *direc_start; /* Start of % directive. */
180 size_t direc_length; /* Length of % directive. */ 182 size_t direc_length; /* Length of % directive. */
181 int field_width; /* Arg to first '*', or -1 if none. */ 183 int field_width; /* Arg to first '*', or -1 if none. */
182 int precision; /* Arg to second '*', or -1 if none. */ 184 int precision; /* Arg to second '*', or -1 if none. */
183 185
184 for (f = format; *f; ++f) 186 for (f = format; *f; ++f) {
185 { 187 switch (*f) {
186 switch (*f) 188 case '%':
187 { 189 direc_start = f++;
188 case '%': 190 direc_length = 1;
189 direc_start = f++; 191 field_width = precision = -1;
190 direc_length = 1; 192 if (*f == '%') {
191 field_width = precision = -1; 193 putchar('%');
192 if (*f == '%') 194 break;
193 { 195 }
194 putchar ('%'); 196 if (*f == 'b') {
195 break; 197 if (argc > 0) {
196 } 198 print_esc_string(*argv);
197 if (*f == 'b') 199 ++argv;
198 { 200 --argc;
199 if (argc > 0) 201 }
200 { 202 break;
201 print_esc_string (*argv); 203 }
202 ++argv; 204 if (strchr("-+ #", *f)) {
203 --argc; 205 ++f;
204 } 206 ++direc_length;
205 break; 207 }
206 } 208 if (*f == '*') {
207 if (strchr ("-+ #", *f)) 209 ++f;
208 { 210 ++direc_length;
209 ++f; 211 if (argc > 0) {
210 ++direc_length; 212 field_width = xstrtoul(*argv);
211 } 213 ++argv;
212 if (*f == '*') 214 --argc;
213 { 215 } else
214 ++f; 216 field_width = 0;
215 ++direc_length; 217 } else
216 if (argc > 0) 218 while (ISDIGIT(*f)) {
217 { 219 ++f;
218 field_width = xstrtoul (*argv); 220 ++direc_length;
219 ++argv; 221 }
220 --argc; 222 if (*f == '.') {
223 ++f;
224 ++direc_length;
225 if (*f == '*') {
226 ++f;
227 ++direc_length;
228 if (argc > 0) {
229 precision = xstrtoul(*argv);
230 ++argv;
231 --argc;
232 } else
233 precision = 0;
234 } else
235 while (ISDIGIT(*f)) {
236 ++f;
237 ++direc_length;
238 }
239 }
240 if (*f == 'l' || *f == 'L' || *f == 'h') {
241 ++f;
242 ++direc_length;
243 }
244 /*
245 if (!strchr ("diouxXfeEgGcs", *f))
246 fprintf(stderr, "%%%c: invalid directive", *f);
247 */
248 ++direc_length;
249 if (argc > 0) {
250 print_direc(direc_start, direc_length, field_width,
251 precision, *argv);
252 ++argv;
253 --argc;
254 } else
255 print_direc(direc_start, direc_length, field_width,
256 precision, "");
257 break;
258
259 case '\\':
260 f += print_esc(f);
261 break;
262
263 default:
264 putchar(*f);
221 } 265 }
222 else
223 field_width = 0;
224 }
225 else
226 while (ISDIGIT (*f))
227 {
228 ++f;
229 ++direc_length;
230 }
231 if (*f == '.')
232 {
233 ++f;
234 ++direc_length;
235 if (*f == '*')
236 {
237 ++f;
238 ++direc_length;
239 if (argc > 0)
240 {
241 precision = xstrtoul (*argv);
242 ++argv;
243 --argc;
244 }
245 else
246 precision = 0;
247 }
248 else
249 while (ISDIGIT (*f))
250 {
251 ++f;
252 ++direc_length;
253 }
254 }
255 if (*f == 'l' || *f == 'L' || *f == 'h')
256 {
257 ++f;
258 ++direc_length;
259 }
260 /*
261 if (!strchr ("diouxXfeEgGcs", *f))
262 fprintf(stderr, "%%%c: invalid directive", *f);
263 */
264 ++direc_length;
265 if (argc > 0)
266 {
267 print_direc (direc_start, direc_length, field_width,
268 precision, *argv);
269 ++argv;
270 --argc;
271 }
272 else
273 print_direc (direc_start, direc_length, field_width,
274 precision, "");
275 break;
276
277 case '\\':
278 f += print_esc (f);
279 break;
280
281 default:
282 putchar (*f);
283 } 266 }
284 }
285 267
286 return save_argc - argc; 268 return save_argc - argc;
287} 269}
288 270
289/* Print a \ escape sequence starting at ESCSTART. 271/* Print a \ escape sequence starting at ESCSTART.
290 Return the number of characters in the escape sequence 272 Return the number of characters in the escape sequence
291 besides the backslash. */ 273 besides the backslash. */
292 274
293static int 275static int print_esc(char *escstart)
294print_esc (char *escstart)
295{ 276{
296 register char *p = escstart + 1; 277 register char *p = escstart + 1;
297 int esc_value = 0; /* Value of \nnn escape. */ 278 int esc_value = 0; /* Value of \nnn escape. */
298 int esc_length; /* Length of \nnn escape. */ 279 int esc_length; /* Length of \nnn escape. */
299 280
300 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */ 281 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
301 if (*p == 'x') 282 if (*p == 'x') {
302 { 283 for (esc_length = 0, ++p;
303 for (esc_length = 0, ++p; 284 esc_length < 3 && ISXDIGIT(*p); ++esc_length, ++p)
304 esc_length < 3 && ISXDIGIT (*p); 285 esc_value = esc_value * 16 + hextobin(*p);
305 ++esc_length, ++p)
306 esc_value = esc_value * 16 + hextobin (*p);
307/* if (esc_length == 0) 286/* if (esc_length == 0)
308 fprintf(stderr, "missing hex in esc"); 287 fprintf(stderr, "missing hex in esc");
309*/ 288*/
310 putchar (esc_value); 289 putchar(esc_value);
311 } 290 } else if (*p == '0') {
312 else if (*p == '0') 291 for (esc_length = 0, ++p;
313 { 292 esc_length < 3 && isodigit(*p); ++esc_length, ++p)
314 for (esc_length = 0, ++p; 293 esc_value = esc_value * 8 + octtobin(*p);
315 esc_length < 3 && isodigit (*p); 294 putchar(esc_value);
316 ++esc_length, ++p) 295 } else if (strchr("\"\\abcfnrtv", *p))
317 esc_value = esc_value * 8 + octtobin (*p); 296 print_esc_char(*p++);
318 putchar (esc_value);
319 }
320 else if (strchr ("\"\\abcfnrtv", *p))
321 print_esc_char (*p++);
322/* else 297/* else
323 fprintf(stderr, "\\%c: invalid esc", *p); 298 fprintf(stderr, "\\%c: invalid esc", *p);
324*/ 299*/
325 return p - escstart - 1; 300 return p - escstart - 1;
326} 301}
327 302
328/* Output a single-character \ escape. */ 303/* Output a single-character \ escape. */
329 304
330static void 305static void print_esc_char(int c)
331print_esc_char (int c)
332{ 306{
333 switch (c) 307 switch (c) {
334 { 308 case 'a': /* Alert. */
335 case 'a': /* Alert. */ 309 putchar(7);
336 putchar (7); 310 break;
337 break; 311 case 'b': /* Backspace. */
338 case 'b': /* Backspace. */ 312 putchar(8);
339 putchar (8); 313 break;
340 break; 314 case 'c': /* Cancel the rest of the output. */
341 case 'c': /* Cancel the rest of the output. */ 315 exit(0);
342 exit (0); 316 break;
343 break; 317 case 'f': /* Form feed. */
344 case 'f': /* Form feed. */ 318 putchar(12);
345 putchar (12); 319 break;
346 break; 320 case 'n': /* New line. */
347 case 'n': /* New line. */ 321 putchar(10);
348 putchar (10); 322 break;
349 break; 323 case 'r': /* Carriage return. */
350 case 'r': /* Carriage return. */ 324 putchar(13);
351 putchar (13); 325 break;
352 break; 326 case 't': /* Horizontal tab. */
353 case 't': /* Horizontal tab. */ 327 putchar(9);
354 putchar (9); 328 break;
355 break; 329 case 'v': /* Vertical tab. */
356 case 'v': /* Vertical tab. */ 330 putchar(11);
357 putchar (11); 331 break;
358 break; 332 default:
359 default: 333 putchar(c);
360 putchar (c); 334 break;
361 break; 335 }
362 }
363} 336}
364 337
365/* Print string STR, evaluating \ escapes. */ 338/* Print string STR, evaluating \ escapes. */
366 339
367static void 340static void print_esc_string(char *str)
368print_esc_string (char *str)
369{ 341{
370 for (; *str; str++) 342 for (; *str; str++)
371 if (*str == '\\') 343 if (*str == '\\')
372 str += print_esc (str); 344 str += print_esc(str);
373 else 345 else
374 putchar (*str); 346 putchar(*str);
375} 347}
376 348
377static void 349static void
378print_direc (char *start, size_t length, int field_width, int precision, char *argument) 350print_direc(char *start, size_t length, int field_width, int precision,
351 char *argument)
379{ 352{
380 char *p; /* Null-terminated copy of % directive. */ 353 char *p; /* Null-terminated copy of % directive. */
381 354
382 p = xmalloc ((unsigned) (length + 1)); 355 p = xmalloc((unsigned) (length + 1));
383 strncpy (p, start, length); 356 strncpy(p, start, length);
384 p[length] = 0; 357 p[length] = 0;
385 358
386 switch (p[length - 1]) 359 switch (p[length - 1]) {
387 { 360 case 'd':
388 case 'd': 361 case 'i':
389 case 'i': 362 if (field_width < 0) {
390 if (field_width < 0) 363 if (precision < 0)
391 { 364 printf(p, xstrtol(argument));
392 if (precision < 0) 365 else
393 printf (p, xstrtol (argument)); 366 printf(p, precision, xstrtol(argument));
394 else 367 } else {
395 printf (p, precision, xstrtol (argument)); 368 if (precision < 0)
396 } 369 printf(p, field_width, xstrtol(argument));
397 else 370 else
398 { 371 printf(p, field_width, precision, xstrtol(argument));
399 if (precision < 0) 372 }
400 printf (p, field_width, xstrtol (argument)); 373 break;
401 else 374
402 printf (p, field_width, precision, xstrtol (argument)); 375 case 'o':
403 } 376 case 'u':
404 break; 377 case 'x':
405 378 case 'X':
406 case 'o': 379 if (field_width < 0) {
407 case 'u': 380 if (precision < 0)
408 case 'x': 381 printf(p, xstrtoul(argument));
409 case 'X': 382 else
410 if (field_width < 0) 383 printf(p, precision, xstrtoul(argument));
411 { 384 } else {
412 if (precision < 0) 385 if (precision < 0)
413 printf (p, xstrtoul (argument)); 386 printf(p, field_width, xstrtoul(argument));
414 else 387 else
415 printf (p, precision, xstrtoul (argument)); 388 printf(p, field_width, precision, xstrtoul(argument));
416 } 389 }
417 else 390 break;
418 { 391
419 if (precision < 0) 392 case 'f':
420 printf (p, field_width, xstrtoul (argument)); 393 case 'e':
421 else 394 case 'E':
422 printf (p, field_width, precision, xstrtoul (argument)); 395 case 'g':
423 } 396 case 'G':
424 break; 397 if (field_width < 0) {
425 398 if (precision < 0)
426 case 'f': 399 printf(p, xstrtod(argument));
427 case 'e': 400 else
428 case 'E': 401 printf(p, precision, xstrtod(argument));
429 case 'g': 402 } else {
430 case 'G': 403 if (precision < 0)
431 if (field_width < 0) 404 printf(p, field_width, xstrtod(argument));
432 { 405 else
433 if (precision < 0) 406 printf(p, field_width, precision, xstrtod(argument));
434 printf (p, xstrtod (argument)); 407 }
435 else 408 break;
436 printf (p, precision, xstrtod (argument)); 409
437 } 410 case 'c':
438 else 411 printf(p, *argument);
439 { 412 break;
440 if (precision < 0) 413
441 printf (p, field_width, xstrtod (argument)); 414 case 's':
442 else 415 if (field_width < 0) {
443 printf (p, field_width, precision, xstrtod (argument)); 416 if (precision < 0)
444 } 417 printf(p, argument);
445 break; 418 else
446 419 printf(p, precision, argument);
447 case 'c': 420 } else {
448 printf (p, *argument); 421 if (precision < 0)
449 break; 422 printf(p, field_width, argument);
450 423 else
451 case 's': 424 printf(p, field_width, precision, argument);
452 if (field_width < 0) 425 }
453 { 426 break;
454 if (precision < 0)
455 printf (p, argument);
456 else
457 printf (p, precision, argument);
458 }
459 else
460 {
461 if (precision < 0)
462 printf (p, field_width, argument);
463 else
464 printf (p, field_width, precision, argument);
465 } 427 }
466 break;
467 }
468 428
469 free (p); 429 free(p);
470} 430}
471 431
472static unsigned long 432static unsigned long xstrtoul(char *s)
473xstrtoul (char *s)
474{ 433{
475 char *end; 434 char *end;
476 unsigned long val; 435 unsigned long val;
477 436
478 errno = 0; 437 errno = 0;
479 val = strtoul (s, &end, 0); 438 val = strtoul(s, &end, 0);
480 verify (s, end); 439 verify(s, end);
481 return val; 440 return val;
482} 441}
483 442
484static long 443static long xstrtol(char *s)
485xstrtol (char *s)
486{ 444{
487 char *end; 445 char *end;
488 long val; 446 long val;
489 447
490 errno = 0; 448 errno = 0;
491 val = strtol (s, &end, 0); 449 val = strtol(s, &end, 0);
492 verify (s, end); 450 verify(s, end);
493 return val; 451 return val;
494} 452}
495 453
496static double 454static double xstrtod(char *s)
497xstrtod (char *s)
498{ 455{
499 char *end; 456 char *end;
500 double val; 457 double val;
501 458
502 errno = 0; 459 errno = 0;
503 val = strtod (s, &end); 460 val = strtod(s, &end);
504 verify (s, end); 461 verify(s, end);
505 return val; 462 return val;
506} 463}
507 464
508static void 465static void verify(char *s, char *end)
509verify (char *s, char *end)
510{ 466{
511 if (errno) 467 if (errno) {
512 { 468 fprintf(stderr, "%s", s);
513 fprintf(stderr, "%s", s); 469 exit_status = 1;
514 exit_status = 1; 470 } else if (*end) {
515 } 471 /*
516 else if (*end) 472 if (s == end)
517 { 473 fprintf(stderr, "%s: expected numeric", s);
518 /* 474 else
519 if (s == end) 475 fprintf(stderr, "%s: not completely converted", s);
520 fprintf(stderr, "%s: expected numeric", s); 476 */
521 else 477 exit_status = 1;
522 fprintf(stderr, "%s: not completely converted", s); 478 }
523 */
524 exit_status = 1;
525 }
526} 479}
527
diff --git a/procps/free.c b/procps/free.c
index 36d357522..b07135430 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini free implementation for busybox 3 * Mini free implementation for busybox
3 * 4 *
@@ -30,6 +31,7 @@
30 31
31extern int free_main(int argc, char **argv) 32extern int free_main(int argc, char **argv)
32{ 33{
33 char* cmd[] = { "cat", "/proc/meminfo", "\0" }; 34 char *cmd[] = { "cat", "/proc/meminfo", "\0" };
34 exit(cat_main( 3, cmd)); 35
36 exit(cat_main(3, cmd));
35} 37}
diff --git a/procps/kill.c b/procps/kill.c
index e72b73493..516621232 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini kill implementation for busybox 3 * Mini kill implementation for busybox
3 * 4 *
@@ -29,188 +30,188 @@
29#include <sys/stat.h> 30#include <sys/stat.h>
30#include <unistd.h> 31#include <unistd.h>
31 32
32static const char* kill_usage = "kill [-signal] process-id [process-id ...]\n\n" 33static const char *kill_usage =
33"Send a signal (default is SIGTERM) to the specified process(es).\n\n" 34 "kill [-signal] process-id [process-id ...]\n\n"
34"Options:\n" 35 "Send a signal (default is SIGTERM) to the specified process(es).\n\n"
35"\t-l\tList all signal names and numbers.\n\n"; 36 "Options:\n" "\t-l\tList all signal names and numbers.\n\n";
36 37
37 38
38struct signal_name { 39struct signal_name {
39 const char *name; 40 const char *name;
40 int number; 41 int number;
41}; 42};
42 43
43const struct signal_name signames[] = { 44const struct signal_name signames[] = {
44 {"HUP", SIGHUP}, 45 {"HUP", SIGHUP},
45 {"INT", SIGINT}, 46 {"INT", SIGINT},
46 {"QUIT", SIGQUIT}, 47 {"QUIT", SIGQUIT},
47 {"ILL", SIGILL}, 48 {"ILL", SIGILL},
48 {"TRAP", SIGTRAP}, 49 {"TRAP", SIGTRAP},
49 {"ABRT", SIGABRT}, 50 {"ABRT", SIGABRT},
50#ifndef __alpha__ 51#ifndef __alpha__
51 {"IOT", SIGIOT}, 52 {"IOT", SIGIOT},
52#endif 53#endif
53#if defined(__sparc__) || defined(__alpha__) 54#if defined(__sparc__) || defined(__alpha__)
54 {"EMT", SIGEMT}, 55 {"EMT", SIGEMT},
55#else 56#else
56 {"BUS", SIGBUS}, 57 {"BUS", SIGBUS},
57#endif 58#endif
58 {"FPE", SIGFPE}, 59 {"FPE", SIGFPE},
59 {"KILL", SIGKILL}, 60 {"KILL", SIGKILL},
60#if defined(__sparc__) || defined(__alpha__) 61#if defined(__sparc__) || defined(__alpha__)
61 {"BUS", SIGBUS}, 62 {"BUS", SIGBUS},
62#else 63#else
63 {"USR1", SIGUSR1}, 64 {"USR1", SIGUSR1},
64#endif 65#endif
65 {"SEGV", SIGSEGV}, 66 {"SEGV", SIGSEGV},
66#if defined(__sparc__) || defined(__alpha__) 67#if defined(__sparc__) || defined(__alpha__)
67 {"SYS", SIGSYS}, 68 {"SYS", SIGSYS},
68#else 69#else
69 {"USR2", SIGUSR2}, 70 {"USR2", SIGUSR2},
70#endif 71#endif
71 {"PIPE", SIGPIPE}, 72 {"PIPE", SIGPIPE},
72 {"ALRM", SIGALRM}, 73 {"ALRM", SIGALRM},
73 {"TERM", SIGTERM}, 74 {"TERM", SIGTERM},
74#if defined(__sparc__) || defined(__alpha__) 75#if defined(__sparc__) || defined(__alpha__)
75 {"URG", SIGURG}, 76 {"URG", SIGURG},
76 {"STOP", SIGSTOP}, 77 {"STOP", SIGSTOP},
77 {"TSTP", SIGTSTP}, 78 {"TSTP", SIGTSTP},
78 {"CONT", SIGCONT}, 79 {"CONT", SIGCONT},
79 {"CHLD", SIGCHLD}, 80 {"CHLD", SIGCHLD},
80 {"TTIN", SIGTTIN}, 81 {"TTIN", SIGTTIN},
81 {"TTOU", SIGTTOU}, 82 {"TTOU", SIGTTOU},
82 {"IO", SIGIO}, 83 {"IO", SIGIO},
83# ifndef __alpha__ 84# ifndef __alpha__
84 {"POLL", SIGIO}, 85 {"POLL", SIGIO},
85# endif 86# endif
86 {"XCPU", SIGXCPU}, 87 {"XCPU", SIGXCPU},
87 {"XFSZ", SIGXFSZ}, 88 {"XFSZ", SIGXFSZ},
88 {"VTALRM", SIGVTALRM}, 89 {"VTALRM", SIGVTALRM},
89 {"PROF", SIGPROF}, 90 {"PROF", SIGPROF},
90 {"WINCH", SIGWINCH}, 91 {"WINCH", SIGWINCH},
91# ifdef __alpha__ 92# ifdef __alpha__
92 {"INFO", SIGINFO}, 93 {"INFO", SIGINFO},
93# else 94# else
94 {"LOST", SIGLOST}, 95 {"LOST", SIGLOST},
95# endif 96# endif
96 {"USR1", SIGUSR1}, 97 {"USR1", SIGUSR1},
97 {"USR2", SIGUSR2}, 98 {"USR2", SIGUSR2},
98#else 99#else
99 {"STKFLT", SIGSTKFLT}, 100 {"STKFLT", SIGSTKFLT},
100 {"CHLD", SIGCHLD}, 101 {"CHLD", SIGCHLD},
101 {"CONT", SIGCONT}, 102 {"CONT", SIGCONT},
102 {"STOP", SIGSTOP}, 103 {"STOP", SIGSTOP},
103 {"TSTP", SIGTSTP}, 104 {"TSTP", SIGTSTP},
104 {"TTIN", SIGTTIN}, 105 {"TTIN", SIGTTIN},
105 {"TTOU", SIGTTOU}, 106 {"TTOU", SIGTTOU},
106 {"URG", SIGURG}, 107 {"URG", SIGURG},
107 {"XCPU", SIGXCPU}, 108 {"XCPU", SIGXCPU},
108 {"XFSZ", SIGXFSZ}, 109 {"XFSZ", SIGXFSZ},
109 {"VTALRM", SIGVTALRM}, 110 {"VTALRM", SIGVTALRM},
110 {"PROF", SIGPROF}, 111 {"PROF", SIGPROF},
111 {"WINCH", SIGWINCH}, 112 {"WINCH", SIGWINCH},
112 {"IO", SIGIO}, 113 {"IO", SIGIO},
113 {"POLL", SIGPOLL}, 114 {"POLL", SIGPOLL},
114 {"PWR", SIGPWR}, 115 {"PWR", SIGPWR},
115 {"UNUSED", SIGUNUSED}, 116 {"UNUSED", SIGUNUSED},
116#endif 117#endif
117 {0, 0} 118 {0, 0}
118}; 119};
119 120
120extern int kill_main (int argc, char **argv) 121extern int kill_main(int argc, char **argv)
121{ 122{
122 int sig = SIGTERM; 123 int sig = SIGTERM;
123 124
124 argc--; 125 argc--;
125 argv++; 126 argv++;
126 /* Parse any options */ 127 /* Parse any options */
127 if (argc < 1) 128 if (argc < 1)
128 usage(kill_usage);
129
130 while (argc > 0 && **argv == '-') {
131 while (*++(*argv)) {
132 switch (**argv) {
133 case 'l':
134 {
135 int col=0;
136 const struct signal_name *s = signames;
137
138 while (s->name != 0) {
139 col+=fprintf(stderr, "%2d) %-8s", s->number, (s++)->name);
140 if (col>60) {
141 fprintf(stderr, "\n");
142 col=0;
143 }
144 }
145 fprintf(stderr, "\n\n");
146 exit( TRUE);
147 }
148 break;
149 case '-':
150 usage(kill_usage); 129 usage(kill_usage);
151 default: 130
152 { 131 while (argc > 0 && **argv == '-') {
153 if (isdigit( **argv)) { 132 while (*++(*argv)) {
154 sig = atoi (*argv); 133 switch (**argv) {
155 if (sig < 0 || sig >= NSIG) 134 case 'l':
156 goto end; 135 {
157 else { 136 int col = 0;
158 argc--; 137 const struct signal_name *s = signames;
159 argv++; 138
160 goto do_it_now; 139 while (s->name != 0) {
161 } 140 col +=
162 } 141 fprintf(stderr, "%2d) %-8s", s->number,
163 else { 142 (s++)->name);
164 const struct signal_name *s = signames; 143 if (col > 60) {
165 while (s->name != 0) { 144 fprintf(stderr, "\n");
166 if (strcasecmp (s->name, *argv) == 0) { 145 col = 0;
167 sig = s->number; 146 }
168 argc--; 147 }
169 argv++; 148 fprintf(stderr, "\n\n");
170 goto do_it_now; 149 exit(TRUE);
171 } 150 }
172 s++; 151 break;
152 case '-':
153 usage(kill_usage);
154 default:
155 {
156 if (isdigit(**argv)) {
157 sig = atoi(*argv);
158 if (sig < 0 || sig >= NSIG)
159 goto end;
160 else {
161 argc--;
162 argv++;
163 goto do_it_now;
164 }
165 } else {
166 const struct signal_name *s = signames;
167
168 while (s->name != 0) {
169 if (strcasecmp(s->name, *argv) == 0) {
170 sig = s->number;
171 argc--;
172 argv++;
173 goto do_it_now;
174 }
175 s++;
176 }
177 if (s->name == 0)
178 goto end;
179 }
180 }
173 } 181 }
174 if (s->name == 0) 182 argc--;
175 goto end; 183 argv++;
176 }
177 } 184 }
178 }
179 argc--;
180 argv++;
181 }
182 }
183
184do_it_now:
185
186 while (--argc >= 0) {
187 int pid;
188 struct stat statbuf;
189 char pidpath[20]="/proc/";
190
191 if (! isdigit( **argv)) {
192 fprintf(stderr, "bad PID: %s\n", *argv);
193 exit( FALSE);
194 }
195 pid = atoi (*argv);
196 snprintf(pidpath, 20, "/proc/%s/stat", *argv);
197 if (stat( pidpath, &statbuf)!=0) {
198 fprintf(stderr, "kill: (%d) - No such pid\n", pid);
199 exit( FALSE);
200 } 185 }
201 fprintf(stderr, "sig = %d\n", sig);
202 if (kill (pid, sig) != 0) {
203 perror (*argv);
204 exit ( FALSE);
205 }
206 argv++;
207 }
208 exit ( TRUE);
209 186
187 do_it_now:
210 188
211end: 189 while (--argc >= 0) {
212 fprintf(stderr, "bad signal name: %s\n", *argv); 190 int pid;
213 exit (TRUE); 191 struct stat statbuf;
214} 192 char pidpath[20] = "/proc/";
193
194 if (!isdigit(**argv)) {
195 fprintf(stderr, "bad PID: %s\n", *argv);
196 exit(FALSE);
197 }
198 pid = atoi(*argv);
199 snprintf(pidpath, 20, "/proc/%s/stat", *argv);
200 if (stat(pidpath, &statbuf) != 0) {
201 fprintf(stderr, "kill: (%d) - No such pid\n", pid);
202 exit(FALSE);
203 }
204 fprintf(stderr, "sig = %d\n", sig);
205 if (kill(pid, sig) != 0) {
206 perror(*argv);
207 exit(FALSE);
208 }
209 argv++;
210 }
211 exit(TRUE);
215 212
216 213
214 end:
215 fprintf(stderr, "bad signal name: %s\n", *argv);
216 exit(TRUE);
217}
diff --git a/procps/ps.c b/procps/ps.c
index 4496faa31..207cdaa02 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini ps implementation for busybox 3 * Mini ps implementation for busybox
3 * 4 *
@@ -33,123 +34,128 @@
33#endif 34#endif
34 35
35typedef struct proc_s { 36typedef struct proc_s {
36 char 37 char
37 cmd[16]; /* basename of executable file in call to exec(2) */ 38 cmd[16]; /* basename of executable file in call to exec(2) */
38 int 39 int
39 ruid, rgid, /* real only (sorry) */ 40 ruid, rgid, /* real only (sorry) */
40 pid, /* process id */ 41 pid, /* process id */
41 ppid; /* pid of parent process */ 42 ppid; /* pid of parent process */
42 char 43 char
43 state; /* single-char code for process state (S=sleeping) */ 44 state; /* single-char code for process state (S=sleeping) */
44} proc_t; 45} proc_t;
45 46
46 47
47 48
48static int file2str(char *filename, char *ret, int cap) 49static int file2str(char *filename, char *ret, int cap)
49{ 50{
50 int fd, num_read; 51 int fd, num_read;
51 52
52 if ( (fd = open(filename, O_RDONLY, 0)) == -1 ) return -1; 53 if ((fd = open(filename, O_RDONLY, 0)) == -1)
53 if ( (num_read = read(fd, ret, cap - 1)) <= 0 ) return -1; 54 return -1;
54 ret[num_read] = 0; 55 if ((num_read = read(fd, ret, cap - 1)) <= 0)
55 close(fd); 56 return -1;
56 return num_read; 57 ret[num_read] = 0;
58 close(fd);
59 return num_read;
57} 60}
58 61
59 62
60static void parse_proc_status(char* S, proc_t* P) 63static void parse_proc_status(char *S, proc_t * P)
61{ 64{
62 char* tmp; 65 char *tmp;
63 memset(P->cmd, 0, sizeof P->cmd); 66
64 sscanf (S, "Name:\t%15c", P->cmd); 67 memset(P->cmd, 0, sizeof P->cmd);
65 tmp = strchr(P->cmd,'\n'); 68 sscanf(S, "Name:\t%15c", P->cmd);
66 if (tmp) 69 tmp = strchr(P->cmd, '\n');
67 *tmp='\0'; 70 if (tmp)
68 tmp = strstr (S,"State"); 71 *tmp = '\0';
69 sscanf (tmp, "State:\t%c", &P->state); 72 tmp = strstr(S, "State");
70 73 sscanf(tmp, "State:\t%c", &P->state);
71 tmp = strstr (S,"Pid:"); 74
72 if(tmp) sscanf (tmp, 75 tmp = strstr(S, "Pid:");
73 "Pid:\t%d\n" 76 if (tmp)
74 "PPid:\t%d\n", 77 sscanf(tmp, "Pid:\t%d\n" "PPid:\t%d\n", &P->pid, &P->ppid);
75 &P->pid, 78 else
76 &P->ppid 79 fprintf(stderr, "Internal error!\n");
77 ); 80
78 else fprintf(stderr, "Internal error!\n"); 81 /* For busybox, ignoring effective, saved, etc */
79 82 tmp = strstr(S, "Uid:");
80 /* For busybox, ignoring effective, saved, etc */ 83 if (tmp)
81 tmp = strstr (S,"Uid:"); 84 sscanf(tmp, "Uid:\t%d", &P->ruid);
82 if(tmp) sscanf (tmp, 85 else
83 "Uid:\t%d", &P->ruid); 86 fprintf(stderr, "Internal error!\n");
84 else fprintf(stderr, "Internal error!\n"); 87
85 88 tmp = strstr(S, "Gid:");
86 tmp = strstr (S,"Gid:"); 89 if (tmp)
87 if(tmp) sscanf (tmp, 90 sscanf(tmp, "Gid:\t%d", &P->rgid);
88 "Gid:\t%d", &P->rgid); 91 else
89 else fprintf(stderr, "Internal error!\n"); 92 fprintf(stderr, "Internal error!\n");
90 93
91} 94}
92 95
93 96
94extern int ps_main(int argc, char **argv) 97extern int ps_main(int argc, char **argv)
95{ 98{
96 proc_t p; 99 proc_t p;
97 DIR *dir; 100 DIR *dir;
98 FILE *file; 101 FILE *file;
99 struct dirent *entry; 102 struct dirent *entry;
100 char path[32], sbuf[512]; 103 char path[32], sbuf[512];
101 char uidName[10]=""; 104 char uidName[10] = "";
102 char groupName[10]=""; 105 char groupName[10] = "";
103 int i, c; 106 int i, c;
104 107
105 if ( argc>1 && **(argv+1) == '-' ) { 108 if (argc > 1 && **(argv + 1) == '-') {
106 usage ("ps\n\nReport process status\n\nThis version of ps accepts no options.\n"); 109 usage
107 } 110 ("ps\n\nReport process status\n\nThis version of ps accepts no options.\n");
108
109 dir = opendir("/proc");
110 if (!dir) {
111 perror("Can't open /proc");
112 exit(FALSE);
113 }
114
115 fprintf(stdout, "%5s %-8s %-3s %5s %s\n", "PID", "Uid", "Gid", "State", "Command");
116 while ((entry = readdir(dir)) != NULL) {
117 uidName[0]='\0';
118 groupName[0]='\0';
119
120 if (! isdigit(*entry->d_name))
121 continue;
122 sprintf(path, "/proc/%s/status", entry->d_name);
123 if ((file2str(path, sbuf, sizeof sbuf)) != -1 ) {
124 parse_proc_status(sbuf, &p);
125 } 111 }
126 112
127 /* Make some adjustments as needed */ 113 dir = opendir("/proc");
128 my_getpwuid( uidName, p.ruid); 114 if (!dir) {
129 my_getgrgid( groupName, p.rgid); 115 perror("Can't open /proc");
130 if (*uidName == '\0') 116 exit(FALSE);
131 sprintf( uidName, "%d", p.ruid);
132 if (*groupName == '\0')
133 sprintf( groupName, "%d", p.rgid);
134
135 fprintf(stdout, "%5d %-8s %-8s %c ", p.pid, uidName, groupName, p.state);
136 sprintf(path, "/proc/%s/cmdline", entry->d_name);
137 file = fopen(path, "r");
138 if (file == NULL) {
139 perror(path);
140 exit(FALSE);
141 } 117 }
142 i=0; 118
143 while (((c = getc(file)) != EOF) && (i < 53)) { 119 fprintf(stdout, "%5s %-8s %-3s %5s %s\n", "PID", "Uid", "Gid",
144 i++; 120 "State", "Command");
145 if (c == '\0') 121 while ((entry = readdir(dir)) != NULL) {
146 c = ' '; 122 uidName[0] = '\0';
147 putc(c, stdout); 123 groupName[0] = '\0';
124
125 if (!isdigit(*entry->d_name))
126 continue;
127 sprintf(path, "/proc/%s/status", entry->d_name);
128 if ((file2str(path, sbuf, sizeof sbuf)) != -1) {
129 parse_proc_status(sbuf, &p);
130 }
131
132 /* Make some adjustments as needed */
133 my_getpwuid(uidName, p.ruid);
134 my_getgrgid(groupName, p.rgid);
135 if (*uidName == '\0')
136 sprintf(uidName, "%d", p.ruid);
137 if (*groupName == '\0')
138 sprintf(groupName, "%d", p.rgid);
139
140 fprintf(stdout, "%5d %-8s %-8s %c ", p.pid, uidName, groupName,
141 p.state);
142 sprintf(path, "/proc/%s/cmdline", entry->d_name);
143 file = fopen(path, "r");
144 if (file == NULL) {
145 perror(path);
146 exit(FALSE);
147 }
148 i = 0;
149 while (((c = getc(file)) != EOF) && (i < 53)) {
150 i++;
151 if (c == '\0')
152 c = ' ';
153 putc(c, stdout);
154 }
155 if (i == 0)
156 fprintf(stdout, "%s", p.cmd);
157 fprintf(stdout, "\n");
148 } 158 }
149 if (i==0) 159 closedir(dir);
150 fprintf(stdout, "%s", p.cmd); 160 exit(TRUE);
151 fprintf(stdout, "\n");
152 }
153 closedir(dir);
154 exit(TRUE);
155} 161}
diff --git a/ps.c b/ps.c
index 4496faa31..207cdaa02 100644
--- a/ps.c
+++ b/ps.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini ps implementation for busybox 3 * Mini ps implementation for busybox
3 * 4 *
@@ -33,123 +34,128 @@
33#endif 34#endif
34 35
35typedef struct proc_s { 36typedef struct proc_s {
36 char 37 char
37 cmd[16]; /* basename of executable file in call to exec(2) */ 38 cmd[16]; /* basename of executable file in call to exec(2) */
38 int 39 int
39 ruid, rgid, /* real only (sorry) */ 40 ruid, rgid, /* real only (sorry) */
40 pid, /* process id */ 41 pid, /* process id */
41 ppid; /* pid of parent process */ 42 ppid; /* pid of parent process */
42 char 43 char
43 state; /* single-char code for process state (S=sleeping) */ 44 state; /* single-char code for process state (S=sleeping) */
44} proc_t; 45} proc_t;
45 46
46 47
47 48
48static int file2str(char *filename, char *ret, int cap) 49static int file2str(char *filename, char *ret, int cap)
49{ 50{
50 int fd, num_read; 51 int fd, num_read;
51 52
52 if ( (fd = open(filename, O_RDONLY, 0)) == -1 ) return -1; 53 if ((fd = open(filename, O_RDONLY, 0)) == -1)
53 if ( (num_read = read(fd, ret, cap - 1)) <= 0 ) return -1; 54 return -1;
54 ret[num_read] = 0; 55 if ((num_read = read(fd, ret, cap - 1)) <= 0)
55 close(fd); 56 return -1;
56 return num_read; 57 ret[num_read] = 0;
58 close(fd);
59 return num_read;
57} 60}
58 61
59 62
60static void parse_proc_status(char* S, proc_t* P) 63static void parse_proc_status(char *S, proc_t * P)
61{ 64{
62 char* tmp; 65 char *tmp;
63 memset(P->cmd, 0, sizeof P->cmd); 66
64 sscanf (S, "Name:\t%15c", P->cmd); 67 memset(P->cmd, 0, sizeof P->cmd);
65 tmp = strchr(P->cmd,'\n'); 68 sscanf(S, "Name:\t%15c", P->cmd);
66 if (tmp) 69 tmp = strchr(P->cmd, '\n');
67 *tmp='\0'; 70 if (tmp)
68 tmp = strstr (S,"State"); 71 *tmp = '\0';
69 sscanf (tmp, "State:\t%c", &P->state); 72 tmp = strstr(S, "State");
70 73 sscanf(tmp, "State:\t%c", &P->state);
71 tmp = strstr (S,"Pid:"); 74
72 if(tmp) sscanf (tmp, 75 tmp = strstr(S, "Pid:");
73 "Pid:\t%d\n" 76 if (tmp)
74 "PPid:\t%d\n", 77 sscanf(tmp, "Pid:\t%d\n" "PPid:\t%d\n", &P->pid, &P->ppid);
75 &P->pid, 78 else
76 &P->ppid 79 fprintf(stderr, "Internal error!\n");
77 ); 80
78 else fprintf(stderr, "Internal error!\n"); 81 /* For busybox, ignoring effective, saved, etc */
79 82 tmp = strstr(S, "Uid:");
80 /* For busybox, ignoring effective, saved, etc */ 83 if (tmp)
81 tmp = strstr (S,"Uid:"); 84 sscanf(tmp, "Uid:\t%d", &P->ruid);
82 if(tmp) sscanf (tmp, 85 else
83 "Uid:\t%d", &P->ruid); 86 fprintf(stderr, "Internal error!\n");
84 else fprintf(stderr, "Internal error!\n"); 87
85 88 tmp = strstr(S, "Gid:");
86 tmp = strstr (S,"Gid:"); 89 if (tmp)
87 if(tmp) sscanf (tmp, 90 sscanf(tmp, "Gid:\t%d", &P->rgid);
88 "Gid:\t%d", &P->rgid); 91 else
89 else fprintf(stderr, "Internal error!\n"); 92 fprintf(stderr, "Internal error!\n");
90 93
91} 94}
92 95
93 96
94extern int ps_main(int argc, char **argv) 97extern int ps_main(int argc, char **argv)
95{ 98{
96 proc_t p; 99 proc_t p;
97 DIR *dir; 100 DIR *dir;
98 FILE *file; 101 FILE *file;
99 struct dirent *entry; 102 struct dirent *entry;
100 char path[32], sbuf[512]; 103 char path[32], sbuf[512];
101 char uidName[10]=""; 104 char uidName[10] = "";
102 char groupName[10]=""; 105 char groupName[10] = "";
103 int i, c; 106 int i, c;
104 107
105 if ( argc>1 && **(argv+1) == '-' ) { 108 if (argc > 1 && **(argv + 1) == '-') {
106 usage ("ps\n\nReport process status\n\nThis version of ps accepts no options.\n"); 109 usage
107 } 110 ("ps\n\nReport process status\n\nThis version of ps accepts no options.\n");
108
109 dir = opendir("/proc");
110 if (!dir) {
111 perror("Can't open /proc");
112 exit(FALSE);
113 }
114
115 fprintf(stdout, "%5s %-8s %-3s %5s %s\n", "PID", "Uid", "Gid", "State", "Command");
116 while ((entry = readdir(dir)) != NULL) {
117 uidName[0]='\0';
118 groupName[0]='\0';
119
120 if (! isdigit(*entry->d_name))
121 continue;
122 sprintf(path, "/proc/%s/status", entry->d_name);
123 if ((file2str(path, sbuf, sizeof sbuf)) != -1 ) {
124 parse_proc_status(sbuf, &p);
125 } 111 }
126 112
127 /* Make some adjustments as needed */ 113 dir = opendir("/proc");
128 my_getpwuid( uidName, p.ruid); 114 if (!dir) {
129 my_getgrgid( groupName, p.rgid); 115 perror("Can't open /proc");
130 if (*uidName == '\0') 116 exit(FALSE);
131 sprintf( uidName, "%d", p.ruid);
132 if (*groupName == '\0')
133 sprintf( groupName, "%d", p.rgid);
134
135 fprintf(stdout, "%5d %-8s %-8s %c ", p.pid, uidName, groupName, p.state);
136 sprintf(path, "/proc/%s/cmdline", entry->d_name);
137 file = fopen(path, "r");
138 if (file == NULL) {
139 perror(path);
140 exit(FALSE);
141 } 117 }
142 i=0; 118
143 while (((c = getc(file)) != EOF) && (i < 53)) { 119 fprintf(stdout, "%5s %-8s %-3s %5s %s\n", "PID", "Uid", "Gid",
144 i++; 120 "State", "Command");
145 if (c == '\0') 121 while ((entry = readdir(dir)) != NULL) {
146 c = ' '; 122 uidName[0] = '\0';
147 putc(c, stdout); 123 groupName[0] = '\0';
124
125 if (!isdigit(*entry->d_name))
126 continue;
127 sprintf(path, "/proc/%s/status", entry->d_name);
128 if ((file2str(path, sbuf, sizeof sbuf)) != -1) {
129 parse_proc_status(sbuf, &p);
130 }
131
132 /* Make some adjustments as needed */
133 my_getpwuid(uidName, p.ruid);
134 my_getgrgid(groupName, p.rgid);
135 if (*uidName == '\0')
136 sprintf(uidName, "%d", p.ruid);
137 if (*groupName == '\0')
138 sprintf(groupName, "%d", p.rgid);
139
140 fprintf(stdout, "%5d %-8s %-8s %c ", p.pid, uidName, groupName,
141 p.state);
142 sprintf(path, "/proc/%s/cmdline", entry->d_name);
143 file = fopen(path, "r");
144 if (file == NULL) {
145 perror(path);
146 exit(FALSE);
147 }
148 i = 0;
149 while (((c = getc(file)) != EOF) && (i < 53)) {
150 i++;
151 if (c == '\0')
152 c = ' ';
153 putc(c, stdout);
154 }
155 if (i == 0)
156 fprintf(stdout, "%s", p.cmd);
157 fprintf(stdout, "\n");
148 } 158 }
149 if (i==0) 159 closedir(dir);
150 fprintf(stdout, "%s", p.cmd); 160 exit(TRUE);
151 fprintf(stdout, "\n");
152 }
153 closedir(dir);
154 exit(TRUE);
155} 161}
diff --git a/pwd.c b/pwd.c
index bacabd77a..00163178b 100644
--- a/pwd.c
+++ b/pwd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini pwd implementation for busybox 3 * Mini pwd implementation for busybox
3 * 4 *
@@ -25,16 +26,15 @@
25#include <dirent.h> 26#include <dirent.h>
26#include <sys/param.h> 27#include <sys/param.h>
27 28
28extern int 29extern int pwd_main(int argc, char **argv)
29pwd_main(int argc, char * * argv)
30{ 30{
31 char buf[PATH_MAX + 1]; 31 char buf[PATH_MAX + 1];
32 32
33 if ( getcwd(buf, sizeof(buf)) == NULL ) { 33 if (getcwd(buf, sizeof(buf)) == NULL) {
34 perror("get working directory"); 34 perror("get working directory");
35 exit( FALSE); 35 exit(FALSE);
36 } 36 }
37 37
38 printf("%s\n", buf); 38 printf("%s\n", buf);
39 exit( TRUE); 39 exit(TRUE);
40} 40}
diff --git a/reboot.c b/reboot.c
index 1339a60f4..ef2a848ee 100644
--- a/reboot.c
+++ b/reboot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini reboot implementation for busybox 3 * Mini reboot implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int reboot_main(int argc, char **argv)
27reboot_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGINT)); 30 exit(kill(findInitPid(), SIGINT));
31} 31}
diff --git a/regexp.c b/regexp.c
index 11b46c720..f4a8aa1b0 100644
--- a/regexp.c
+++ b/regexp.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* regexp.c */ 2/* regexp.c */
2 3
3#include "internal.h" 4#include "internal.h"
@@ -17,44 +18,47 @@
17 */ 18 */
18extern int find_match(char *haystack, char *needle, int ignoreCase) 19extern int find_match(char *haystack, char *needle, int ignoreCase)
19{ 20{
20 int status; 21 int status;
21 struct regexp* re; 22 struct regexp *re;
22 re = regcomp( needle); 23
23 status = regexec(re, haystack, FALSE, ignoreCase); 24 re = regcomp(needle);
24 free( re); 25 status = regexec(re, haystack, FALSE, ignoreCase);
25 return( status); 26 free(re);
27 return (status);
26} 28}
27 29
28#if defined BB_SED 30#if defined BB_SED
29/* This performs substitutions after a regexp match has been found. 31/* This performs substitutions after a regexp match has been found.
30 * The new string is returned. It is malloc'ed, and do must be freed. */ 32 * The new string is returned. It is malloc'ed, and do must be freed. */
31extern int replace_match(char *haystack, char *needle, char *newNeedle, int ignoreCase) 33extern int replace_match(char *haystack, char *needle, char *newNeedle,
34 int ignoreCase)
32{ 35{
33 int status; 36 int status;
34 struct regexp* re; 37 struct regexp *re;
35 char *s, buf[BUF_SIZE], *d = buf; 38 char *s, buf[BUF_SIZE], *d = buf;
36 39
37 re = regcomp( needle); 40 re = regcomp(needle);
38 status = regexec(re, haystack, FALSE, ignoreCase); 41 status = regexec(re, haystack, FALSE, ignoreCase);
39 if (status==TRUE) { 42 if (status == TRUE) {
40 s=haystack; 43 s = haystack;
41 44
42 do { 45 do {
43 /* copy stuff from before the match */ 46 /* copy stuff from before the match */
44 while (s < re->startp[0]) 47 while (s < re->startp[0])
45 *d++ = *s++; 48 *d++ = *s++;
46 /* substitute for the matched part */ 49 /* substitute for the matched part */
47 regsub(re, newNeedle, d); 50 regsub(re, newNeedle, d);
48 s = re->endp[0]; 51 s = re->endp[0];
49 d += strlen(d); 52 d += strlen(d);
50 } while (regexec(re, s, FALSE, ignoreCase) == TRUE); 53 } while (regexec(re, s, FALSE, ignoreCase) == TRUE);
51 /* copy stuff from after the match */ 54 /* copy stuff from after the match */
52 while ( (*d++ = *s++) ) {} 55 while ((*d++ = *s++)) {
53 d[0] = '\0'; 56 }
54 strcpy(haystack, buf); 57 d[0] = '\0';
55 } 58 strcpy(haystack, buf);
56 free( re); 59 }
57 return( status); 60 free(re);
61 return (status);
58} 62}
59#endif 63#endif
60 64
@@ -97,9 +101,10 @@ extern int replace_match(char *haystack, char *needle, char *newNeedle, int igno
97 101
98 102
99 103
100static char *previous; /* the previous regexp, used when null regexp is given */ 104static char *previous; /* the previous regexp, used when null regexp is given */
105
101#if defined BB_SED 106#if defined BB_SED
102static char *previous1; /* a copy of the text from the previous substitution for regsub()*/ 107static char *previous1; /* a copy of the text from the previous substitution for regsub() */
103#endif 108#endif
104 109
105 110
@@ -116,27 +121,28 @@ static char *previous1; /* a copy of the text from the previous substitution for
116#define GET_META(s) (*(s) == META ? INT_META(*++(s)) : *s) 121#define GET_META(s) (*(s) == META ? INT_META(*++(s)) : *s)
117 122
118/* These are the internal codes used for each type of meta-character */ 123/* These are the internal codes used for each type of meta-character */
119#define M_BEGLINE 256 /* internal code for ^ */ 124#define M_BEGLINE 256 /* internal code for ^ */
120#define M_ENDLINE 257 /* internal code for $ */ 125#define M_ENDLINE 257 /* internal code for $ */
121#define M_BEGWORD 258 /* internal code for \< */ 126#define M_BEGWORD 258 /* internal code for \< */
122#define M_ENDWORD 259 /* internal code for \> */ 127#define M_ENDWORD 259 /* internal code for \> */
123#define M_ANY 260 /* internal code for . */ 128#define M_ANY 260 /* internal code for . */
124#define M_SPLAT 261 /* internal code for * */ 129#define M_SPLAT 261 /* internal code for * */
125#define M_PLUS 262 /* internal code for \+ */ 130#define M_PLUS 262 /* internal code for \+ */
126#define M_QMARK 263 /* internal code for \? */ 131#define M_QMARK 263 /* internal code for \? */
127#define M_CLASS(n) (264+(n)) /* internal code for [] */ 132#define M_CLASS(n) (264+(n)) /* internal code for [] */
128#define M_START(n) (274+(n)) /* internal code for \( */ 133#define M_START(n) (274+(n)) /* internal code for \( */
129#define M_END(n) (284+(n)) /* internal code for \) */ 134#define M_END(n) (284+(n)) /* internal code for \) */
130 135
131/* These are used during compilation */ 136/* These are used during compilation */
132static int class_cnt; /* used to assign class IDs */ 137static int class_cnt; /* used to assign class IDs */
133static int start_cnt; /* used to assign start IDs */ 138static int start_cnt; /* used to assign start IDs */
134static int end_stk[NSUBEXP];/* used to assign end IDs */ 139static int end_stk[NSUBEXP]; /* used to assign end IDs */
135static int end_sp; 140static int end_sp;
136static char *retext; /* points to the text being compiled */ 141static char *retext; /* points to the text being compiled */
137 142
138/* error-handling stuff */ 143/* error-handling stuff */
139jmp_buf errorhandler; 144jmp_buf errorhandler;
145
140#define FAIL(why) do {fprintf(stderr, why); longjmp(errorhandler, 1);} while (0) 146#define FAIL(why) do {fprintf(stderr, why); longjmp(errorhandler, 1);} while (0)
141 147
142 148
@@ -145,68 +151,56 @@ jmp_buf errorhandler;
145/* This function builds a bitmap for a particular class */ 151/* This function builds a bitmap for a particular class */
146/* text -- start of the class */ 152/* text -- start of the class */
147/* bmap -- the bitmap */ 153/* bmap -- the bitmap */
148static char *makeclass(char* text, char* bmap) 154static char *makeclass(char *text, char *bmap)
149{ 155{
150 int i; 156 int i;
151 int complement = 0; 157 int complement = 0;
152 158
153 159
154 /* zero the bitmap */ 160 /* zero the bitmap */
155 for (i = 0; bmap && i < 32; i++) 161 for (i = 0; bmap && i < 32; i++) {
156 {
157 bmap[i] = 0; 162 bmap[i] = 0;
158 } 163 }
159 164
160 /* see if we're going to complement this class */ 165 /* see if we're going to complement this class */
161 if (*text == '^') 166 if (*text == '^') {
162 {
163 text++; 167 text++;
164 complement = 1; 168 complement = 1;
165 } 169 }
166 170
167 /* add in the characters */ 171 /* add in the characters */
168 while (*text && *text != ']') 172 while (*text && *text != ']') {
169 {
170 /* is this a span of characters? */ 173 /* is this a span of characters? */
171 if (text[1] == '-' && text[2]) 174 if (text[1] == '-' && text[2]) {
172 {
173 /* spans can't be backwards */ 175 /* spans can't be backwards */
174 if (text[0] > text[2]) 176 if (text[0] > text[2]) {
175 {
176 FAIL("Backwards span in []"); 177 FAIL("Backwards span in []");
177 } 178 }
178 179
179 /* add each character in the span to the bitmap */ 180 /* add each character in the span to the bitmap */
180 for (i = text[0]; bmap && i <= text[2]; i++) 181 for (i = text[0]; bmap && i <= text[2]; i++) {
181 {
182 bmap[i >> 3] |= (1 << (i & 7)); 182 bmap[i >> 3] |= (1 << (i & 7));
183 } 183 }
184 184
185 /* move past this span */ 185 /* move past this span */
186 text += 3; 186 text += 3;
187 } 187 } else {
188 else
189 {
190 /* add this single character to the span */ 188 /* add this single character to the span */
191 i = *text++; 189 i = *text++;
192 if (bmap) 190 if (bmap) {
193 {
194 bmap[i >> 3] |= (1 << (i & 7)); 191 bmap[i >> 3] |= (1 << (i & 7));
195 } 192 }
196 } 193 }
197 } 194 }
198 195
199 /* make sure the closing ] is missing */ 196 /* make sure the closing ] is missing */
200 if (*text++ != ']') 197 if (*text++ != ']') {
201 {
202 FAIL("] missing"); 198 FAIL("] missing");
203 } 199 }
204 200
205 /* if we're supposed to complement this class, then do so */ 201 /* if we're supposed to complement this class, then do so */
206 if (complement && bmap) 202 if (complement && bmap) {
207 { 203 for (i = 0; i < 32; i++) {
208 for (i = 0; i < 32; i++)
209 {
210 bmap[i] = ~bmap[i]; 204 bmap[i] = ~bmap[i];
211 } 205 }
212 } 206 }
@@ -223,105 +217,92 @@ static char *makeclass(char* text, char* bmap)
223 * character-class text is skipped. 217 * character-class text is skipped.
224 */ 218 */
225static int gettoken(sptr, re) 219static int gettoken(sptr, re)
226 char **sptr; 220char **sptr;
227 regexp *re; 221regexp *re;
228{ 222{
229 int c; 223 int c;
230 224
231 c = **sptr; 225 c = **sptr;
232 ++*sptr; 226 ++*sptr;
233 if (c == '\\') 227 if (c == '\\') {
234 {
235 c = **sptr; 228 c = **sptr;
236 ++*sptr; 229 ++*sptr;
237 switch (c) 230 switch (c) {
238 { 231 case '<':
239 case '<':
240 return M_BEGWORD; 232 return M_BEGWORD;
241 233
242 case '>': 234 case '>':
243 return M_ENDWORD; 235 return M_ENDWORD;
244 236
245 case '(': 237 case '(':
246 if (start_cnt >= NSUBEXP) 238 if (start_cnt >= NSUBEXP) {
247 {
248 FAIL("Too many \\(s"); 239 FAIL("Too many \\(s");
249 } 240 }
250 end_stk[end_sp++] = start_cnt; 241 end_stk[end_sp++] = start_cnt;
251 return M_START(start_cnt++); 242 return M_START(start_cnt++);
252 243
253 case ')': 244 case ')':
254 if (end_sp <= 0) 245 if (end_sp <= 0) {
255 {
256 FAIL("Mismatched \\)"); 246 FAIL("Mismatched \\)");
257 } 247 }
258 return M_END(end_stk[--end_sp]); 248 return M_END(end_stk[--end_sp]);
259 249
260 case '*': 250 case '*':
261 return M_SPLAT; 251 return M_SPLAT;
262 252
263 case '.': 253 case '.':
264 return M_ANY; 254 return M_ANY;
265 255
266 case '+': 256 case '+':
267 return M_PLUS; 257 return M_PLUS;
268 258
269 case '?': 259 case '?':
270 return M_QMARK; 260 return M_QMARK;
271 261
272 default: 262 default:
273 return c; 263 return c;
274 } 264 }
275 } 265 } else {
276 else { 266 switch (c) {
277 switch (c) 267 case '^':
278 { 268 if (*sptr == retext + 1) {
279 case '^':
280 if (*sptr == retext + 1)
281 {
282 return M_BEGLINE; 269 return M_BEGLINE;
283 } 270 }
284 return c; 271 return c;
285 272
286 case '$': 273 case '$':
287 if (!**sptr) 274 if (!**sptr) {
288 {
289 return M_ENDLINE; 275 return M_ENDLINE;
290 } 276 }
291 return c; 277 return c;
292 278
293 case '.': 279 case '.':
294 return M_ANY; 280 return M_ANY;
295 281
296 case '*': 282 case '*':
297 return M_SPLAT; 283 return M_SPLAT;
298 284
299 case '[': 285 case '[':
300 /* make sure we don't have too many classes */ 286 /* make sure we don't have too many classes */
301 if (class_cnt >= 10) 287 if (class_cnt >= 10) {
302 {
303 FAIL("Too many []s"); 288 FAIL("Too many []s");
304 } 289 }
305 290
306 /* process the character list for this class */ 291 /* process the character list for this class */
307 if (re) 292 if (re) {
308 {
309 /* generate the bitmap for this class */ 293 /* generate the bitmap for this class */
310 *sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt); 294 *sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt);
311 } 295 } else {
312 else
313 {
314 /* skip to end of the class */ 296 /* skip to end of the class */
315 *sptr = makeclass(*sptr, (char *)0); 297 *sptr = makeclass(*sptr, (char *) 0);
316 } 298 }
317 return M_CLASS(class_cnt++); 299 return M_CLASS(class_cnt++);
318 300
319 default: 301 default:
320 return c; 302 return c;
321 } 303 }
322 } 304 }
323 /*NOTREACHED*/ 305 /*NOTREACHED*/}
324}
325 306
326 307
327 308
@@ -331,28 +312,22 @@ static int gettoken(sptr, re)
331 * about catching syntax errors; that is done in a later pass. 312 * about catching syntax errors; that is done in a later pass.
332 */ 313 */
333static unsigned calcsize(text) 314static unsigned calcsize(text)
334 char *text; 315char *text;
335{ 316{
336 unsigned size; 317 unsigned size;
337 int token; 318 int token;
338 319
339 retext = text; 320 retext = text;
340 class_cnt = 0; 321 class_cnt = 0;
341 start_cnt = 1; 322 start_cnt = 1;
342 end_sp = 0; 323 end_sp = 0;
343 size = 5; 324 size = 5;
344 while ((token = gettoken(&text, (regexp *)0)) != 0) 325 while ((token = gettoken(&text, (regexp *) 0)) != 0) {
345 { 326 if (IS_CLASS(token)) {
346 if (IS_CLASS(token))
347 {
348 size += 34; 327 size += 34;
349 } 328 } else if (IS_META(token)) {
350 else if (IS_META(token))
351 {
352 size += 2; 329 size += 2;
353 } 330 } else {
354 else
355 {
356 size++; 331 size++;
357 } 332 }
358 } 333 }
@@ -369,26 +344,23 @@ static unsigned calcsize(text)
369 * known to represent a single character. It returns 0 if they match, or 344 * known to represent a single character. It returns 0 if they match, or
370 * 1 if they don't. 345 * 1 if they don't.
371 */ 346 */
372static int match1(regexp* re, char ch, int token, int ignoreCase) 347static int match1(regexp * re, char ch, int token, int ignoreCase)
373{ 348{
374 if (!ch) 349 if (!ch) {
375 {
376 /* the end of a line can't match any RE of width 1 */ 350 /* the end of a line can't match any RE of width 1 */
377 return 1; 351 return 1;
378 } 352 }
379 if (token == M_ANY) 353 if (token == M_ANY) {
380 {
381 return 0; 354 return 0;
382 } 355 } else if (IS_CLASS(token)) {
383 else if (IS_CLASS(token)) 356 if (re->
384 { 357 program[1 + 32 * (token - M_CLASS(0)) +
385 if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7))) 358 (ch >> 3)] & (1 << (ch & 7)))
386 return 0; 359 return 0;
387 } 360 }
388//fprintf(stderr, "match1: ch='%c' token='%c': ", ch, token); 361//fprintf(stderr, "match1: ch='%c' token='%c': ", ch, token);
389 if (ch == token 362 if (ch == token
390 || (ignoreCase==TRUE && tolower(ch) == tolower(token))) 363 || (ignoreCase == TRUE && tolower(ch) == tolower(token))) {
391 {
392//fprintf(stderr, "match\n"); 364//fprintf(stderr, "match\n");
393 return 0; 365 return 0;
394 } 366 }
@@ -406,65 +378,63 @@ static int match1(regexp* re, char ch, int token, int ignoreCase)
406/* str -- the string */ 378/* str -- the string */
407/* prog -- a portion of re->program, an compiled RE */ 379/* prog -- a portion of re->program, an compiled RE */
408/* here -- a portion of str, the string to compare it to */ 380/* here -- a portion of str, the string to compare it to */
409static int match(regexp* re, char* str, char* prog, char* here, int ignoreCase) 381static int match(regexp * re, char *str, char *prog, char *here,
382 int ignoreCase)
410{ 383{
411 int token; 384 int token;
412 int nmatched; 385 int nmatched;
413 int closure; 386 int closure;
414 387
415 for (token = GET_META(prog); !IS_CLOSURE(token); prog++, token = GET_META(prog)) 388 for (token = GET_META(prog); !IS_CLOSURE(token);
416 { 389 prog++, token = GET_META(prog)) {
417 switch (token) 390 switch (token) {
418 { 391 /*case M_BEGLINE: can't happen; re->bol is used instead */
419 /*case M_BEGLINE: can't happen; re->bol is used instead */ 392 case M_ENDLINE:
420 case M_ENDLINE:
421 if (*here) 393 if (*here)
422 return 1; 394 return 1;
423 break; 395 break;
424 396
425 case M_BEGWORD: 397 case M_BEGWORD:
426 if (here != str && 398 if (here != str &&
427 (here[-1] == '_' || 399 (here[-1] == '_' ||
428 (isascii(here[-1]) && isalnum(here[-1])))) 400 (isascii(here[-1]) && isalnum(here[-1])))) return 1;
429 return 1;
430 break; 401 break;
431 402
432 case M_ENDWORD: 403 case M_ENDWORD:
433 if ((here[0] == '_' || isascii(here[0])) && isalnum(here[0])) 404 if ((here[0] == '_' || isascii(here[0])) && isalnum(here[0]))
434 return 1; 405 return 1;
435 break; 406 break;
436 407
437 case M_START(0): 408 case M_START(0):
438 case M_START(1): 409 case M_START(1):
439 case M_START(2): 410 case M_START(2):
440 case M_START(3): 411 case M_START(3):
441 case M_START(4): 412 case M_START(4):
442 case M_START(5): 413 case M_START(5):
443 case M_START(6): 414 case M_START(6):
444 case M_START(7): 415 case M_START(7):
445 case M_START(8): 416 case M_START(8):
446 case M_START(9): 417 case M_START(9):
447 re->startp[token - M_START(0)] = (char *)here; 418 re->startp[token - M_START(0)] = (char *) here;
448 break; 419 break;
449 420
450 case M_END(0): 421 case M_END(0):
451 case M_END(1): 422 case M_END(1):
452 case M_END(2): 423 case M_END(2):
453 case M_END(3): 424 case M_END(3):
454 case M_END(4): 425 case M_END(4):
455 case M_END(5): 426 case M_END(5):
456 case M_END(6): 427 case M_END(6):
457 case M_END(7): 428 case M_END(7):
458 case M_END(8): 429 case M_END(8):
459 case M_END(9): 430 case M_END(9):
460 re->endp[token - M_END(0)] = (char *)here; 431 re->endp[token - M_END(0)] = (char *) here;
461 if (token == M_END(0)) 432 if (token == M_END(0)) {
462 {
463 return 0; 433 return 0;
464 } 434 }
465 break; 435 break;
466 436
467 default: /* literal, M_CLASS(n), or M_ANY */ 437 default: /* literal, M_CLASS(n), or M_ANY */
468 if (match1(re, *here, token, ignoreCase) != 0) 438 if (match1(re, *here, token, ignoreCase) != 0)
469 return 1; 439 return 1;
470 here++; 440 here++;
@@ -482,14 +452,12 @@ static int match(regexp* re, char* str, char* prog, char* here, int ignoreCase)
482 452
483 /* step 2: see how many times we can match that token against the string */ 453 /* step 2: see how many times we can match that token against the string */
484 for (nmatched = 0; 454 for (nmatched = 0;
485 (closure != M_QMARK || nmatched < 1) && *here && match1(re, *here, token, ignoreCase) == 0; 455 (closure != M_QMARK || nmatched < 1) && *here
486 nmatched++, here++) 456 && match1(re, *here, token, ignoreCase) == 0; nmatched++, here++) {
487 {
488 } 457 }
489 458
490 /* step 3: try to match the remainder, and back off if it doesn't */ 459 /* step 3: try to match the remainder, and back off if it doesn't */
491 while (nmatched >= 0 && match(re, str, prog, here, ignoreCase) != 0) 460 while (nmatched >= 0 && match(re, str, prog, here, ignoreCase) != 0) {
492 {
493 nmatched--; 461 nmatched--;
494 here--; 462 here--;
495 } 463 }
@@ -502,41 +470,36 @@ static int match(regexp* re, char* str, char* prog, char* here, int ignoreCase)
502 470
503 471
504/* This function compiles a regexp. */ 472/* This function compiles a regexp. */
505extern regexp *regcomp(char* text) 473extern regexp *regcomp(char *text)
506{ 474{
507 int needfirst; 475 int needfirst;
508 unsigned size; 476 unsigned size;
509 int token; 477 int token;
510 int peek; 478 int peek;
511 char *build; 479 char *build;
512 regexp *re; // Ignore compiler whining. If we longjmp, we don't use re anymore. 480 regexp *re; // Ignore compiler whining. If we longjmp, we don't use re anymore.
513 481
514 482
515 /* prepare for error handling */ 483 /* prepare for error handling */
516 re = (regexp *)0; 484 re = (regexp *) 0;
517 if (setjmp(errorhandler)) 485 if (setjmp(errorhandler)) {
518 { 486 if (re) {
519 if (re)
520 {
521 free(re); 487 free(re);
522 } 488 }
523 return (regexp *)0; 489 return (regexp *) 0;
524 } 490 }
525 491
526 /* if an empty regexp string was given, use the previous one */ 492 /* if an empty regexp string was given, use the previous one */
527 if (*text == 0) 493 if (*text == 0) {
528 { 494 if (!previous) {
529 if (!previous)
530 {
531 FAIL("No previous RE"); 495 FAIL("No previous RE");
532 } 496 }
533 text = previous; 497 text = previous;
534 } 498 } else { /* non-empty regexp given, so remember it */
535 else /* non-empty regexp given, so remember it */ 499
536 {
537 if (previous) 500 if (previous)
538 free(previous); 501 free(previous);
539 previous = (char *)malloc((unsigned)(strlen(text) + 1)); 502 previous = (char *) malloc((unsigned) (strlen(text) + 1));
540 if (previous) 503 if (previous)
541 strcpy(previous, text); 504 strcpy(previous, text);
542 } 505 }
@@ -547,19 +510,17 @@ extern regexp *regcomp(char* text)
547 end_sp = 0; 510 end_sp = 0;
548 retext = text; 511 retext = text;
549 size = calcsize(text) + sizeof(regexp); 512 size = calcsize(text) + sizeof(regexp);
550 re = (regexp *)malloc((unsigned)size); 513 re = (regexp *) malloc((unsigned) size);
551 514
552 if (!re) 515 if (!re) {
553 {
554 FAIL("Not enough memory for this RE"); 516 FAIL("Not enough memory for this RE");
555 } 517 }
556 518
557 /* compile it */ 519 /* compile it */
558 build = &re->program[1 + 32 * class_cnt]; 520 build = &re->program[1 + 32 * class_cnt];
559 re->program[0] = class_cnt; 521 re->program[0] = class_cnt;
560 for (token = 0; token < NSUBEXP; token++) 522 for (token = 0; token < NSUBEXP; token++) {
561 { 523 re->startp[token] = re->endp[token] = (char *) 0;
562 re->startp[token] = re->endp[token] = (char *)0;
563 } 524 }
564 re->first = 0; 525 re->first = 0;
565 re->bol = 0; 526 re->bol = 0;
@@ -570,76 +531,60 @@ extern regexp *regcomp(char* text)
570 end_sp = 0; 531 end_sp = 0;
571 retext = text; 532 retext = text;
572 for (token = M_START(0), peek = gettoken(&text, re); 533 for (token = M_START(0), peek = gettoken(&text, re);
573 token; 534 token; token = peek, peek = gettoken(&text, re)) {
574 token = peek, peek = gettoken(&text, re))
575 {
576 /* special processing for the closure operator */ 535 /* special processing for the closure operator */
577 if (IS_CLOSURE(peek)) 536 if (IS_CLOSURE(peek)) {
578 {
579 /* detect misuse of closure operator */ 537 /* detect misuse of closure operator */
580 if (IS_START(token)) 538 if (IS_START(token)) {
581 {
582 FAIL("* or \\+ or \\? follows nothing"); 539 FAIL("* or \\+ or \\? follows nothing");
583 } 540 }
584 else if (IS_META(token) && token != M_ANY && !IS_CLASS(token)) 541 else if (IS_META(token) && token != M_ANY
585 { 542 && !IS_CLASS(token)) {
586 FAIL("* or \\+ or \\? can only follow a normal character or . or []"); 543 FAIL
544 ("* or \\+ or \\? can only follow a normal character or . or []");
587 } 545 }
588 546
589 /* it is okay -- make it prefix instead of postfix */ 547 /* it is okay -- make it prefix instead of postfix */
590 ADD_META(build, peek); 548 ADD_META(build, peek);
591 549
592 /* take care of "needfirst" - is this the first char? */ 550 /* take care of "needfirst" - is this the first char? */
593 if (needfirst && peek == M_PLUS && !IS_META(token)) 551 if (needfirst && peek == M_PLUS && !IS_META(token)) {
594 {
595 re->first = token; 552 re->first = token;
596 } 553 }
597 needfirst = 0; 554 needfirst = 0;
598 555
599 /* we used "peek" -- need to refill it */ 556 /* we used "peek" -- need to refill it */
600 peek = gettoken(&text, re); 557 peek = gettoken(&text, re);
601 if (IS_CLOSURE(peek)) 558 if (IS_CLOSURE(peek)) {
602 {
603 FAIL("* or \\+ or \\? doubled up"); 559 FAIL("* or \\+ or \\? doubled up");
604 } 560 }
605 } 561 } else if (!IS_META(token)) {
606 else if (!IS_META(token))
607 {
608 /* normal char is NOT argument of closure */ 562 /* normal char is NOT argument of closure */
609 if (needfirst) 563 if (needfirst) {
610 {
611 re->first = token; 564 re->first = token;
612 needfirst = 0; 565 needfirst = 0;
613 } 566 }
614 re->minlen++; 567 re->minlen++;
615 } 568 } else if (token == M_ANY || IS_CLASS(token)) {
616 else if (token == M_ANY || IS_CLASS(token))
617 {
618 /* . or [] is NOT argument of closure */ 569 /* . or [] is NOT argument of closure */
619 needfirst = 0; 570 needfirst = 0;
620 re->minlen++; 571 re->minlen++;
621 } 572 }
622 573
623 /* the "token" character is not closure -- process it normally */ 574 /* the "token" character is not closure -- process it normally */
624 if (token == M_BEGLINE) 575 if (token == M_BEGLINE) {
625 {
626 /* set the BOL flag instead of storing M_BEGLINE */ 576 /* set the BOL flag instead of storing M_BEGLINE */
627 re->bol = 1; 577 re->bol = 1;
628 } 578 } else if (IS_META(token)) {
629 else if (IS_META(token))
630 {
631 ADD_META(build, token); 579 ADD_META(build, token);
632 } 580 } else {
633 else
634 {
635 *build++ = token; 581 *build++ = token;
636 } 582 }
637 } 583 }
638 584
639 /* end it with a \) which MUST MATCH the opening \( */ 585 /* end it with a \) which MUST MATCH the opening \( */
640 ADD_META(build, M_END(0)); 586 ADD_META(build, M_END(0));
641 if (end_sp > 0) 587 if (end_sp > 0) {
642 {
643 FAIL("Not enough \\)s"); 588 FAIL("Not enough \\)s");
644 } 589 }
645 590
@@ -654,15 +599,14 @@ extern regexp *regcomp(char* text)
654/* str -- the string to search through */ 599/* str -- the string to search through */
655/* bol -- does str start at the beginning of a line? (boolean) */ 600/* bol -- does str start at the beginning of a line? (boolean) */
656/* ignoreCase -- ignoreCase or not */ 601/* ignoreCase -- ignoreCase or not */
657extern int regexec(struct regexp* re, char* str, int bol, int ignoreCase) 602extern int regexec(struct regexp *re, char *str, int bol, int ignoreCase)
658{ 603{
659 char *prog; /* the entry point of re->program */ 604 char *prog; /* the entry point of re->program */
660 int len; /* length of the string */ 605 int len; /* length of the string */
661 char *here; 606 char *here;
662 607
663 /* if must start at the beginning of a line, and this isn't, then fail */ 608 /* if must start at the beginning of a line, and this isn't, then fail */
664 if (re->bol && bol==TRUE) 609 if (re->bol && bol == TRUE) {
665 {
666 return FALSE; 610 return FALSE;
667 } 611 }
668 612
@@ -670,35 +614,26 @@ extern int regexec(struct regexp* re, char* str, int bol, int ignoreCase)
670 prog = re->program + 1 + 32 * re->program[0]; 614 prog = re->program + 1 + 32 * re->program[0];
671 615
672 /* search for the RE in the string */ 616 /* search for the RE in the string */
673 if (re->bol) 617 if (re->bol) {
674 {
675 /* must occur at BOL */ 618 /* must occur at BOL */
676 if ((re->first 619 if ((re->first && match1(re, *(char *) str, re->first, ignoreCase)) /* wrong first letter? */
677 && match1(re, *(char *)str, re->first, ignoreCase))/* wrong first letter? */ 620 ||len < re->minlen /* not long enough? */
678 || len < re->minlen /* not long enough? */ 621 || match(re, (char *) str, prog, str, ignoreCase)) /* doesn't match? */
679 || match(re, (char *)str, prog, str, ignoreCase)) /* doesn't match? */ 622 return FALSE; /* THEN FAIL! */
680 return FALSE; /* THEN FAIL! */ 623 } else if (ignoreCase == FALSE) {
681 }
682 else if (ignoreCase == FALSE)
683 {
684 /* can occur anywhere in the line, noignorecase */ 624 /* can occur anywhere in the line, noignorecase */
685 for (here = (char *)str; 625 for (here = (char *) str; (re->first && re->first != *here)
686 (re->first && re->first != *here) 626 || match(re, (char *) str, prog, here, ignoreCase);
687 || match(re, (char *)str, prog, here, ignoreCase); 627 here++, len--) {
688 here++, len--)
689 {
690 if (len < re->minlen) 628 if (len < re->minlen)
691 return FALSE; 629 return FALSE;
692 } 630 }
693 } 631 } else {
694 else
695 {
696 /* can occur anywhere in the line, ignorecase */ 632 /* can occur anywhere in the line, ignorecase */
697 for (here = (char *)str; 633 for (here = (char *) str;
698 (re->first && match1(re, *here, (int)re->first, ignoreCase)) 634 (re->first && match1(re, *here, (int) re->first, ignoreCase))
699 || match(re, (char *)str, prog, here, ignoreCase); 635 || match(re, (char *) str, prog, here, ignoreCase);
700 here++, len--) 636 here++, len--) {
701 {
702 if (len < re->minlen) 637 if (len < re->minlen)
703 return FALSE; 638 return FALSE;
704 } 639 }
@@ -713,82 +648,72 @@ extern int regexec(struct regexp* re, char* str, int bol, int ignoreCase)
713 648
714#if defined BB_SED 649#if defined BB_SED
715/* This performs substitutions after a regexp match has been found. */ 650/* This performs substitutions after a regexp match has been found. */
716extern void regsub(regexp* re, char* src, char* dst) 651extern void regsub(regexp * re, char *src, char *dst)
717{ 652{
718 char *cpy; 653 char *cpy;
719 char *end; 654 char *end;
720 char c; 655 char c;
721 char *start; 656 char *start;
722 int mod; 657 int mod;
723 658
724 mod = 0; 659 mod = 0;
725 660
726 start = src; 661 start = src;
727 while ((c = *src++) != '\0') 662 while ((c = *src++) != '\0') {
728 {
729 /* recognize any meta characters */ 663 /* recognize any meta characters */
730 if (c == '&') 664 if (c == '&') {
731 {
732 cpy = re->startp[0]; 665 cpy = re->startp[0];
733 end = re->endp[0]; 666 end = re->endp[0];
734 } 667 } else if (c == '~') {
735 else if (c == '~')
736 {
737 cpy = previous1; 668 cpy = previous1;
738 if (cpy) 669 if (cpy)
739 end = cpy + strlen(cpy); 670 end = cpy + strlen(cpy);
740 } 671 } else if (c == '\\') {
741 else
742 if (c == '\\')
743 {
744 c = *src++; 672 c = *src++;
745 switch (c) 673 switch (c) {
746 { 674 case '0':
747 case '0': 675 case '1':
748 case '1': 676 case '2':
749 case '2': 677 case '3':
750 case '3': 678 case '4':
751 case '4': 679 case '5':
752 case '5': 680 case '6':
753 case '6': 681 case '7':
754 case '7': 682 case '8':
755 case '8': 683 case '9':
756 case '9':
757 /* \0 thru \9 mean "copy subexpression" */ 684 /* \0 thru \9 mean "copy subexpression" */
758 c -= '0'; 685 c -= '0';
759 cpy = re->startp[(int)c]; 686 cpy = re->startp[(int) c];
760 end = re->endp[(int)c]; 687 end = re->endp[(int) c];
761 break; 688 break;
762 case 'U': 689 case 'U':
763 case 'u': 690 case 'u':
764 case 'L': 691 case 'L':
765 case 'l': 692 case 'l':
766 /* \U and \L mean "convert to upper/lowercase" */ 693 /* \U and \L mean "convert to upper/lowercase" */
767 mod = c; 694 mod = c;
768 continue; 695 continue;
769 696
770 case 'E': 697 case 'E':
771 case 'e': 698 case 'e':
772 /* \E ends the \U or \L */ 699 /* \E ends the \U or \L */
773 mod = 0; 700 mod = 0;
774 continue; 701 continue;
775 case '&': 702 case '&':
776 /* "\&" means "original text" */ 703 /* "\&" means "original text" */
777 *dst++ = c; 704 *dst++ = c;
778 continue; 705 continue;
779 706
780 case '~': 707 case '~':
781 /* "\~" means "previous text, if any" */ 708 /* "\~" means "previous text, if any" */
782 *dst++ = c; 709 *dst++ = c;
783 continue; 710 continue;
784 default: 711 default:
785 /* ordinary char preceded by backslash */ 712 /* ordinary char preceded by backslash */
786 *dst++ = c; 713 *dst++ = c;
787 continue; 714 continue;
788 } 715 }
789 } 716 } else {
790 else
791 {
792 /* ordinary character, so just copy it */ 717 /* ordinary character, so just copy it */
793 *dst++ = c; 718 *dst++ = c;
794 continue; 719 continue;
@@ -804,46 +729,37 @@ extern void regsub(regexp* re, char* src, char* dst)
804 continue; 729 continue;
805 730
806 /* copy over a portion of the original */ 731 /* copy over a portion of the original */
807 while (cpy < end) 732 while (cpy < end) {
808 { 733 switch (mod) {
809 switch (mod) 734 case 'U':
810 { 735 case 'u':
811 case 'U':
812 case 'u':
813 /* convert to uppercase */ 736 /* convert to uppercase */
814 if (isascii(*cpy) && islower(*cpy)) 737 if (isascii(*cpy) && islower(*cpy)) {
815 {
816 *dst++ = toupper(*cpy); 738 *dst++ = toupper(*cpy);
817 cpy++; 739 cpy++;
818 } 740 } else {
819 else
820 {
821 *dst++ = *cpy++; 741 *dst++ = *cpy++;
822 } 742 }
823 break; 743 break;
824 744
825 case 'L': 745 case 'L':
826 case 'l': 746 case 'l':
827 /* convert to lowercase */ 747 /* convert to lowercase */
828 if (isascii(*cpy) && isupper(*cpy)) 748 if (isascii(*cpy) && isupper(*cpy)) {
829 {
830 *dst++ = tolower(*cpy); 749 *dst++ = tolower(*cpy);
831 cpy++; 750 cpy++;
832 } 751 } else {
833 else
834 {
835 *dst++ = *cpy++; 752 *dst++ = *cpy++;
836 } 753 }
837 break; 754 break;
838 755
839 default: 756 default:
840 /* copy without any conversion */ 757 /* copy without any conversion */
841 *dst++ = *cpy++; 758 *dst++ = *cpy++;
842 } 759 }
843 760
844 /* \u and \l end automatically after the first char */ 761 /* \u and \l end automatically after the first char */
845 if (mod && (mod == 'u' || mod == 'l')) 762 if (mod && (mod == 'u' || mod == 'l')) {
846 {
847 mod = 0; 763 mod = 0;
848 } 764 }
849 } 765 }
@@ -853,12 +769,10 @@ extern void regsub(regexp* re, char* src, char* dst)
853 /* remember what text we inserted this time */ 769 /* remember what text we inserted this time */
854 if (previous1) 770 if (previous1)
855 free(previous1); 771 free(previous1);
856 previous1 = (char *)malloc((unsigned)(strlen(start) + 1)); 772 previous1 = (char *) malloc((unsigned) (strlen(start) + 1));
857 if (previous1) 773 if (previous1)
858 strcpy(previous1, start); 774 strcpy(previous1, start);
859} 775}
860#endif 776#endif
861 777
862#endif /* BB_REGEXP */ 778#endif /* BB_REGEXP */
863
864
diff --git a/regexp.h b/regexp.h
index e8880fb4f..0c7c9d9ae 100644
--- a/regexp.h
+++ b/regexp.h
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Busybox regexp header file 3 * Busybox regexp header file
3 * 4 *
diff --git a/rm.c b/rm.c
index ee434fb39..41afedaf9 100644
--- a/rm.c
+++ b/rm.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rm implementation for busybox 3 * Mini rm implementation for busybox
3 * 4 *
@@ -28,11 +29,12 @@
28#include <dirent.h> 29#include <dirent.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char* rm_usage = "rm [OPTION]... FILE...\n\n" 32static const char *rm_usage = "rm [OPTION]... FILE...\n\n"
32"Remove (unlink) the FILE(s).\n\n" 33 "Remove (unlink) the FILE(s).\n\n"
33"Options:\n" 34 "Options:\n"
34"\t-f\t\tremove existing destinations, never prompt\n" 35
35"\t-r or -R\tremove the contents of directories recursively\n"; 36 "\t-f\t\tremove existing destinations, never prompt\n"
37 "\t-r or -R\tremove the contents of directories recursively\n";
36 38
37 39
38static int recursiveFlag = FALSE; 40static int recursiveFlag = FALSE;
@@ -40,63 +42,63 @@ static int forceFlag = FALSE;
40static const char *srcName; 42static const char *srcName;
41 43
42 44
43static int fileAction(const char *fileName, struct stat* statbuf) 45static int fileAction(const char *fileName, struct stat *statbuf)
44{ 46{
45 if (unlink( fileName) < 0 ) { 47 if (unlink(fileName) < 0) {
46 perror( fileName); 48 perror(fileName);
47 return ( FALSE); 49 return (FALSE);
48 } 50 }
49 return ( TRUE); 51 return (TRUE);
50} 52}
51 53
52static int dirAction(const char *fileName, struct stat* statbuf) 54static int dirAction(const char *fileName, struct stat *statbuf)
53{ 55{
54 if (rmdir( fileName) < 0 ) { 56 if (rmdir(fileName) < 0) {
55 perror( fileName); 57 perror(fileName);
56 return ( FALSE); 58 return (FALSE);
57 } 59 }
58 return ( TRUE); 60 return (TRUE);
59} 61}
60 62
61extern int rm_main(int argc, char **argv) 63extern int rm_main(int argc, char **argv)
62{ 64{
63 struct stat statbuf; 65 struct stat statbuf;
64 66
65 if (argc < 2) { 67 if (argc < 2) {
66 usage( rm_usage); 68 usage(rm_usage);
67 } 69 }
68 argc--;
69 argv++;
70
71 /* Parse any options */
72 while (**argv == '-') {
73 while (*++(*argv))
74 switch (**argv) {
75 case 'R':
76 case 'r':
77 recursiveFlag = TRUE;
78 break;
79 case 'f':
80 forceFlag = TRUE;
81 break;
82 default:
83 usage( rm_usage);
84 }
85 argc--; 70 argc--;
86 argv++; 71 argv++;
87 }
88 72
89 while (argc-- > 0) { 73 /* Parse any options */
90 srcName = *(argv++); 74 while (**argv == '-') {
91 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0 && errno == ENOENT) { 75 while (*++(*argv))
92 /* do not reports errors for non-existent files if -f, just skip them */ 76 switch (**argv) {
77 case 'R':
78 case 'r':
79 recursiveFlag = TRUE;
80 break;
81 case 'f':
82 forceFlag = TRUE;
83 break;
84 default:
85 usage(rm_usage);
86 }
87 argc--;
88 argv++;
93 } 89 }
94 else { 90
95 if (recursiveAction( srcName, recursiveFlag, FALSE, 91 while (argc-- > 0) {
96 TRUE, fileAction, dirAction) == FALSE) { 92 srcName = *(argv++);
97 exit( FALSE); 93 if (forceFlag == TRUE && lstat(srcName, &statbuf) != 0
98 } 94 && errno == ENOENT) {
95 /* do not reports errors for non-existent files if -f, just skip them */
96 } else {
97 if (recursiveAction(srcName, recursiveFlag, FALSE,
98 TRUE, fileAction, dirAction) == FALSE) {
99 exit(FALSE);
100 }
101 }
99 } 102 }
100 } 103 exit(TRUE);
101 exit( TRUE);
102} 104}
diff --git a/rmdir.c b/rmdir.c
index 013fef1a4..f49569749 100644
--- a/rmdir.c
+++ b/rmdir.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rmdir implementation for busybox 3 * Mini rmdir implementation for busybox
3 * 4 *
@@ -28,15 +29,16 @@
28 29
29extern int rmdir_main(int argc, char **argv) 30extern int rmdir_main(int argc, char **argv)
30{ 31{
31 if ( argc==1 || **(argv+1) == '-' ) { 32 if (argc == 1 || **(argv + 1) == '-') {
32 usage( "rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n"); 33 usage
33 } 34 ("rmdir [OPTION]... DIRECTORY...\n\nRemove the DIRECTORY(ies), if they are empty.\n");
35 }
34 36
35 while (--argc > 0) { 37 while (--argc > 0) {
36 if ( rmdir(*(++argv)) == -1 ) { 38 if (rmdir(*(++argv)) == -1) {
37 fprintf(stderr, "%s: %s\n", *argv, strerror(errno)); 39 fprintf(stderr, "%s: %s\n", *argv, strerror(errno));
38 exit(FALSE); 40 exit(FALSE);
41 }
39 } 42 }
40 } 43 exit(TRUE);
41 exit(TRUE);
42} 44}
diff --git a/rmmod.c b/rmmod.c
index 6b15b48bb..a0db4ae5c 100644
--- a/rmmod.c
+++ b/rmmod.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini rmmod implementation for busybox 3 * Mini rmmod implementation for busybox
3 * 4 *
@@ -33,41 +34,41 @@ _syscall1(int, delete_module, const char *, name)
33 34
34 35
35static const char rmmod_usage[] = 36static const char rmmod_usage[] =
36 "rmmod [OPTION]... [MODULE]...\n\n" 37 "rmmod [OPTION]... [MODULE]...\n\n"
37 "Unloads the specified kernel modules from the kernel.\n\n" 38 "Unloads the specified kernel modules from the kernel.\n\n"
38 "Options:\n" 39
39 "\t-a\tTry to remove all unused kernel modules.\n"; 40 "Options:\n" "\t-a\tTry to remove all unused kernel modules.\n";
40 41
41 42
42 43
43extern int rmmod_main(int argc, char **argv) 44extern int rmmod_main(int argc, char **argv)
44{ 45{
45 if (argc<=1) { 46 if (argc <= 1) {
46 usage(rmmod_usage); 47 usage(rmmod_usage);
47 } 48 }
48 49
49 /* Parse any options */ 50 /* Parse any options */
50 while (--argc > 0 && **(++argv) == '-') { 51 while (--argc > 0 && **(++argv) == '-') {
51 while (*(++(*argv))) { 52 while (*(++(*argv))) {
52 switch (**argv) { 53 switch (**argv) {
53 case 'a': 54 case 'a':
54 /* Unload _all_ unused modules via NULL delete_module() call */ 55 /* Unload _all_ unused modules via NULL delete_module() call */
55 if (delete_module(NULL)) { 56 if (delete_module(NULL)) {
56 perror("rmmod"); 57 perror("rmmod");
57 exit( FALSE); 58 exit(FALSE);
59 }
60 exit(TRUE);
61 default:
62 usage(rmmod_usage);
63 }
58 } 64 }
59 exit( TRUE);
60 default:
61 usage(rmmod_usage);
62 }
63 } 65 }
64 }
65 66
66 while (argc-- > 0 ) { 67 while (argc-- > 0) {
67 if (delete_module(*argv) < 0) { 68 if (delete_module(*argv) < 0) {
68 perror(*argv); 69 perror(*argv);
70 }
71 argv++;
69 } 72 }
70 argv++; 73 exit(TRUE);
71 }
72 exit( TRUE);
73} 74}
diff --git a/sed.c b/sed.c
index 25777243d..3a7737e2f 100644
--- a/sed.c
+++ b/sed.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sed implementation for busybox 3 * Mini sed implementation for busybox
3 * 4 *
@@ -37,27 +38,27 @@
37#include <ctype.h> 38#include <ctype.h>
38 39
39static const char sed_usage[] = 40static const char sed_usage[] =
40 "sed [-n] -e script [file...]\n\n" 41 "sed [-n] -e script [file...]\n\n"
41 "Allowed sed scripts come in the following form:\n" 42 "Allowed sed scripts come in the following form:\n"
42 "\t'ADDR [!] COMMAND'\n\n" 43 "\t'ADDR [!] COMMAND'\n\n"
43 "\twhere address ADDR can be:\n" 44 "\twhere address ADDR can be:\n"
44 "\t NUMBER Match specified line number\n" 45 "\t NUMBER Match specified line number\n"
45 "\t $ Match last line\n" 46 "\t $ Match last line\n"
46 "\t /REGEXP/ Match specified regexp\n" 47 "\t /REGEXP/ Match specified regexp\n"
47 "\t (! inverts the meaning of the match)\n\n" 48 "\t (! inverts the meaning of the match)\n\n"
48 "\tand COMMAND can be:\n" 49 "\tand COMMAND can be:\n"
49 "\t s/regexp/replacement/[igp]\n" 50 "\t s/regexp/replacement/[igp]\n"
50 "\t which attempt to match regexp against the pattern space\n" 51 "\t which attempt to match regexp against the pattern space\n"
51 "\t and if successful replaces the matched portion with replacement.\n\n" 52 "\t and if successful replaces the matched portion with replacement.\n\n"
52 "\t aTEXT\n" 53 "\t aTEXT\n"
53 "\t which appends TEXT after the pattern space\n" 54 "\t which appends TEXT after the pattern space\n"
54 "Options:\n" 55 "Options:\n"
55 "-e\tadd the script to the commands to be executed\n" 56 "-e\tadd the script to the commands to be executed\n"
56 "-n\tsuppress automatic printing of pattern space\n\n" 57 "-n\tsuppress automatic printing of pattern space\n\n"
57#if defined BB_REGEXP 58#if defined BB_REGEXP
58 "This version of sed matches full regular expresions.\n"; 59 "This version of sed matches full regular expresions.\n";
59#else 60#else
60 "This version of sed matches strings (not full regular expresions).\n"; 61 "This version of sed matches strings (not full regular expresions).\n";
61#endif 62#endif
62 63
63/* Flags & variables */ 64/* Flags & variables */
@@ -76,276 +77,277 @@ static int negated = 0;
76 77
77static inline int at_last(FILE * fp) 78static inline int at_last(FILE * fp)
78{ 79{
79 int res = 0; 80 int res = 0;
80 81
81 if (feof(fp)) 82 if (feof(fp))
82 return 1; 83 return 1;
83 else { 84 else {
84 char ch; 85 char ch;
85 if ((ch = fgetc(fp)) == EOF) 86
86 res++; 87 if ((ch = fgetc(fp)) == EOF)
87 ungetc(ch, fp); 88 res++;
88 } 89 ungetc(ch, fp);
89 return res; 90 }
91 return res;
90} 92}
91 93
92static void do_sed_repl(FILE * fp, char *needle, char *newNeedle, 94static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
93 int ignoreCase, int printFlag, int quietFlag) 95 int ignoreCase, int printFlag, int quietFlag)
94{ 96{
95 int foundOne = FALSE; 97 int foundOne = FALSE;
96 char haystack[BUFSIZE]; 98 char haystack[BUFSIZE];
97 int line = 1, doit; 99 int line = 1, doit;
98 100
99 while (fgets(haystack, BUFSIZE - 1, fp)) { 101 while (fgets(haystack, BUFSIZE - 1, fp)) {
100 doit = 0; 102 doit = 0;
101 if (addr_pattern) { 103 if (addr_pattern) {
102 doit = !find_match(haystack, addr_pattern, FALSE); 104 doit = !find_match(haystack, addr_pattern, FALSE);
103 } else if (addr_line == NO_LINE) 105 } else if (addr_line == NO_LINE)
104 doit = 1; 106 doit = 1;
105 else if (addr_line == LAST_LINE) { 107 else if (addr_line == LAST_LINE) {
106 if (at_last(fp)) 108 if (at_last(fp))
107 doit = 1; 109 doit = 1;
108 } else { 110 } else {
109 if (line == addr_line) 111 if (line == addr_line)
110 doit = 1; 112 doit = 1;
111 } 113 }
112 if (negated) 114 if (negated)
113 doit = 1 - doit; 115 doit = 1 - doit;
114 if (doit) { 116 if (doit) {
115 foundOne = 117 foundOne =
116 replace_match(haystack, needle, newNeedle, ignoreCase); 118 replace_match(haystack, needle, newNeedle, ignoreCase);
117 119
118 if (foundOne == TRUE && printFlag == TRUE) { 120 if (foundOne == TRUE && printFlag == TRUE) {
119 fprintf(stdout, haystack); 121 fprintf(stdout, haystack);
120 } 122 }
121 } 123 }
122 124
123 if (quietFlag == FALSE) { 125 if (quietFlag == FALSE) {
124 fprintf(stdout, haystack); 126 fprintf(stdout, haystack);
125 } 127 }
126 128
127 line++; 129 line++;
128 } 130 }
129} 131}
130 132
131static void do_sed_append(FILE * fp, char *appendline, int quietFlag) 133static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
132{ 134{
133 char buffer[BUFSIZE]; 135 char buffer[BUFSIZE];
134 int line = 1, doit; 136 int line = 1, doit;
135 137
136 while (fgets(buffer, BUFSIZE - 1, fp)) { 138 while (fgets(buffer, BUFSIZE - 1, fp)) {
137 doit = 0; 139 doit = 0;
138 if (addr_pattern) { 140 if (addr_pattern) {
139 doit = !find_match(buffer, addr_pattern, FALSE); 141 doit = !find_match(buffer, addr_pattern, FALSE);
140 } else if (addr_line == NO_LINE) 142 } else if (addr_line == NO_LINE)
141 doit = 1; 143 doit = 1;
142 else if (addr_line == LAST_LINE) { 144 else if (addr_line == LAST_LINE) {
143 if (at_last(fp)) 145 if (at_last(fp))
144 doit = 1; 146 doit = 1;
145 } else { 147 } else {
146 if (line == addr_line) 148 if (line == addr_line)
147 doit = 1; 149 doit = 1;
148 } 150 }
149 if (negated) 151 if (negated)
150 doit = 1 - doit; 152 doit = 1 - doit;
151 if (quietFlag == FALSE) { 153 if (quietFlag == FALSE) {
152 fprintf(stdout, buffer); 154 fprintf(stdout, buffer);
153 } 155 }
154 if (doit) { 156 if (doit) {
155 fputs(appendline, stdout); 157 fputs(appendline, stdout);
156 fputc('\n', stdout); 158 fputc('\n', stdout);
157 } 159 }
158 160
159 line++; 161 line++;
160 } 162 }
161} 163}
162 164
163extern int sed_main(int argc, char **argv) 165extern int sed_main(int argc, char **argv)
164{ 166{
165 FILE *fp; 167 FILE *fp;
166 char *needle = NULL, *newNeedle = NULL; 168 char *needle = NULL, *newNeedle = NULL;
167 char *name; 169 char *name;
168 char *cp; 170 char *cp;
169 int ignoreCase = FALSE; 171 int ignoreCase = FALSE;
170 int printFlag = FALSE; 172 int printFlag = FALSE;
171 int quietFlag = FALSE; 173 int quietFlag = FALSE;
172 int stopNow; 174 int stopNow;
173 char *line_s = NULL, saved; 175 char *line_s = NULL, saved;
174 char *appendline = NULL; 176 char *appendline = NULL;
175 char *pos; 177 char *pos;
176 sed_function sed_f = f_none; 178 sed_function sed_f = f_none;
177
178 argc--;
179 argv++;
180 if (argc < 1) {
181 usage(sed_usage);
182 }
183
184 if (**argv == '-') {
185 argc--;
186 cp = *argv++;
187 stopNow = FALSE;
188
189 while (*++cp && stopNow == FALSE) {
190 switch (*cp) {
191 case 'n':
192 quietFlag = TRUE;
193 break;
194 case 'e':
195 if (*(cp + 1) == 0 && --argc < 0) {
196 usage(sed_usage);
197 }
198 if (*++cp != 's')
199 cp = *argv++;
200
201 /* Read address if present */
202 SKIPSPACES(cp);
203 if (*cp == '$') {
204 addr_line = LAST_LINE;
205 cp++;
206 } else {
207 if (isdigit(*cp)) { /* LINE ADDRESS */
208 line_s = cp;
209 while (isdigit(*cp))
210 cp++;
211 if (cp > line_s) {
212 /* numeric line */
213 saved = *cp;
214 *cp = '\0';
215 addr_line = atoi(line_s);
216 *cp = saved;
217 }
218 } else if (*cp == '/') { /* PATTERN ADDRESS */
219 pos = addr_pattern = cp + 1;
220 pos = strchr(pos, '/');
221 if (!pos)
222 usage(sed_usage);
223 *pos = '\0';
224 cp = pos + 1;
225 }
226 }
227
228 SKIPSPACES(cp);
229 if (*cp == '!') {
230 negated++;
231 cp++;
232 }
233 179
234 /* Read command */ 180 argc--;
181 argv++;
182 if (argc < 1) {
183 usage(sed_usage);
184 }
235 185
236 SKIPSPACES(cp); 186 if (**argv == '-') {
237 switch (*cp) { 187 argc--;
238 case 's': /* REPLACE */ 188 cp = *argv++;
239 if (strlen(cp) <= 3 || *(cp + 1) != '/') 189 stopNow = FALSE;
240 break;
241 sed_f = f_replace;
242 190
243 pos = needle = cp + 2; 191 while (*++cp && stopNow == FALSE) {
192 switch (*cp) {
193 case 'n':
194 quietFlag = TRUE;
195 break;
196 case 'e':
197 if (*(cp + 1) == 0 && --argc < 0) {
198 usage(sed_usage);
199 }
200 if (*++cp != 's')
201 cp = *argv++;
202
203 /* Read address if present */
204 SKIPSPACES(cp);
205 if (*cp == '$') {
206 addr_line = LAST_LINE;
207 cp++;
208 } else {
209 if (isdigit(*cp)) { /* LINE ADDRESS */
210 line_s = cp;
211 while (isdigit(*cp))
212 cp++;
213 if (cp > line_s) {
214 /* numeric line */
215 saved = *cp;
216 *cp = '\0';
217 addr_line = atoi(line_s);
218 *cp = saved;
219 }
220 } else if (*cp == '/') { /* PATTERN ADDRESS */
221 pos = addr_pattern = cp + 1;
222 pos = strchr(pos, '/');
223 if (!pos)
224 usage(sed_usage);
225 *pos = '\0';
226 cp = pos + 1;
227 }
228 }
229
230 SKIPSPACES(cp);
231 if (*cp == '!') {
232 negated++;
233 cp++;
234 }
235
236 /* Read command */
237
238 SKIPSPACES(cp);
239 switch (*cp) {
240 case 's': /* REPLACE */
241 if (strlen(cp) <= 3 || *(cp + 1) != '/')
242 break;
243 sed_f = f_replace;
244
245 pos = needle = cp + 2;
246
247 for (;;) {
248 pos = strchr(pos, '/');
249 if (pos == NULL) {
250 usage(sed_usage);
251 }
252 if (*(pos - 1) == '\\') {
253 pos++;
254 continue;
255 }
256 break;
257 }
258 *pos = 0;
259 newNeedle = ++pos;
260 for (;;) {
261 pos = strchr(pos, '/');
262 if (pos == NULL) {
263 usage(sed_usage);
264 }
265 if (*(pos - 1) == '\\') {
266 pos++;
267 continue;
268 }
269 break;
270 }
271 *pos = 0;
272 if (pos + 2 != 0) {
273 while (*++pos) {
274 switch (*pos) {
275 case 'i':
276 ignoreCase = TRUE;
277 break;
278 case 'p':
279 printFlag = TRUE;
280 break;
281 case 'g':
282 break;
283 default:
284 usage(sed_usage);
285 }
286 }
287 }
288 cp = pos;
289 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
290 break;
291
292 case 'a': /* APPEND */
293 if (strlen(cp) < 2)
294 break;
295 sed_f = f_append;
296 appendline = ++cp;
297 /* fprintf(stderr, "append '%s'\n", appendline); */
298 break;
299 }
300
301 stopNow = TRUE;
302 break;
244 303
245 for (;;) { 304 default:
246 pos = strchr(pos, '/'); 305 usage(sed_usage);
247 if (pos == NULL) {
248 usage(sed_usage);
249 }
250 if (*(pos - 1) == '\\') {
251 pos++;
252 continue;
253 } 306 }
307 }
308 }
309
310 if (argc == 0) {
311 switch (sed_f) {
312 case f_none:
254 break; 313 break;
255 } 314 case f_replace:
256 *pos = 0; 315 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
257 newNeedle = ++pos; 316 quietFlag);
258 for (;;) {
259 pos = strchr(pos, '/');
260 if (pos == NULL) {
261 usage(sed_usage);
262 }
263 if (*(pos - 1) == '\\') {
264 pos++;
265 continue;
266 }
267 break; 317 break;
268 } 318 case f_append:
269 *pos = 0; 319 do_sed_append(stdin, appendline, quietFlag);
270 if (pos + 2 != 0) { 320 break;
271 while (*++pos) { 321 }
272 switch (*pos) { 322 } else {
273 case 'i': 323 while (argc-- > 0) {
274 ignoreCase = TRUE; 324 name = *argv++;
325
326 fp = fopen(name, "r");
327 if (fp == NULL) {
328 perror(name);
329 continue;
330 }
331
332 switch (sed_f) {
333 case f_none:
275 break; 334 break;
276 case 'p': 335 case f_replace:
277 printFlag = TRUE; 336 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
337 quietFlag);
278 break; 338 break;
279 case 'g': 339 case f_append:
340 do_sed_append(fp, appendline, quietFlag);
280 break; 341 break;
281 default:
282 usage(sed_usage);
283 }
284 } 342 }
285 }
286 cp = pos;
287 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
288 break;
289 343
290 case 'a': /* APPEND */ 344 if (ferror(fp))
291 if (strlen(cp) < 2) 345 perror(name);
292 break;
293 sed_f = f_append;
294 appendline = ++cp;
295 /* fprintf(stderr, "append '%s'\n", appendline); */
296 break;
297 }
298 346
299 stopNow = TRUE; 347 fclose(fp);
300 break; 348 }
301
302 default:
303 usage(sed_usage);
304 }
305 }
306 }
307
308 if (argc == 0) {
309 switch (sed_f) {
310 case f_none:
311 break;
312 case f_replace:
313 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
314 quietFlag);
315 break;
316 case f_append:
317 do_sed_append(stdin, appendline, quietFlag);
318 break;
319 }
320 } else {
321 while (argc-- > 0) {
322 name = *argv++;
323
324 fp = fopen(name, "r");
325 if (fp == NULL) {
326 perror(name);
327 continue;
328 }
329
330 switch (sed_f) {
331 case f_none:
332 break;
333 case f_replace:
334 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
335 quietFlag);
336 break;
337 case f_append:
338 do_sed_append(fp, appendline, quietFlag);
339 break;
340 }
341
342 if (ferror(fp))
343 perror(name);
344
345 fclose(fp);
346 } 349 }
347 } 350 exit(TRUE);
348 exit(TRUE);
349} 351}
350 352
351 353
diff --git a/sfdisk.c b/sfdisk.c
index 5dc44eacc..116a019ab 100644
--- a/sfdisk.c
+++ b/sfdisk.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * sfdisk version 3.0 - aeb - 950813 3 * sfdisk version 3.0 - aeb - 950813
3 * 4 *
@@ -39,52 +40,53 @@
39 40
40#include "internal.h" 41#include "internal.h"
41#include <stdio.h> 42#include <stdio.h>
42#include <stdlib.h> /* atoi, free */ 43#include <stdlib.h> /* atoi, free */
43#include <stdarg.h> /* varargs */ 44#include <stdarg.h> /* varargs */
44#include <unistd.h> /* read, write */ 45#include <unistd.h> /* read, write */
45#include <fcntl.h> /* O_RDWR */ 46#include <fcntl.h> /* O_RDWR */
46#include <errno.h> /* ERANGE */ 47#include <errno.h> /* ERANGE */
47#include <string.h> /* index() */ 48#include <string.h> /* index() */
48#include <ctype.h> 49#include <ctype.h>
49#include <getopt.h> 50#include <getopt.h>
50#include <sys/ioctl.h> 51#include <sys/ioctl.h>
51#include <sys/stat.h> 52#include <sys/stat.h>
52#include <linux/unistd.h> /* _syscall */ 53#include <linux/unistd.h> /* _syscall */
53#include <linux/hdreg.h> /* HDIO_GETGEO */ 54#include <linux/hdreg.h> /* HDIO_GETGEO */
54#include <linux/fs.h> /* BLKGETSIZE */ 55#include <linux/fs.h> /* BLKGETSIZE */
55 56
56 57
57static const char sfdisk_usage[] = 58static const char sfdisk_usage[] =
58"sfdisk [options] device ...\n" 59 "sfdisk [options] device ...\n"
59"device: something like /dev/hda or /dev/sda\n" 60 "device: something like /dev/hda or /dev/sda\n"
60"useful options:\n" 61 "useful options:\n"
61" -s [or --show-size]: list size of a partition\n" 62 " -s [or --show-size]: list size of a partition\n"
62" -c [or --id]: print or change partition Id\n" 63 " -c [or --id]: print or change partition Id\n"
63" -l [or --list]: list partitions of each device\n" 64 " -l [or --list]: list partitions of each device\n"
64" -d [or --dump]: idem, but in a format suitable for later input\n" 65 " -d [or --dump]: idem, but in a format suitable for later input\n"
65" -i [or --increment]: number cylinders etc. from 1 instead of from 0\n" 66 " -i [or --increment]: number cylinders etc. from 1 instead of from 0\n"
66" -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n" 67 " -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n"
67" -T [or --list-types]:list the known partition types\n" 68 " -T [or --list-types]:list the known partition types\n"
68" -D [or --DOS]: for DOS-compatibility: waste a little space\n" 69 " -D [or --DOS]: for DOS-compatibility: waste a little space\n"
69" -R [or --re-read]: make kernel reread partition table\n" 70 " -R [or --re-read]: make kernel reread partition table\n"
70" -N# : change only the partition with number #\n" 71 " -N# : change only the partition with number #\n"
71" -n : do not actually write to disk\n" 72 " -n : do not actually write to disk\n"
72" -O file : save the sectors that will be overwritten to file\n" 73 " -O file : save the sectors that will be overwritten to file\n"
73" -I file : restore these sectors again\n" 74 " -I file : restore these sectors again\n"
74" -v [or --version]: print version\n" 75 " -v [or --version]: print version\n"
75" -? [or --help]: print this message\n" 76 " -? [or --help]: print this message\n"
76"dangerous options:\n" 77 "dangerous options:\n"
77" -g [or --show-geometry]: print the kernel's idea of the geometry\n" 78 " -g [or --show-geometry]: print the kernel's idea of the geometry\n"
78" -x [or --show-extended]: also list extended partitions on output\n\n" 79 " -x [or --show-extended]: also list extended partitions on output\n\n"
79" or expect descriptors for them on input\n" 80 " or expect descriptors for them on input\n"
80" -L [or --Linux]: do not complain about things irrelevant for Linux\n" 81 " -L [or --Linux]: do not complain about things irrelevant for Linux\n"
81" -q [or --quiet]: suppress warning messages\n" 82 " -q [or --quiet]: suppress warning messages\n"
82" You can override the detected geometry using:\n" 83 " You can override the detected geometry using:\n"
83" -C# [or --cylinders #]:set the number of cylinders to use\n" 84 " -C# [or --cylinders #]:set the number of cylinders to use\n"
84" -H# [or --heads #]: set the number of heads to use\n" 85 " -H# [or --heads #]: set the number of heads to use\n"
85" -S# [or --sectors #]: set the number of sectors to use\n" 86 " -S# [or --sectors #]: set the number of sectors to use\n"
86"You can disable all consistency checking with:\n" 87
87" -f [or --force]: do what I say, even if it is stupid\n"; 88 "You can disable all consistency checking with:\n"
89 " -f [or --force]: do what I say, even if it is stupid\n";
88 90
89 91
90 92
@@ -100,14 +102,14 @@ static struct systypes i386_sys_types[] = {
100 {0x02, "XENIX root"}, 102 {0x02, "XENIX root"},
101 {0x03, "XENIX usr"}, 103 {0x03, "XENIX usr"},
102 {0x04, "FAT16 <32M"}, 104 {0x04, "FAT16 <32M"},
103 {0x05, "Extended"}, /* DOS 3.3+ extended partition */ 105 {0x05, "Extended"}, /* DOS 3.3+ extended partition */
104 {0x06, "FAT16"}, /* DOS 16-bit >=32M */ 106 {0x06, "FAT16"}, /* DOS 16-bit >=32M */
105 {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ 107 {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
106 {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */ 108 {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */
107 {0x09, "AIX bootable"}, /* AIX data or Coherent */ 109 {0x09, "AIX bootable"}, /* AIX data or Coherent */
108 {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */ 110 {0x0a, "OS/2 Boot Manager"}, /* OS/2 Boot Manager */
109 {0x0b, "Win95 FAT32"}, 111 {0x0b, "Win95 FAT32"},
110 {0x0c, "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */ 112 {0x0c, "Win95 FAT32 (LBA)"}, /* LBA really is `Extended Int 13h' */
111 {0x0e, "Win95 FAT16 (LBA)"}, 113 {0x0e, "Win95 FAT16 (LBA)"},
112 {0x0f, "Win95 Ext'd (LBA)"}, 114 {0x0f, "Win95 Ext'd (LBA)"},
113 {0x10, "OPUS"}, 115 {0x10, "OPUS"},
@@ -130,7 +132,7 @@ static struct systypes i386_sys_types[] = {
130 {0x4f, "QNX4.x 3rd part"}, 132 {0x4f, "QNX4.x 3rd part"},
131 {0x50, "OnTrack DM"}, 133 {0x50, "OnTrack DM"},
132 {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */ 134 {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */
133 {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */ 135 {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */
134 {0x53, "OnTrack DM6 Aux3"}, 136 {0x53, "OnTrack DM6 Aux3"},
135 {0x54, "OnTrackDM6"}, 137 {0x54, "OnTrackDM6"},
136 {0x55, "EZ-Drive"}, 138 {0x55, "EZ-Drive"},
@@ -142,16 +144,16 @@ static struct systypes i386_sys_types[] = {
142 {0x65, "Novell Netware 386"}, 144 {0x65, "Novell Netware 386"},
143 {0x70, "DiskSecure Multi-Boot"}, 145 {0x70, "DiskSecure Multi-Boot"},
144 {0x75, "PC/IX"}, 146 {0x75, "PC/IX"},
145 {0x80, "Old Minix"}, /* Minix 1.4a and earlier */ 147 {0x80, "Old Minix"}, /* Minix 1.4a and earlier */
146 {0x81, "Minix / old Linux"},/* Minix 1.4b and later */ 148 {0x81, "Minix / old Linux"}, /* Minix 1.4b and later */
147 {0x82, "Linux swap"}, /* also Solaris */ 149 {0x82, "Linux swap"}, /* also Solaris */
148 {0x83, "Linux"}, 150 {0x83, "Linux"},
149 {0x84, "OS/2 hidden C: drive"}, 151 {0x84, "OS/2 hidden C: drive"},
150 {0x85, "Linux extended"}, 152 {0x85, "Linux extended"},
151 {0x86, "NTFS volume set"}, 153 {0x86, "NTFS volume set"},
152 {0x87, "NTFS volume set"}, 154 {0x87, "NTFS volume set"},
153 {0x93, "Amoeba"}, 155 {0x93, "Amoeba"},
154 {0x94, "Amoeba BBT"}, /* (bad block table) */ 156 {0x94, "Amoeba BBT"}, /* (bad block table) */
155 {0xa0, "IBM Thinkpad hibernation"}, 157 {0xa0, "IBM Thinkpad hibernation"},
156 {0xa5, "BSD/386"}, 158 {0xa5, "BSD/386"},
157 {0xa6, "OpenBSD"}, 159 {0xa6, "OpenBSD"},
@@ -162,19 +164,19 @@ static struct systypes i386_sys_types[] = {
162 {0xc4, "DRDOS/sec (FAT-16 < 32M)"}, 164 {0xc4, "DRDOS/sec (FAT-16 < 32M)"},
163 {0xc6, "DRDOS/sec (FAT-16)"}, 165 {0xc6, "DRDOS/sec (FAT-16)"},
164 {0xc7, "Syrinx"}, 166 {0xc7, "Syrinx"},
165 {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ 167 {0xdb, "CP/M / CTOS / ..."}, /* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
166 {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */ 168 {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */
167 {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */ 169 {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */
168 {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ 170 {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
169 {0xeb, "BeOS fs"}, 171 {0xeb, "BeOS fs"},
170 {0xf1, "SpeedStor"}, 172 {0xf1, "SpeedStor"},
171 {0xf4, "SpeedStor"}, /* SpeedStor large partition */ 173 {0xf4, "SpeedStor"}, /* SpeedStor large partition */
172 {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */ 174 {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */
173 {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with autodetect 175 {0xfd, "Linux raid autodetect"}, /* New (2.2.x) raid partition with autodetect
174 using persistent superblock */ 176 using persistent superblock */
175 {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */ 177 {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
176 {0xff, "BBT"}, /* Xenix Bad Block Table */ 178 {0xff, "BBT"}, /* Xenix Bad Block Table */
177 { 0, 0 } 179 {0, 0}
178}; 180};
179 181
180#define SIZE(a) (sizeof(a)/sizeof(a[0])) 182#define SIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -193,51 +195,51 @@ static struct systypes i386_sys_types[] = {
193 */ 195 */
194static int exit_status = 0; 196static int exit_status = 0;
195 197
196static int force = 0; /* 1: do what I say, even if it is stupid ... */ 198static int force = 0; /* 1: do what I say, even if it is stupid ... */
197static int quiet = 0; /* 1: suppress all warnings */ 199static int quiet = 0; /* 1: suppress all warnings */
198static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */ 200static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */
199static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */ 201static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */
200static int dump = 0; /* 1: list in a format suitable for later input */ 202static int dump = 0; /* 1: list in a format suitable for later input */
201static int verify = 0; /* 1: check that listed partition is reasonable */ 203static int verify = 0; /* 1: check that listed partition is reasonable */
202static int no_write = 0; /* 1: do not actually write to disk */ 204static int no_write = 0; /* 1: do not actually write to disk */
203static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */ 205static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */
204static int leave_last = 0; /* 1: don't allocate the last cylinder */ 206static int leave_last = 0; /* 1: don't allocate the last cylinder */
205static int opt_list = 0; 207static int opt_list = 0;
206static char *save_sector_file = NULL; 208static char *save_sector_file = NULL;
207static char *restore_sector_file = NULL; 209static char *restore_sector_file = NULL;
208 210
209static void 211static void warn(char *s, ...)
210warn(char *s, ...) { 212{
211 va_list p; 213 va_list p;
212 214
213 va_start(p, s); 215 va_start(p, s);
214 fflush(stdout); 216 fflush(stdout);
215 if (!quiet) 217 if (!quiet)
216 vfprintf (stderr, s, p); 218 vfprintf(stderr, s, p);
217 va_end(p); 219 va_end(p);
218} 220}
219 221
220static void 222static void error(char *s, ...)
221error(char *s, ...) { 223{
222 va_list p; 224 va_list p;
223 225
224 va_start(p, s); 226 va_start(p, s);
225 fflush(stdout); 227 fflush(stdout);
226 fprintf(stderr, "\n" PROGNAME ": "); 228 fprintf(stderr, "\n" PROGNAME ": ");
227 vfprintf(stderr, s, p); 229 vfprintf(stderr, s, p);
228 va_end(p); 230 va_end(p);
229} 231}
230 232
231static void 233static void fatal(char *s, ...)
232fatal(char *s, ...) { 234{
233 va_list p; 235 va_list p;
234 236
235 va_start(p, s); 237 va_start(p, s);
236 fflush(stdout); 238 fflush(stdout);
237 fprintf(stderr, "\n" PROGNAME ": "); 239 fprintf(stderr, "\n" PROGNAME ": ");
238 vfprintf(stderr, s, p); 240 vfprintf(stderr, s, p);
239 va_end(p); 241 va_end(p);
240 exit(1); 242 exit(1);
241} 243}
242 244
243/* 245/*
@@ -254,33 +256,34 @@ fatal(char *s, ...) {
254 */ 256 */
255#ifndef __alpha__ 257#ifndef __alpha__
256static 258static
257_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, 259_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
258 loff_t *, res, uint, wh); 260 loff_t *, res, uint, wh);
259#endif 261#endif
260 262
261static int 263static int sseek(char *dev, unsigned int fd, unsigned long s)
262sseek(char *dev, unsigned int fd, unsigned long s) { 264{
263 loff_t in, out; 265 loff_t in, out;
264 in = ((loff_t) s << 9); 266
265 out = 1; 267 in = ((loff_t) s << 9);
268 out = 1;
266 269
267#ifndef __alpha__ 270#ifndef __alpha__
268 if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) { 271 if (_llseek(fd, in >> 32, in & 0xffffffff, &out, SEEK_SET) != 0) {
269#else 272#else
270 if ((out = lseek(fd, in, SEEK_SET)) != in) { 273 if ((out = lseek(fd, in, SEEK_SET)) != in) {
271#endif 274#endif
272 perror("llseek"); 275 perror("llseek");
273 error("seek error on %s - cannot seek to %lu\n", dev, s); 276 error("seek error on %s - cannot seek to %lu\n", dev, s);
274 return 0; 277 return 0;
275 } 278 }
276 279
277 if (in != out) { 280 if (in != out) {
278 error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", 281 error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n",
279 (uint)(in>>32), (uint)(in & 0xffffffff), 282 (uint) (in >> 32), (uint) (in & 0xffffffff),
280 (uint)(out>>32), (uint)(out & 0xffffffff)); 283 (uint) (out >> 32), (uint) (out & 0xffffffff));
281 return 0; 284 return 0;
282 } 285 }
283 return 1; 286 return 1;
284} 287}
285 288
286/* 289/*
@@ -292,196 +295,196 @@ sseek(char *dev, unsigned int fd, unsigned long s) {
292 * have to be modified and written back. 295 * have to be modified and written back.
293 */ 296 */
294struct sector { 297struct sector {
295 struct sector *next; 298 struct sector *next;
296 unsigned long sectornumber; 299 unsigned long sectornumber;
297 int to_be_written; 300 int to_be_written;
298 char data[512]; 301 char data[512];
299} *sectorhead; 302} *sectorhead;
300 303
301static void 304static void free_sectors(void)
302free_sectors(void) { 305{
303 struct sector *s; 306 struct sector *s;
304 307
305 while (sectorhead) { 308 while (sectorhead) {
306 s = sectorhead; 309 s = sectorhead;
307 sectorhead = s->next; 310 sectorhead = s->next;
308 free(s); 311 free(s);
309 } 312 }
310} 313}
311 314
312static struct sector * 315static struct sector *get_sector(char *dev, int fd, unsigned long sno)
313get_sector(char *dev, int fd, unsigned long sno) { 316{
314 struct sector *s; 317 struct sector *s;
315
316 for(s = sectorhead; s; s = s->next)
317 if(s->sectornumber == sno)
318 return s;
319 318
320 if (!sseek(dev, fd, sno)) 319 for (s = sectorhead; s; s = s->next)
321 return 0; 320 if (s->sectornumber == sno)
321 return s;
322 322
323 if (!(s = (struct sector *) malloc(sizeof(struct sector)))) 323 if (!sseek(dev, fd, sno))
324 fatal("out of memory - giving up\n"); 324 return 0;
325 325
326 if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { 326 if (!(s = (struct sector *) malloc(sizeof(struct sector))))
327 perror("read"); 327 fatal("out of memory - giving up\n");
328 error("read error on %s - cannot read sector %lu\n", dev, sno);
329 free(s);
330 return 0;
331 }
332 328
333 s->next = sectorhead; 329 if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
334 sectorhead = s; 330 perror("read");
335 s->sectornumber = sno; 331 error("read error on %s - cannot read sector %lu\n", dev, sno);
336 s->to_be_written = 0; 332 free(s);
333 return 0;
334 }
337 335
338 return s; 336 s->next = sectorhead;
339} 337 sectorhead = s;
338 s->sectornumber = sno;
339 s->to_be_written = 0;
340 340
341static int 341 return s;
342msdos_signature (struct sector *s) {
343 if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) {
344 error("ERROR: sector %lu does not have an msdos signature\n",
345 s->sectornumber);
346 return 0;
347 }
348 return 1;
349} 342}
350 343
351static int 344static int msdos_signature(struct sector *s)
352write_sectors(char *dev, int fd) { 345{
353 struct sector *s; 346 if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) {
354 347 error("ERROR: sector %lu does not have an msdos signature\n",
355 for (s = sectorhead; s; s = s->next) 348 s->sectornumber);
356 if (s->to_be_written) {
357 if (!sseek(dev, fd, s->sectornumber))
358 return 0; 349 return 0;
359 if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
360 perror("write");
361 error("write error on %s - cannot write sector %lu\n",
362 dev, s->sectornumber);
363 return 0;
364 }
365 s->to_be_written = 0;
366 } 350 }
367 return 1; 351 return 1;
368} 352}
369 353
370static void 354static int write_sectors(char *dev, int fd)
371ulong_to_chars(unsigned long u, char *uu) { 355{
372 int i; 356 struct sector *s;
373 357
374 for(i=0; i<4; i++) { 358 for (s = sectorhead; s; s = s->next)
375 uu[i] = (u & 0xff); 359 if (s->to_be_written) {
376 u >>= 8; 360 if (!sseek(dev, fd, s->sectornumber))
377 } 361 return 0;
362 if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
363 perror("write");
364 error("write error on %s - cannot write sector %lu\n",
365 dev, s->sectornumber);
366 return 0;
367 }
368 s->to_be_written = 0;
369 }
370 return 1;
378} 371}
379 372
380static unsigned long 373static void ulong_to_chars(unsigned long u, char *uu)
381chars_to_ulong(unsigned char *uu) { 374{
382 int i; 375 int i;
383 unsigned long u = 0;
384 376
385 for(i=3; i>=0; i--) 377 for (i = 0; i < 4; i++) {
386 u = (u << 8) | uu[i]; 378 uu[i] = (u & 0xff);
387 return u; 379 u >>= 8;
380 }
388} 381}
389 382
390static int 383static unsigned long chars_to_ulong(unsigned char *uu)
391save_sectors(char *dev, int fdin) { 384{
392 struct sector *s; 385 int i;
393 char ss[516]; 386 unsigned long u = 0;
394 int fdout;
395
396 fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);
397 if (fdout < 0) {
398 perror(save_sector_file);
399 error("cannot open partition sector save file (%s)\n",
400 save_sector_file);
401 return 0;
402 }
403 387
404 for (s = sectorhead; s; s = s->next) 388 for (i = 3; i >= 0; i--)
405 if (s->to_be_written) { 389 u = (u << 8) | uu[i];
406 ulong_to_chars(s->sectornumber, ss); 390 return u;
407 if (!sseek(dev, fdin, s->sectornumber)) 391}
408 return 0; 392
409 if (read(fdin, ss+4, 512) != 512) { 393static int save_sectors(char *dev, int fdin)
410 perror("read"); 394{
411 error("read error on %s - cannot read sector %lu\n", 395 struct sector *s;
412 dev, s->sectornumber); 396 char ss[516];
413 return 0; 397 int fdout;
414 } 398
415 if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) { 399 fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);
416 perror("write"); 400 if (fdout < 0) {
417 error("write error on %s\n"), save_sector_file; 401 perror(save_sector_file);
402 error("cannot open partition sector save file (%s)\n",
403 save_sector_file);
418 return 0; 404 return 0;
419 }
420 } 405 }
421 return 1; 406
407 for (s = sectorhead; s; s = s->next)
408 if (s->to_be_written) {
409 ulong_to_chars(s->sectornumber, ss);
410 if (!sseek(dev, fdin, s->sectornumber))
411 return 0;
412 if (read(fdin, ss + 4, 512) != 512) {
413 perror("read");
414 error("read error on %s - cannot read sector %lu\n",
415 dev, s->sectornumber);
416 return 0;
417 }
418 if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) {
419 perror("write");
420 error("write error on %s\n"), save_sector_file;
421 return 0;
422 }
423 }
424 return 1;
422} 425}
423 426
424static void reread_disk_partition(char *dev, int fd); 427static void reread_disk_partition(char *dev, int fd);
425 428
426static int 429static int restore_sectors(char *dev)
427restore_sectors(char *dev) { 430{
428 int fdin, fdout, ct; 431 int fdin, fdout, ct;
429 struct stat statbuf; 432 struct stat statbuf;
430 char *ss0, *ss; 433 char *ss0, *ss;
431 unsigned long sno; 434 unsigned long sno;
432 435
433 if (stat(restore_sector_file, &statbuf) < 0) { 436 if (stat(restore_sector_file, &statbuf) < 0) {
434 perror(restore_sector_file); 437 perror(restore_sector_file);
435 error("cannot stat partition restore file (%s)\n", 438 error("cannot stat partition restore file (%s)\n",
436 restore_sector_file); 439 restore_sector_file);
437 return 0; 440 return 0;
438 } 441 }
439 if (statbuf.st_size % 516) { 442 if (statbuf.st_size % 516) {
440 error("partition restore file has wrong size - not restoring\n"); 443 error("partition restore file has wrong size - not restoring\n");
441 return 0; 444 return 0;
442 } 445 }
443 if (!(ss = (char *) malloc(statbuf.st_size))) { 446 if (!(ss = (char *) malloc(statbuf.st_size))) {
444 error("out of memory?\n"); 447 error("out of memory?\n");
445 return 0; 448 return 0;
446 } 449 }
447 fdin = open(restore_sector_file, O_RDONLY); 450 fdin = open(restore_sector_file, O_RDONLY);
448 if (fdin < 0) { 451 if (fdin < 0) {
449 perror(restore_sector_file); 452 perror(restore_sector_file);
450 error("cannot open partition restore file (%s)\n", 453 error("cannot open partition restore file (%s)\n",
451 restore_sector_file); 454 restore_sector_file);
452 return 0; 455 return 0;
453 } 456 }
454 if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) { 457 if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) {
455 perror("read"); 458 perror("read");
456 error("error reading %s\n"), restore_sector_file; 459 error("error reading %s\n"), restore_sector_file;
457 return 0; 460 return 0;
458 } 461 }
459 462
460 fdout = open(dev, O_WRONLY); 463 fdout = open(dev, O_WRONLY);
461 if (fdout < 0) { 464 if (fdout < 0) {
462 perror(dev); 465 perror(dev);
463 error("cannot open device %s for writing\n"), dev; 466 error("cannot open device %s for writing\n"), dev;
464 return 0; 467 return 0;
465 } 468 }
466 469
467 ss0 = ss; 470 ss0 = ss;
468 ct = statbuf.st_size/516; 471 ct = statbuf.st_size / 516;
469 while(ct--) { 472 while (ct--) {
470 sno = chars_to_ulong(ss); 473 sno = chars_to_ulong(ss);
471 if (!sseek(dev, fdout, sno)) 474 if (!sseek(dev, fdout, sno))
472 return 0; 475 return 0;
473 if (write(fdout, ss+4, 512) != 512) { 476 if (write(fdout, ss + 4, 512) != 512) {
474 perror(dev); 477 perror(dev);
475 error("error writing sector %lu on %s\n", sno, dev); 478 error("error writing sector %lu on %s\n", sno, dev);
476 return 0; 479 return 0;
480 }
481 ss += 516;
477 } 482 }
478 ss += 516; 483 free(ss0);
479 }
480 free(ss0);
481 484
482 reread_disk_partition(dev, fdout); 485 reread_disk_partition(dev, fdout);
483 486
484 return 1; 487 return 1;
485} 488}
486 489
487/* 490/*
@@ -511,105 +514,111 @@ struct geometry {
511 unsigned long heads, sectors, cylinders; 514 unsigned long heads, sectors, cylinders;
512} B, F, U; 515} B, F, U;
513 516
514static void 517static void get_cylindersize(char *dev, int fd, int silent)
515get_cylindersize(char *dev, int fd, int silent) { 518{
516 struct hd_geometry g; 519 struct hd_geometry g;
517 int ioctl_ok = 0; 520 int ioctl_ok = 0;
518 521
519 B.heads = B.sectors = B.cylinders = 0; 522 B.heads = B.sectors = B.cylinders = 0;
520 523
521 if (!ioctl(fd, HDIO_GETGEO, &g)) { 524 if (!ioctl(fd, HDIO_GETGEO, &g)) {
522 ioctl_ok = 1; 525 ioctl_ok = 1;
523 526
524 B.heads = g.heads; 527 B.heads = g.heads;
525 B.sectors = g.sectors; 528 B.sectors = g.sectors;
526 B.cylinders = g.cylinders; 529 B.cylinders = g.cylinders;
527 } 530 }
528 531
529 if (U.heads) 532 if (U.heads)
530 B.heads = U.heads; 533 B.heads = U.heads;
531 if (U.sectors) 534 if (U.sectors)
532 B.sectors = U.sectors; 535 B.sectors = U.sectors;
533 if (U.cylinders) 536 if (U.cylinders)
534 B.cylinders = U.cylinders; 537 B.cylinders = U.cylinders;
535 538
536 B.cylindersize = B.heads * B.sectors; 539 B.cylindersize = B.heads * B.sectors;
537 540
538 if (ioctl_ok) { 541 if (ioctl_ok) {
539 if (g.start && !force) { 542 if (g.start && !force) {
540 warn( 543 warn
541 "Warning: start=%d - this looks like a partition rather than\n" 544 ("Warning: start=%d - this looks like a partition rather than\n"
542 "the entire disk. Using fdisk on it is probably meaningless.\n" 545 "the entire disk. Using fdisk on it is probably meaningless.\n"
543 "[Use the --force option if you really want this]\n", g.start); 546 "[Use the --force option if you really want this]\n",
544 exit(1); 547 g.start);
545 } 548 exit(1);
546 if (B.heads != g.heads) 549 }
547 warn("Warning: HDIO_GETGEO says that there are %d heads\n", 550 if (B.heads != g.heads)
548 g.heads); 551 warn("Warning: HDIO_GETGEO says that there are %d heads\n",
549 if (B.sectors != g.sectors) 552 g.heads);
550 warn("Warning: HDIO_GETGEO says that there are %d sectors\n", 553 if (B.sectors != g.sectors)
551 g.sectors); 554 warn("Warning: HDIO_GETGEO says that there are %d sectors\n",
552 if (B.cylinders != g.cylinders) 555 g.sectors);
553 warn("Warning: HDIO_GETGEO says that there are %d cylinders\n", 556 if (B.cylinders != g.cylinders)
554 g.cylinders); 557 warn("Warning: HDIO_GETGEO says that there are %d cylinders\n",
555 } else if (!silent) 558 g.cylinders);
556 if (!B.heads || !B.sectors || !B.cylinders) 559 } else if (!silent)
557 printf("Disk %s: cannot get geometry\n", dev); 560 if (!B.heads || !B.sectors || !B.cylinders)
558 if (B.sectors > 63) 561 printf("Disk %s: cannot get geometry\n", dev);
559 warn("Warning: unlikely number of sectors (%d - usually at most 63\n" 562 if (B.sectors > 63)
560 "This will give problems with all software that uses C/H/S addressing.\n", 563 warn
561 B.sectors); 564 ("Warning: unlikely number of sectors (%d - usually at most 63\n"
562 if (!silent) 565 "This will give problems with all software that uses C/H/S addressing.\n",
563 printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n", 566 B.sectors);
564 dev, B.cylinders, B.heads, B.sectors); 567 if (!silent)
565} 568 printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n",
566 569 dev, B.cylinders, B.heads, B.sectors);
567typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */ 570}
568static chs zero_chs = { 0,0,0 }; 571
569 572typedef struct {
570typedef struct { unsigned long h,s,c; } longchs; 573 unsigned char h, s, c;
574} chs; /* has some c bits in s */
575static chs zero_chs = { 0, 0, 0 };
576
577typedef struct {
578 unsigned long h, s, c;
579} longchs;
571static longchs zero_longchs; 580static longchs zero_longchs;
572 581
573static chs 582static chs longchs_to_chs(longchs aa, struct geometry G)
574longchs_to_chs (longchs aa, struct geometry G) { 583{
575 chs a; 584 chs a;
576 585
577 if (aa.h < 256 && aa.s < 64 && aa.c < 1024) { 586 if (aa.h < 256 && aa.s < 64 && aa.c < 1024) {
578 a.h = aa.h; 587 a.h = aa.h;
579 a.s = aa.s | ((aa.c >> 2) & 0xc0); 588 a.s = aa.s | ((aa.c >> 2) & 0xc0);
580 a.c = (aa.c & 0xff); 589 a.c = (aa.c & 0xff);
581 } else if (G.heads && G.sectors) { 590 } else if (G.heads && G.sectors) {
582 a.h = G.heads - 1; 591 a.h = G.heads - 1;
583 a.s = G.sectors | 0xc0; 592 a.s = G.sectors | 0xc0;
584 a.c = 0xff; 593 a.c = 0xff;
585 } else 594 } else
586 a = zero_chs; 595 a = zero_chs;
587 return a; 596 return a;
588} 597}
589 598
590static longchs 599static longchs chs_to_longchs(chs a)
591chs_to_longchs (chs a) { 600{
592 longchs aa; 601 longchs aa;
593 602
594 aa.h = a.h; 603 aa.h = a.h;
595 aa.s = (a.s & 0x3f); 604 aa.s = (a.s & 0x3f);
596 aa.c = (a.s & 0xc0); 605 aa.c = (a.s & 0xc0);
597 aa.c = (aa.c << 2) + a.c; 606 aa.c = (aa.c << 2) + a.c;
598 return aa;
599}
600
601static longchs
602ulong_to_longchs (unsigned long sno, struct geometry G) {
603 longchs aa;
604
605 if (G.heads && G.sectors && G.cylindersize) {
606 aa.s = 1 + sno % G.sectors;
607 aa.h = (sno / G.sectors) % G.heads;
608 aa.c = sno / G.cylindersize;
609 return aa; 607 return aa;
610 } else { 608}
611 return zero_longchs; 609
612 } 610static longchs ulong_to_longchs(unsigned long sno, struct geometry G)
611{
612 longchs aa;
613
614 if (G.heads && G.sectors && G.cylindersize) {
615 aa.s = 1 + sno % G.sectors;
616 aa.h = (sno / G.sectors) % G.heads;
617 aa.c = sno / G.cylindersize;
618 return aa;
619 } else {
620 return zero_longchs;
621 }
613} 622}
614 623
615//static unsigned long 624//static unsigned long
@@ -617,9 +626,9 @@ ulong_to_longchs (unsigned long sno, struct geometry G) {
617// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1); 626// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1);
618//} 627//}
619 628
620static chs 629static chs ulong_to_chs(unsigned long sno, struct geometry G)
621ulong_to_chs (unsigned long sno, struct geometry G) { 630{
622 return longchs_to_chs(ulong_to_longchs(sno, G), G); 631 return longchs_to_chs(ulong_to_longchs(sno, G), G);
623} 632}
624 633
625//static unsigned long 634//static unsigned long
@@ -627,34 +636,34 @@ ulong_to_chs (unsigned long sno, struct geometry G) {
627// return longchs_to_ulong(chs_to_longchs(a), G); 636// return longchs_to_ulong(chs_to_longchs(a), G);
628//} 637//}
629 638
630static int 639static int is_equal_chs(chs a, chs b)
631is_equal_chs (chs a, chs b) { 640{
632 return (a.h == b.h && a.s == b.s && a.c == b.c); 641 return (a.h == b.h && a.s == b.s && a.c == b.c);
633} 642}
634 643
635static int 644static int chs_ok(chs a, char *v, char *w)
636chs_ok (chs a, char *v, char *w) { 645{
637 longchs aa = chs_to_longchs(a); 646 longchs aa = chs_to_longchs(a);
638 int ret = 1; 647 int ret = 1;
639 648
640 if (is_equal_chs(a, zero_chs)) 649 if (is_equal_chs(a, zero_chs))
641 return 1; 650 return 1;
642 if (B.heads && aa.h >= B.heads) { 651 if (B.heads && aa.h >= B.heads) {
643 warn("%s of partition %s has impossible value for head: " 652 warn("%s of partition %s has impossible value for head: "
644 "%d (should be in 0-%d)\n", w, v, aa.h, B.heads-1); 653 "%d (should be in 0-%d)\n", w, v, aa.h, B.heads - 1);
645 ret = 0; 654 ret = 0;
646 } 655 }
647 if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { 656 if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) {
648 warn("%s of partition %s has impossible value for sector: " 657 warn("%s of partition %s has impossible value for sector: "
649 "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors); 658 "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors);
650 ret = 0; 659 ret = 0;
651 } 660 }
652 if (B.cylinders && aa.c >= B.cylinders) { 661 if (B.cylinders && aa.c >= B.cylinders) {
653 warn("%s of partition %s has impossible value for cylinders: " 662 warn("%s of partition %s has impossible value for cylinders: "
654 "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders-1); 663 "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders - 1);
655 ret = 0; 664 ret = 0;
656 } 665 }
657 return ret; 666 return ret;
658} 667}
659 668
660/* 669/*
@@ -675,34 +684,33 @@ chs_ok (chs a, char *v, char *w) {
675 684
676/* List of partition types now in i386_sys_types.c */ 685/* List of partition types now in i386_sys_types.c */
677 686
678static const char * 687static const char *sysname(unsigned char type)
679sysname(unsigned char type) { 688{
680 struct systypes *s; 689 struct systypes *s;
681 690
682 for (s = i386_sys_types; s->name; s++) 691 for (s = i386_sys_types; s->name; s++)
683 if (s->type == type) 692 if (s->type == type)
684 return s->name; 693 return s->name;
685 return "Unknown"; 694 return "Unknown";
686} 695}
687 696
688static void 697static void list_types(void)
689list_types(void) { 698{
690 struct systypes *s; 699 struct systypes *s;
691 700
692 printf("Id Name\n\n"); 701 printf("Id Name\n\n");
693 for (s = i386_sys_types; s->name; s++) 702 for (s = i386_sys_types; s->name; s++)
694 printf("%2x %s\n", s->type, s->name); 703 printf("%2x %s\n", s->type, s->name);
695} 704}
696 705
697static int 706static int is_extended(unsigned char type)
698is_extended(unsigned char type) { 707{
699 return (type == EXTENDED_PARTITION 708 return (type == EXTENDED_PARTITION
700 || type == LINUX_EXTENDED 709 || type == LINUX_EXTENDED || type == WIN98_EXTENDED);
701 || type == WIN98_EXTENDED);
702} 710}
703 711
704static int 712static int is_bsd(unsigned char type)
705is_bsd(unsigned char type) { 713{
706 return (type == BSD_PARTITION); 714 return (type == BSD_PARTITION);
707} 715}
708 716
@@ -713,61 +721,64 @@ is_bsd(unsigned char type) {
713/* MS/DOS partition */ 721/* MS/DOS partition */
714 722
715struct partition { 723struct partition {
716 unsigned char bootable; /* 0 or 0x80 */ 724 unsigned char bootable; /* 0 or 0x80 */
717 chs begin_chs; 725 chs begin_chs;
718 unsigned char sys_type; 726 unsigned char sys_type;
719 chs end_chs; 727 chs end_chs;
720 unsigned int start_sect; /* starting sector counting from 0 */ 728 unsigned int start_sect; /* starting sector counting from 0 */
721 unsigned int nr_sects; /* nr of sectors in partition */ 729 unsigned int nr_sects; /* nr of sectors in partition */
722}; 730};
723 731
724/* Unfortunately, partitions are not aligned, and non-Intel machines 732/* Unfortunately, partitions are not aligned, and non-Intel machines
725 are unhappy with non-aligned integers. So, we need a copy by hand. */ 733 are unhappy with non-aligned integers. So, we need a copy by hand. */
726static int 734static int copy_to_int(unsigned char *cp)
727copy_to_int(unsigned char *cp) { 735{
728 unsigned int m; 736 unsigned int m;
729 737
730 m = *cp++; 738 m = *cp++;
731 m += (*cp++ << 8); 739 m += (*cp++ << 8);
732 m += (*cp++ << 16); 740 m += (*cp++ << 16);
733 m += (*cp++ << 24); 741 m += (*cp++ << 24);
734 return m; 742 return m;
735} 743}
736 744
737static void 745static void copy_from_int(int m, char *cp)
738copy_from_int(int m, char *cp) { 746{
739 *cp++ = (m & 0xff); m >>= 8; 747 *cp++ = (m & 0xff);
740 *cp++ = (m & 0xff); m >>= 8; 748 m >>= 8;
741 *cp++ = (m & 0xff); m >>= 8; 749 *cp++ = (m & 0xff);
742 *cp++ = (m & 0xff); 750 m >>= 8;
743} 751 *cp++ = (m & 0xff);
744 752 m >>= 8;
745static void 753 *cp++ = (m & 0xff);
746copy_to_part(char *cp, struct partition *p) { 754}
747 p->bootable = *cp++; 755
748 p->begin_chs.h = *cp++; 756static void copy_to_part(char *cp, struct partition *p)
749 p->begin_chs.s = *cp++; 757{
750 p->begin_chs.c = *cp++; 758 p->bootable = *cp++;
751 p->sys_type = *cp++; 759 p->begin_chs.h = *cp++;
752 p->end_chs.h = *cp++; 760 p->begin_chs.s = *cp++;
753 p->end_chs.s = *cp++; 761 p->begin_chs.c = *cp++;
754 p->end_chs.c = *cp++; 762 p->sys_type = *cp++;
755 p->start_sect = copy_to_int(cp); 763 p->end_chs.h = *cp++;
756 p->nr_sects = copy_to_int(cp+4); 764 p->end_chs.s = *cp++;
757} 765 p->end_chs.c = *cp++;
758 766 p->start_sect = copy_to_int(cp);
759static void 767 p->nr_sects = copy_to_int(cp + 4);
760copy_from_part(struct partition *p, char *cp) { 768}
761 *cp++ = p->bootable; 769
762 *cp++ = p->begin_chs.h; 770static void copy_from_part(struct partition *p, char *cp)
763 *cp++ = p->begin_chs.s; 771{
764 *cp++ = p->begin_chs.c; 772 *cp++ = p->bootable;
765 *cp++ = p->sys_type; 773 *cp++ = p->begin_chs.h;
766 *cp++ = p->end_chs.h; 774 *cp++ = p->begin_chs.s;
767 *cp++ = p->end_chs.s; 775 *cp++ = p->begin_chs.c;
768 *cp++ = p->end_chs.c; 776 *cp++ = p->sys_type;
769 copy_from_int(p->start_sect, cp); 777 *cp++ = p->end_chs.h;
770 copy_from_int(p->nr_sects, cp+4); 778 *cp++ = p->end_chs.s;
779 *cp++ = p->end_chs.c;
780 copy_from_int(p->start_sect, cp);
781 copy_from_int(p->nr_sects, cp + 4);
771} 782}
772 783
773/* Roughly speaking, Linux doesn't use any of the above fields except 784/* Roughly speaking, Linux doesn't use any of the above fields except
@@ -777,122 +788,125 @@ copy_from_part(struct partition *p, char *cp) {
777 for equality with EXTENDED_PARTITION (and these Disk Manager types). */ 788 for equality with EXTENDED_PARTITION (and these Disk Manager types). */
778 789
779struct part_desc { 790struct part_desc {
780 unsigned long start; 791 unsigned long start;
781 unsigned long size; 792 unsigned long size;
782 unsigned long sector, offset; /* disk location of this info */ 793 unsigned long sector, offset; /* disk location of this info */
783 struct partition p; 794 struct partition p;
784 struct part_desc *ep; /* extended partition containing this one */ 795 struct part_desc *ep; /* extended partition containing this one */
785 int ptype; 796 int ptype;
786#define DOS_TYPE 0 797#define DOS_TYPE 0
787#define BSD_TYPE 1 798#define BSD_TYPE 1
788} zero_part_desc; 799} zero_part_desc;
789 800
790struct part_desc * 801struct part_desc *outer_extended_partition(struct part_desc *p)
791outer_extended_partition(struct part_desc *p) { 802{
792 while (p->ep) 803 while (p->ep)
793 p = p->ep; 804 p = p->ep;
794 return p; 805 return p;
795} 806}
796 807
797static int 808static int is_parent(struct part_desc *pp, struct part_desc *p)
798is_parent(struct part_desc *pp, struct part_desc *p) { 809{
799 while (p) { 810 while (p) {
800 if (pp == p) 811 if (pp == p)
801 return 1; 812 return 1;
802 p = p->ep; 813 p = p->ep;
803 } 814 }
804 return 0; 815 return 0;
805} 816}
806 817
807struct disk_desc { 818struct disk_desc {
808 struct part_desc partitions[128]; 819 struct part_desc partitions[128];
809 int partno; 820 int partno;
810} oldp, newp; 821} oldp, newp;
811 822
812/* determine where on the disk this information goes */ 823/* determine where on the disk this information goes */
813static void 824static void add_sector_and_offset(struct disk_desc *z)
814add_sector_and_offset(struct disk_desc *z) { 825{
815 int pno; 826 int pno;
816 struct part_desc *p; 827 struct part_desc *p;
828
829 for (pno = 0; pno < z->partno; pno++) {
830 p = &(z->partitions[pno]);
831 p->offset = 0x1be + (pno % 4) * sizeof(struct partition);
817 832
818 for (pno = 0; pno < z->partno; pno++) { 833 p->sector = (p->ep ? p->ep->start : 0);
819 p = &(z->partitions[pno]); 834 }
820 p->offset = 0x1be + (pno%4)*sizeof(struct partition);
821 p->sector = (p->ep ? p->ep->start : 0);
822 }
823} 835}
824 836
825/* tell the kernel to reread the partition tables */ 837/* tell the kernel to reread the partition tables */
826static int 838static int reread_ioctl(int fd)
827reread_ioctl(int fd) { 839{
828 if(ioctl(fd, BLKRRPART)) { 840 if (ioctl(fd, BLKRRPART)) {
829 perror("BLKRRPART"); 841 perror("BLKRRPART");
830 return -1; 842 return -1;
831 } 843 }
832 return 0; 844 return 0;
833} 845}
834 846
835static int 847static int is_blockdev(int fd)
836is_blockdev(int fd) { 848{
837 struct stat statbuf; 849 struct stat statbuf;
838 850
839 return(fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)); 851 return (fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode));
840} 852}
841 853
842/* reread after writing */ 854/* reread after writing */
843static void 855static void reread_disk_partition(char *dev, int fd)
844reread_disk_partition(char *dev, int fd) { 856{
845 printf("Re-reading the partition table ...\n"); 857 printf("Re-reading the partition table ...\n");
846 fflush(stdout); 858 fflush(stdout);
847 sync(); 859 sync();
848 sleep(3); /* superfluous since 1.3.20 */ 860 sleep(3); /* superfluous since 1.3.20 */
849 861
850 if(reread_ioctl(fd) && is_blockdev(fd)) 862 if (reread_ioctl(fd) && is_blockdev(fd))
851 printf("The command to re-read the partition table failed\n" 863 printf("The command to re-read the partition table failed\n"
852 "Reboot your system now, before using mkfs\n"); 864 "Reboot your system now, before using mkfs\n");
853 865
854 if (close(fd)) { 866 if (close(fd)) {
855 perror(dev); 867 perror(dev);
856 printf("Error closing %s\n", dev); 868 printf("Error closing %s\n", dev);
857 } 869 }
858 printf("\n"); 870 printf("\n");
859} 871}
860 872
861/* find Linux name of this partition, assuming that it will have a name */ 873/* find Linux name of this partition, assuming that it will have a name */
862static int 874static int index_to_linux(int pno, struct disk_desc *z)
863index_to_linux(int pno, struct disk_desc *z) { 875{
864 int i, ct = 1; 876 int i, ct = 1;
865 struct part_desc *p = &(z->partitions[0]); 877 struct part_desc *p = &(z->partitions[0]);
866 for (i=0; i<pno; i++,p++) 878
867 if(i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) 879 for (i = 0; i < pno; i++, p++)
868 ct++; 880 if (i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
869 return ct; 881 ct++;
870} 882 return ct;
871 883}
872static int 884
873linux_to_index(int lpno, struct disk_desc *z) { 885static int linux_to_index(int lpno, struct disk_desc *z)
874 int i, ct = 0; 886{
875 struct part_desc *p = &(z->partitions[0]); 887 int i, ct = 0;
876 for (i=0; i<z->partno && ct < lpno; i++,p++) 888 struct part_desc *p = &(z->partitions[0]);
877 if((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) 889
878 && ++ct == lpno) 890 for (i = 0; i < z->partno && ct < lpno; i++, p++)
879 return i; 891 if ((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
880 return -1; 892 && ++ct == lpno)
893 return i;
894 return -1;
881} 895}
882 896
883static int 897static int asc_to_index(char *pnam, struct disk_desc *z)
884asc_to_index(char *pnam, struct disk_desc *z) { 898{
885 int pnum, pno; 899 int pnum, pno;
886 900
887 if (*pnam == '#') { 901 if (*pnam == '#') {
888 pno = atoi(pnam+1); 902 pno = atoi(pnam + 1);
889 } else { 903 } else {
890 pnum = atoi(pnam); 904 pnum = atoi(pnam);
891 pno = linux_to_index(pnum, z); 905 pno = linux_to_index(pnum, z);
892 } 906 }
893 if (!(pno >= 0 && pno < z->partno)) 907 if (!(pno >= 0 && pno < z->partno))
894 fatal("%s: no such partition\n"), pnam; 908 fatal("%s: no such partition\n"), pnam;
895 return pno; 909 return pno;
896} 910}
897 911
898/* 912/*
@@ -910,523 +924,573 @@ static int one_only = 0;
910static int one_only_pno; 924static int one_only_pno;
911static int increment = 0; 925static int increment = 0;
912 926
913static void 927static void set_format(char c)
914set_format(char c) { 928{
915 switch(c) { 929 switch (c) {
916 default: 930 default:
917 printf("unrecognized format - using sectors\n"); 931 printf("unrecognized format - using sectors\n");
918 case 'S': specified_format = F_SECTOR; break; 932 case 'S':
919 case 'B': specified_format = F_BLOCK; break; 933 specified_format = F_SECTOR;
920 case 'C': specified_format = F_CYLINDER; break; 934 break;
921 case 'M': specified_format = F_MEGABYTE; break; 935 case 'B':
922 } 936 specified_format = F_BLOCK;
937 break;
938 case 'C':
939 specified_format = F_CYLINDER;
940 break;
941 case 'M':
942 specified_format = F_MEGABYTE;
943 break;
944 }
923} 945}
924 946
925static unsigned long 947static unsigned long unitsize(int format)
926unitsize(int format) { 948{
927 default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE); 949 default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE);
928 if (!format && !(format = specified_format)) 950 if (!format && !(format = specified_format))
929 format = default_format; 951 format = default_format;
930 952
931 switch(format) { 953 switch (format) {
932 default: 954 default:
933 case F_CYLINDER: 955 case F_CYLINDER:
934 if(B.cylindersize) 956 if (B.cylindersize)
935 return B.cylindersize; 957 return B.cylindersize;
936 case F_SECTOR: 958 case F_SECTOR:
937 return 1; 959 return 1;
938 case F_BLOCK: 960 case F_BLOCK:
939 return 2; 961 return 2;
940 case F_MEGABYTE: 962 case F_MEGABYTE:
941 return 2048; 963 return 2048;
942 } 964 }
943} 965}
944 966
945static unsigned long 967static unsigned long get_disksize(int format)
946get_disksize(int format) { 968{
947 unsigned long cs = B.cylinders; 969 unsigned long cs = B.cylinders;
948 if (cs && leave_last) 970
949 cs--; 971 if (cs && leave_last)
950 return (cs * B.cylindersize) / unitsize(format); 972 cs--;
973 return (cs * B.cylindersize) / unitsize(format);
951} 974}
952 975
953static void 976static void out_partition_header(char *dev, int format, struct geometry G)
954out_partition_header(char *dev, int format, struct geometry G) { 977{
955 if (dump) { 978 if (dump) {
956 printf("# partition table of %s\n", dev); 979 printf("# partition table of %s\n", dev);
957 printf("unit: sectors\n\n"); 980 printf("unit: sectors\n\n");
958 return; 981 return;
959 } 982 }
960 983
961 default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE); 984 default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE);
962 if (!format && !(format = specified_format)) 985 if (!format && !(format = specified_format))
963 format = default_format; 986 format = default_format;
964 987
965 switch(format) { 988 switch (format) {
966 default: 989 default:
967 printf("unimplemented format - using %s\n", 990 printf("unimplemented format - using %s\n",
968 G.cylindersize ? "cylinders" : "sectors"); 991 G.cylindersize ? "cylinders" : "sectors");
969 case F_CYLINDER: 992 case F_CYLINDER:
970 if (G.cylindersize) { 993 if (G.cylindersize) {
971 printf("Units = cylinders of %lu bytes, blocks of 1024 bytes" 994 printf("Units = cylinders of %lu bytes, blocks of 1024 bytes"
972 ", counting from %d\n\n", 995 ", counting from %d\n\n",
973 G.cylindersize<<9, increment); 996 G.cylindersize << 9, increment);
974 printf(" Device Boot Start End #cyls #blocks Id System\n"); 997 printf
975 break; 998 (" Device Boot Start End #cyls #blocks Id System\n");
976 } 999 break;
977 /* fall through */ 1000 }
978 case F_SECTOR: 1001 /* fall through */
979 printf("Units = sectors of 512 bytes, counting from %d\n\n", 1002 case F_SECTOR:
980 increment); 1003 printf("Units = sectors of 512 bytes, counting from %d\n\n",
981 printf(" Device Boot Start End #sectors Id System\n"); 1004 increment);
982 break; 1005 printf
983 case F_BLOCK: 1006 (" Device Boot Start End #sectors Id System\n");
984 printf("Units = blocks of 1024 bytes, counting from %d\n\n", 1007 break;
985 increment); 1008 case F_BLOCK:
986 printf(" Device Boot Start End #blocks Id System\n"); 1009 printf("Units = blocks of 1024 bytes, counting from %d\n\n",
987 break; 1010 increment);
988 case F_MEGABYTE: 1011 printf
989 printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" 1012 (" Device Boot Start End #blocks Id System\n");
990 ", counting from %d\n\n", increment); 1013 break;
991 printf(" Device Boot Start End MB #blocks Id System\n"); 1014 case F_MEGABYTE:
992 break; 1015 printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes"
993 } 1016 ", counting from %d\n\n", increment);
1017 printf
1018 (" Device Boot Start End MB #blocks Id System\n");
1019 break;
1020 }
994} 1021}
995 1022
996static void 1023static void
997out_rounddown(int width, unsigned long n, unsigned long unit, int inc) { 1024out_rounddown(int width, unsigned long n, unsigned long unit, int inc)
998 printf("%*lu", width, inc + n/unit); 1025{
999 if (unit != 1) 1026 printf("%*lu", width, inc + n / unit);
1000 putchar((n % unit) ? '+' : ' '); 1027 if (unit != 1)
1001 putchar(' '); 1028 putchar((n % unit) ? '+' : ' ');
1029 putchar(' ');
1002} 1030}
1003 1031
1004static void 1032static void
1005out_roundup(int width, unsigned long n, unsigned long unit, int inc) { 1033out_roundup(int width, unsigned long n, unsigned long unit, int inc)
1006 if (n == (unsigned long)(-1)) 1034{
1007 printf("%*s", width, "-"); 1035 if (n == (unsigned long) (-1))
1008 else 1036 printf("%*s", width, "-");
1009 printf("%*lu", width, inc + n/unit); 1037 else
1010 if (unit != 1) 1038 printf("%*lu", width, inc + n / unit);
1011 putchar(((n+1) % unit) ? '-' : ' '); 1039 if (unit != 1)
1012 putchar(' '); 1040 putchar(((n + 1) % unit) ? '-' : ' ');
1041 putchar(' ');
1013} 1042}
1014 1043
1015static void 1044static void
1016out_roundup_size(int width, unsigned long n, unsigned long unit) { 1045out_roundup_size(int width, unsigned long n, unsigned long unit)
1017 printf("%*lu", width, (n+unit-1)/unit); 1046{
1018 if (unit != 1) 1047 printf("%*lu", width, (n + unit - 1) / unit);
1019 putchar((n % unit) ? '-' : ' '); 1048 if (unit != 1)
1020 putchar(' '); 1049 putchar((n % unit) ? '-' : ' ');
1050 putchar(' ');
1021} 1051}
1022 1052
1023static int 1053static int get_fdisk_geometry(struct part_desc *p)
1024get_fdisk_geometry(struct part_desc *p) { 1054{
1025 chs b = p->p.end_chs; 1055 chs b = p->p.end_chs;
1026 longchs bb = chs_to_longchs(b); 1056 longchs bb = chs_to_longchs(b);
1027 F.heads = bb.h+1; 1057
1028 F.sectors = bb.s; 1058 F.heads = bb.h + 1;
1029 F.cylindersize = F.heads*F.sectors; 1059 F.sectors = bb.s;
1030 return (F.sectors != B.sectors || F.heads != B.heads); 1060 F.cylindersize = F.heads * F.sectors;
1061 return (F.sectors != B.sectors || F.heads != B.heads);
1031} 1062}
1032 1063
1033static void 1064static void
1034out_partition(char *dev, int format, struct part_desc *p, 1065out_partition(char *dev, int format, struct part_desc *p,
1035 struct disk_desc *z, struct geometry G) { 1066 struct disk_desc *z, struct geometry G)
1036 unsigned long start, end, size; 1067{
1037 int pno, lpno; 1068 unsigned long start, end, size;
1038 1069 int pno, lpno;
1039 if (!format && !(format = specified_format)) 1070
1040 format = default_format; 1071 if (!format && !(format = specified_format))
1041 1072 format = default_format;
1042 pno = p - &(z->partitions[0]); /* our index */ 1073
1043 lpno = index_to_linux(pno, z); /* name of next one that has a name */ 1074 pno = p - &(z->partitions[0]); /* our index */
1044 if(pno == linux_to_index(lpno, z)) /* was that us? */ 1075 lpno = index_to_linux(pno, z); /* name of next one that has a name */
1045 printf("%8s%-2u", dev, lpno); /* yes */ 1076 if (pno == linux_to_index(lpno, z)) /* was that us? */
1046 else if(show_extended) 1077 printf("%8s%-2u", dev, lpno); /* yes */
1047 printf(" - "); 1078 else if (show_extended)
1048 else 1079 printf(" - ");
1049 return; 1080 else
1050 putchar(dump ? ':' : ' '); 1081 return;
1051 1082 putchar(dump ? ':' : ' ');
1052 start = p->start; 1083
1053 end = p->start + p->size - 1; 1084 start = p->start;
1054 size = p->size; 1085 end = p->start + p->size - 1;
1055 1086 size = p->size;
1056 if (dump) { 1087
1057 printf(" start=%9lu", start); 1088 if (dump) {
1058 printf(", size=%8lu", size); 1089 printf(" start=%9lu", start);
1059 if (p->ptype == DOS_TYPE) { 1090 printf(", size=%8lu", size);
1060 printf(", Id=%2x", p->p.sys_type); 1091 if (p->ptype == DOS_TYPE) {
1061 if (p->p.bootable == 0x80) 1092 printf(", Id=%2x", p->p.sys_type);
1062 printf(", bootable"); 1093 if (p->p.bootable == 0x80)
1094 printf(", bootable");
1095 }
1096 printf("\n");
1097 return;
1063 } 1098 }
1064 printf("\n"); 1099
1065 return; 1100 if (p->ptype != DOS_TYPE || p->p.bootable == 0)
1066 } 1101 printf(" ");
1067 1102 else if (p->p.bootable == 0x80)
1068 if(p->ptype != DOS_TYPE || p->p.bootable == 0) 1103 printf(" * ");
1069 printf(" "); 1104 else
1070 else if(p->p.bootable == 0x80) 1105 printf(" ? "); /* garbage */
1071 printf(" * "); 1106
1072 else 1107 switch (format) {
1073 printf(" ? "); /* garbage */ 1108 case F_CYLINDER:
1074 1109 if (G.cylindersize) {
1075 switch(format) { 1110 out_rounddown(6, start, G.cylindersize, increment);
1076 case F_CYLINDER: 1111 out_roundup(6, end, G.cylindersize, increment);
1077 if (G.cylindersize) { 1112 out_roundup_size(6, size, G.cylindersize);
1078 out_rounddown(6, start, G.cylindersize, increment); 1113 out_rounddown(8, size, 2, 0);
1079 out_roundup(6, end, G.cylindersize, increment); 1114 break;
1080 out_roundup_size(6, size, G.cylindersize); 1115 }
1081 out_rounddown(8, size, 2, 0); 1116 /* fall through */
1082 break; 1117 default:
1083 } 1118 case F_SECTOR:
1084 /* fall through */ 1119 out_rounddown(9, start, 1, increment);
1085 default: 1120 out_roundup(9, end, 1, increment);
1086 case F_SECTOR: 1121 out_rounddown(9, size, 1, 0);
1087 out_rounddown(9, start, 1, increment); 1122 break;
1088 out_roundup(9, end, 1, increment); 1123 case F_BLOCK:
1089 out_rounddown(9, size, 1, 0);
1090 break;
1091 case F_BLOCK:
1092#if 0 1124#if 0
1093 printf("%8lu,%3lu ", 1125 printf("%8lu,%3lu ",
1094 p->sector/2, ((p->sector & 1) ? 512 : 0) + p->offset); 1126 p->sector / 2, ((p->sector & 1) ? 512 : 0) + p->offset);
1095#endif 1127#endif
1096 out_rounddown(8, start, 2, increment); 1128 out_rounddown(8, start, 2, increment);
1097 out_roundup(8, end, 2, increment); 1129 out_roundup(8, end, 2, increment);
1098 out_rounddown(8, size, 2, 0); 1130 out_rounddown(8, size, 2, 0);
1099 break; 1131 break;
1100 case F_MEGABYTE: 1132 case F_MEGABYTE:
1101 out_rounddown(5, start, 2048, increment); 1133 out_rounddown(5, start, 2048, increment);
1102 out_roundup(5, end, 2048, increment); 1134 out_roundup(5, end, 2048, increment);
1103 out_roundup_size(5, size, 2048); 1135 out_roundup_size(5, size, 2048);
1104 out_rounddown(8, size, 2, 0); 1136 out_rounddown(8, size, 2, 0);
1105 break;
1106 }
1107 if (p->ptype == DOS_TYPE) {
1108 printf(" %2x %s\n",
1109 p->p.sys_type, sysname(p->p.sys_type));
1110 } else {
1111 printf("\n");
1112 }
1113
1114 /* Is chs as we expect? */
1115 if (!quiet && p->ptype == DOS_TYPE) {
1116 chs a, b;
1117 longchs aa, bb;
1118 a = (size ? ulong_to_chs(start,G) : zero_chs);
1119 b = p->p.begin_chs;
1120 aa = chs_to_longchs(a);
1121 bb = chs_to_longchs(b);
1122 if(a.s && !is_equal_chs(a, b))
1123 printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1124 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1125 a = (size ? ulong_to_chs(end,G) : zero_chs);
1126 b = p->p.end_chs;
1127 aa = chs_to_longchs(a);
1128 bb = chs_to_longchs(b);
1129 if(a.s && !is_equal_chs(a, b))
1130 printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1131 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1132 if(G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders)
1133 printf("partition ends on cylinder %ld, beyond the end of the disk\n",
1134 bb.c);
1135 }
1136}
1137
1138static void
1139out_partitions(char *dev, struct disk_desc *z) {
1140 struct part_desc *p;
1141 int pno, format = 0;
1142
1143 if (z->partno == 0)
1144 printf("No partitions found\n");
1145 else {
1146 for (pno=0; pno < z->partno; pno++) {
1147 p = &(z->partitions[pno]);
1148 if (p->size != 0 && p->p.sys_type != 0) {
1149 if (get_fdisk_geometry(p))
1150 printf(
1151 "Warning: The first partition looks like it was made\n"
1152 " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
1153 "For this listing I'll assume that geometry.\n",
1154 F.heads, F.sectors, B.cylinders, B.heads, B.sectors);
1155 break; 1137 break;
1156 }
1157 } 1138 }
1158 out_partition_header(dev, format, F); 1139 if (p->ptype == DOS_TYPE) {
1159 for(pno=0; pno < z->partno; pno++) { 1140 printf(" %2x %s\n", p->p.sys_type, sysname(p->p.sys_type));
1160 out_partition(dev, format, &(z->partitions[pno]), z, F); 1141 } else {
1161 if(show_extended && pno%4==3) 1142 printf("\n");
1162 printf("\n"); 1143 }
1144
1145 /* Is chs as we expect? */
1146 if (!quiet && p->ptype == DOS_TYPE) {
1147 chs a, b;
1148 longchs aa, bb;
1149
1150 a = (size ? ulong_to_chs(start, G) : zero_chs);
1151 b = p->p.begin_chs;
1152 aa = chs_to_longchs(a);
1153 bb = chs_to_longchs(b);
1154 if (a.s && !is_equal_chs(a, b))
1155 printf
1156 ("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1157 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1158 a = (size ? ulong_to_chs(end, G) : zero_chs);
1159 b = p->p.end_chs;
1160 aa = chs_to_longchs(a);
1161 bb = chs_to_longchs(b);
1162 if (a.s && !is_equal_chs(a, b))
1163 printf
1164 ("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1165 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1166 if (G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders)
1167 printf
1168 ("partition ends on cylinder %ld, beyond the end of the disk\n",
1169 bb.c);
1163 } 1170 }
1164 }
1165} 1171}
1166 1172
1167static int 1173static void out_partitions(char *dev, struct disk_desc *z)
1168disj(struct part_desc *p, struct part_desc *q) { 1174{
1169 return 1175 struct part_desc *p;
1170 ((p->start + p->size <= q->start) 1176 int pno, format = 0;
1171 || (is_extended(p->p.sys_type) 1177
1172 && q->start + q->size <= p->start + p->size)); 1178 if (z->partno == 0)
1179 printf("No partitions found\n");
1180 else {
1181 for (pno = 0; pno < z->partno; pno++) {
1182 p = &(z->partitions[pno]);
1183 if (p->size != 0 && p->p.sys_type != 0) {
1184 if (get_fdisk_geometry(p))
1185 printf
1186 ("Warning: The first partition looks like it was made\n"
1187 " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
1188 "For this listing I'll assume that geometry.\n",
1189 F.heads, F.sectors, B.cylinders, B.heads,
1190 B.sectors);
1191 break;
1192 }
1193 }
1194 out_partition_header(dev, format, F);
1195 for (pno = 0; pno < z->partno; pno++) {
1196 out_partition(dev, format, &(z->partitions[pno]), z, F);
1197 if (show_extended && pno % 4 == 3)
1198 printf("\n");
1199 }
1200 }
1173} 1201}
1174 1202
1175static char * 1203static int disj(struct part_desc *p, struct part_desc *q)
1176pnumber(struct part_desc *p, struct disk_desc *z) { 1204{
1177 static char buf[20]; 1205 return ((p->start + p->size <= q->start)
1178 int this, next; 1206 || (is_extended(p->p.sys_type)
1179 struct part_desc *p0 = &(z->partitions[0]); 1207 && q->start + q->size <= p->start + p->size));
1208}
1209
1210static char *pnumber(struct part_desc *p, struct disk_desc *z)
1211{
1212 static char buf[20];
1213 int this, next;
1214 struct part_desc *p0 = &(z->partitions[0]);
1180 1215
1181 this = index_to_linux(p-p0, z); 1216 this = index_to_linux(p - p0, z);
1182 next = index_to_linux(p-p0+1, z); 1217 next = index_to_linux(p - p0 + 1, z);
1183 1218
1184 if (next > this) 1219 if (next > this)
1185 sprintf(buf, "%d", this); 1220 sprintf(buf, "%d", this);
1186 else 1221 else
1187 sprintf(buf, "[%d]", this); 1222 sprintf(buf, "[%d]", this);
1188 return buf; 1223 return buf;
1189} 1224}
1190 1225
1191static int 1226static int partitions_ok(struct disk_desc *z)
1192partitions_ok(struct disk_desc *z) { 1227{
1193 struct part_desc *partitions = &(z->partitions[0]), *p, *q; 1228 struct part_desc *partitions = &(z->partitions[0]), *p, *q;
1194 int partno = z->partno; 1229 int partno = z->partno;
1195 1230
1196#define PNO(p) pnumber(p, z) 1231#define PNO(p) pnumber(p, z)
1197 1232
1198 /* Have at least 4 partitions been defined? */ 1233 /* Have at least 4 partitions been defined? */
1199 if (partno < 4) { 1234 if (partno < 4) {
1200 if (!partno) 1235 if (!partno)
1201 fatal("no partition table present.\n"); 1236 fatal("no partition table present.\n");
1202 else 1237 else
1203 fatal("strange, only %d partitions defined.\n"), partno; 1238 fatal("strange, only %d partitions defined.\n"), partno;
1204 return 0;
1205 }
1206
1207 /* Are the partitions of size 0 marked empty?
1208 And do they have start = 0? And bootable = 0? */
1209 for (p = partitions; p - partitions < partno; p++)
1210 if (p->size == 0) {
1211 if(p->p.sys_type != EMPTY_PARTITION)
1212 warn("Warning: partition %s has size 0 but is not marked Empty\n",
1213 PNO(p));
1214 else if(p->p.bootable != 0)
1215 warn("Warning: partition %s has size 0 and is bootable\n",
1216 PNO(p));
1217 else if(p->p.start_sect != 0)
1218 warn("Warning: partition %s has size 0 and nonzero start\n",
1219 PNO(p));
1220 /* all this is probably harmless, no error return */
1221 }
1222
1223 /* Are the logical partitions contained in their extended partitions? */
1224 for (p = partitions+4; p < partitions+partno; p++)
1225 if (p->ptype == DOS_TYPE)
1226 if (p->size && !is_extended(p->p.sys_type)) {
1227 q = p->ep;
1228 if (p->start < q->start || p->start + p->size > q->start + q->size) {
1229 warn("Warning: partition %s "), PNO(p);
1230 warn("is not contained in partition %s\n"), PNO(q);
1231 return 0;
1232 }
1233 }
1234
1235 /* Are the data partitions mutually disjoint? */
1236 for (p = partitions; p < partitions+partno; p++)
1237 if (p->size && !is_extended(p->p.sys_type))
1238 for (q = p+1; q < partitions+partno; q++)
1239 if (q->size && !is_extended(q->p.sys_type))
1240 if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) {
1241 warn("Warning: partitions %s "), PNO(p);
1242 warn("and %s overlap\n"), PNO(q);
1243 return 0;
1244 }
1245
1246 /* Are the data partitions and the extended partition
1247 table sectors disjoint? */
1248 for (p = partitions; p < partitions+partno; p++)
1249 if (p->size && !is_extended(p->p.sys_type))
1250 for (q = partitions; q < partitions+partno; q++)
1251 if (is_extended(q->p.sys_type))
1252 if (p->start <= q->start && p->start + p->size > q->start) {
1253 warn("Warning: partition %s contains part of ", PNO(p));
1254 warn("the partition table (sector %lu),\n", q->start);
1255 warn("and will destroy it when filled\n");
1256 return 0; 1239 return 0;
1257 } 1240 }
1258 1241
1259 /* Do they start past zero and end before end-of-disk? */ 1242 /* Are the partitions of size 0 marked empty?
1260 { unsigned long ds = get_disksize(F_SECTOR); 1243 And do they have start = 0? And bootable = 0? */
1261 for (p = partitions; p < partitions+partno; p++) 1244 for (p = partitions; p - partitions < partno; p++)
1262 if (p->size) { 1245 if (p->size == 0) {
1263 if(p->start == 0) { 1246 if (p->p.sys_type != EMPTY_PARTITION)
1264 warn("Warning: partition %s starts at sector 0\n", PNO(p)); 1247 warn
1265 return 0; 1248 ("Warning: partition %s has size 0 but is not marked Empty\n",
1266 } 1249 PNO(p));
1267 if (p->size && p->start + p->size > ds) { 1250 else if (p->p.bootable != 0)
1268 warn("Warning: partition %s extends past end of disk\n", PNO(p)); 1251 warn("Warning: partition %s has size 0 and is bootable\n",
1269 return 0; 1252 PNO(p));
1270 } 1253 else if (p->p.start_sect != 0)
1271 } 1254 warn
1272 } 1255 ("Warning: partition %s has size 0 and nonzero start\n",
1273 1256 PNO(p));
1274 /* At most one chain of DOS extended partitions ? */ 1257 /* all this is probably harmless, no error return */
1275 /* It seems that the OS/2 fdisk has the additional requirement 1258 }
1276 that the extended partition must be the fourth one */ 1259
1277 { int ect = 0; 1260 /* Are the logical partitions contained in their extended partitions? */
1278 for (p = partitions; p < partitions+4; p++) 1261 for (p = partitions + 4; p < partitions + partno; p++)
1279 if (p->p.sys_type == EXTENDED_PARTITION) 1262 if (p->ptype == DOS_TYPE)
1280 ect++; 1263 if (p->size && !is_extended(p->p.sys_type)) {
1281 if (ect > 1 && !Linux) { 1264 q = p->ep;
1282 warn("Among the primary partitions, at most one can be extended\n"); 1265 if (p->start < q->start
1283 warn(" (although this is not a problem under Linux)\n"); 1266 || p->start + p->size > q->start + q->size) {
1284 return 0; 1267 warn("Warning: partition %s "), PNO(p);
1285 } 1268 warn("is not contained in partition %s\n"), PNO(q);
1286 } 1269 return 0;
1287 1270 }
1288 /* 1271 }
1289 * Do all partitions start at a cylinder boundary ? 1272
1290 * (this is not required for Linux) 1273 /* Are the data partitions mutually disjoint? */
1291 * The first partition starts after MBR. 1274 for (p = partitions; p < partitions + partno; p++)
1292 * Logical partitions start slightly after the containing extended partn. 1275 if (p->size && !is_extended(p->p.sys_type))
1293 */ 1276 for (q = p + 1; q < partitions + partno; q++)
1294 if (B.cylindersize) { 1277 if (q->size && !is_extended(q->p.sys_type))
1295 for(p = partitions; p < partitions+partno; p++) 1278 if (!((p->start > q->start) ? disj(q, p) : disj(p, q))) {
1296 if (p->size) { 1279 warn("Warning: partitions %s "), PNO(p);
1297 if(p->start % B.cylindersize != 0 1280 warn("and %s overlap\n"), PNO(q);
1298 && (!p->ep || p->start / B.cylindersize != p->ep->start / B.cylindersize) 1281 return 0;
1299 && (p->p.start_sect >= B.cylindersize)) { 1282 }
1300 warn("Warning: partition %s does not start " 1283
1301 "at a cylinder boundary\n", PNO(p)); 1284 /* Are the data partitions and the extended partition
1302 if (!Linux) 1285 table sectors disjoint? */
1303 return 0; 1286 for (p = partitions; p < partitions + partno; p++)
1304 } 1287 if (p->size && !is_extended(p->p.sys_type))
1305 if((p->start + p->size) % B.cylindersize) { 1288 for (q = partitions; q < partitions + partno; q++)
1306 warn("Warning: partition %s does not end " 1289 if (is_extended(q->p.sys_type))
1307 "at a cylinder boundary\n", PNO(p)); 1290 if (p->start <= q->start
1308 if (!Linux) 1291 && p->start + p->size > q->start) {
1309 return 0; 1292 warn("Warning: partition %s contains part of ",
1310 } 1293 PNO(p));
1311 } 1294 warn("the partition table (sector %lu),\n",
1312 } 1295 q->start);
1313 1296 warn("and will destroy it when filled\n");
1314 /* Usually, one can boot only from primary partitions. */ 1297 return 0;
1315 /* In fact, from a unique one only. */ 1298 }
1316 /* do not warn about bootable extended partitions - 1299
1317 often LILO is there */ 1300 /* Do they start past zero and end before end-of-disk? */
1318 { int pno = -1; 1301 {
1319 for(p = partitions; p < partitions+partno; p++) 1302 unsigned long ds = get_disksize(F_SECTOR);
1320 if (p->p.bootable) { 1303
1321 if (pno == -1) 1304 for (p = partitions; p < partitions + partno; p++)
1322 pno = p - partitions; 1305 if (p->size) {
1323 else if (p - partitions < 4) { 1306 if (p->start == 0) {
1324 warn("Warning: more than one primary partition is marked " 1307 warn("Warning: partition %s starts at sector 0\n",
1325 "bootable (active)\n" 1308 PNO(p));
1326 "This does not matter for LILO, but the DOS MBR will " 1309 return 0;
1327 "not boot this disk.\n"); 1310 }
1328 break; 1311 if (p->size && p->start + p->size > ds) {
1329 } 1312 warn
1330 if (p - partitions >= 4) { 1313 ("Warning: partition %s extends past end of disk\n",
1331 warn("Warning: usually one can boot from primary partitions " 1314 PNO(p));
1332 "only\nLILO disregards the `bootable' flag.\n"); 1315 return 0;
1333 break; 1316 }
1334 } 1317 }
1335 } 1318 }
1336 if (pno == -1 || pno >= 4) 1319
1337 warn("Warning: no primary partition is marked bootable (active)\n" 1320 /* At most one chain of DOS extended partitions ? */
1338 "This does not matter for LILO, but the DOS MBR will " 1321 /* It seems that the OS/2 fdisk has the additional requirement
1339 "not boot this disk.\n"); 1322 that the extended partition must be the fourth one */
1340 } 1323 {
1341 1324 int ect = 0;
1342 /* Is chs as we expect? */ 1325
1343 for(p = partitions; p < partitions+partno; p++) 1326 for (p = partitions; p < partitions + 4; p++)
1344 if(p->ptype == DOS_TYPE) { 1327 if (p->p.sys_type == EXTENDED_PARTITION)
1345 chs a, b; 1328 ect++;
1346 longchs aa, bb; 1329 if (ect > 1 && !Linux) {
1347 a = p->size ? ulong_to_chs(p->start,B) : zero_chs; 1330 warn
1348 b = p->p.begin_chs; 1331 ("Among the primary partitions, at most one can be extended\n");
1349 aa = chs_to_longchs(a); 1332 warn(" (although this is not a problem under Linux)\n");
1350 bb = chs_to_longchs(b); 1333 return 0;
1351 if (!chs_ok(b, PNO(p), "start")) 1334 }
1352 return 0; 1335 }
1353 if(a.s && !is_equal_chs(a, b)) 1336
1354 warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 1337 /*
1355 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); 1338 * Do all partitions start at a cylinder boundary ?
1356 a = p->size ? ulong_to_chs(p->start + p->size - 1, B) : zero_chs; 1339 * (this is not required for Linux)
1357 b = p->p.end_chs; 1340 * The first partition starts after MBR.
1358 aa = chs_to_longchs(a); 1341 * Logical partitions start slightly after the containing extended partn.
1359 bb = chs_to_longchs(b); 1342 */
1360 if (!chs_ok(b, PNO(p), "end")) 1343 if (B.cylindersize) {
1361 return 0; 1344 for (p = partitions; p < partitions + partno; p++)
1362 if(a.s && !is_equal_chs(a, b)) 1345 if (p->size) {
1363 warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 1346 if (p->start % B.cylindersize != 0
1364 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); 1347 && (!p->ep
1365 if(B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders) 1348 || p->start / B.cylindersize !=
1366 warn("partition %s ends on cylinder %ld, beyond the end of the disk\n", 1349 p->ep->start / B.cylindersize)
1367 PNO(p), bb.c); 1350 && (p->p.start_sect >= B.cylindersize)) {
1368 } 1351 warn("Warning: partition %s does not start "
1369 1352 "at a cylinder boundary\n", PNO(p));
1370 return 1; 1353 if (!Linux)
1354 return 0;
1355 }
1356 if ((p->start + p->size) % B.cylindersize) {
1357 warn("Warning: partition %s does not end "
1358 "at a cylinder boundary\n", PNO(p));
1359 if (!Linux)
1360 return 0;
1361 }
1362 }
1363 }
1364
1365 /* Usually, one can boot only from primary partitions. */
1366 /* In fact, from a unique one only. */
1367 /* do not warn about bootable extended partitions -
1368 often LILO is there */
1369 {
1370 int pno = -1;
1371
1372 for (p = partitions; p < partitions + partno; p++)
1373 if (p->p.bootable) {
1374 if (pno == -1)
1375 pno = p - partitions;
1376 else if (p - partitions < 4) {
1377 warn
1378 ("Warning: more than one primary partition is marked "
1379 "bootable (active)\n"
1380 "This does not matter for LILO, but the DOS MBR will "
1381 "not boot this disk.\n");
1382 break;
1383 }
1384 if (p - partitions >= 4) {
1385 warn
1386 ("Warning: usually one can boot from primary partitions "
1387 "only\nLILO disregards the `bootable' flag.\n");
1388 break;
1389 }
1390 }
1391 if (pno == -1 || pno >= 4)
1392 warn
1393 ("Warning: no primary partition is marked bootable (active)\n"
1394 "This does not matter for LILO, but the DOS MBR will "
1395 "not boot this disk.\n");
1396 }
1397
1398 /* Is chs as we expect? */
1399 for (p = partitions; p < partitions + partno; p++)
1400 if (p->ptype == DOS_TYPE) {
1401 chs a, b;
1402 longchs aa, bb;
1403
1404 a = p->size ? ulong_to_chs(p->start, B) : zero_chs;
1405 b = p->p.begin_chs;
1406 aa = chs_to_longchs(a);
1407 bb = chs_to_longchs(b);
1408 if (!chs_ok(b, PNO(p), "start"))
1409 return 0;
1410 if (a.s && !is_equal_chs(a, b))
1411 warn
1412 ("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1413 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1414 a =
1415 p->size ? ulong_to_chs(p->start + p->size - 1,
1416 B) : zero_chs;
1417 b = p->p.end_chs;
1418 aa = chs_to_longchs(a);
1419 bb = chs_to_longchs(b);
1420 if (!chs_ok(b, PNO(p), "end"))
1421 return 0;
1422 if (a.s && !is_equal_chs(a, b))
1423 warn
1424 ("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1425 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1426 if (B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders)
1427 warn
1428 ("partition %s ends on cylinder %ld, beyond the end of the disk\n",
1429 PNO(p), bb.c);
1430 }
1431
1432 return 1;
1371 1433
1372#undef PNO 1434#undef PNO
1373} 1435}
1374 1436
1375static void 1437static void
1376extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { 1438extended_partition(char *dev, int fd, struct part_desc *ep,
1377 char *cp; 1439 struct disk_desc *z)
1378 struct sector *s; 1440{
1379 unsigned long start, here, next; 1441 char *cp;
1380 int i, moretodo = 1; 1442 struct sector *s;
1381 struct partition p; 1443 unsigned long start, here, next;
1382 struct part_desc *partitions = &(z->partitions[0]); 1444 int i, moretodo = 1;
1383 int pno = z->partno; 1445 struct partition p;
1446 struct part_desc *partitions = &(z->partitions[0]);
1447 int pno = z->partno;
1384 1448
1385 here = start = ep->start; 1449 here = start = ep->start;
1386 1450
1387 while (moretodo) { 1451 while (moretodo) {
1388 moretodo = 0; 1452 moretodo = 0;
1389 1453
1390 if (!(s = get_sector(dev, fd, here))) 1454 if (!(s = get_sector(dev, fd, here)))
1391 break; 1455 break;
1392 1456
1393 if (!msdos_signature(s)) 1457 if (!msdos_signature(s))
1394 break; 1458 break;
1395 1459
1396 cp = s->data + 0x1be; 1460 cp = s->data + 0x1be;
1397 1461
1398 if (pno+4 >= SIZE(z->partitions)) { 1462 if (pno + 4 >= SIZE(z->partitions)) {
1399 printf("too many partitions - ignoring those past nr (%d)\n", 1463 printf("too many partitions - ignoring those past nr (%d)\n",
1400 pno-1); 1464 pno - 1);
1401 break; 1465 break;
1402 } 1466 }
1403 1467
1404 next = 0; 1468 next = 0;
1469
1470 for (i = 0; i < 4; i++, cp += sizeof(struct partition)) {
1471 partitions[pno].sector = here;
1472 partitions[pno].offset = cp - s->data;
1473 partitions[pno].ep = ep;
1474 copy_to_part(cp, &p);
1475 if (is_extended(p.sys_type)) {
1476 partitions[pno].start = start + p.start_sect;
1477 if (next)
1478 printf("tree of partitions?\n");
1479 else
1480 next = partitions[pno].start; /* follow `upper' branch */
1481 moretodo = 1;
1482 } else {
1483 partitions[pno].start = here + p.start_sect;
1484 }
1485 partitions[pno].size = p.nr_sects;
1486 partitions[pno].ptype = DOS_TYPE;
1487 partitions[pno].p = p;
1488 pno++;
1489 }
1490 here = next;
1491 }
1405 1492
1406 for (i=0; i<4; i++,cp += sizeof(struct partition)) { 1493 z->partno = pno;
1407 partitions[pno].sector = here;
1408 partitions[pno].offset = cp - s->data;
1409 partitions[pno].ep = ep;
1410 copy_to_part(cp,&p);
1411 if (is_extended(p.sys_type)) {
1412 partitions[pno].start = start + p.start_sect;
1413 if (next)
1414 printf("tree of partitions?\n");
1415 else
1416 next = partitions[pno].start; /* follow `upper' branch */
1417 moretodo = 1;
1418 } else {
1419 partitions[pno].start = here + p.start_sect;
1420 }
1421 partitions[pno].size = p.nr_sects;
1422 partitions[pno].ptype = DOS_TYPE;
1423 partitions[pno].p = p;
1424 pno++;
1425 }
1426 here = next;
1427 }
1428
1429 z->partno = pno;
1430} 1494}
1431 1495
1432#define BSD_DISKMAGIC (0x82564557UL) 1496#define BSD_DISKMAGIC (0x82564557UL)
@@ -1436,27 +1500,28 @@ typedef unsigned char u8;
1436typedef unsigned short u16; 1500typedef unsigned short u16;
1437typedef unsigned int u32; 1501typedef unsigned int u32;
1438struct bsd_disklabel { 1502struct bsd_disklabel {
1439 u32 d_magic; 1503 u32 d_magic;
1440 char d_junk1[4]; 1504 char d_junk1[4];
1441 char d_typename[16]; 1505 char d_typename[16];
1442 char d_packname[16]; 1506 char d_packname[16];
1443 char d_junk2[92]; 1507 char d_junk2[92];
1444 u32 d_magic2; 1508 u32 d_magic2;
1445 char d_junk3[2]; 1509 char d_junk3[2];
1446 u16 d_npartitions; /* number of partitions in following */ 1510 u16 d_npartitions; /* number of partitions in following */
1447 char d_junk4[8]; 1511 char d_junk4[8];
1448 struct bsd_partition { /* the partition table */ 1512 struct bsd_partition { /* the partition table */
1449 u32 p_size; /* number of sectors in partition */ 1513 u32 p_size; /* number of sectors in partition */
1450 u32 p_offset; /* starting sector */ 1514 u32 p_offset; /* starting sector */
1451 u32 p_fsize; /* filesystem basic fragment size */ 1515 u32 p_fsize; /* filesystem basic fragment size */
1452 u8 p_fstype; /* filesystem type, see below */ 1516 u8 p_fstype; /* filesystem type, see below */
1453 u8 p_frag; /* filesystem fragments per block */ 1517 u8 p_frag; /* filesystem fragments per block */
1454 u16 p_cpg; /* filesystem cylinders per group */ 1518 u16 p_cpg; /* filesystem cylinders per group */
1455 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ 1519 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
1456}; 1520};
1457 1521
1458static void 1522static void
1459bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { 1523bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z)
1524{
1460 struct bsd_disklabel *l; 1525 struct bsd_disklabel *l;
1461 struct bsd_partition *bp, *bp0; 1526 struct bsd_partition *bp, *bp0;
1462 unsigned long start = ep->start; 1527 unsigned long start = ep->start;
@@ -1464,7 +1529,7 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1464 struct part_desc *partitions = &(z->partitions[0]); 1529 struct part_desc *partitions = &(z->partitions[0]);
1465 int pno = z->partno; 1530 int pno = z->partno;
1466 1531
1467 if (!(s = get_sector(dev,fd,start+1))) 1532 if (!(s = get_sector(dev, fd, start + 1)))
1468 return; 1533 return;
1469 l = (struct bsd_disklabel *) (s->data); 1534 l = (struct bsd_disklabel *) (s->data);
1470 if (l->d_magic != BSD_DISKMAGIC) 1535 if (l->d_magic != BSD_DISKMAGIC)
@@ -1472,16 +1537,16 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1472 1537
1473 bp = bp0 = &l->d_partitions[0]; 1538 bp = bp0 = &l->d_partitions[0];
1474 while (bp - bp0 <= BSD_MAXPARTITIONS) { 1539 while (bp - bp0 <= BSD_MAXPARTITIONS) {
1475 if (pno+1 >= SIZE(z->partitions)) { 1540 if (pno + 1 >= SIZE(z->partitions)) {
1476 printf("too many partitions - ignoring those " 1541 printf("too many partitions - ignoring those "
1477 "past nr (%d)\n", pno-1); 1542 "past nr (%d)\n", pno - 1);
1478 break; 1543 break;
1479 } 1544 }
1480 if (bp->p_fstype != BSD_FS_UNUSED) { 1545 if (bp->p_fstype != BSD_FS_UNUSED) {
1481 partitions[pno].start = bp->p_offset; 1546 partitions[pno].start = bp->p_offset;
1482 partitions[pno].size = bp->p_size; 1547 partitions[pno].size = bp->p_size;
1483 partitions[pno].sector = start+1; 1548 partitions[pno].sector = start + 1;
1484 partitions[pno].offset = (char *)bp - (char *)bp0; 1549 partitions[pno].offset = (char *) bp - (char *) bp0;
1485 partitions[pno].ep = 0; 1550 partitions[pno].ep = 0;
1486 partitions[pno].ptype = BSD_TYPE; 1551 partitions[pno].ptype = BSD_TYPE;
1487 pno++; 1552 pno++;
@@ -1492,129 +1557,138 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1492} 1557}
1493 1558
1494static int 1559static int
1495msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1560msdos_partition(char *dev, int fd, unsigned long start,
1496 int i; 1561 struct disk_desc *z)
1497 char *cp; 1562{
1498 struct partition pt; 1563 int i;
1499 struct sector *s; 1564 char *cp;
1500 struct part_desc *partitions = &(z->partitions[0]); 1565 struct partition pt;
1501 int pno = z->partno; 1566 struct sector *s;
1502 1567 struct part_desc *partitions = &(z->partitions[0]);
1503 if (!(s = get_sector(dev, fd, start))) 1568 int pno = z->partno;
1504 return 0;
1505 1569
1506 if (!msdos_signature(s)) 1570 if (!(s = get_sector(dev, fd, start)))
1507 return 0; 1571 return 0;
1508 1572
1509 cp = s->data + 0x1be; 1573 if (!msdos_signature(s))
1510 copy_to_part(cp,&pt); 1574 return 0;
1511 1575
1512 /* If I am not mistaken, recent kernels will hide this from us, 1576 cp = s->data + 0x1be;
1577 copy_to_part(cp, &pt);
1578
1579 /* If I am not mistaken, recent kernels will hide this from us,
1513 so we will never actually see traces of a Disk Manager */ 1580 so we will never actually see traces of a Disk Manager */
1514 if (pt.sys_type == DM6_PARTITION 1581 if (pt.sys_type == DM6_PARTITION
1515 || pt.sys_type == EZD_PARTITION 1582 || pt.sys_type == EZD_PARTITION
1516 || pt.sys_type == DM6_AUX1PARTITION 1583 || pt.sys_type == DM6_AUX1PARTITION
1517 || pt.sys_type == DM6_AUX3PARTITION) { 1584 || pt.sys_type == DM6_AUX3PARTITION) {
1518 printf("detected Disk Manager - unable to handle that\n"); 1585 printf("detected Disk Manager - unable to handle that\n");
1519 return 0; 1586 return 0;
1520 } 1587 }
1521 { unsigned int sig = *(unsigned short *)(s->data + 2); 1588 {
1522 if (sig <= 0x1ae 1589 unsigned int sig = *(unsigned short *) (s->data + 2);
1523 && *(unsigned short *)(s->data + sig) == 0x55aa 1590
1524 && (1 & *(unsigned char *)(s->data + sig + 2))) { 1591 if (sig <= 0x1ae
1525 printf("DM6 signature found - giving up\n"); 1592 && *(unsigned short *) (s->data + sig) == 0x55aa
1526 return 0; 1593 && (1 & *(unsigned char *) (s->data + sig + 2))) {
1527 } 1594 printf("DM6 signature found - giving up\n");
1528 } 1595 return 0;
1529 1596 }
1530 for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) { 1597 }
1531 partitions[pno].sector = start; 1598
1532 partitions[pno].offset = cp - s->data; 1599 for (pno = 0; pno < 4; pno++, cp += sizeof(struct partition)) {
1533 copy_to_part(cp,&pt); 1600 partitions[pno].sector = start;
1534 partitions[pno].start = start + pt.start_sect; 1601 partitions[pno].offset = cp - s->data;
1535 partitions[pno].size = pt.nr_sects; 1602 copy_to_part(cp, &pt);
1536 partitions[pno].ep = 0; 1603 partitions[pno].start = start + pt.start_sect;
1537 partitions[pno].p = pt; 1604 partitions[pno].size = pt.nr_sects;
1538 } 1605 partitions[pno].ep = 0;
1539 1606 partitions[pno].p = pt;
1540 z->partno = pno; 1607 }
1541 1608
1542 for (i=0; i<4; i++) { 1609 z->partno = pno;
1543 if (is_extended(partitions[i].p.sys_type)) { 1610
1544 if (!partitions[i].size) { 1611 for (i = 0; i < 4; i++) {
1545 printf("strange..., an extended partition of size 0?\n"); 1612 if (is_extended(partitions[i].p.sys_type)) {
1546 continue; 1613 if (!partitions[i].size) {
1547 } 1614 printf("strange..., an extended partition of size 0?\n");
1548 extended_partition(dev, fd, &partitions[i], z); 1615 continue;
1549 } 1616 }
1550 if (is_bsd(partitions[i].p.sys_type)) { 1617 extended_partition(dev, fd, &partitions[i], z);
1551 if (!partitions[i].size) { 1618 }
1552 printf("strange..., a BSD partition of size 0?\n"); 1619 if (is_bsd(partitions[i].p.sys_type)) {
1553 continue; 1620 if (!partitions[i].size) {
1554 } 1621 printf("strange..., a BSD partition of size 0?\n");
1555 bsd_partition(dev, fd, &partitions[i], z); 1622 continue;
1556 } 1623 }
1557 } 1624 bsd_partition(dev, fd, &partitions[i], z);
1558 return 1; 1625 }
1626 }
1627 return 1;
1559} 1628}
1560 1629
1561static int 1630static int
1562osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1631osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z)
1632{
1563 return 0; 1633 return 0;
1564} 1634}
1565 1635
1566static int 1636static int
1567sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1637sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z)
1638{
1568 return 0; 1639 return 0;
1569} 1640}
1570 1641
1571static int 1642static int
1572amiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1643amiga_partition(char *dev, int fd, unsigned long start,
1644 struct disk_desc *z)
1645{
1573 return 0; 1646 return 0;
1574} 1647}
1575 1648
1576static void 1649static void get_partitions(char *dev, int fd, struct disk_desc *z)
1577get_partitions(char *dev, int fd, struct disk_desc *z) { 1650{
1578 z->partno = 0; 1651 z->partno = 0;
1579 1652
1580 if (!msdos_partition(dev, fd, 0, z) 1653 if (!msdos_partition(dev, fd, 0, z)
1581 && !osf_partition(dev, fd, 0, z) 1654 && !osf_partition(dev, fd, 0, z)
1582 && !sun_partition(dev, fd, 0, z) 1655 && !sun_partition(dev, fd, 0, z)
1583 && !amiga_partition(dev, fd, 0, z)) { 1656 && !amiga_partition(dev, fd, 0, z)) {
1584 printf(" %s: unrecognized partition\n", dev); 1657 printf(" %s: unrecognized partition\n", dev);
1585 return; 1658 return;
1586 } 1659 }
1587} 1660}
1588 1661
1589static int 1662static int write_partitions(char *dev, int fd, struct disk_desc *z)
1590write_partitions(char *dev, int fd, struct disk_desc *z) { 1663{
1591 struct sector *s; 1664 struct sector *s;
1592 struct part_desc *partitions = &(z->partitions[0]), *p; 1665 struct part_desc *partitions = &(z->partitions[0]), *p;
1593 int pno = z->partno; 1666 int pno = z->partno;
1594 1667
1595 if (no_write) { 1668 if (no_write) {
1596 printf("-n flag was given: Nothing changed\n"); 1669 printf("-n flag was given: Nothing changed\n");
1597 exit(0); 1670 exit(0);
1598 } 1671 }
1599 1672
1600 for (p = partitions; p < partitions+pno; p++) { 1673 for (p = partitions; p < partitions + pno; p++) {
1601 s = get_sector(dev, fd, p->sector); 1674 s = get_sector(dev, fd, p->sector);
1602 if (!s) return 0; 1675 if (!s)
1603 s->to_be_written = 1; 1676 return 0;
1604 copy_from_part(&(p->p), s->data + p->offset); 1677 s->to_be_written = 1;
1605 *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55; 1678 copy_from_part(&(p->p), s->data + p->offset);
1606 } 1679 *(unsigned short *) (&(s->data[0x1fe])) = 0xaa55;
1607 if (save_sector_file) { 1680 }
1608 if (!save_sectors(dev, fd)) { 1681 if (save_sector_file) {
1609 fatal("Failed saving the old sectors - aborting\n"); 1682 if (!save_sectors(dev, fd)) {
1610 return 0; 1683 fatal("Failed saving the old sectors - aborting\n");
1611 } 1684 return 0;
1612 } 1685 }
1613 if (!write_sectors(dev, fd)) { 1686 }
1614 error("Failed writing the partition on %s\n"), dev; 1687 if (!write_sectors(dev, fd)) {
1615 return 0; 1688 error("Failed writing the partition on %s\n"), dev;
1616 } 1689 return 0;
1617 return 1; 1690 }
1691 return 1;
1618} 1692}
1619 1693
1620/* 1694/*
@@ -1644,20 +1718,21 @@ write_partitions(char *dev, int fd, struct disk_desc *z) {
1644static int eof, eob; 1718static int eof, eob;
1645 1719
1646struct dumpfld { 1720struct dumpfld {
1647 int fldno; 1721 int fldno;
1648 char *fldname; 1722 char *fldname;
1649 int is_bool; 1723 int is_bool;
1650} dumpflds[] = { 1724} dumpflds[] = {
1651 { 0, "start", 0 }, 1725 {
1652 { 1, "size", 0 }, 1726 0, "start", 0}, {
1653 { 2, "Id", 0 }, 1727 1, "size", 0}, {
1654 { 3, "bootable", 1 }, 1728 2, "Id", 0}, {
1655 { 4, "bh", 0 }, 1729 3, "bootable", 1}, {
1656 { 5, "bs", 0 }, 1730 4, "bh", 0}, {
1657 { 6, "bc", 0 }, 1731 5, "bs", 0}, {
1658 { 7, "eh", 0 }, 1732 6, "bc", 0}, {
1659 { 8, "es", 0 }, 1733 7, "eh", 0}, {
1660 { 9, "ec", 0 } 1734 8, "es", 0}, {
1735 9, "ec", 0}
1661}; 1736};
1662 1737
1663/* 1738/*
@@ -1670,115 +1745,117 @@ struct dumpfld {
1670#define RD_CMD (-2) 1745#define RD_CMD (-2)
1671 1746
1672static int 1747static int
1673read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) { 1748read_stdin(unsigned char **fields, unsigned char *line, int fieldssize,
1674 unsigned char *lp, *ip; 1749 int linesize)
1675 int c, fno; 1750{
1676 1751 unsigned char *lp, *ip;
1677 /* boolean true and empty string at start */ 1752 int c, fno;
1678 line[0] = '*'; 1753
1679 line[1] = 0; 1754 /* boolean true and empty string at start */
1680 for (fno=0; fno < fieldssize; fno++) 1755 line[0] = '*';
1681 fields[fno] = line + 1; 1756 line[1] = 0;
1682 fno = 0; 1757 for (fno = 0; fno < fieldssize; fno++)
1683 1758 fields[fno] = line + 1;
1684 /* read a line from stdin */ 1759 fno = 0;
1685 lp = fgets(line+2, linesize, stdin); 1760
1686 if (lp == NULL) { 1761 /* read a line from stdin */
1687 eof = 1; 1762 lp = fgets(line + 2, linesize, stdin);
1688 return RD_EOF; 1763 if (lp == NULL) {
1689 } 1764 eof = 1;
1690 if (!(lp = index(lp, '\n'))) 1765 return RD_EOF;
1691 fatal("long or incomplete input line - quitting\n"); 1766 }
1692 *lp = 0; 1767 if (!(lp = index(lp, '\n')))
1693 1768 fatal("long or incomplete input line - quitting\n");
1694 /* remove comments, if any */ 1769 *lp = 0;
1695 if ((lp = index(line+2, '#')) != 0) 1770
1696 *lp = 0; 1771 /* remove comments, if any */
1697 1772 if ((lp = index(line + 2, '#')) != 0)
1698 /* recognize a few commands - to be expanded */ 1773 *lp = 0;
1699 if (!strcmp(line+2, "unit: sectors")) { 1774
1700 specified_format = F_SECTOR; 1775 /* recognize a few commands - to be expanded */
1701 return RD_CMD; 1776 if (!strcmp(line + 2, "unit: sectors")) {
1702 } 1777 specified_format = F_SECTOR;
1703 1778 return RD_CMD;
1704 /* dump style? - then bad input is fatal */ 1779 }
1705 if ((ip = index(line+2, ':')) != 0) { 1780
1706 struct dumpfld *d; 1781 /* dump style? - then bad input is fatal */
1707 1782 if ((ip = index(line + 2, ':')) != 0) {
1708 nxtfld: 1783 struct dumpfld *d;
1709 ip++; 1784
1710 while(isspace(*ip)) 1785 nxtfld:
1711 ip++; 1786 ip++;
1712 if (*ip == 0) 1787 while (isspace(*ip))
1713 return fno; 1788 ip++;
1714 for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) { 1789 if (*ip == 0)
1715 if(!strncmp(ip, d->fldname, strlen(d->fldname))) { 1790 return fno;
1716 ip += strlen(d->fldname); 1791 for (d = dumpflds; d - dumpflds < SIZE(dumpflds); d++) {
1717 while(isspace(*ip)) 1792 if (!strncmp(ip, d->fldname, strlen(d->fldname))) {
1718 ip++; 1793 ip += strlen(d->fldname);
1719 if (d->is_bool) 1794 while (isspace(*ip))
1720 fields[d->fldno] = line; 1795 ip++;
1721 else if (*ip == '=') { 1796 if (d->is_bool)
1722 while(isspace(*++ip)) ; 1797 fields[d->fldno] = line;
1723 fields[d->fldno] = ip; 1798 else if (*ip == '=') {
1724 while(isalnum(*ip)) /* 0x07FF */ 1799 while (isspace(*++ip));
1725 ip++; 1800 fields[d->fldno] = ip;
1726 } else 1801 while (isalnum(*ip)) /* 0x07FF */
1727 fatal("input error: `=' expected after %s field\n", 1802 ip++;
1728 d->fldname); 1803 } else
1729 if (fno <= d->fldno) 1804 fatal("input error: `=' expected after %s field\n",
1730 fno = d->fldno + 1; 1805 d->fldname);
1731 if(*ip == 0) 1806 if (fno <= d->fldno)
1732 return fno; 1807 fno = d->fldno + 1;
1733 if(*ip != ',' && *ip != ';') 1808 if (*ip == 0)
1734 fatal("input error: unexpected character %c after %s field\n", 1809 return fno;
1735 *ip, d->fldname); 1810 if (*ip != ',' && *ip != ';')
1736 *ip = 0; 1811 fatal
1737 goto nxtfld; 1812 ("input error: unexpected character %c after %s field\n",
1813 *ip, d->fldname);
1814 *ip = 0;
1815 goto nxtfld;
1816 }
1738 } 1817 }
1739 } 1818 fatal("unrecognized input: %s\n"), ip;
1740 fatal("unrecognized input: %s\n"), ip; 1819 }
1741 } 1820
1742 1821 /* split line into fields */
1743 /* split line into fields */ 1822 lp = ip = line + 2;
1744 lp = ip = line+2; 1823 fields[fno++] = lp;
1745 fields[fno++] = lp; 1824 while ((c = *ip++) != 0) {
1746 while((c = *ip++) != 0) { 1825 if (!lp[-1] && (c == '\t' || c == ' '));
1747 if (!lp[-1] && (c == '\t' || c == ' ')) 1826 else if (c == '\t' || c == ' ' || c == ',' || c == ';') {
1748 ; 1827 *lp++ = 0;
1749 else if (c == '\t' || c == ' ' || c == ',' || c == ';') { 1828 if (fno < fieldssize)
1750 *lp++ = 0; 1829 fields[fno++] = lp;
1751 if (fno < fieldssize) 1830 continue;
1752 fields[fno++] = lp; 1831 } else
1753 continue; 1832 *lp++ = c;
1754 } else 1833 }
1755 *lp++ = c;
1756 }
1757 1834
1758 if (lp == fields[fno-1]) 1835 if (lp == fields[fno - 1])
1759 fno--; 1836 fno--;
1760 return fno; 1837 return fno;
1761} 1838}
1762 1839
1763/* read a number, use default if absent */ 1840/* read a number, use default if absent */
1764static int 1841static int get_ul(char *u, unsigned long *up, unsigned long def, int base)
1765get_ul(char *u, unsigned long *up, unsigned long def, int base) { 1842{
1766 char *nu; 1843 char *nu;
1767 1844
1768 if (*u) { 1845 if (*u) {
1769 errno = 0; 1846 errno = 0;
1770 *up = strtoul(u, &nu, base); 1847 *up = strtoul(u, &nu, base);
1771 if (errno == ERANGE) { 1848 if (errno == ERANGE) {
1772 printf("number too big\n"); 1849 printf("number too big\n");
1773 return -1; 1850 return -1;
1774 } 1851 }
1775 if (*nu) { 1852 if (*nu) {
1776 printf("trailing junk after number\n"); 1853 printf("trailing junk after number\n");
1777 return -1; 1854 return -1;
1778 } 1855 }
1779 } else 1856 } else
1780 *up = def; 1857 *up = def;
1781 return 0; 1858 return 0;
1782} 1859}
1783 1860
1784/* There are two common ways to structure extended partitions: 1861/* There are two common ways to structure extended partitions:
@@ -1800,445 +1877,460 @@ static enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED;
1800/* find the default value for <start> - assuming entire units */ 1877/* find the default value for <start> - assuming entire units */
1801static unsigned long 1878static unsigned long
1802first_free(int pno, int is_extended, struct part_desc *ep, int format, 1879first_free(int pno, int is_extended, struct part_desc *ep, int format,
1803 unsigned long mid, struct disk_desc *z) { 1880 unsigned long mid, struct disk_desc *z)
1804 unsigned long ff, fff; 1881{
1805 unsigned long unit = unitsize(format); 1882 unsigned long ff, fff;
1806 struct part_desc *partitions = &(z->partitions[0]), *pp = 0; 1883 unsigned long unit = unitsize(format);
1807 1884 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1808 /* if containing ep undefined, look at its container */ 1885
1809 if (ep && ep->p.sys_type == EMPTY_PARTITION) 1886 /* if containing ep undefined, look at its container */
1810 ep = ep->ep; 1887 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1811 1888 ep = ep->ep;
1812 if (ep) { 1889
1813 if (boxes == NESTED || (boxes == CHAINED && !is_extended)) 1890 if (ep) {
1814 pp = ep; 1891 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1815 else if (all_logicals_inside_outermost_extended) 1892 pp = ep;
1816 pp = outer_extended_partition(ep); 1893 else if (all_logicals_inside_outermost_extended)
1817 } 1894 pp = outer_extended_partition(ep);
1895 }
1818#if 0 1896#if 0
1819 ff = pp ? (pp->start + unit - 1) / unit : 0; 1897 ff = pp ? (pp->start + unit - 1) / unit : 0;
1820#else 1898#else
1821 /* rounding up wastes almost an entire cylinder - round down 1899 /* rounding up wastes almost an entire cylinder - round down
1822 and leave it to compute_start_sect() to fix the difference */ 1900 and leave it to compute_start_sect() to fix the difference */
1823 ff = pp ? pp->start / unit : 0; 1901 ff = pp ? pp->start / unit : 0;
1824#endif 1902#endif
1825 /* MBR and 1st sector of an extended partition are never free */ 1903 /* MBR and 1st sector of an extended partition are never free */
1826 if (unit == 1) 1904 if (unit == 1)
1827 ff++; 1905 ff++;
1828 1906
1829 again: 1907 again:
1830 for(pp = partitions; pp < partitions+pno; pp++) { 1908 for (pp = partitions; pp < partitions + pno; pp++) {
1831 if (!is_parent(pp, ep) && pp->size > 0) { 1909 if (!is_parent(pp, ep) && pp->size > 0) {
1832 if ((partitions_in_order || pp->start / unit <= ff 1910 if ((partitions_in_order || pp->start / unit <= ff
1833 || (mid && pp->start / unit <= mid)) 1911 || (mid && pp->start / unit <= mid))
1834 && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) { 1912 && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) {
1835 ff = fff; 1913 ff = fff;
1836 goto again; 1914 goto again;
1837 } 1915 }
1916 }
1838 } 1917 }
1839 }
1840 1918
1841 return ff; 1919 return ff;
1842} 1920}
1843 1921
1844/* find the default value for <size> - assuming entire units */ 1922/* find the default value for <size> - assuming entire units */
1845static unsigned long 1923static unsigned long
1846max_length(int pno, int is_extended, struct part_desc *ep, int format, 1924max_length(int pno, int is_extended, struct part_desc *ep, int format,
1847 unsigned long start, struct disk_desc *z) { 1925 unsigned long start, struct disk_desc *z)
1848 unsigned long fu; 1926{
1849 unsigned long unit = unitsize(format); 1927 unsigned long fu;
1850 struct part_desc *partitions = &(z->partitions[0]), *pp = 0; 1928 unsigned long unit = unitsize(format);
1851 1929 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1852 /* if containing ep undefined, look at its container */ 1930
1853 if (ep && ep->p.sys_type == EMPTY_PARTITION) 1931 /* if containing ep undefined, look at its container */
1854 ep = ep->ep; 1932 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1855 1933 ep = ep->ep;
1856 if (ep) { 1934
1857 if (boxes == NESTED || (boxes == CHAINED && !is_extended)) 1935 if (ep) {
1858 pp = ep; 1936 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1859 else if (all_logicals_inside_outermost_extended) 1937 pp = ep;
1860 pp = outer_extended_partition(ep); 1938 else if (all_logicals_inside_outermost_extended)
1861 } 1939 pp = outer_extended_partition(ep);
1862 fu = pp ? (pp->start + pp->size) / unit : get_disksize(format); 1940 }
1863 1941 fu = pp ? (pp->start + pp->size) / unit : get_disksize(format);
1864 for(pp = partitions; pp < partitions+pno; pp++) 1942
1865 if (!is_parent(pp, ep) && pp->size > 0 1943 for (pp = partitions; pp < partitions + pno; pp++)
1866 && pp->start / unit >= start && pp->start / unit < fu) 1944 if (!is_parent(pp, ep) && pp->size > 0
1867 fu = pp->start / unit; 1945 && pp->start / unit >= start && pp->start / unit < fu)
1868 1946 fu = pp->start / unit;
1869 return (fu > start) ? fu - start : 0; 1947
1948 return (fu > start) ? fu - start : 0;
1870} 1949}
1871 1950
1872/* compute starting sector of a partition inside an extended one */ 1951/* compute starting sector of a partition inside an extended one */
1873/* ep is 0 or points to surrounding extended partition */ 1952/* ep is 0 or points to surrounding extended partition */
1874static int 1953static int compute_start_sect(struct part_desc *p, struct part_desc *ep)
1875compute_start_sect(struct part_desc *p, struct part_desc *ep) { 1954{
1876 unsigned long base; 1955 unsigned long base;
1877 int inc = (DOS && B.sectors) ? B.sectors : 1; 1956 int inc = (DOS && B.sectors) ? B.sectors : 1;
1878 int delta; 1957 int delta;
1879 1958
1880 if (ep && p->start + p->size >= ep->start + 1) 1959 if (ep && p->start + p->size >= ep->start + 1)
1881 delta = p->start - ep->start - inc; 1960 delta = p->start - ep->start - inc;
1882 else if (p->start == 0 && p->size > 0) 1961 else if (p->start == 0 && p->size > 0)
1883 delta = -inc; 1962 delta = -inc;
1884 else 1963 else
1885 delta = 0; 1964 delta = 0;
1886 if (delta < 0) { 1965 if (delta < 0) {
1887 p->start -= delta; 1966 p->start -= delta;
1888 p->size += delta; 1967 p->size += delta;
1889 if (is_extended(p->p.sys_type) && boxes == ONESECTOR) 1968 if (is_extended(p->p.sys_type) && boxes == ONESECTOR)
1890 p->size = inc; 1969 p->size = inc;
1891 else if ((int)(p->size) <= 0) { 1970 else if ((int) (p->size) <= 0) {
1892 warn("no room for partition descriptor\n"); 1971 warn("no room for partition descriptor\n");
1893 return 0; 1972 return 0;
1894 } 1973 }
1895 } 1974 }
1896 base = (!ep ? 0 1975 base = (!ep ? 0
1897 : (is_extended(p->p.sys_type) ? 1976 : (is_extended(p->p.sys_type) ?
1898 outer_extended_partition(ep) : ep)->start); 1977 outer_extended_partition(ep) : ep)->start);
1899 p->ep = ep; 1978 p->ep = ep;
1900 if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) { 1979 if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) {
1901 p->p.start_sect = 0; 1980 p->p.start_sect = 0;
1902 p->p.begin_chs = zero_chs; 1981 p->p.begin_chs = zero_chs;
1903 p->p.end_chs = zero_chs; 1982 p->p.end_chs = zero_chs;
1904 } else { 1983 } else {
1905 p->p.start_sect = p->start - base; 1984 p->p.start_sect = p->start - base;
1906 p->p.begin_chs = ulong_to_chs(p->start,B); 1985 p->p.begin_chs = ulong_to_chs(p->start, B);
1907 p->p.end_chs = ulong_to_chs(p->start + p->size - 1,B); 1986 p->p.end_chs = ulong_to_chs(p->start + p->size - 1, B);
1908 } 1987 }
1909 p->p.nr_sects = p->size; 1988 p->p.nr_sects = p->size;
1910 return 1; 1989 return 1;
1911} 1990}
1912 1991
1913/* build the extended partition surrounding a given logical partition */ 1992/* build the extended partition surrounding a given logical partition */
1914static int 1993static int
1915build_surrounding_extended(struct part_desc *p, struct part_desc *ep, 1994build_surrounding_extended(struct part_desc *p, struct part_desc *ep,
1916 struct disk_desc *z) { 1995 struct disk_desc *z)
1917 int inc = (DOS && B.sectors) ? B.sectors : 1; 1996{
1918 int format = F_SECTOR; 1997 int inc = (DOS && B.sectors) ? B.sectors : 1;
1919 struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep; 1998 int format = F_SECTOR;
1920 1999 struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep;
1921 if (boxes == NESTED) { 2000
1922 ep->start = first_free(ep-p0, 1, eep, format, p->start, z); 2001 if (boxes == NESTED) {
1923 ep->size = max_length(ep-p0, 1, eep, format, ep->start, z); 2002 ep->start = first_free(ep - p0, 1, eep, format, p->start, z);
1924 if (ep->start > p->start || ep->start + ep->size < p->start + p->size) { 2003 ep->size = max_length(ep - p0, 1, eep, format, ep->start, z);
1925 warn("cannot build surrounding extended partition\n"); 2004 if (ep->start > p->start
1926 return 0; 2005 || ep->start + ep->size < p->start + p->size) {
1927 } 2006 warn("cannot build surrounding extended partition\n");
1928 } else { 2007 return 0;
1929 ep->start = p->start; 2008 }
1930 if(boxes == CHAINED) 2009 } else {
1931 ep->size = p->size; 2010 ep->start = p->start;
1932 else 2011 if (boxes == CHAINED)
1933 ep->size = inc; 2012 ep->size = p->size;
1934 } 2013 else
1935 2014 ep->size = inc;
1936 ep->p.nr_sects = ep->size; 2015 }
1937 ep->p.bootable = 0; 2016
1938 ep->p.sys_type = EXTENDED_PARTITION; 2017 ep->p.nr_sects = ep->size;
1939 if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) { 2018 ep->p.bootable = 0;
1940 ep->p.sys_type = EMPTY_PARTITION; 2019 ep->p.sys_type = EXTENDED_PARTITION;
1941 ep->size = 0; 2020 if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) {
1942 return 0; 2021 ep->p.sys_type = EMPTY_PARTITION;
1943 } 2022 ep->size = 0;
2023 return 0;
2024 }
1944 2025
1945 return 1; 2026 return 1;
1946} 2027}
1947 2028
1948static int 2029static int
1949read_line(int pno, struct part_desc *ep, char *dev, int interactive, 2030read_line(int pno, struct part_desc *ep, char *dev, int interactive,
1950 struct disk_desc *z) { 2031 struct disk_desc *z)
1951 unsigned char line[1000]; 2032{
1952 unsigned char *fields[11]; 2033 unsigned char line[1000];
1953 int fno, pct = pno%4; 2034 unsigned char *fields[11];
1954 struct part_desc p, *orig; 2035 int fno, pct = pno % 4;
1955 unsigned long ff, ff1, ul, ml, ml1, def; 2036 struct part_desc p, *orig;
1956 int format, lpno, is_extd; 2037 unsigned long ff, ff1, ul, ml, ml1, def;
1957 2038 int format, lpno, is_extd;
1958 if (eof || eob)
1959 return -1;
1960
1961 lpno = index_to_linux(pno, z);
1962
1963 if (interactive) {
1964 if (pct == 0 && (show_extended || pno == 0))
1965 warn("\n");
1966 warn("%8s%d: ", dev, lpno);
1967 }
1968
1969 /* read input line - skip blank lines when reading from a file */
1970 do {
1971 fno = read_stdin(fields, line, SIZE(fields), SIZE(line));
1972 } while(fno == RD_CMD || (fno == 0 && !interactive));
1973 if (fno == RD_EOF) {
1974 return -1;
1975 } else if (fno > 10 && *(fields[10]) != 0) {
1976 printf("too many input fields\n");
1977 return 0;
1978 }
1979 2039
1980 if (fno == 1 && !strcmp(fields[0], ".")) { 2040 if (eof || eob)
1981 eob = 1; 2041 return -1;
1982 return -1; 2042
1983 } 2043 lpno = index_to_linux(pno, z);
2044
2045 if (interactive) {
2046 if (pct == 0 && (show_extended || pno == 0))
2047 warn("\n");
2048 warn("%8s%d: ", dev, lpno);
2049 }
1984 2050
1985 /* use specified format, but round to cylinders if F_MEGABYTE specified */ 2051 /* read input line - skip blank lines when reading from a file */
1986 format = 0; 2052 do {
1987 if (B.cylindersize && specified_format == F_MEGABYTE) 2053 fno = read_stdin(fields, line, SIZE(fields), SIZE(line));
1988 format = F_CYLINDER; 2054 } while (fno == RD_CMD || (fno == 0 && !interactive));
2055 if (fno == RD_EOF) {
2056 return -1;
2057 } else if (fno > 10 && *(fields[10]) != 0) {
2058 printf("too many input fields\n");
2059 return 0;
2060 }
1989 2061
1990 orig = (one_only ? &(oldp.partitions[pno]) : 0); 2062 if (fno == 1 && !strcmp(fields[0], ".")) {
2063 eob = 1;
2064 return -1;
2065 }
1991 2066
1992 p = zero_part_desc; 2067 /* use specified format, but round to cylinders if F_MEGABYTE specified */
1993 p.ep = ep; 2068 format = 0;
2069 if (B.cylindersize && specified_format == F_MEGABYTE)
2070 format = F_CYLINDER;
2071
2072 orig = (one_only ? &(oldp.partitions[pno]) : 0);
2073
2074 p = zero_part_desc;
2075 p.ep = ep;
2076
2077 /* first read the type - we need to know whether it is extended */
2078 /* stop reading when input blank (defaults) and all is full */
2079 is_extd = 0;
2080 if (fno == 0) { /* empty line */
2081 if (orig && is_extended(orig->p.sys_type))
2082 is_extd = 1;
2083 ff = first_free(pno, is_extd, ep, format, 0, z);
2084 ml = max_length(pno, is_extd, ep, format, ff, z);
2085 if (ml == 0 && is_extd == 0) {
2086 is_extd = 1;
2087 ff = first_free(pno, is_extd, ep, format, 0, z);
2088 ml = max_length(pno, is_extd, ep, format, ff, z);
2089 }
2090 if (ml == 0 && pno >= 4) {
2091 /* no free blocks left - don't read any further */
2092 warn("No room for more\n");
2093 return -1;
2094 }
2095 }
2096 if (fno < 3 || !*(fields[2]))
2097 ul = orig ? orig->p.sys_type :
2098 (is_extd || (pno > 3 && pct == 1 && show_extended))
2099 ? EXTENDED_PARTITION : LINUX_NATIVE;
2100 else if (!strcmp(fields[2], "L"))
2101 ul = LINUX_NATIVE;
2102 else if (!strcmp(fields[2], "S"))
2103 ul = LINUX_SWAP;
2104 else if (!strcmp(fields[2], "E"))
2105 ul = EXTENDED_PARTITION;
2106 else if (!strcmp(fields[2], "X"))
2107 ul = LINUX_EXTENDED;
2108 else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16))
2109 return 0;
2110 if (ul > 255) {
2111 warn("Illegal type\n");
2112 return 0;
2113 }
2114 p.p.sys_type = ul;
2115 is_extd = is_extended(ul);
1994 2116
1995 /* first read the type - we need to know whether it is extended */ 2117 /* find start */
1996 /* stop reading when input blank (defaults) and all is full */
1997 is_extd = 0;
1998 if (fno == 0) { /* empty line */
1999 if (orig && is_extended(orig->p.sys_type))
2000 is_extd = 1;
2001 ff = first_free(pno, is_extd, ep, format, 0, z); 2118 ff = first_free(pno, is_extd, ep, format, 0, z);
2002 ml = max_length(pno, is_extd, ep, format, ff, z); 2119 ff1 = ff * unitsize(format);
2003 if (ml == 0 && is_extd == 0) { 2120 def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1;
2004 is_extd = 1; 2121 if (fno < 1 || !*(fields[0]))
2005 ff = first_free(pno, is_extd, ep, format, 0, z); 2122 p.start = def;
2006 ml = max_length(pno, is_extd, ep, format, ff, z); 2123 else {
2007 } 2124 if (get_ul(fields[0], &ul, def / unitsize(0), 0))
2008 if (ml == 0 && pno >= 4) { 2125 return 0;
2009 /* no free blocks left - don't read any further */ 2126 p.start = ul * unitsize(0);
2010 warn("No room for more\n"); 2127 p.start -= (p.start % unitsize(format));
2011 return -1; 2128 }
2012 }
2013 }
2014 if (fno < 3 || !*(fields[2]))
2015 ul = orig ? orig->p.sys_type :
2016 (is_extd || (pno > 3 && pct == 1 && show_extended))
2017 ? EXTENDED_PARTITION : LINUX_NATIVE;
2018 else if(!strcmp(fields[2], "L"))
2019 ul = LINUX_NATIVE;
2020 else if(!strcmp(fields[2], "S"))
2021 ul = LINUX_SWAP;
2022 else if(!strcmp(fields[2], "E"))
2023 ul = EXTENDED_PARTITION;
2024 else if(!strcmp(fields[2], "X"))
2025 ul = LINUX_EXTENDED;
2026 else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16))
2027 return 0;
2028 if (ul > 255) {
2029 warn("Illegal type\n");
2030 return 0;
2031 }
2032 p.p.sys_type = ul;
2033 is_extd = is_extended(ul);
2034
2035 /* find start */
2036 ff = first_free(pno, is_extd, ep, format, 0, z);
2037 ff1 = ff * unitsize(format);
2038 def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1;
2039 if (fno < 1 || !*(fields[0]))
2040 p.start = def;
2041 else {
2042 if (get_ul(fields[0], &ul, def / unitsize(0), 0))
2043 return 0;
2044 p.start = ul * unitsize(0);
2045 p.start -= (p.start % unitsize(format));
2046 }
2047
2048 /* find length */
2049 ml = max_length(pno, is_extd, ep, format, p.start / unitsize(format), z);
2050 ml1 = ml * unitsize(format);
2051 def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1;
2052 if (fno < 2 || !*(fields[1]))
2053 p.size = def;
2054 else {
2055 if (get_ul(fields[1], &ul, def / unitsize(0), 0))
2056 return 0;
2057 p.size = ul * unitsize(0) + unitsize(format) - 1;
2058 p.size -= (p.size % unitsize(format));
2059 }
2060 if (p.size > ml1) {
2061 warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0));
2062 if (!force)
2063 return 0;
2064 }
2065 if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) {
2066 warn("Warning: empty partition\n");
2067 if (!force)
2068 return 0;
2069 }
2070 p.p.nr_sects = p.size;
2071
2072 if (p.size == 0 && !orig) {
2073 if(fno < 1 || !*(fields[0]))
2074 p.start = 0;
2075 if(fno < 3 || !*(fields[2]))
2076 p.p.sys_type = EMPTY_PARTITION;
2077 }
2078
2079 if (p.start < ff1 && p.size > 0) {
2080 warn("Warning: bad partition start (earliest %lu)\n",
2081 (ff1 + unitsize(0) - 1) / unitsize(0));
2082 if (!force)
2083 return 0;
2084 }
2085
2086 if (fno < 4 || !*(fields[3]))
2087 ul = (orig ? orig->p.bootable : 0);
2088 else if (!strcmp(fields[3], "-"))
2089 ul = 0;
2090 else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+"))
2091 ul = 0x80;
2092 else {
2093 warn("unrecognized bootable flag - choose - or *\n");
2094 return 0;
2095 }
2096 p.p.bootable = ul;
2097
2098 if (ep && ep->p.sys_type == EMPTY_PARTITION) {
2099 if(!build_surrounding_extended(&p, ep, z))
2100 return 0;
2101 } else
2102 if(!compute_start_sect(&p, ep))
2103 return 0;
2104 2129
2105 { longchs aa = chs_to_longchs(p.p.begin_chs), bb; 2130 /* find length */
2131 ml =
2132 max_length(pno, is_extd, ep, format, p.start / unitsize(format),
2133 z);
2134 ml1 = ml * unitsize(format);
2135 def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1;
2136 if (fno < 2 || !*(fields[1]))
2137 p.size = def;
2138 else {
2139 if (get_ul(fields[1], &ul, def / unitsize(0), 0))
2140 return 0;
2141 p.size = ul * unitsize(0) + unitsize(format) - 1;
2142 p.size -= (p.size % unitsize(format));
2143 }
2144 if (p.size > ml1) {
2145 warn("Warning: exceeds max allowable size (%lu)\n",
2146 ml1 / unitsize(0));
2147 if (!force)
2148 return 0;
2149 }
2150 if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) {
2151 warn("Warning: empty partition\n");
2152 if (!force)
2153 return 0;
2154 }
2155 p.p.nr_sects = p.size;
2106 2156
2107 if (fno < 5) { 2157 if (p.size == 0 && !orig) {
2108 bb = aa; 2158 if (fno < 1 || !*(fields[0]))
2109 } else if (fno < 7) { 2159 p.start = 0;
2110 warn("partial c,h,s specification?\n"); 2160 if (fno < 3 || !*(fields[2]))
2111 return 0; 2161 p.p.sys_type = EMPTY_PARTITION;
2112 } else if(get_ul(fields[4], &bb.c, aa.c, 0) || 2162 }
2113 get_ul(fields[5], &bb.h, aa.h, 0) || 2163
2114 get_ul(fields[6], &bb.s, aa.s, 0)) 2164 if (p.start < ff1 && p.size > 0) {
2115 return 0; 2165 warn("Warning: bad partition start (earliest %lu)\n",
2116 p.p.begin_chs = longchs_to_chs(bb,B); 2166 (ff1 + unitsize(0) - 1) / unitsize(0));
2117 } 2167 if (!force)
2118 { longchs aa = chs_to_longchs(p.p.end_chs), bb; 2168 return 0;
2119 2169 }
2120 if (fno < 8) { 2170
2121 bb = aa; 2171 if (fno < 4 || !*(fields[3]))
2122 } else if (fno < 10) { 2172 ul = (orig ? orig->p.bootable : 0);
2123 warn("partial c,h,s specification?\n"); 2173 else if (!strcmp(fields[3], "-"))
2124 return 0; 2174 ul = 0;
2125 } else if(get_ul(fields[7], &bb.c, aa.c, 0) || 2175 else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+"))
2126 get_ul(fields[8], &bb.h, aa.h, 0) || 2176 ul = 0x80;
2127 get_ul(fields[9], &bb.s, aa.s, 0)) 2177 else {
2128 return 0; 2178 warn("unrecognized bootable flag - choose - or *\n");
2129 p.p.end_chs = longchs_to_chs(bb, B); 2179 return 0;
2130 } 2180 }
2181 p.p.bootable = ul;
2182
2183 if (ep && ep->p.sys_type == EMPTY_PARTITION) {
2184 if (!build_surrounding_extended(&p, ep, z))
2185 return 0;
2186 } else if (!compute_start_sect(&p, ep))
2187 return 0;
2131 2188
2132 if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION 2189 {
2133 && (is_extended(p.p.sys_type) != (pct == 1))) { 2190 longchs aa = chs_to_longchs(p.p.begin_chs), bb;
2134 warn("Extended partition not where expected\n"); 2191
2135 if (!force) 2192 if (fno < 5) {
2136 return 0; 2193 bb = aa;
2137 } 2194 } else if (fno < 7) {
2195 warn("partial c,h,s specification?\n");
2196 return 0;
2197 } else if (get_ul(fields[4], &bb.c, aa.c, 0) ||
2198 get_ul(fields[5], &bb.h, aa.h, 0) ||
2199 get_ul(fields[6], &bb.s, aa.s, 0))
2200 return 0;
2201 p.p.begin_chs = longchs_to_chs(bb, B);
2202 }
2203 {
2204 longchs aa = chs_to_longchs(p.p.end_chs), bb;
2205
2206 if (fno < 8) {
2207 bb = aa;
2208 } else if (fno < 10) {
2209 warn("partial c,h,s specification?\n");
2210 return 0;
2211 } else if (get_ul(fields[7], &bb.c, aa.c, 0) ||
2212 get_ul(fields[8], &bb.h, aa.h, 0) ||
2213 get_ul(fields[9], &bb.s, aa.s, 0))
2214 return 0;
2215 p.p.end_chs = longchs_to_chs(bb, B);
2216 }
2217
2218 if (pno > 3 && p.size && show_extended
2219 && p.p.sys_type != EMPTY_PARTITION
2220 && (is_extended(p.p.sys_type) != (pct == 1))) {
2221 warn("Extended partition not where expected\n");
2222 if (!force)
2223 return 0;
2224 }
2138 2225
2139 z->partitions[pno] = p; 2226 z->partitions[pno] = p;
2140 if (pno >= z->partno) 2227 if (pno >= z->partno)
2141 z->partno += 4; /* reqd for out_partition() */ 2228 z->partno += 4; /* reqd for out_partition() */
2142 2229
2143 if (interactive) 2230 if (interactive)
2144 out_partition(dev, 0, &(z->partitions[pno]), z, B); 2231 out_partition(dev, 0, &(z->partitions[pno]), z, B);
2145 2232
2146 return 1; 2233 return 1;
2147} 2234}
2148 2235
2149/* ep either points to the extended partition to contain this one, 2236/* ep either points to the extended partition to contain this one,
2150 or to the empty partition that may become extended or is 0 */ 2237 or to the empty partition that may become extended or is 0 */
2151static int 2238static int
2152read_partition(char *dev, int interactive, int pno, struct part_desc *ep, 2239read_partition(char *dev, int interactive, int pno, struct part_desc *ep,
2153 struct disk_desc *z) { 2240 struct disk_desc *z)
2154 struct part_desc *p = &(z->partitions[pno]); 2241{
2155 int i; 2242 struct part_desc *p = &(z->partitions[pno]);
2156 2243 int i;
2157 if (one_only) { 2244
2158 *p = oldp.partitions[pno]; 2245 if (one_only) {
2159 if (one_only_pno != pno) 2246 *p = oldp.partitions[pno];
2160 goto ret; 2247 if (one_only_pno != pno)
2161 } else if (!show_extended && pno > 4 && pno%4) 2248 goto ret;
2162 goto ret; 2249 } else if (!show_extended && pno > 4 && pno % 4)
2163 2250 goto ret;
2164 while (!(i = read_line(pno, ep, dev, interactive, z))) 2251
2165 if (!interactive) 2252 while (!(i = read_line(pno, ep, dev, interactive, z)))
2166 fatal("bad input\n"); 2253 if (!interactive)
2167 if (i < 0) { 2254 fatal("bad input\n");
2168 p->ep = ep; 2255 if (i < 0) {
2169 return 0; 2256 p->ep = ep;
2170 } 2257 return 0;
2258 }
2171 2259
2172 ret: 2260 ret:
2173 p->ep = ep; 2261 p->ep = ep;
2174 if (pno >= z->partno) 2262 if (pno >= z->partno)
2175 z->partno += 4; 2263 z->partno += 4;
2176 return 1; 2264 return 1;
2177} 2265}
2178 2266
2179static void 2267static void
2180read_partition_chain(char *dev, int interactive, struct part_desc *ep, 2268read_partition_chain(char *dev, int interactive, struct part_desc *ep,
2181 struct disk_desc *z) { 2269 struct disk_desc *z)
2182 int i, base; 2270{
2183 2271 int i, base;
2184 eob = 0; 2272
2185 while (1) { 2273 eob = 0;
2186 base = z->partno; 2274 while (1) {
2187 if (base+4 > SIZE(z->partitions)) { 2275 base = z->partno;
2188 printf("too many partitions\n"); 2276 if (base + 4 > SIZE(z->partitions)) {
2189 break; 2277 printf("too many partitions\n");
2190 } 2278 break;
2191 for (i=0; i<4; i++) 2279 }
2192 if (!read_partition(dev, interactive, base+i, ep, z)) 2280 for (i = 0; i < 4; i++)
2193 return; 2281 if (!read_partition(dev, interactive, base + i, ep, z))
2194 for (i=0; i<4; i++) { 2282 return;
2195 ep = &(z->partitions[base+i]); 2283 for (i = 0; i < 4; i++) {
2196 if (is_extended(ep->p.sys_type) && ep->size) 2284 ep = &(z->partitions[base + i]);
2197 break; 2285 if (is_extended(ep->p.sys_type) && ep->size)
2198 } 2286 break;
2199 if (i == 4) { 2287 }
2200 /* nothing found - maybe an empty partition is going 2288 if (i == 4) {
2201 to be extended */ 2289 /* nothing found - maybe an empty partition is going
2202 if (one_only || show_extended) 2290 to be extended */
2203 break; 2291 if (one_only || show_extended)
2204 ep = &(z->partitions[base+1]); 2292 break;
2205 if (ep->size || ep->p.sys_type != EMPTY_PARTITION) 2293 ep = &(z->partitions[base + 1]);
2206 break; 2294 if (ep->size || ep->p.sys_type != EMPTY_PARTITION)
2207 } 2295 break;
2208 } 2296 }
2297 }
2209} 2298}
2210 2299
2211static void 2300static void read_input(char *dev, int interactive, struct disk_desc *z)
2212read_input(char *dev, int interactive, struct disk_desc *z) { 2301{
2213 int i; 2302 int i;
2214 struct part_desc *partitions = &(z->partitions[0]), *ep; 2303 struct part_desc *partitions = &(z->partitions[0]), *ep;
2215 2304
2216 for (i=0; i < SIZE(z->partitions); i++) 2305 for (i = 0; i < SIZE(z->partitions); i++)
2217 partitions[i] = zero_part_desc; 2306 partitions[i] = zero_part_desc;
2218 z->partno = 0; 2307 z->partno = 0;
2219 2308
2220 if (interactive) 2309 if (interactive)
2221 warn("Input in the following format; absent fields get a default value.\n" 2310 warn
2222 "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n" 2311 ("Input in the following format; absent fields get a default value.\n"
2223 "Usually you only need to specify <start> and <size> (and perhaps <type>).\n"); 2312 "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n"
2224 eof = 0; 2313 "Usually you only need to specify <start> and <size> (and perhaps <type>).\n");
2225 2314 eof = 0;
2226 for (i=0; i<4; i++) 2315
2227 read_partition(dev, interactive, i, 0, z); 2316 for (i = 0; i < 4; i++)
2228 for (i=0; i<4; i++) { 2317 read_partition(dev, interactive, i, 0, z);
2229 ep = partitions+i; 2318 for (i = 0; i < 4; i++) {
2230 if (is_extended(ep->p.sys_type) && ep->size) 2319 ep = partitions + i;
2231 read_partition_chain(dev, interactive, ep, z); 2320 if (is_extended(ep->p.sys_type) && ep->size)
2232 } 2321 read_partition_chain(dev, interactive, ep, z);
2233 add_sector_and_offset(z); 2322 }
2323 add_sector_and_offset(z);
2234} 2324}
2235 2325
2236/* 2326/*
2237 * G. The command line 2327 * G. The command line
2238 */ 2328 */
2239 2329
2240static void version(void) { 2330static void version(void)
2241 printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION, DATE); 2331{
2332 printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION,
2333 DATE);
2242} 2334}
2243 2335
2244static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V"; 2336static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V";
@@ -2247,77 +2339,78 @@ static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V";
2247#define CHANGE_ID 01000 2339#define CHANGE_ID 01000
2248 2340
2249static const struct option long_opts[] = { 2341static const struct option long_opts[] = {
2250 { "change-id", no_argument, NULL, 'c' + CHANGE_ID }, 2342 {"change-id", no_argument, NULL, 'c' + CHANGE_ID},
2251 { "print-id", no_argument, NULL, 'c' + PRINT_ID }, 2343 {"print-id", no_argument, NULL, 'c' + PRINT_ID},
2252 { "id", no_argument, NULL, 'c' }, 2344 {"id", no_argument, NULL, 'c'},
2253 { "dump", no_argument, NULL, 'd' }, 2345 {"dump", no_argument, NULL, 'd'},
2254 { "force", no_argument, NULL, 'f' }, 2346 {"force", no_argument, NULL, 'f'},
2255 { "show-geometry", no_argument, NULL, 'g' }, 2347 {"show-geometry", no_argument, NULL, 'g'},
2256 { "increment", no_argument, NULL, 'i' }, 2348 {"increment", no_argument, NULL, 'i'},
2257 { "list", no_argument, NULL, 'l' }, 2349 {"list", no_argument, NULL, 'l'},
2258 { "quiet", no_argument, NULL, 'q' }, 2350 {"quiet", no_argument, NULL, 'q'},
2259 { "show-size", no_argument, NULL, 's' }, 2351 {"show-size", no_argument, NULL, 's'},
2260 { "unit", required_argument, NULL, 'u' }, 2352 {"unit", required_argument, NULL, 'u'},
2261 { "version", no_argument, NULL, 'v' }, 2353 {"version", no_argument, NULL, 'v'},
2262 { "show-extended", no_argument, NULL, 'x' }, 2354 {"show-extended", no_argument, NULL, 'x'},
2263 { "help", no_argument, NULL, '?' }, 2355 {"help", no_argument, NULL, '?'},
2264 { "one-only", no_argument, NULL, '1' }, 2356 {"one-only", no_argument, NULL, '1'},
2265 { "cylinders", required_argument, NULL, 'C' }, 2357 {"cylinders", required_argument, NULL, 'C'},
2266 { "heads", required_argument, NULL, 'H' }, 2358 {"heads", required_argument, NULL, 'H'},
2267 { "sectors", required_argument, NULL, 'S' }, 2359 {"sectors", required_argument, NULL, 'S'},
2268 { "activate", optional_argument, NULL, 'A' }, 2360 {"activate", optional_argument, NULL, 'A'},
2269 { "DOS", no_argument, NULL, 'D' }, 2361 {"DOS", no_argument, NULL, 'D'},
2270 { "Linux", no_argument, NULL, 'L' }, 2362 {"Linux", no_argument, NULL, 'L'},
2271 { "re-read", no_argument, NULL, 'R' }, 2363 {"re-read", no_argument, NULL, 'R'},
2272 { "list-types", no_argument, NULL, 'T' }, 2364 {"list-types", no_argument, NULL, 'T'},
2273 { "unhide", optional_argument, NULL, 'U' }, 2365 {"unhide", optional_argument, NULL, 'U'},
2274 { "no-reread", no_argument, NULL, 160 }, 2366 {"no-reread", no_argument, NULL, 160},
2275 { "IBM", no_argument, NULL, 161 }, 2367 {"IBM", no_argument, NULL, 161},
2276 { "leave-last", no_argument, NULL, 161 }, 2368 {"leave-last", no_argument, NULL, 161},
2277/* undocumented flags - not all completely implemented */ 2369/* undocumented flags - not all completely implemented */
2278 { "in-order", no_argument, NULL, 128 }, 2370 {"in-order", no_argument, NULL, 128},
2279 { "not-in-order", no_argument, NULL, 129 }, 2371 {"not-in-order", no_argument, NULL, 129},
2280 { "inside-outer", no_argument, NULL, 130 }, 2372 {"inside-outer", no_argument, NULL, 130},
2281 { "not-inside-outer", no_argument, NULL, 131 }, 2373 {"not-inside-outer", no_argument, NULL, 131},
2282 { "nested", no_argument, NULL, 132 }, 2374 {"nested", no_argument, NULL, 132},
2283 { "chained", no_argument, NULL, 133 }, 2375 {"chained", no_argument, NULL, 133},
2284 { "onesector", no_argument, NULL, 134 }, 2376 {"onesector", no_argument, NULL, 134},
2285 { NULL, 0, NULL, 0 } 2377 {NULL, 0, NULL, 0}
2286}; 2378};
2287 2379
2288/* default devices to list */ 2380/* default devices to list */
2289static struct devd { 2381static struct devd {
2290 char *pref, *letters; 2382 char *pref, *letters;
2291} defdevs[] = { 2383} defdevs[] = {
2292 { "hd", "abcdefgh" }, 2384 {
2293 { "sd", "abcde" }, 2385 "hd", "abcdefgh"}, {
2294 { "xd", "ab" }, 2386 "sd", "abcde"}, {
2295 { "ed", "abcd" } 2387 "xd", "ab"}, {
2388 "ed", "abcd"}
2296}; 2389};
2297 2390
2298static int 2391static int is_ide_cdrom(char *device)
2299is_ide_cdrom(char *device) { 2392{
2300 /* No device was given explicitly, and we are trying some 2393 /* No device was given explicitly, and we are trying some
2301 likely things. But opening /dev/hdc may produce errors like 2394 likely things. But opening /dev/hdc may produce errors like
2302 "hdc: tray open or drive not ready" 2395 "hdc: tray open or drive not ready"
2303 if it happens to be a CD-ROM drive. So try to be careful. 2396 if it happens to be a CD-ROM drive. So try to be careful.
2304 This only works since 2.1.73. */ 2397 This only works since 2.1.73. */
2305 2398
2306 FILE *procf; 2399 FILE *procf;
2307 char buf[100]; 2400 char buf[100];
2308 struct stat statbuf; 2401 struct stat statbuf;
2309 2402
2310 sprintf(buf, "/proc/ide/%s/media", device+5); 2403 sprintf(buf, "/proc/ide/%s/media", device + 5);
2311 procf = fopen(buf, "r"); 2404 procf = fopen(buf, "r");
2312 if (procf != NULL && fgets(buf, sizeof(buf), procf)) 2405 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2313 return !strncmp(buf, "cdrom", 5); 2406 return !strncmp(buf, "cdrom", 5);
2314 2407
2315 /* Now when this proc file does not exist, skip the 2408 /* Now when this proc file does not exist, skip the
2316 device when it is read-only. */ 2409 device when it is read-only. */
2317 if (stat(device, &statbuf) == 0) 2410 if (stat(device, &statbuf) == 0)
2318 return (statbuf.st_mode & 0222) == 0; 2411 return (statbuf.st_mode & 0222) == 0;
2319 2412
2320 return 0; 2413 return 0;
2321} 2414}
2322 2415
2323static void do_list(char *dev, int silent); 2416static void do_list(char *dev, int silent);
@@ -2331,275 +2424,310 @@ static void do_activate(char **av, int ac, char *arg);
2331 2424
2332static int total_size; 2425static int total_size;
2333 2426
2334extern int 2427extern int sfdisk_main(int argc, char **argv)
2335sfdisk_main(int argc, char **argv) { 2428{
2336 int c; 2429 int c;
2337 char *dev; 2430 char *dev;
2338 int opt_size = 0; 2431 int opt_size = 0;
2339 int opt_out_geom = 0; 2432 int opt_out_geom = 0;
2340 int opt_reread = 0; 2433 int opt_reread = 0;
2341 int activate = 0; 2434 int activate = 0;
2342 int do_id = 0; 2435 int do_id = 0;
2343 int unhide = 0; 2436 int unhide = 0;
2344 char *activatearg = 0; 2437 char *activatearg = 0;
2345 char *unhidearg = 0; 2438 char *unhidearg = 0;
2346 2439
2347 if (argc < 1) 2440 if (argc < 1)
2348 usage(sfdisk_usage); 2441 usage(sfdisk_usage);
2349 2442
2350 while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { 2443 while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) !=
2351 switch (c) { 2444 -1) {
2352 case 'f': 2445 switch (c) {
2353 force = 1; break; /* does not imply quiet */ 2446 case 'f':
2354 case 'g': 2447 force = 1;
2355 opt_out_geom = 1; break; 2448 break; /* does not imply quiet */
2356 case 'i': 2449 case 'g':
2357 increment = 1; break; 2450 opt_out_geom = 1;
2358 case 'c': 2451 break;
2359 case 'c' + PRINT_ID: 2452 case 'i':
2360 case 'c' + CHANGE_ID: 2453 increment = 1;
2361 do_id = c; break; 2454 break;
2362 case 'd': 2455 case 'c':
2363 dump = 1; /* fall through */ 2456 case 'c' + PRINT_ID:
2364 case 'l': 2457 case 'c' + CHANGE_ID:
2365 opt_list = 1; break; 2458 do_id = c;
2366 case 'n': 2459 break;
2367 no_write = 1; break; 2460 case 'd':
2368 case 'q': 2461 dump = 1; /* fall through */
2369 quiet = 1; break; 2462 case 'l':
2370 case 's': 2463 opt_list = 1;
2371 opt_size = 1; break; 2464 break;
2372 case 'u': 2465 case 'n':
2373 set_format(*optarg); break; 2466 no_write = 1;
2374 case 'v': 2467 break;
2375 version(); 2468 case 'q':
2376 exit(0); 2469 quiet = 1;
2377 case 'x': 2470 break;
2378 show_extended = 1; break; 2471 case 's':
2379 case 'A': 2472 opt_size = 1;
2380 activatearg = optarg; 2473 break;
2381 activate = 1; break; 2474 case 'u':
2382 case 'C': 2475 set_format(*optarg);
2383 U.cylinders = atoi(optarg); break; 2476 break;
2384 case 'D': 2477 case 'v':
2385 DOS = 1; break; 2478 version();
2386 case 'H': 2479 exit(0);
2387 U.heads = atoi(optarg); break; 2480 case 'x':
2388 case 'L': 2481 show_extended = 1;
2389 Linux = 1; break; 2482 break;
2390 case 'N': 2483 case 'A':
2391 one_only = atoi(optarg); break; 2484 activatearg = optarg;
2392 case 'I': 2485 activate = 1;
2393 restore_sector_file = optarg; break; 2486 break;
2394 case 'O': 2487 case 'C':
2395 save_sector_file = optarg; break; 2488 U.cylinders = atoi(optarg);
2396 case 'R': 2489 break;
2397 opt_reread = 1; break; 2490 case 'D':
2398 case 'S': 2491 DOS = 1;
2399 U.sectors = atoi(optarg); break; 2492 break;
2400 case 'T': 2493 case 'H':
2401 list_types(); 2494 U.heads = atoi(optarg);
2402 exit(0); 2495 break;
2403 case 'U': 2496 case 'L':
2404 unhidearg = optarg; 2497 Linux = 1;
2405 unhide = 1; break; 2498 break;
2406 case 'V': 2499 case 'N':
2407 verify = 1; break; 2500 one_only = atoi(optarg);
2408 case '?': 2501 break;
2409 default: 2502 case 'I':
2410 usage(sfdisk_usage); 2503 restore_sector_file = optarg;
2411 2504 break;
2412 /* undocumented flags */ 2505 case 'O':
2413 case 128: 2506 save_sector_file = optarg;
2414 partitions_in_order = 1; break; 2507 break;
2415 case 129: 2508 case 'R':
2416 partitions_in_order = 0; break; 2509 opt_reread = 1;
2417 case 130: 2510 break;
2418 all_logicals_inside_outermost_extended = 1; break; 2511 case 'S':
2419 case 131: 2512 U.sectors = atoi(optarg);
2420 all_logicals_inside_outermost_extended = 0; break; 2513 break;
2421 case 132: 2514 case 'T':
2422 boxes = NESTED; break; 2515 list_types();
2423 case 133: 2516 exit(0);
2424 boxes = CHAINED; break; 2517 case 'U':
2425 case 134: 2518 unhidearg = optarg;
2426 boxes = ONESECTOR; break; 2519 unhide = 1;
2427 2520 break;
2428 /* more flags */ 2521 case 'V':
2429 case 160: 2522 verify = 1;
2430 no_reread = 1; break; 2523 break;
2431 case 161: 2524 case '?':
2432 leave_last = 1; break; 2525 default:
2433 } 2526 usage(sfdisk_usage);
2434 } 2527
2435 2528 /* undocumented flags */
2436 if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) { 2529 case 128:
2437 struct devd *dp; 2530 partitions_in_order = 1;
2438 char *lp; 2531 break;
2439 char device[10]; 2532 case 129:
2440 2533 partitions_in_order = 0;
2441 total_size = 0; 2534 break;
2442 2535 case 130:
2443 for(dp = defdevs; dp-defdevs < SIZE(defdevs); dp++) { 2536 all_logicals_inside_outermost_extended = 1;
2444 lp = dp->letters; 2537 break;
2445 while(*lp) { 2538 case 131:
2446 sprintf(device, "/dev/%s%c", dp->pref, *lp++); 2539 all_logicals_inside_outermost_extended = 0;
2447 if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device)) 2540 break;
2448 continue; 2541 case 132:
2449 if (opt_out_geom) 2542 boxes = NESTED;
2450 do_geom(device, 1); 2543 break;
2451 if (opt_size) 2544 case 133:
2452 do_size(device, 1); 2545 boxes = CHAINED;
2453 if (opt_list || verify) 2546 break;
2454 do_list(device, 1); 2547 case 134:
2455 } 2548 boxes = ONESECTOR;
2549 break;
2550
2551 /* more flags */
2552 case 160:
2553 no_reread = 1;
2554 break;
2555 case 161:
2556 leave_last = 1;
2557 break;
2558 }
2456 } 2559 }
2457 2560
2458 if (opt_size) 2561 if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) {
2459 printf("total: %d blocks\n", total_size); 2562 struct devd *dp;
2563 char *lp;
2564 char device[10];
2565
2566 total_size = 0;
2567
2568 for (dp = defdevs; dp - defdevs < SIZE(defdevs); dp++) {
2569 lp = dp->letters;
2570 while (*lp) {
2571 sprintf(device, "/dev/%s%c", dp->pref, *lp++);
2572 if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device))
2573 continue;
2574 if (opt_out_geom)
2575 do_geom(device, 1);
2576 if (opt_size)
2577 do_size(device, 1);
2578 if (opt_list || verify)
2579 do_list(device, 1);
2580 }
2581 }
2582
2583 if (opt_size)
2584 printf("total: %d blocks\n", total_size);
2460 2585
2461 exit(exit_status); 2586 exit(exit_status);
2462 } 2587 }
2463 2588
2464 if (optind == argc) usage(sfdisk_usage); 2589 if (optind == argc)
2590 usage(sfdisk_usage);
2591
2592 if (opt_list || opt_out_geom || opt_size || verify) {
2593 while (optind < argc) {
2594 if (opt_out_geom)
2595 do_geom(argv[optind], 0);
2596 if (opt_size)
2597 do_size(argv[optind], 0);
2598 if (opt_list || verify)
2599 do_list(argv[optind], 0);
2600 optind++;
2601 }
2602 exit(exit_status);
2603 }
2465 2604
2466 if (opt_list || opt_out_geom || opt_size || verify) { 2605 if (activate) {
2467 while (optind < argc) { 2606 do_activate(argv + optind, argc - optind, activatearg);
2468 if (opt_out_geom) 2607 exit(exit_status);
2469 do_geom(argv[optind], 0); 2608 }
2470 if (opt_size) 2609 if (unhide) {
2471 do_size(argv[optind], 0); 2610 do_unhide(argv + optind, argc - optind, unhidearg);
2472 if (opt_list || verify) 2611 exit(exit_status);
2473 do_list(argv[optind], 0); 2612 }
2474 optind++; 2613 if (do_id) {
2614 if ((do_id & PRINT_ID) != 0 && optind != argc - 2)
2615 fatal("usage: sfdisk --print-id device partition-number\n");
2616 else if ((do_id & CHANGE_ID) != 0 && optind != argc - 3)
2617 fatal
2618 ("usage: sfdisk --change-id device partition-number Id\n");
2619 else if (optind != argc - 3 && optind != argc - 2)
2620 fatal("usage: sfdisk --id device partition-number [Id]\n");
2621 do_change_id(argv[optind], argv[optind + 1],
2622 (optind == argc - 2) ? 0 : argv[optind + 2]);
2623 exit(exit_status);
2475 } 2624 }
2476 exit(exit_status);
2477 }
2478 2625
2479 if (activate) { 2626 if (optind != argc - 1)
2480 do_activate(argv+optind, argc-optind, activatearg); 2627 fatal("can specify only one device (except with -l or -s)\n");
2481 exit(exit_status); 2628 dev = argv[optind];
2482 }
2483 if (unhide) {
2484 do_unhide(argv+optind, argc-optind, unhidearg);
2485 exit(exit_status);
2486 }
2487 if (do_id) {
2488 if ((do_id & PRINT_ID) != 0 && optind != argc-2)
2489 fatal("usage: sfdisk --print-id device partition-number\n");
2490 else if ((do_id & CHANGE_ID) != 0 && optind != argc-3)
2491 fatal("usage: sfdisk --change-id device partition-number Id\n");
2492 else if (optind != argc-3 && optind != argc-2)
2493 fatal("usage: sfdisk --id device partition-number [Id]\n");
2494 do_change_id(argv[optind], argv[optind+1],
2495 (optind == argc-2) ? 0 : argv[optind+2]);
2496 exit(exit_status);
2497 }
2498
2499 if (optind != argc-1)
2500 fatal("can specify only one device (except with -l or -s)\n");
2501 dev = argv[optind];
2502 2629
2503 if (opt_reread) 2630 if (opt_reread)
2504 do_reread(dev); 2631 do_reread(dev);
2505 else if (restore_sector_file) 2632 else if (restore_sector_file)
2506 restore_sectors(dev); 2633 restore_sectors(dev);
2507 else 2634 else
2508 do_fdisk(dev); 2635 do_fdisk(dev);
2509 2636
2510 return ( TRUE); 2637 return (TRUE);
2511} 2638}
2512 2639
2513/* 2640/*
2514 * H. Listing the current situation 2641 * H. Listing the current situation
2515 */ 2642 */
2516 2643
2517static int 2644static int my_open(char *dev, int rw, int silent)
2518my_open (char *dev, int rw, int silent) { 2645{
2519 int fd, mode; 2646 int fd, mode;
2520 2647
2521 mode = (rw ? O_RDWR : O_RDONLY); 2648 mode = (rw ? O_RDWR : O_RDONLY);
2522 fd = open(dev, mode); 2649 fd = open(dev, mode);
2523 if (fd < 0 && !silent) { 2650 if (fd < 0 && !silent) {
2524 perror(dev); 2651 perror(dev);
2525 fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading"); 2652 fatal("cannot open %s %s\n", dev,
2526 } 2653 rw ? "read-write" : "for reading");
2527 return fd; 2654 }
2655 return fd;
2528} 2656}
2529 2657
2530static void 2658static void do_list(char *dev, int silent)
2531do_list (char *dev, int silent) { 2659{
2532 int fd; 2660 int fd;
2533 struct disk_desc *z; 2661 struct disk_desc *z;
2534 2662
2535 fd = my_open(dev, 0, silent); 2663 fd = my_open(dev, 0, silent);
2536 if (fd < 0) 2664 if (fd < 0)
2537 return; 2665 return;
2538 2666
2539 z = &oldp; 2667 z = &oldp;
2540 2668
2541 free_sectors(); 2669 free_sectors();
2542 get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1); 2670 get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1);
2543 get_partitions(dev, fd, z); 2671 get_partitions(dev, fd, z);
2544 2672
2545 if (opt_list) 2673 if (opt_list)
2546 out_partitions(dev, z); 2674 out_partitions(dev, z);
2547 2675
2548 if (verify) { 2676 if (verify) {
2549 if (partitions_ok(z)) 2677 if (partitions_ok(z))
2550 warn("%s: OK\n"), dev; 2678 warn("%s: OK\n"), dev;
2551 else 2679 else
2552 exit_status = 1; 2680 exit_status = 1;
2553 } 2681 }
2554} 2682}
2555 2683
2556static void 2684static void do_geom(char *dev, int silent)
2557do_geom (char *dev, int silent) { 2685{
2558 int fd; 2686 int fd;
2559 struct hd_geometry g; 2687 struct hd_geometry g;
2560 2688
2561 fd = my_open(dev, 0, silent); 2689 fd = my_open(dev, 0, silent);
2562 if (fd < 0) 2690 if (fd < 0)
2563 return; 2691 return;
2564 2692
2565 /* get_cylindersize(dev, fd, silent); */ 2693 /* get_cylindersize(dev, fd, silent); */
2566 if (!ioctl(fd, HDIO_GETGEO, &g)) 2694 if (!ioctl(fd, HDIO_GETGEO, &g))
2567 printf("%s: %d cylinders, %d heads, %d sectors/track\n", 2695 printf("%s: %d cylinders, %d heads, %d sectors/track\n",
2568 dev, g.cylinders, g.heads, g.sectors); 2696 dev, g.cylinders, g.heads, g.sectors);
2569 else 2697 else
2570 printf("%s: unknown geometry\n", dev); 2698 printf("%s: unknown geometry\n", dev);
2571} 2699}
2572 2700
2573/* for compatibility with earlier fdisk: provide option -s */ 2701/* for compatibility with earlier fdisk: provide option -s */
2574static void 2702static void do_size(char *dev, int silent)
2575do_size (char *dev, int silent) { 2703{
2576 int fd; 2704 int fd;
2577 long size; 2705 long size;
2578 2706
2579 fd = my_open(dev, 0, silent); 2707 fd = my_open(dev, 0, silent);
2580 if (fd < 0) 2708 if (fd < 0)
2581 return; 2709 return;
2582 2710
2583 if(ioctl(fd, BLKGETSIZE, &size)) { 2711 if (ioctl(fd, BLKGETSIZE, &size)) {
2584 if(!silent) { 2712 if (!silent) {
2585 perror(dev); 2713 perror(dev);
2586 fatal("BLKGETSIZE ioctl failed for %s\n"), dev; 2714 fatal("BLKGETSIZE ioctl failed for %s\n"), dev;
2715 }
2716 return;
2587 } 2717 }
2588 return;
2589 }
2590 2718
2591 size /= 2; /* convert sectors to blocks */ 2719 size /= 2; /* convert sectors to blocks */
2592 2720
2593 /* a CDROM drive without mounted CD yields MAXINT */ 2721 /* a CDROM drive without mounted CD yields MAXINT */
2594 if (silent && size == ((1<<30)-1)) 2722 if (silent && size == ((1 << 30) - 1))
2595 return; 2723 return;
2596 2724
2597 if (silent) 2725 if (silent)
2598 printf("%s: %9ld\n", dev, size); 2726 printf("%s: %9ld\n", dev, size);
2599 else 2727 else
2600 printf("%ld\n", size); 2728 printf("%ld\n", size);
2601 2729
2602 total_size += size; 2730 total_size += size;
2603} 2731}
2604 2732
2605/* 2733/*
@@ -2626,255 +2754,263 @@ do_size (char *dev, int silent) {
2626 * The present syntax was chosen to be (somewhat) compatible with the 2754 * The present syntax was chosen to be (somewhat) compatible with the
2627 * activate from the LILO package. 2755 * activate from the LILO package.
2628 */ 2756 */
2629static void 2757static void set_active(struct disk_desc *z, char *pnam)
2630set_active (struct disk_desc *z, char *pnam) { 2758{
2631 int pno; 2759 int pno;
2632 2760
2633 pno = asc_to_index(pnam, z); 2761 pno = asc_to_index(pnam, z);
2634 z->partitions[pno].p.bootable = 0x80; 2762 z->partitions[pno].p.bootable = 0x80;
2635} 2763}
2636 2764
2637static void 2765static void do_activate(char **av, int ac, char *arg)
2638do_activate (char **av, int ac, char *arg) { 2766{
2639 char *dev = av[0]; 2767 char *dev = av[0];
2640 int fd; 2768 int fd;
2641 int rw, i, pno, lpno; 2769 int rw, i, pno, lpno;
2642 struct disk_desc *z; 2770 struct disk_desc *z;
2643 2771
2644 z = &oldp; 2772 z = &oldp;
2645 2773
2646 rw = (!no_write && (arg || ac > 1)); 2774 rw = (!no_write && (arg || ac > 1));
2647 fd = my_open(dev, rw, 0); 2775 fd = my_open(dev, rw, 0);
2648 2776
2649 free_sectors(); 2777 free_sectors();
2650 get_cylindersize(dev, fd, 1); 2778 get_cylindersize(dev, fd, 1);
2651 get_partitions(dev, fd, z); 2779 get_partitions(dev, fd, z);
2652 2780
2653 if (!arg && ac == 1) { 2781 if (!arg && ac == 1) {
2654 /* list active partitions */ 2782 /* list active partitions */
2655 for (pno=0; pno < z->partno; pno++) { 2783 for (pno = 0; pno < z->partno; pno++) {
2656 if (z->partitions[pno].p.bootable) { 2784 if (z->partitions[pno].p.bootable) {
2657 lpno = index_to_linux(pno, z); 2785 lpno = index_to_linux(pno, z);
2658 if (pno == linux_to_index(lpno, z)) 2786 if (pno == linux_to_index(lpno, z))
2659 printf("%s%d\n", dev, lpno); 2787 printf("%s%d\n", dev, lpno);
2788 else
2789 printf("%s#%d\n", dev, pno);
2790 if (z->partitions[pno].p.bootable != 0x80)
2791 warn("bad active byte: 0x%x instead of 0x80\n",
2792 z->partitions[pno].p.bootable);
2793 }
2794 }
2795 } else {
2796 /* clear `active byte' everywhere */
2797 for (pno = 0; pno < z->partno; pno++)
2798 z->partitions[pno].p.bootable = 0;
2799
2800 /* then set where desired */
2801 if (ac == 1)
2802 set_active(z, arg);
2660 else 2803 else
2661 printf("%s#%d\n", dev, pno); 2804 for (i = 1; i < ac; i++)
2662 if (z->partitions[pno].p.bootable != 0x80) 2805 set_active(z, av[i]);
2663 warn("bad active byte: 0x%x instead of 0x80\n",
2664 z->partitions[pno].p.bootable);
2665 }
2666 }
2667 } else {
2668 /* clear `active byte' everywhere */
2669 for (pno=0; pno < z->partno; pno++)
2670 z->partitions[pno].p.bootable = 0;
2671
2672 /* then set where desired */
2673 if (ac == 1)
2674 set_active(z, arg);
2675 else for(i=1; i<ac; i++)
2676 set_active(z, av[i]);
2677 2806
2678 /* then write to disk */ 2807 /* then write to disk */
2679 if(write_partitions(dev, fd, z)) 2808 if (write_partitions(dev, fd, z))
2680 warn("Done\n\n"); 2809 warn("Done\n\n");
2810 else
2811 exit_status = 1;
2812 }
2813 i = 0;
2814 for (pno = 0; pno < z->partno && pno < 4; pno++)
2815 if (z->partitions[pno].p.bootable)
2816 i++;
2817 if (i != 1)
2818 warn
2819 ("You have %d active primary partitions. This does not matter for LILO,\n"
2820 "but the DOS MBR will only boot a disk with 1 active partition.\n",
2821 i);
2822}
2823
2824static void set_unhidden(struct disk_desc *z, char *pnam)
2825{
2826 int pno;
2827 unsigned char id;
2828
2829 pno = asc_to_index(pnam, z);
2830 id = z->partitions[pno].p.sys_type;
2831 if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17)
2832 id -= 0x10;
2681 else 2833 else
2682 exit_status = 1; 2834 fatal("partition %s has id %x and is not hidden\n", pnam, id);
2683 } 2835 z->partitions[pno].p.sys_type = id;
2684 i = 0;
2685 for (pno=0; pno < z->partno && pno < 4; pno++)
2686 if (z->partitions[pno].p.bootable)
2687 i++;
2688 if (i != 1)
2689 warn("You have %d active primary partitions. This does not matter for LILO,\n"
2690 "but the DOS MBR will only boot a disk with 1 active partition.\n", i);
2691}
2692
2693static void
2694set_unhidden (struct disk_desc *z, char *pnam) {
2695 int pno;
2696 unsigned char id;
2697
2698 pno = asc_to_index(pnam, z);
2699 id = z->partitions[pno].p.sys_type;
2700 if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17)
2701 id -= 0x10;
2702 else
2703 fatal("partition %s has id %x and is not hidden\n", pnam, id);
2704 z->partitions[pno].p.sys_type = id;
2705} 2836}
2706 2837
2707/* 2838/*
2708 * maybe remove and make part of --change-id 2839 * maybe remove and make part of --change-id
2709 */ 2840 */
2710static void 2841static void do_unhide(char **av, int ac, char *arg)
2711do_unhide (char **av, int ac, char *arg) { 2842{
2712 char *dev = av[0]; 2843 char *dev = av[0];
2713 int fd, rw, i; 2844 int fd, rw, i;
2714 struct disk_desc *z; 2845 struct disk_desc *z;
2715 2846
2716 z = &oldp; 2847 z = &oldp;
2717 2848
2718 rw = !no_write; 2849 rw = !no_write;
2719 fd = my_open(dev, rw, 0); 2850 fd = my_open(dev, rw, 0);
2720 2851
2721 free_sectors(); 2852 free_sectors();
2722 get_cylindersize(dev, fd, 1); 2853 get_cylindersize(dev, fd, 1);
2723 get_partitions(dev, fd, z); 2854 get_partitions(dev, fd, z);
2724 2855
2725 /* unhide where desired */ 2856 /* unhide where desired */
2726 if (ac == 1) 2857 if (ac == 1)
2727 set_unhidden(z, arg); 2858 set_unhidden(z, arg);
2728 else for(i=1; i<ac; i++) 2859 else
2729 set_unhidden(z, av[i]); 2860 for (i = 1; i < ac; i++)
2861 set_unhidden(z, av[i]);
2730 2862
2731 /* then write to disk */ 2863 /* then write to disk */
2732 if(write_partitions(dev, fd, z)) 2864 if (write_partitions(dev, fd, z))
2733 warn("Done\n\n"); 2865 warn("Done\n\n");
2734 else 2866 else
2735 exit_status = 1; 2867 exit_status = 1;
2736} 2868}
2737 2869
2738static void do_change_id(char *dev, char *pnam, char *id) { 2870static void do_change_id(char *dev, char *pnam, char *id)
2739 int fd, rw, pno; 2871{
2740 struct disk_desc *z; 2872 int fd, rw, pno;
2741 unsigned long i; 2873 struct disk_desc *z;
2874 unsigned long i;
2742 2875
2743 z = &oldp; 2876 z = &oldp;
2744 2877
2745 rw = !no_write; 2878 rw = !no_write;
2746 fd = my_open(dev, rw, 0); 2879 fd = my_open(dev, rw, 0);
2747 2880
2748 free_sectors(); 2881 free_sectors();
2749 get_cylindersize(dev, fd, 1); 2882 get_cylindersize(dev, fd, 1);
2750 get_partitions(dev, fd, z); 2883 get_partitions(dev, fd, z);
2751 2884
2752 pno = asc_to_index(pnam, z); 2885 pno = asc_to_index(pnam, z);
2753 if (id == 0) { 2886 if (id == 0) {
2754 printf("%x\n", z->partitions[pno].p.sys_type); 2887 printf("%x\n", z->partitions[pno].p.sys_type);
2755 return; 2888 return;
2756 } 2889 }
2757 i = strtoul(id, NULL, 16); 2890 i = strtoul(id, NULL, 16);
2758 if (i > 255) 2891 if (i > 255)
2759 fatal("Bad Id %x\n"), i; 2892 fatal("Bad Id %x\n"), i;
2760 z->partitions[pno].p.sys_type = i; 2893 z->partitions[pno].p.sys_type = i;
2761 2894
2762 if(write_partitions(dev, fd, z)) 2895 if (write_partitions(dev, fd, z))
2763 warn("Done\n\n"); 2896 warn("Done\n\n");
2764 else 2897 else
2765 exit_status = 1; 2898 exit_status = 1;
2766} 2899}
2767 2900
2768static void 2901static void do_reread(char *dev)
2769do_reread(char *dev) { 2902{
2770 int fd; 2903 int fd;
2771 2904
2772 fd = my_open(dev, 0, 0); 2905 fd = my_open(dev, 0, 0);
2773 if(reread_ioctl(fd)) 2906 if (reread_ioctl(fd))
2774 printf("This disk is currently in use.\n"); 2907 printf("This disk is currently in use.\n");
2775} 2908}
2776 2909
2777/* 2910/*
2778 * I. Writing the new situation 2911 * I. Writing the new situation
2779 */ 2912 */
2780 2913
2781static void 2914static void do_fdisk(char *dev)
2782do_fdisk(char *dev){ 2915{
2783 int fd; 2916 int fd;
2784 int c, answer; 2917 int c, answer;
2785 struct stat statbuf; 2918 struct stat statbuf;
2786 int interactive = isatty(0); 2919 int interactive = isatty(0);
2787 struct disk_desc *z; 2920 struct disk_desc *z;
2788 2921
2789 if (stat(dev, &statbuf) < 0) { 2922 if (stat(dev, &statbuf) < 0) {
2790 perror(dev); 2923 perror(dev);
2791 fatal("Fatal error: cannot find %s\n"), dev; 2924 fatal("Fatal error: cannot find %s\n"), dev;
2792 } 2925 }
2793 if (!S_ISBLK(statbuf.st_mode)) { 2926 if (!S_ISBLK(statbuf.st_mode)) {
2794 warn("Warning: %s is not a block device\n"), dev; 2927 warn("Warning: %s is not a block device\n"), dev;
2795 no_reread = 1; 2928 no_reread = 1;
2796 } 2929 }
2797 fd = my_open(dev, !no_write, 0); 2930 fd = my_open(dev, !no_write, 0);
2798 2931
2799 if(!no_write && !no_reread) { 2932 if (!no_write && !no_reread) {
2800 warn("Checking that no-one is using this disk right now ...\n"); 2933 warn("Checking that no-one is using this disk right now ...\n");
2801 if(reread_ioctl(fd)) { 2934 if (reread_ioctl(fd)) {
2802 printf("\nThis disk is currently in use - repartitioning is probably a bad idea." 2935 printf
2803 "Umount all file systems, and swapoff all swap partitions on this disk." 2936 ("\nThis disk is currently in use - repartitioning is probably a bad idea."
2804 "Use the --no-reread flag to suppress this check.\n"); 2937 "Umount all file systems, and swapoff all swap partitions on this disk."
2805 if (!force) { 2938 "Use the --no-reread flag to suppress this check.\n");
2806 printf("Use the --force flag to overrule all checks.\n"); 2939 if (!force) {
2807 exit(1); 2940 printf("Use the --force flag to overrule all checks.\n");
2808 } 2941 exit(1);
2809 } else 2942 }
2810 warn("OK"); 2943 } else
2811 } 2944 warn("OK");
2945 }
2812 2946
2813 z = &oldp; 2947 z = &oldp;
2814 2948
2815 free_sectors(); 2949 free_sectors();
2816 get_cylindersize(dev, fd, 0); 2950 get_cylindersize(dev, fd, 0);
2817 get_partitions(dev, fd, z); 2951 get_partitions(dev, fd, z);
2818 2952
2819 printf("Old situation:\n"); 2953 printf("Old situation:\n");
2820 out_partitions(dev, z); 2954 out_partitions(dev, z);
2821 2955
2822 if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0) 2956 if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0)
2823 fatal("Partition %d does not exist, cannot change it\n"), one_only; 2957 fatal("Partition %d does not exist, cannot change it\n"), one_only;
2824 2958
2825 z = &newp; 2959 z = &newp;
2826 2960
2827 while(1) { 2961 while (1) {
2828 2962
2829 read_input(dev, interactive, z); 2963 read_input(dev, interactive, z);
2830 2964
2831 printf("New situation:\n"); 2965 printf("New situation:\n");
2832 out_partitions(dev, z); 2966 out_partitions(dev, z);
2833 2967
2834 if (!partitions_ok(z) && !force) { 2968 if (!partitions_ok(z) && !force) {
2835 if(!interactive) 2969 if (!interactive)
2836 fatal("I don't like these partitions - nothing changed.\n" 2970 fatal("I don't like these partitions - nothing changed.\n"
2837 "(If you really want this, use the --force option.)\n"); 2971 "(If you really want this, use the --force option.)\n");
2838 else 2972 else
2839 printf("I don't like this - probably you should answer No\n"); 2973 printf
2974 ("I don't like this - probably you should answer No\n");
2975 }
2976 ask:
2977 if (interactive) {
2978 if (no_write)
2979 printf("Are you satisfied with this? [ynq] ");
2980 else
2981 printf("Do you want to write this to disk? [ynq] ");
2982 answer = c = getchar();
2983 while (c != '\n' && c != EOF)
2984 c = getchar();
2985 if (c == EOF)
2986 printf("\nsfdisk: premature end of input\n");
2987 if (c == EOF || answer == 'q' || answer == 'Q') {
2988 fatal("Quitting - nothing changed\n");
2989 } else if (answer == 'n' || answer == 'N') {
2990 continue;
2991 } else if (answer == 'y' || answer == 'Y') {
2992 break;
2993 } else {
2994 printf("Please answer one of y,n,q\n");
2995 goto ask;
2996 }
2997 } else
2998 break;
2840 } 2999 }
2841 ask: 3000
2842 if (interactive) { 3001 if (write_partitions(dev, fd, z))
2843 if (no_write) 3002 printf("Successfully wrote the new partition table\n\n");
2844 printf("Are you satisfied with this? [ynq] "); 3003 else
2845 else 3004 exit_status = 1;
2846 printf("Do you want to write this to disk? [ynq] "); 3005
2847 answer = c = getchar(); 3006 reread_disk_partition(dev, fd);
2848 while (c != '\n' && c != EOF) 3007
2849 c = getchar(); 3008 warn
2850 if (c == EOF) 3009 ("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n"
2851 printf("\nsfdisk: premature end of input\n"); 3010 "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n"
2852 if (c == EOF || answer == 'q' || answer == 'Q') { 3011 "(See fdisk(8).)\n");
2853 fatal("Quitting - nothing changed\n"); 3012
2854 } else if (answer == 'n' || answer == 'N') { 3013 sync(); /* superstition */
2855 continue; 3014 sleep(3);
2856 } else if (answer == 'y' || answer == 'Y') { 3015 exit(exit_status);
2857 break;
2858 } else {
2859 printf("Please answer one of y,n,q\n");
2860 goto ask;
2861 }
2862 } else
2863 break;
2864 }
2865
2866 if(write_partitions(dev, fd, z))
2867 printf("Successfully wrote the new partition table\n\n");
2868 else
2869 exit_status = 1;
2870
2871 reread_disk_partition(dev, fd);
2872
2873 warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n"
2874 "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n"
2875 "(See fdisk(8).)\n");
2876
2877 sync(); /* superstition */
2878 sleep(3);
2879 exit(exit_status);
2880} 3016}
diff --git a/sleep.c b/sleep.c
index bfbb78f61..9687b8446 100644
--- a/sleep.c
+++ b/sleep.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sleep implementation for busybox 3 * Mini sleep implementation for busybox
3 * 4 *
@@ -23,19 +24,17 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26const char sleep_usage[] = "sleep N\n\n" 27const char sleep_usage[] = "sleep N\n\n" "Pause for N seconds.\n";
27"Pause for N seconds.\n";
28 28
29extern int 29extern int sleep_main(int argc, char **argv)
30sleep_main(int argc, char * * argv)
31{ 30{
32 if ( (argc < 2) || (**(argv+1) == '-') ) { 31 if ((argc < 2) || (**(argv + 1) == '-')) {
33 usage( sleep_usage ); 32 usage(sleep_usage);
34 } 33 }
35 34
36 if ( sleep(atoi(*(++argv))) != 0 ) { 35 if (sleep(atoi(*(++argv))) != 0) {
37 perror( "sleep"); 36 perror("sleep");
38 exit (FALSE); 37 exit(FALSE);
39 } else 38 } else
40 exit (TRUE); 39 exit(TRUE);
41} 40}
diff --git a/sort.c b/sort.c
index d529ce722..609c5e08c 100644
--- a/sort.c
+++ b/sort.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sort implementation for busybox 3 * Mini sort implementation for busybox
3 * 4 *
@@ -28,29 +29,27 @@
28#include <stdio.h> 29#include <stdio.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char sort_usage[] = 32static const char sort_usage[] = "sort [OPTION]... [FILE]...\n\n";
32"sort [OPTION]... [FILE]...\n\n"
33;
34 33
35/* typedefs _______________________________________________________________ */ 34/* typedefs _______________________________________________________________ */
36 35
37/* line node */ 36/* line node */
38typedef struct Line { 37typedef struct Line {
39 char *data; /* line data */ 38 char *data; /* line data */
40 struct Line *next; /* pointer to next line node */ 39 struct Line *next; /* pointer to next line node */
41} Line; 40} Line;
42 41
43/* singly-linked list of lines */ 42/* singly-linked list of lines */
44typedef struct { 43typedef struct {
45 int len; /* number of Lines */ 44 int len; /* number of Lines */
46 Line **sorted; /* array fed to qsort */ 45 Line **sorted; /* array fed to qsort */
47 46
48 Line *head; /* head of List */ 47 Line *head; /* head of List */
49 Line *current; /* current Line */ 48 Line *current; /* current Line */
50} List; 49} List;
51 50
52/* comparison function */ 51/* comparison function */
53typedef int (Compare)(const void *, const void *); 52typedef int (Compare) (const void *, const void *);
54 53
55 54
56/* methods ________________________________________________________________ */ 55/* methods ________________________________________________________________ */
@@ -58,175 +57,176 @@ typedef int (Compare)(const void *, const void *);
58static const int max = 1024; 57static const int max = 1024;
59 58
60/* mallocate Line */ 59/* mallocate Line */
61static Line * 60static Line *line_alloc()
62line_alloc()
63{ 61{
64 Line *self; 62 Line *self;
65 self = malloc(1 * sizeof(Line)); 63
66 return self; 64 self = malloc(1 * sizeof(Line));
65 return self;
67} 66}
68 67
69/* Initialize Line with string */ 68/* Initialize Line with string */
70static Line * 69static Line *line_init(Line * self, const char *string)
71line_init(Line *self, const char *string)
72{ 70{
73 self->data = malloc((strlen(string) + 1) * sizeof(char)); 71 self->data = malloc((strlen(string) + 1) * sizeof(char));
74 if (self->data == NULL) { return NULL; } 72
75 strcpy(self->data, string); 73 if (self->data == NULL) {
76 self->next = NULL; 74 return NULL;
77 return self; 75 }
76 strcpy(self->data, string);
77 self->next = NULL;
78 return self;
78} 79}
79 80
80/* Construct Line from FILE* */ 81/* Construct Line from FILE* */
81static Line * 82static Line *line_newFromFile(FILE * src)
82line_newFromFile(FILE *src)
83{ 83{
84 char buffer[max]; 84 char buffer[max];
85 Line *self; 85 Line *self;
86 86
87 if (fgets(buffer, max, src)) { 87 if (fgets(buffer, max, src)) {
88 self = line_alloc(); 88 self = line_alloc();
89 if (self == NULL) { return NULL; } 89 if (self == NULL) {
90 line_init(self, buffer); 90 return NULL;
91 return self; 91 }
92 } 92 line_init(self, buffer);
93 return NULL; 93 return self;
94 }
95 return NULL;
94} 96}
95 97
96/* Line destructor */ 98/* Line destructor */
97static Line * 99static Line *line_release(Line * self)
98line_release(Line *self)
99{ 100{
100 if (self->data) { 101 if (self->data) {
101 free(self->data); 102 free(self->data);
102 free(self); 103 free(self);
103 } 104 }
104 return self; 105 return self;
105} 106}
106 107
107 108
108/* Comparison */ 109/* Comparison */
109 110
110/* ascii order */ 111/* ascii order */
111static int 112static int compare_ascii(const void *a, const void *b)
112compare_ascii(const void *a, const void *b)
113{ 113{
114 Line **doh; 114 Line **doh;
115 Line *x, *y; 115 Line *x, *y;
116 116
117 doh = (Line **) a; 117 doh = (Line **) a;
118 x = *doh; 118 x = *doh;
119 doh = (Line **) b; 119 doh = (Line **) b;
120 y = *doh; 120 y = *doh;
121 121
122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); 122 // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data);
123 return strcmp(x->data, y->data); 123 return strcmp(x->data, y->data);
124} 124}
125 125
126/* numeric order */ 126/* numeric order */
127static int 127static int compare_numeric(const void *a, const void *b)
128compare_numeric(const void *a, const void *b)
129{ 128{
130 Line **doh; 129 Line **doh;
131 Line *x, *y; 130 Line *x, *y;
132 int xint, yint; 131 int xint, yint;
133 132
134 doh = (Line **) a; 133 doh = (Line **) a;
135 x = *doh; 134 x = *doh;
136 doh = (Line **) b; 135 doh = (Line **) b;
137 y = *doh; 136 y = *doh;
138 137
139 xint = strtoul(x->data, NULL, 10); 138 xint = strtoul(x->data, NULL, 10);
140 yint = strtoul(y->data, NULL, 10); 139 yint = strtoul(y->data, NULL, 10);
141 140
142 return (xint - yint); 141 return (xint - yint);
143} 142}
144 143
145 144
146/* List */ 145/* List */
147 146
148/* */ 147/* */
149static List * 148static List *list_init(List * self)
150list_init(List *self)
151{ 149{
152 self->len = 0; 150 self->len = 0;
153 self->sorted = NULL; 151 self->sorted = NULL;
154 self->head = NULL; 152 self->head = NULL;
155 self->current = NULL; 153 self->current = NULL;
156 return self; 154 return self;
157} 155}
158 156
159/* for simplicity, the List gains ownership of the line */ 157/* for simplicity, the List gains ownership of the line */
160static List * 158static List *list_insert(List * self, Line * line)
161list_insert(List *self, Line *line)
162{ 159{
163 if (line == NULL) { return NULL; } 160 if (line == NULL) {
164 161 return NULL;
165 /* first insertion */ 162 }
166 if (self->head == NULL) { 163
167 self->head = line; 164 /* first insertion */
168 self->current = line; 165 if (self->head == NULL) {
169 166 self->head = line;
170 /* all subsequent insertions */ 167 self->current = line;
171 } else { 168
172 self->current->next = line; 169 /* all subsequent insertions */
173 self->current = line; 170 } else {
174 } 171 self->current->next = line;
175 self->len++; 172 self->current = line;
176 return self; 173 }
174 self->len++;
175 return self;
177} 176}
178 177
179/* order the list according to compare() */ 178/* order the list according to compare() */
180static List * 179static List *list_sort(List * self, Compare * compare)
181list_sort(List *self, Compare *compare)
182{ 180{
183 int i; 181 int i;
184 Line *line; 182 Line *line;
185 183
186 /* mallocate array of Line*s */ 184 /* mallocate array of Line*s */
187 self->sorted = (Line **) malloc(self->len * sizeof(Line*)); 185 self->sorted = (Line **) malloc(self->len * sizeof(Line *));
188 if (self->sorted == NULL) { return NULL; } 186 if (self->sorted == NULL) {
189 187 return NULL;
190 /* fill array w/ List's contents */ 188 }
191 i = 0; 189
192 line = self->head; 190 /* fill array w/ List's contents */
193 while (line) { 191 i = 0;
194 self->sorted[i++] = line; 192 line = self->head;
195 line = line->next; 193 while (line) {
196 } 194 self->sorted[i++] = line;
197 195 line = line->next;
198 /* apply qsort */ 196 }
199 qsort(self->sorted, self->len, sizeof(Line*), compare); 197
200 return self; 198 /* apply qsort */
199 qsort(self->sorted, self->len, sizeof(Line *), compare);
200 return self;
201} 201}
202 202
203/* precondition: list must be sorted */ 203/* precondition: list must be sorted */
204static List * 204static List *list_writeToFile(List * self, FILE * dst)
205list_writeToFile(List *self, FILE* dst)
206{ 205{
207 int i; 206 int i;
208 Line **line = self->sorted; 207 Line **line = self->sorted;
209 208
210 if (self->sorted == NULL) { return NULL; } 209 if (self->sorted == NULL) {
211 for (i = 0; i < self->len; i++) { 210 return NULL;
212 fprintf(dst, "%s", line[i]->data); 211 }
213 } 212 for (i = 0; i < self->len; i++) {
214 return self; 213 fprintf(dst, "%s", line[i]->data);
214 }
215 return self;
215} 216}
216 217
217/* deallocate */ 218/* deallocate */
218static void 219static void list_release(List * self)
219list_release(List *self)
220{ 220{
221 Line *i; 221 Line *i;
222 Line *die; 222 Line *die;
223 223
224 i = self->head; 224 i = self->head;
225 while (i) { 225 while (i) {
226 die = i; 226 die = i;
227 i = die->next; 227 i = die->next;
228 line_release(die); 228 line_release(die);
229 } 229 }
230} 230}
231 231
232 232
@@ -237,76 +237,77 @@ list_release(List *self)
237 * and finally print it 237 * and finally print it
238 */ 238 */
239 239
240int 240int sort_main(int argc, char **argv)
241sort_main(int argc, char **argv)
242{ 241{
243 int i; 242 int i;
244 char opt; 243 char opt;
245 List list; 244 List list;
246 Line *l; 245 Line *l;
247 Compare *compare; 246 Compare *compare;
248 247
249 /* init */ 248 /* init */
250 compare = compare_ascii; 249 compare = compare_ascii;
251 list_init(&list); 250 list_init(&list);
252 251
253 /* parse argv[] */ 252 /* parse argv[] */
254 for (i = 1; i < argc; i++) { 253 for (i = 1; i < argc; i++) {
255 if (argv[i][0] == '-') { 254 if (argv[i][0] == '-') {
256 opt = argv[i][1]; 255 opt = argv[i][1];
257 switch (opt) { 256 switch (opt) {
258 case 'g': 257 case 'g':
259 /* what's the diff between -g && -n? */ 258 /* what's the diff between -g && -n? */
260 compare = compare_numeric; 259 compare = compare_numeric;
261 break; 260 break;
262 case 'h': 261 case 'h':
263 usage(sort_usage); 262 usage(sort_usage);
264 break; 263 break;
265 case 'n': 264 case 'n':
266 /* what's the diff between -g && -n? */ 265 /* what's the diff between -g && -n? */
267 compare = compare_numeric; 266 compare = compare_numeric;
268 break; 267 break;
269 case 'r': 268 case 'r':
270 /* reverse */ 269 /* reverse */
271 break; 270 break;
272 default: 271 default:
273 fprintf(stderr, "sort: invalid option -- %c\n", opt); 272 fprintf(stderr, "sort: invalid option -- %c\n", opt);
274 usage(sort_usage); 273 usage(sort_usage);
275 } 274 }
276 } else { 275 } else {
277 break; 276 break;
277 }
278 } 278 }
279 }
280 279
281 /* this could be factored better */ 280 /* this could be factored better */
282 281
283 /* work w/ stdin */ 282 /* work w/ stdin */
284 if (i >= argc) { 283 if (i >= argc) {
285 while ( (l = line_newFromFile(stdin))) { 284 while ((l = line_newFromFile(stdin))) {
286 list_insert(&list, l); 285 list_insert(&list, l);
287 } 286 }
288 list_sort(&list, compare); 287 list_sort(&list, compare);
289 list_writeToFile(&list, stdout); 288 list_writeToFile(&list, stdout);
290 list_release(&list); 289 list_release(&list);
291 290
292 /* work w/ what's left in argv[] */ 291 /* work w/ what's left in argv[] */
293 } else { 292 } else {
294 FILE *src; 293 FILE *src;
295 294
296 for ( ; i < argc; i++) { 295 for (; i < argc; i++) {
297 src = fopen(argv[i], "r"); 296 src = fopen(argv[i], "r");
298 if (src == NULL) { break; } 297 if (src == NULL) {
299 while ( (l = line_newFromFile(src))) { 298 break;
300 list_insert(&list, l); 299 }
301 } 300 while ((l = line_newFromFile(src))) {
302 fclose(src); 301 list_insert(&list, l);
302 }
303 fclose(src);
304 }
305 list_sort(&list, compare);
306 list_writeToFile(&list, stdout);
307 list_release(&list);
303 } 308 }
304 list_sort(&list, compare);
305 list_writeToFile(&list, stdout);
306 list_release(&list);
307 }
308 309
309 exit(0); 310 exit(0);
310} 311}
311 312
312/* $Id: sort.c,v 1.10 2000/02/07 05:29:42 erik Exp $ */ 313/* $Id: sort.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */
diff --git a/swaponoff.c b/swaponoff.c
index 3c02bdd42..6bda22277 100644
--- a/swaponoff.c
+++ b/swaponoff.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini swapon/swapoff implementation for busybox 3 * Mini swapon/swapoff implementation for busybox
3 * 4 *
@@ -32,91 +33,93 @@
32 33
33 34
34static int whichApp; 35static int whichApp;
35static const char* appName; 36static const char *appName;
36 37
37static const char swapoff_usage[] = 38static const char swapoff_usage[] =
38"swapoff device\n" 39
39"\nStop swapping virtual memory pages on the given device.\n"; 40 "swapoff device\n"
40static const char swapon_usage[] = 41 "\nStop swapping virtual memory pages on the given device.\n";
41"swapon device\n" 42static const char swapon_usage[] =
42"\nStart swapping virtual memory pages on the given device.\n"; 43
44 "swapon device\n"
45 "\nStart swapping virtual memory pages on the given device.\n";
43 46
44 47
45#define SWAPON_APP 1 48#define SWAPON_APP 1
46#define SWAPOFF_APP 2 49#define SWAPOFF_APP 2
47 50
48 51
49static void 52static void swap_enable_disable(char *device)
50swap_enable_disable( char *device)
51{ 53{
52 int status; 54 int status;
53 if ( whichApp == SWAPON_APP ) 55
54 status = swapon(device, 0); 56 if (whichApp == SWAPON_APP)
55 else 57 status = swapon(device, 0);
56 status = swapoff(device); 58 else
57 59 status = swapoff(device);
58 if ( status != 0 ) { 60
59 perror(appName); 61 if (status != 0) {
60 exit( FALSE); 62 perror(appName);
61 } 63 exit(FALSE);
64 }
62} 65}
63 66
64static void 67static void do_em_all()
65do_em_all()
66{ 68{
67 struct mntent *m; 69 struct mntent *m;
68 FILE *f = setmntent ("/etc/fstab", "r"); 70 FILE *f = setmntent("/etc/fstab", "r");
69 71
70 if (f == NULL) { 72 if (f == NULL) {
71 perror("/etc/fstab"); 73 perror("/etc/fstab");
72 exit( FALSE); 74 exit(FALSE);
73 } 75 }
74 while ((m = getmntent (f)) != NULL) { 76 while ((m = getmntent(f)) != NULL) {
75 if (!strstr (m->mnt_type, MNTTYPE_SWAP)) { 77 if (!strstr(m->mnt_type, MNTTYPE_SWAP)) {
76 swap_enable_disable( m->mnt_fsname); 78 swap_enable_disable(m->mnt_fsname);
77 } 79 }
78 } 80 }
79 endmntent (f); 81 endmntent(f);
80 exit( TRUE); 82 exit(TRUE);
81} 83}
82 84
83 85
84extern int 86extern int swap_on_off_main(int argc, char **argv)
85swap_on_off_main(int argc, char * * argv)
86{ 87{
87 struct stat statBuf; 88 struct stat statBuf;
88 if (stat("/etc/fstab", &statBuf) < 0) 89
89 fprintf(stderr, "/etc/fstab file missing -- Please install one.\n\n"); 90 if (stat("/etc/fstab", &statBuf) < 0)
90 91 fprintf(stderr,
91 if (strcmp(*argv, "swapon")==0) { 92 "/etc/fstab file missing -- Please install one.\n\n");
92 appName = *argv; 93
93 whichApp = SWAPON_APP; 94 if (strcmp(*argv, "swapon") == 0) {
94 95 appName = *argv;
95 } else { 96 whichApp = SWAPON_APP;
96 appName = *argv; 97
97 whichApp = SWAPOFF_APP; 98 } else {
98 } 99 appName = *argv;
99 100 whichApp = SWAPOFF_APP;
100 if (argc < 2) 101 }
101 goto usage_and_exit; 102
102 argc--; 103 if (argc < 2)
103 argv++;
104
105 /* Parse any options */
106 while (**argv == '-') {
107 while (*++(*argv)) switch (**argv) {
108 case 'a':
109 do_em_all();
110 break;
111 default:
112 goto usage_and_exit; 104 goto usage_and_exit;
105 argc--;
106 argv++;
107
108 /* Parse any options */
109 while (**argv == '-') {
110 while (*++(*argv))
111 switch (**argv) {
112 case 'a':
113 do_em_all();
114 break;
115 default:
116 goto usage_and_exit;
117 }
113 } 118 }
114 } 119 swap_enable_disable(*argv);
115 swap_enable_disable(*argv); 120 exit(TRUE);
116 exit( TRUE);
117 121
118usage_and_exit: 122 usage_and_exit:
119 usage( (whichApp==SWAPON_APP)? swapon_usage : swapoff_usage); 123 usage((whichApp == SWAPON_APP) ? swapon_usage : swapoff_usage);
120 exit( FALSE); 124 exit(FALSE);
121} 125}
122
diff --git a/sync.c b/sync.c
index 145ed1eda..f8160c8dc 100644
--- a/sync.c
+++ b/sync.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini sync implementation for busybox 3 * Mini sync implementation for busybox
3 * 4 *
@@ -23,12 +24,10 @@
23#include "internal.h" 24#include "internal.h"
24#include <stdio.h> 25#include <stdio.h>
25 26
26extern int 27extern int sync_main(int argc, char **argv)
27sync_main(int argc, char * * argv)
28{ 28{
29 if ( argc>1 && **(argv+1) == '-' ) { 29 if (argc > 1 && **(argv + 1) == '-') {
30 usage( "sync\n\nWrite all buffered filesystem blocks to disk.\n"); 30 usage("sync\n\nWrite all buffered filesystem blocks to disk.\n");
31 } 31 }
32 exit( sync()); 32 exit(sync());
33} 33}
34
diff --git a/sysklogd/logger.c b/sysklogd/logger.c
index aab95b984..a9e0afcc8 100644
--- a/sysklogd/logger.c
+++ b/sysklogd/logger.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini logger implementation for busybox 3 * Mini logger implementation for busybox
3 * 4 *
@@ -39,21 +40,22 @@
39 */ 40 */
40#include <sys/syslog.h> 41#include <sys/syslog.h>
41typedef struct _code { 42typedef struct _code {
42 char *c_name; 43 char *c_name;
43 int c_val; 44 int c_val;
44} CODE; 45} CODE;
45extern CODE prioritynames[]; 46extern CODE prioritynames[];
46extern CODE facilitynames[]; 47extern CODE facilitynames[];
47#endif 48#endif
48 49
49static const char logger_usage[] = 50static const char logger_usage[] =
50 "logger [OPTION]... [MESSAGE]\n\n" 51 "logger [OPTION]... [MESSAGE]\n\n"
51 "Write MESSAGE to the system log. If MESSAGE is '-', log stdin.\n\n" 52 "Write MESSAGE to the system log. If MESSAGE is '-', log stdin.\n\n"
52 "Options:\n" 53 "Options:\n"
53 "\t-s\tLog to stderr as well as the system log.\n" 54 "\t-s\tLog to stderr as well as the system log.\n"
54 "\t-t\tLog using the specified tag (defaults to user name).\n" 55 "\t-t\tLog using the specified tag (defaults to user name).\n"
55 "\t-p\tEnter the message with the specified priority.\n" 56
56 "\t\tThis may be numerical or a ``facility.level'' pair.\n"; 57 "\t-p\tEnter the message with the specified priority.\n"
58 "\t\tThis may be numerical or a ``facility.level'' pair.\n";
57 59
58 60
59/* Decode a symbolic name to a numeric value 61/* Decode a symbolic name to a numeric value
@@ -61,20 +63,19 @@ static const char logger_usage[] =
61 * Copyright (c) 1983, 1993 63 * Copyright (c) 1983, 1993
62 * The Regents of the University of California. All rights reserved. 64 * The Regents of the University of California. All rights reserved.
63 */ 65 */
64static int 66static int decode(char *name, CODE * codetab)
65decode(char* name, CODE* codetab)
66{ 67{
67 CODE *c; 68 CODE *c;
68 69
69 if (isdigit(*name)) 70 if (isdigit(*name))
70 return (atoi(name)); 71 return (atoi(name));
71 for (c = codetab; c->c_name; c++) { 72 for (c = codetab; c->c_name; c++) {
72 if (!strcasecmp(name, c->c_name)) { 73 if (!strcasecmp(name, c->c_name)) {
73 return (c->c_val); 74 return (c->c_val);
75 }
74 } 76 }
75 }
76 77
77 return (-1); 78 return (-1);
78} 79}
79 80
80/* Decode a symbolic name to a numeric value 81/* Decode a symbolic name to a numeric value
@@ -82,96 +83,94 @@ decode(char* name, CODE* codetab)
82 * Copyright (c) 1983, 1993 83 * Copyright (c) 1983, 1993
83 * The Regents of the University of California. All rights reserved. 84 * The Regents of the University of California. All rights reserved.
84 */ 85 */
85static int 86static int pencode(char *s)
86pencode(char* s)
87{ 87{
88 char *save; 88 char *save;
89 int lev, fac=LOG_USER; 89 int lev, fac = LOG_USER;
90 90
91 for (save = s; *s && *s != '.'; ++s); 91 for (save = s; *s && *s != '.'; ++s);
92 if (*s) { 92 if (*s) {
93 *s = '\0'; 93 *s = '\0';
94 fac = decode(save, facilitynames); 94 fac = decode(save, facilitynames);
95 if (fac < 0) { 95 if (fac < 0) {
96 fprintf(stderr, "unknown facility name: %s\n", save); 96 fprintf(stderr, "unknown facility name: %s\n", save);
97 exit( FALSE); 97 exit(FALSE);
98 }
99 *s++ = '.';
100 } else {
101 s = save;
102 }
103 lev = decode(s, prioritynames);
104 if (lev < 0) {
105 fprintf(stderr, "unknown priority name: %s\n", save);
106 exit(FALSE);
98 } 107 }
99 *s++ = '.'; 108 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
100 }
101 else {
102 s = save;
103 }
104 lev = decode(s, prioritynames);
105 if (lev < 0) {
106 fprintf(stderr, "unknown priority name: %s\n", save);
107 exit( FALSE);
108 }
109 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
110} 109}
111 110
112 111
113extern int logger_main(int argc, char **argv) 112extern int logger_main(int argc, char **argv)
114{ 113{
115 int pri = LOG_USER|LOG_NOTICE; 114 int pri = LOG_USER | LOG_NOTICE;
116 int option = 0; 115 int option = 0;
117 int fromStdinFlag=FALSE; 116 int fromStdinFlag = FALSE;
118 int stopLookingAtMeLikeThat=FALSE; 117 int stopLookingAtMeLikeThat = FALSE;
119 char *message, buf[1024], name[128]; 118 char *message, buf[1024], name[128];
120 119
121 /* Fill out the name string early (may be overwritten later */ 120 /* Fill out the name string early (may be overwritten later */
122 my_getpwuid(name, geteuid()); 121 my_getpwuid(name, geteuid());
123 122
124 /* Parse any options */ 123 /* Parse any options */
125 while (--argc > 0 && **(++argv) == '-') { 124 while (--argc > 0 && **(++argv) == '-') {
126 if (*((*argv)+1) == '\0') { 125 if (*((*argv) + 1) == '\0') {
127 fromStdinFlag=TRUE; 126 fromStdinFlag = TRUE;
128 }
129 stopLookingAtMeLikeThat=FALSE;
130 while (*(++(*argv)) && stopLookingAtMeLikeThat==FALSE) {
131 switch (**argv) {
132 case 's':
133 option |= LOG_PERROR;
134 break;
135 case 'p':
136 if (--argc == 0) {
137 usage(logger_usage);
138 } 127 }
139 pri = pencode(*(++argv)); 128 stopLookingAtMeLikeThat = FALSE;
140 stopLookingAtMeLikeThat=TRUE; 129 while (*(++(*argv)) && stopLookingAtMeLikeThat == FALSE) {
141 break; 130 switch (**argv) {
142 case 't': 131 case 's':
143 if (--argc == 0) { 132 option |= LOG_PERROR;
144 usage(logger_usage); 133 break;
134 case 'p':
135 if (--argc == 0) {
136 usage(logger_usage);
137 }
138 pri = pencode(*(++argv));
139 stopLookingAtMeLikeThat = TRUE;
140 break;
141 case 't':
142 if (--argc == 0) {
143 usage(logger_usage);
144 }
145 strncpy(name, *(++argv), sizeof(name));
146 stopLookingAtMeLikeThat = TRUE;
147 break;
148 default:
149 usage(logger_usage);
150 }
145 } 151 }
146 strncpy(name, *(++argv), sizeof(name));
147 stopLookingAtMeLikeThat=TRUE;
148 break;
149 default:
150 usage(logger_usage);
151 }
152 } 152 }
153 }
154 153
155 if (fromStdinFlag==TRUE) { 154 if (fromStdinFlag == TRUE) {
156 /* read from stdin */ 155 /* read from stdin */
157 int c, i=0; 156 int c, i = 0;
158 while ((c = getc(stdin)) != EOF && i<sizeof(buf)) { 157
159 buf[i++]=c; 158 while ((c = getc(stdin)) != EOF && i < sizeof(buf)) {
160 } 159 buf[i++] = c;
161 message=buf; 160 }
162 } else { 161 message = buf;
163 if (argc>=1) {
164 message = *argv;
165 } else { 162 } else {
166 fprintf(stderr, "No message\n"); 163 if (argc >= 1) {
167 exit( FALSE); 164 message = *argv;
165 } else {
166 fprintf(stderr, "No message\n");
167 exit(FALSE);
168 }
168 } 169 }
169 }
170 170
171 openlog( name, option, (pri | LOG_FACMASK)); 171 openlog(name, option, (pri | LOG_FACMASK));
172 syslog( pri, message); 172 syslog(pri, message);
173 closelog(); 173 closelog();
174 174
175 exit( TRUE); 175 exit(TRUE);
176} 176}
177
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index c48d5a435..db535044c 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini syslogd implementation for busybox 3 * Mini syslogd implementation for busybox
3 * 4 *
@@ -49,266 +50,272 @@ extern int ksyslog(int type, char *buf, int len);
49#define __LOG_FILE "/var/log/messages" 50#define __LOG_FILE "/var/log/messages"
50 51
51 52
52static char* logFilePath = __LOG_FILE; 53static char *logFilePath = __LOG_FILE;
54
53/* interval between marks in seconds */ 55/* interval between marks in seconds */
54static int MarkInterval = 20*60; 56static int MarkInterval = 20 * 60;
57
55/* localhost's name */ 58/* localhost's name */
56static char LocalHostName[32]; 59static char LocalHostName[32];
57 60
58static const char syslogd_usage[] = 61static const char syslogd_usage[] =
59 "syslogd [OPTION]...\n\n" 62 "syslogd [OPTION]...\n\n"
60 "Linux system and kernel (provides klogd) logging utility.\n" 63 "Linux system and kernel (provides klogd) logging utility.\n"
61 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n" 64 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n"
62 "Options:\n" 65 "Options:\n"
63 "\t-m\tChange the mark timestamp interval. default=20min. 0=off\n" 66 "\t-m\tChange the mark timestamp interval. default=20min. 0=off\n"
64 "\t-n\tDo not fork into the background (for when run by init)\n" 67 "\t-n\tDo not fork into the background (for when run by init)\n"
65#ifdef BB_KLOGD 68#ifdef BB_KLOGD
66 "\t-K\tDo not start up the klogd process (by default syslogd spawns klogd).\n" 69 "\t-K\tDo not start up the klogd process (by default syslogd spawns klogd).\n"
67#endif 70#endif
68 "\t-O\tSpecify an alternate log file. default=/var/log/messages\n"; 71 "\t-O\tSpecify an alternate log file. default=/var/log/messages\n";
69 72
70 73
71/* print a message to the log file */ 74/* print a message to the log file */
72static void message(char *fmt, ...) 75static void message(char *fmt, ...)
73{ 76{
74 int fd; 77 int fd;
75 va_list arguments; 78 va_list arguments;
76 79
77 if ((fd = device_open(logFilePath, O_WRONLY|O_CREAT|O_NOCTTY|O_APPEND|O_NONBLOCK)) >= 0) { 80 if (
78 va_start(arguments, fmt); 81 (fd =
79 vdprintf(fd, fmt, arguments); 82 device_open(logFilePath,
80 va_end(arguments); 83 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
81 close(fd); 84 O_NONBLOCK)) >= 0) {
82 } else { 85 va_start(arguments, fmt);
83 /* Always send console messages to /dev/console so people will see them. */ 86 vdprintf(fd, fmt, arguments);
84 if ((fd = device_open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY|O_NONBLOCK)) >= 0) { 87 va_end(arguments);
85 va_start(arguments, fmt); 88 close(fd);
86 vdprintf(fd, fmt, arguments);
87 va_end(arguments);
88 close(fd);
89 } else { 89 } else {
90 fprintf(stderr, "Bummer, can't print: "); 90 /* Always send console messages to /dev/console so people will see them. */
91 va_start(arguments, fmt); 91 if (
92 vfprintf(stderr, fmt, arguments); 92 (fd =
93 fflush(stderr); 93 device_open(_PATH_CONSOLE,
94 va_end(arguments); 94 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
95 va_start(arguments, fmt);
96 vdprintf(fd, fmt, arguments);
97 va_end(arguments);
98 close(fd);
99 } else {
100 fprintf(stderr, "Bummer, can't print: ");
101 va_start(arguments, fmt);
102 vfprintf(stderr, fmt, arguments);
103 fflush(stderr);
104 va_end(arguments);
105 }
95 } 106 }
96 }
97} 107}
98 108
99static void logMessage( int pri, char* msg) 109static void logMessage(int pri, char *msg)
100{ 110{
101 time_t now; 111 time_t now;
102 char *timestamp; 112 char *timestamp;
103 static char res[20]; 113 static char res[20];
104 CODE *c_pri, *c_fac; 114 CODE *c_pri, *c_fac;
105 115
106 for (c_fac=facilitynames; c_fac->c_name && !(c_fac->c_val==LOG_FAC(pri)<<3); c_fac++); 116 for (c_fac = facilitynames;
107 for (c_pri=prioritynames; c_pri->c_name && !(c_pri->c_val==LOG_PRI(pri)); c_pri++); 117 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
108 if (*c_fac->c_name=='\0' || *c_pri->c_name=='\0') 118 for (c_pri = prioritynames;
109 snprintf (res, sizeof(res), "<%d>", pri); 119 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
110 else 120 if (*c_fac->c_name == '\0' || *c_pri->c_name == '\0')
111 snprintf (res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); 121 snprintf(res, sizeof(res), "<%d>", pri);
112 122 else
113 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || 123 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
114 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') 124
115 { 125 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
116 time(&now); 126 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
117 timestamp = ctime(&now) + 4; 127 time(&now);
118 timestamp[15] = '\0'; 128 timestamp = ctime(&now) + 4;
119 } else { 129 timestamp[15] = '\0';
120 timestamp = msg; 130 } else {
121 timestamp[15] = '\0'; 131 timestamp = msg;
122 msg += 16; 132 timestamp[15] = '\0';
123 } 133 msg += 16;
124 134 }
125 /* todo: supress duplicates */ 135
126 136 /* todo: supress duplicates */
127 /* now spew out the message to wherever it is supposed to go */ 137
128 message( "%s %s %s %s\n", timestamp, LocalHostName, res, msg); 138 /* now spew out the message to wherever it is supposed to go */
139 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
129} 140}
130 141
131static void quit_signal(int sig) 142static void quit_signal(int sig)
132{ 143{
133 logMessage(LOG_SYSLOG|LOG_INFO, "System log daemon exiting."); 144 logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
134 unlink( _PATH_LOG); 145 unlink(_PATH_LOG);
135 exit( TRUE); 146 exit(TRUE);
136} 147}
137 148
138static void restart_signal(int sig) 149static void restart_signal(int sig)
139{ 150{
140 /* pretend to restart */ 151 /* pretend to restart */
141 logMessage(LOG_SYSLOG|LOG_INFO, "syslogd restarting"); 152 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd restarting");
142} 153}
143 154
144static void domark(int sig) 155static void domark(int sig)
145{ 156{
146 if (MarkInterval > 0) { 157 if (MarkInterval > 0) {
147 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --"); 158 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
148 alarm(MarkInterval); 159 alarm(MarkInterval);
149 } 160 }
150} 161}
151 162
152static void doSyslogd(void) 163static void doSyslogd(void)
153{ 164{
154 struct sockaddr_un sunx; 165 struct sockaddr_un sunx;
155 int fd, conn; 166 int fd, conn;
156 size_t addrLength; 167 size_t addrLength;
157 char buf[1024]; 168 char buf[1024];
158 char *q, *p = buf; 169 char *q, *p = buf;
159 int readSize; 170 int readSize;
160 171
161 /* Set up sig handlers */ 172 /* Set up sig handlers */
162 signal(SIGINT, quit_signal); 173 signal(SIGINT, quit_signal);
163 signal(SIGTERM, quit_signal); 174 signal(SIGTERM, quit_signal);
164 signal(SIGQUIT, quit_signal); 175 signal(SIGQUIT, quit_signal);
165 signal(SIGHUP, restart_signal); 176 signal(SIGHUP, restart_signal);
166 signal(SIGALRM, domark); 177 signal(SIGALRM, domark);
167 alarm(MarkInterval); 178 alarm(MarkInterval);
168 179
169 /* Remove any preexisting socket/file */ 180 /* Remove any preexisting socket/file */
170 unlink(_PATH_LOG); 181 unlink(_PATH_LOG);
171 182
172 memset(&sunx, 0, sizeof(sunx)); 183 memset(&sunx, 0, sizeof(sunx));
173 sunx.sun_family = AF_UNIX; /* Unix domain socket */ 184 sunx.sun_family = AF_UNIX; /* Unix domain socket */
174 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path)); 185 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path));
175 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 ) { 186 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
176 perror("Couldn't obtain descriptor for socket " _PATH_LOG); 187 perror("Couldn't obtain descriptor for socket " _PATH_LOG);
177 exit( FALSE); 188 exit(FALSE);
178 } 189 }
179
180 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
181 if ( (bind(fd, (struct sockaddr *) &sunx, addrLength)) ||
182 (listen(fd, 5)) )
183 {
184 perror("Could not connect to socket " _PATH_LOG);
185 exit( FALSE);
186 }
187
188 umask(0);
189 if (chmod(_PATH_LOG, 0666) < 0) {
190 perror("Could not set permission on " _PATH_LOG);
191 exit (FALSE);
192 }
193
194 logMessage(LOG_SYSLOG|LOG_INFO, "syslogd started: "
195 "BusyBox v" BB_VER " (" BB_BT ")");
196
197
198 while ((conn = accept(fd, (struct sockaddr *) &sunx,
199 &addrLength)) >= 0)
200 {
201 while ((readSize=read(conn, buf, sizeof(buf))) > 0)
202 {
203 char line[1025];
204 unsigned char c;
205 int pri = (LOG_USER|LOG_NOTICE);
206
207 memset (line, 0, sizeof(line));
208 p = buf;
209 q = line;
210 while ( p && (c = *p) && q < &line[sizeof(line) - 1]) {
211 if (c == '<') {
212 /* Parse the magic priority number */
213 pri = 0;
214 while (isdigit(*(++p))) {
215 pri = 10 * pri + (*p - '0');
216 }
217 if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
218 pri = (LOG_USER|LOG_NOTICE);
219 } else if (c == '\n') {
220 *q++ = ' ';
221 } else if (iscntrl(c)&&(c<0177)) {
222 *q++ = '^';
223 *q++ = c ^ 0100;
224 } else {
225 *q++ = c;
226 }
227 p++;
228 }
229 *q = '\0';
230 190
231 /* Now log it */ 191 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
232 logMessage( pri, line); 192 if ((bind(fd, (struct sockaddr *) &sunx, addrLength)) ||
193 (listen(fd, 5))) {
194 perror("Could not connect to socket " _PATH_LOG);
195 exit(FALSE);
233 } 196 }
234 close(conn);
235 }
236 197
237 close(fd); 198 umask(0);
199 if (chmod(_PATH_LOG, 0666) < 0) {
200 perror("Could not set permission on " _PATH_LOG);
201 exit(FALSE);
202 }
203
204 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: "
205 "BusyBox v" BB_VER " (" BB_BT ")");
206
207
208 while ((conn = accept(fd, (struct sockaddr *) &sunx,
209 &addrLength)) >= 0) {
210 while ((readSize = read(conn, buf, sizeof(buf))) > 0) {
211 char line[1025];
212 unsigned char c;
213 int pri = (LOG_USER | LOG_NOTICE);
214
215 memset(line, 0, sizeof(line));
216 p = buf;
217 q = line;
218 while (p && (c = *p) && q < &line[sizeof(line) - 1]) {
219 if (c == '<') {
220 /* Parse the magic priority number */
221 pri = 0;
222 while (isdigit(*(++p))) {
223 pri = 10 * pri + (*p - '0');
224 }
225 if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
226 pri = (LOG_USER | LOG_NOTICE);
227 } else if (c == '\n') {
228 *q++ = ' ';
229 } else if (iscntrl(c) && (c < 0177)) {
230 *q++ = '^';
231 *q++ = c ^ 0100;
232 } else {
233 *q++ = c;
234 }
235 p++;
236 }
237 *q = '\0';
238
239 /* Now log it */
240 logMessage(pri, line);
241 }
242 close(conn);
243 }
244
245 close(fd);
238} 246}
239 247
240#ifdef BB_KLOGD 248#ifdef BB_KLOGD
241 249
242static void klogd_signal(int sig) 250static void klogd_signal(int sig)
243{ 251{
244 ksyslog(7, NULL, 0); 252 ksyslog(7, NULL, 0);
245 ksyslog(0, 0, 0); 253 ksyslog(0, 0, 0);
246 logMessage(LOG_SYSLOG|LOG_INFO, "Kernel log daemon exiting."); 254 logMessage(LOG_SYSLOG | LOG_INFO, "Kernel log daemon exiting.");
247 exit( TRUE); 255 exit(TRUE);
248} 256}
249 257
250static void doKlogd(void) 258static void doKlogd(void)
251{ 259{
252 int priority=LOG_INFO; 260 int priority = LOG_INFO;
253 char log_buffer[4096]; 261 char log_buffer[4096];
254 char *logp; 262 char *logp;
255 263
256 /* Set up sig handlers */ 264 /* Set up sig handlers */
257 signal(SIGINT, klogd_signal); 265 signal(SIGINT, klogd_signal);
258 signal(SIGKILL, klogd_signal); 266 signal(SIGKILL, klogd_signal);
259 signal(SIGTERM, klogd_signal); 267 signal(SIGTERM, klogd_signal);
260 signal(SIGHUP, klogd_signal); 268 signal(SIGHUP, klogd_signal);
261 logMessage(LOG_SYSLOG|LOG_INFO, "klogd started: " 269 logMessage(LOG_SYSLOG | LOG_INFO, "klogd started: "
262 "BusyBox v" BB_VER " (" BB_BT ")"); 270 "BusyBox v" BB_VER " (" BB_BT ")");
263 271
264 ksyslog(1, NULL, 0); 272 ksyslog(1, NULL, 0);
265 273
266 while (1) { 274 while (1) {
267 /* Use kernel syscalls */ 275 /* Use kernel syscalls */
268 memset(log_buffer, '\0', sizeof(log_buffer)); 276 memset(log_buffer, '\0', sizeof(log_buffer));
269 if ( ksyslog(2, log_buffer, sizeof(log_buffer)) < 0 ) { 277 if (ksyslog(2, log_buffer, sizeof(log_buffer)) < 0) {
270 char message[80]; 278 char message[80];
271 if ( errno == EINTR ) 279
272 continue; 280 if (errno == EINTR)
273 snprintf(message, 79, "klogd: Error return from sys_sycall: " \ 281 continue;
274 "%d - %s.\n", errno, strerror(errno)); 282 snprintf(message, 79, "klogd: Error return from sys_sycall: " \
275 logMessage(LOG_SYSLOG|LOG_ERR, message); 283 "%d - %s.\n", errno, strerror(errno));
276 exit(1); 284 logMessage(LOG_SYSLOG | LOG_ERR, message);
285 exit(1);
286 }
287 logp = log_buffer;
288 if (*log_buffer == '<') {
289 switch (*(log_buffer + 1)) {
290 case '0':
291 priority = LOG_EMERG;
292 break;
293 case '1':
294 priority = LOG_ALERT;
295 break;
296 case '2':
297 priority = LOG_CRIT;
298 break;
299 case '3':
300 priority = LOG_ERR;
301 break;
302 case '4':
303 priority = LOG_WARNING;
304 break;
305 case '5':
306 priority = LOG_NOTICE;
307 break;
308 case '6':
309 priority = LOG_INFO;
310 break;
311 case '7':
312 default:
313 priority = LOG_DEBUG;
314 }
315 logp += 3;
316 }
317 logMessage(LOG_KERN | priority, logp);
277 } 318 }
278 logp=log_buffer;
279 if ( *log_buffer == '<' )
280 {
281 switch ( *(log_buffer+1) )
282 {
283 case '0':
284 priority = LOG_EMERG;
285 break;
286 case '1':
287 priority = LOG_ALERT;
288 break;
289 case '2':
290 priority = LOG_CRIT;
291 break;
292 case '3':
293 priority = LOG_ERR;
294 break;
295 case '4':
296 priority = LOG_WARNING;
297 break;
298 case '5':
299 priority = LOG_NOTICE;
300 break;
301 case '6':
302 priority = LOG_INFO;
303 break;
304 case '7':
305 default:
306 priority = LOG_DEBUG;
307 }
308 logp+=3;
309 }
310 logMessage(LOG_KERN|priority, logp);
311 }
312 319
313} 320}
314 321
@@ -316,76 +323,75 @@ static void doKlogd(void)
316 323
317extern int syslogd_main(int argc, char **argv) 324extern int syslogd_main(int argc, char **argv)
318{ 325{
319 int pid, klogd_pid; 326 int pid, klogd_pid;
320 int doFork = TRUE; 327 int doFork = TRUE;
328
321#ifdef BB_KLOGD 329#ifdef BB_KLOGD
322 int startKlogd = TRUE; 330 int startKlogd = TRUE;
323#endif 331#endif
324 int stopDoingThat = FALSE; 332 int stopDoingThat = FALSE;
325 char *p; 333 char *p;
326 char **argv1=argv; 334 char **argv1 = argv;
327 335
328 while (--argc > 0 && **(++argv1) == '-') { 336 while (--argc > 0 && **(++argv1) == '-') {
329 stopDoingThat = FALSE; 337 stopDoingThat = FALSE;
330 while (stopDoingThat == FALSE && *(++(*argv1))) { 338 while (stopDoingThat == FALSE && *(++(*argv1))) {
331 switch (**argv1) { 339 switch (**argv1) {
332 case 'm': 340 case 'm':
333 if (--argc == 0) { 341 if (--argc == 0) {
334 usage(syslogd_usage); 342 usage(syslogd_usage);
335 } 343 }
336 MarkInterval = atoi(*(++argv1))*60; 344 MarkInterval = atoi(*(++argv1)) * 60;
337 break; 345 break;
338 case 'n': 346 case 'n':
339 doFork = FALSE; 347 doFork = FALSE;
340 break; 348 break;
341#ifdef BB_KLOGD 349#ifdef BB_KLOGD
342 case 'K': 350 case 'K':
343 startKlogd = FALSE; 351 startKlogd = FALSE;
344 break; 352 break;
345#endif 353#endif
346 case 'O': 354 case 'O':
347 if (--argc == 0) { 355 if (--argc == 0) {
348 usage(syslogd_usage); 356 usage(syslogd_usage);
357 }
358 logFilePath = *(++argv1);
359 stopDoingThat = TRUE;
360 break;
361 default:
362 usage(syslogd_usage);
363 }
349 } 364 }
350 logFilePath = *(++argv1);
351 stopDoingThat = TRUE;
352 break;
353 default:
354 usage(syslogd_usage);
355 }
356 } 365 }
357 } 366
358 367 /* Store away localhost's name before the fork */
359 /* Store away localhost's name before the fork */ 368 gethostname(LocalHostName, sizeof(LocalHostName));
360 gethostname(LocalHostName, sizeof(LocalHostName)); 369 if ((p = strchr(LocalHostName, '.'))) {
361 if ( (p = strchr(LocalHostName, '.')) ) { 370 *p++ = '\0';
362 *p++ = '\0'; 371 }
363 } 372
364 373 if (doFork == TRUE) {
365 if (doFork == TRUE) { 374 pid = fork();
366 pid = fork(); 375 if (pid < 0)
367 if ( pid < 0 ) 376 exit(pid);
368 exit( pid); 377 else if (pid == 0) {
369 else if ( pid == 0 ) { 378 strncpy(argv[0], "syslogd", strlen(argv[0]));
370 strncpy(argv[0], "syslogd",strlen(argv[0])); 379 doSyslogd();
371 doSyslogd(); 380 }
381 } else {
382 doSyslogd();
372 } 383 }
373 } else {
374 doSyslogd();
375 }
376 384
377#ifdef BB_KLOGD 385#ifdef BB_KLOGD
378 /* Start up the klogd process */ 386 /* Start up the klogd process */
379 if (startKlogd == TRUE) { 387 if (startKlogd == TRUE) {
380 klogd_pid = fork(); 388 klogd_pid = fork();
381 if (klogd_pid == 0 ) { 389 if (klogd_pid == 0) {
382 strncpy(argv[0], "klogd", strlen(argv[0])); 390 strncpy(argv[0], "klogd", strlen(argv[0]));
383 doKlogd(); 391 doKlogd();
392 }
384 } 393 }
385 }
386#endif 394#endif
387 395
388 exit( TRUE); 396 exit(TRUE);
389} 397}
390
391
diff --git a/syslogd.c b/syslogd.c
index c48d5a435..db535044c 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini syslogd implementation for busybox 3 * Mini syslogd implementation for busybox
3 * 4 *
@@ -49,266 +50,272 @@ extern int ksyslog(int type, char *buf, int len);
49#define __LOG_FILE "/var/log/messages" 50#define __LOG_FILE "/var/log/messages"
50 51
51 52
52static char* logFilePath = __LOG_FILE; 53static char *logFilePath = __LOG_FILE;
54
53/* interval between marks in seconds */ 55/* interval between marks in seconds */
54static int MarkInterval = 20*60; 56static int MarkInterval = 20 * 60;
57
55/* localhost's name */ 58/* localhost's name */
56static char LocalHostName[32]; 59static char LocalHostName[32];
57 60
58static const char syslogd_usage[] = 61static const char syslogd_usage[] =
59 "syslogd [OPTION]...\n\n" 62 "syslogd [OPTION]...\n\n"
60 "Linux system and kernel (provides klogd) logging utility.\n" 63 "Linux system and kernel (provides klogd) logging utility.\n"
61 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n" 64 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n"
62 "Options:\n" 65 "Options:\n"
63 "\t-m\tChange the mark timestamp interval. default=20min. 0=off\n" 66 "\t-m\tChange the mark timestamp interval. default=20min. 0=off\n"
64 "\t-n\tDo not fork into the background (for when run by init)\n" 67 "\t-n\tDo not fork into the background (for when run by init)\n"
65#ifdef BB_KLOGD 68#ifdef BB_KLOGD
66 "\t-K\tDo not start up the klogd process (by default syslogd spawns klogd).\n" 69 "\t-K\tDo not start up the klogd process (by default syslogd spawns klogd).\n"
67#endif 70#endif
68 "\t-O\tSpecify an alternate log file. default=/var/log/messages\n"; 71 "\t-O\tSpecify an alternate log file. default=/var/log/messages\n";
69 72
70 73
71/* print a message to the log file */ 74/* print a message to the log file */
72static void message(char *fmt, ...) 75static void message(char *fmt, ...)
73{ 76{
74 int fd; 77 int fd;
75 va_list arguments; 78 va_list arguments;
76 79
77 if ((fd = device_open(logFilePath, O_WRONLY|O_CREAT|O_NOCTTY|O_APPEND|O_NONBLOCK)) >= 0) { 80 if (
78 va_start(arguments, fmt); 81 (fd =
79 vdprintf(fd, fmt, arguments); 82 device_open(logFilePath,
80 va_end(arguments); 83 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
81 close(fd); 84 O_NONBLOCK)) >= 0) {
82 } else { 85 va_start(arguments, fmt);
83 /* Always send console messages to /dev/console so people will see them. */ 86 vdprintf(fd, fmt, arguments);
84 if ((fd = device_open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY|O_NONBLOCK)) >= 0) { 87 va_end(arguments);
85 va_start(arguments, fmt); 88 close(fd);
86 vdprintf(fd, fmt, arguments);
87 va_end(arguments);
88 close(fd);
89 } else { 89 } else {
90 fprintf(stderr, "Bummer, can't print: "); 90 /* Always send console messages to /dev/console so people will see them. */
91 va_start(arguments, fmt); 91 if (
92 vfprintf(stderr, fmt, arguments); 92 (fd =
93 fflush(stderr); 93 device_open(_PATH_CONSOLE,
94 va_end(arguments); 94 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
95 va_start(arguments, fmt);
96 vdprintf(fd, fmt, arguments);
97 va_end(arguments);
98 close(fd);
99 } else {
100 fprintf(stderr, "Bummer, can't print: ");
101 va_start(arguments, fmt);
102 vfprintf(stderr, fmt, arguments);
103 fflush(stderr);
104 va_end(arguments);
105 }
95 } 106 }
96 }
97} 107}
98 108
99static void logMessage( int pri, char* msg) 109static void logMessage(int pri, char *msg)
100{ 110{
101 time_t now; 111 time_t now;
102 char *timestamp; 112 char *timestamp;
103 static char res[20]; 113 static char res[20];
104 CODE *c_pri, *c_fac; 114 CODE *c_pri, *c_fac;
105 115
106 for (c_fac=facilitynames; c_fac->c_name && !(c_fac->c_val==LOG_FAC(pri)<<3); c_fac++); 116 for (c_fac = facilitynames;
107 for (c_pri=prioritynames; c_pri->c_name && !(c_pri->c_val==LOG_PRI(pri)); c_pri++); 117 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
108 if (*c_fac->c_name=='\0' || *c_pri->c_name=='\0') 118 for (c_pri = prioritynames;
109 snprintf (res, sizeof(res), "<%d>", pri); 119 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
110 else 120 if (*c_fac->c_name == '\0' || *c_pri->c_name == '\0')
111 snprintf (res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); 121 snprintf(res, sizeof(res), "<%d>", pri);
112 122 else
113 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || 123 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
114 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') 124
115 { 125 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
116 time(&now); 126 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
117 timestamp = ctime(&now) + 4; 127 time(&now);
118 timestamp[15] = '\0'; 128 timestamp = ctime(&now) + 4;
119 } else { 129 timestamp[15] = '\0';
120 timestamp = msg; 130 } else {
121 timestamp[15] = '\0'; 131 timestamp = msg;
122 msg += 16; 132 timestamp[15] = '\0';
123 } 133 msg += 16;
124 134 }
125 /* todo: supress duplicates */ 135
126 136 /* todo: supress duplicates */
127 /* now spew out the message to wherever it is supposed to go */ 137
128 message( "%s %s %s %s\n", timestamp, LocalHostName, res, msg); 138 /* now spew out the message to wherever it is supposed to go */
139 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
129} 140}
130 141
131static void quit_signal(int sig) 142static void quit_signal(int sig)
132{ 143{
133 logMessage(LOG_SYSLOG|LOG_INFO, "System log daemon exiting."); 144 logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
134 unlink( _PATH_LOG); 145 unlink(_PATH_LOG);
135 exit( TRUE); 146 exit(TRUE);
136} 147}
137 148
138static void restart_signal(int sig) 149static void restart_signal(int sig)
139{ 150{
140 /* pretend to restart */ 151 /* pretend to restart */
141 logMessage(LOG_SYSLOG|LOG_INFO, "syslogd restarting"); 152 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd restarting");
142} 153}
143 154
144static void domark(int sig) 155static void domark(int sig)
145{ 156{
146 if (MarkInterval > 0) { 157 if (MarkInterval > 0) {
147 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --"); 158 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
148 alarm(MarkInterval); 159 alarm(MarkInterval);
149 } 160 }
150} 161}
151 162
152static void doSyslogd(void) 163static void doSyslogd(void)
153{ 164{
154 struct sockaddr_un sunx; 165 struct sockaddr_un sunx;
155 int fd, conn; 166 int fd, conn;
156 size_t addrLength; 167 size_t addrLength;
157 char buf[1024]; 168 char buf[1024];
158 char *q, *p = buf; 169 char *q, *p = buf;
159 int readSize; 170 int readSize;
160 171
161 /* Set up sig handlers */ 172 /* Set up sig handlers */
162 signal(SIGINT, quit_signal); 173 signal(SIGINT, quit_signal);
163 signal(SIGTERM, quit_signal); 174 signal(SIGTERM, quit_signal);
164 signal(SIGQUIT, quit_signal); 175 signal(SIGQUIT, quit_signal);
165 signal(SIGHUP, restart_signal); 176 signal(SIGHUP, restart_signal);
166 signal(SIGALRM, domark); 177 signal(SIGALRM, domark);
167 alarm(MarkInterval); 178 alarm(MarkInterval);
168 179
169 /* Remove any preexisting socket/file */ 180 /* Remove any preexisting socket/file */
170 unlink(_PATH_LOG); 181 unlink(_PATH_LOG);
171 182
172 memset(&sunx, 0, sizeof(sunx)); 183 memset(&sunx, 0, sizeof(sunx));
173 sunx.sun_family = AF_UNIX; /* Unix domain socket */ 184 sunx.sun_family = AF_UNIX; /* Unix domain socket */
174 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path)); 185 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path));
175 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 ) { 186 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
176 perror("Couldn't obtain descriptor for socket " _PATH_LOG); 187 perror("Couldn't obtain descriptor for socket " _PATH_LOG);
177 exit( FALSE); 188 exit(FALSE);
178 } 189 }
179
180 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
181 if ( (bind(fd, (struct sockaddr *) &sunx, addrLength)) ||
182 (listen(fd, 5)) )
183 {
184 perror("Could not connect to socket " _PATH_LOG);
185 exit( FALSE);
186 }
187
188 umask(0);
189 if (chmod(_PATH_LOG, 0666) < 0) {
190 perror("Could not set permission on " _PATH_LOG);
191 exit (FALSE);
192 }
193
194 logMessage(LOG_SYSLOG|LOG_INFO, "syslogd started: "
195 "BusyBox v" BB_VER " (" BB_BT ")");
196
197
198 while ((conn = accept(fd, (struct sockaddr *) &sunx,
199 &addrLength)) >= 0)
200 {
201 while ((readSize=read(conn, buf, sizeof(buf))) > 0)
202 {
203 char line[1025];
204 unsigned char c;
205 int pri = (LOG_USER|LOG_NOTICE);
206
207 memset (line, 0, sizeof(line));
208 p = buf;
209 q = line;
210 while ( p && (c = *p) && q < &line[sizeof(line) - 1]) {
211 if (c == '<') {
212 /* Parse the magic priority number */
213 pri = 0;
214 while (isdigit(*(++p))) {
215 pri = 10 * pri + (*p - '0');
216 }
217 if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
218 pri = (LOG_USER|LOG_NOTICE);
219 } else if (c == '\n') {
220 *q++ = ' ';
221 } else if (iscntrl(c)&&(c<0177)) {
222 *q++ = '^';
223 *q++ = c ^ 0100;
224 } else {
225 *q++ = c;
226 }
227 p++;
228 }
229 *q = '\0';
230 190
231 /* Now log it */ 191 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
232 logMessage( pri, line); 192 if ((bind(fd, (struct sockaddr *) &sunx, addrLength)) ||
193 (listen(fd, 5))) {
194 perror("Could not connect to socket " _PATH_LOG);
195 exit(FALSE);
233 } 196 }
234 close(conn);
235 }
236 197
237 close(fd); 198 umask(0);
199 if (chmod(_PATH_LOG, 0666) < 0) {
200 perror("Could not set permission on " _PATH_LOG);
201 exit(FALSE);
202 }
203
204 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: "
205 "BusyBox v" BB_VER " (" BB_BT ")");
206
207
208 while ((conn = accept(fd, (struct sockaddr *) &sunx,
209 &addrLength)) >= 0) {
210 while ((readSize = read(conn, buf, sizeof(buf))) > 0) {
211 char line[1025];
212 unsigned char c;
213 int pri = (LOG_USER | LOG_NOTICE);
214
215 memset(line, 0, sizeof(line));
216 p = buf;
217 q = line;
218 while (p && (c = *p) && q < &line[sizeof(line) - 1]) {
219 if (c == '<') {
220 /* Parse the magic priority number */
221 pri = 0;
222 while (isdigit(*(++p))) {
223 pri = 10 * pri + (*p - '0');
224 }
225 if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
226 pri = (LOG_USER | LOG_NOTICE);
227 } else if (c == '\n') {
228 *q++ = ' ';
229 } else if (iscntrl(c) && (c < 0177)) {
230 *q++ = '^';
231 *q++ = c ^ 0100;
232 } else {
233 *q++ = c;
234 }
235 p++;
236 }
237 *q = '\0';
238
239 /* Now log it */
240 logMessage(pri, line);
241 }
242 close(conn);
243 }
244
245 close(fd);
238} 246}
239 247
240#ifdef BB_KLOGD 248#ifdef BB_KLOGD
241 249
242static void klogd_signal(int sig) 250static void klogd_signal(int sig)
243{ 251{
244 ksyslog(7, NULL, 0); 252 ksyslog(7, NULL, 0);
245 ksyslog(0, 0, 0); 253 ksyslog(0, 0, 0);
246 logMessage(LOG_SYSLOG|LOG_INFO, "Kernel log daemon exiting."); 254 logMessage(LOG_SYSLOG | LOG_INFO, "Kernel log daemon exiting.");
247 exit( TRUE); 255 exit(TRUE);
248} 256}
249 257
250static void doKlogd(void) 258static void doKlogd(void)
251{ 259{
252 int priority=LOG_INFO; 260 int priority = LOG_INFO;
253 char log_buffer[4096]; 261 char log_buffer[4096];
254 char *logp; 262 char *logp;
255 263
256 /* Set up sig handlers */ 264 /* Set up sig handlers */
257 signal(SIGINT, klogd_signal); 265 signal(SIGINT, klogd_signal);
258 signal(SIGKILL, klogd_signal); 266 signal(SIGKILL, klogd_signal);
259 signal(SIGTERM, klogd_signal); 267 signal(SIGTERM, klogd_signal);
260 signal(SIGHUP, klogd_signal); 268 signal(SIGHUP, klogd_signal);
261 logMessage(LOG_SYSLOG|LOG_INFO, "klogd started: " 269 logMessage(LOG_SYSLOG | LOG_INFO, "klogd started: "
262 "BusyBox v" BB_VER " (" BB_BT ")"); 270 "BusyBox v" BB_VER " (" BB_BT ")");
263 271
264 ksyslog(1, NULL, 0); 272 ksyslog(1, NULL, 0);
265 273
266 while (1) { 274 while (1) {
267 /* Use kernel syscalls */ 275 /* Use kernel syscalls */
268 memset(log_buffer, '\0', sizeof(log_buffer)); 276 memset(log_buffer, '\0', sizeof(log_buffer));
269 if ( ksyslog(2, log_buffer, sizeof(log_buffer)) < 0 ) { 277 if (ksyslog(2, log_buffer, sizeof(log_buffer)) < 0) {
270 char message[80]; 278 char message[80];
271 if ( errno == EINTR ) 279
272 continue; 280 if (errno == EINTR)
273 snprintf(message, 79, "klogd: Error return from sys_sycall: " \ 281 continue;
274 "%d - %s.\n", errno, strerror(errno)); 282 snprintf(message, 79, "klogd: Error return from sys_sycall: " \
275 logMessage(LOG_SYSLOG|LOG_ERR, message); 283 "%d - %s.\n", errno, strerror(errno));
276 exit(1); 284 logMessage(LOG_SYSLOG | LOG_ERR, message);
285 exit(1);
286 }
287 logp = log_buffer;
288 if (*log_buffer == '<') {
289 switch (*(log_buffer + 1)) {
290 case '0':
291 priority = LOG_EMERG;
292 break;
293 case '1':
294 priority = LOG_ALERT;
295 break;
296 case '2':
297 priority = LOG_CRIT;
298 break;
299 case '3':
300 priority = LOG_ERR;
301 break;
302 case '4':
303 priority = LOG_WARNING;
304 break;
305 case '5':
306 priority = LOG_NOTICE;
307 break;
308 case '6':
309 priority = LOG_INFO;
310 break;
311 case '7':
312 default:
313 priority = LOG_DEBUG;
314 }
315 logp += 3;
316 }
317 logMessage(LOG_KERN | priority, logp);
277 } 318 }
278 logp=log_buffer;
279 if ( *log_buffer == '<' )
280 {
281 switch ( *(log_buffer+1) )
282 {
283 case '0':
284 priority = LOG_EMERG;
285 break;
286 case '1':
287 priority = LOG_ALERT;
288 break;
289 case '2':
290 priority = LOG_CRIT;
291 break;
292 case '3':
293 priority = LOG_ERR;
294 break;
295 case '4':
296 priority = LOG_WARNING;
297 break;
298 case '5':
299 priority = LOG_NOTICE;
300 break;
301 case '6':
302 priority = LOG_INFO;
303 break;
304 case '7':
305 default:
306 priority = LOG_DEBUG;
307 }
308 logp+=3;
309 }
310 logMessage(LOG_KERN|priority, logp);
311 }
312 319
313} 320}
314 321
@@ -316,76 +323,75 @@ static void doKlogd(void)
316 323
317extern int syslogd_main(int argc, char **argv) 324extern int syslogd_main(int argc, char **argv)
318{ 325{
319 int pid, klogd_pid; 326 int pid, klogd_pid;
320 int doFork = TRUE; 327 int doFork = TRUE;
328
321#ifdef BB_KLOGD 329#ifdef BB_KLOGD
322 int startKlogd = TRUE; 330 int startKlogd = TRUE;
323#endif 331#endif
324 int stopDoingThat = FALSE; 332 int stopDoingThat = FALSE;
325 char *p; 333 char *p;
326 char **argv1=argv; 334 char **argv1 = argv;
327 335
328 while (--argc > 0 && **(++argv1) == '-') { 336 while (--argc > 0 && **(++argv1) == '-') {
329 stopDoingThat = FALSE; 337 stopDoingThat = FALSE;
330 while (stopDoingThat == FALSE && *(++(*argv1))) { 338 while (stopDoingThat == FALSE && *(++(*argv1))) {
331 switch (**argv1) { 339 switch (**argv1) {
332 case 'm': 340 case 'm':
333 if (--argc == 0) { 341 if (--argc == 0) {
334 usage(syslogd_usage); 342 usage(syslogd_usage);
335 } 343 }
336 MarkInterval = atoi(*(++argv1))*60; 344 MarkInterval = atoi(*(++argv1)) * 60;
337 break; 345 break;
338 case 'n': 346 case 'n':
339 doFork = FALSE; 347 doFork = FALSE;
340 break; 348 break;
341#ifdef BB_KLOGD 349#ifdef BB_KLOGD
342 case 'K': 350 case 'K':
343 startKlogd = FALSE; 351 startKlogd = FALSE;
344 break; 352 break;
345#endif 353#endif
346 case 'O': 354 case 'O':
347 if (--argc == 0) { 355 if (--argc == 0) {
348 usage(syslogd_usage); 356 usage(syslogd_usage);
357 }
358 logFilePath = *(++argv1);
359 stopDoingThat = TRUE;
360 break;
361 default:
362 usage(syslogd_usage);
363 }
349 } 364 }
350 logFilePath = *(++argv1);
351 stopDoingThat = TRUE;
352 break;
353 default:
354 usage(syslogd_usage);
355 }
356 } 365 }
357 } 366
358 367 /* Store away localhost's name before the fork */
359 /* Store away localhost's name before the fork */ 368 gethostname(LocalHostName, sizeof(LocalHostName));
360 gethostname(LocalHostName, sizeof(LocalHostName)); 369 if ((p = strchr(LocalHostName, '.'))) {
361 if ( (p = strchr(LocalHostName, '.')) ) { 370 *p++ = '\0';
362 *p++ = '\0'; 371 }
363 } 372
364 373 if (doFork == TRUE) {
365 if (doFork == TRUE) { 374 pid = fork();
366 pid = fork(); 375 if (pid < 0)
367 if ( pid < 0 ) 376 exit(pid);
368 exit( pid); 377 else if (pid == 0) {
369 else if ( pid == 0 ) { 378 strncpy(argv[0], "syslogd", strlen(argv[0]));
370 strncpy(argv[0], "syslogd",strlen(argv[0])); 379 doSyslogd();
371 doSyslogd(); 380 }
381 } else {
382 doSyslogd();
372 } 383 }
373 } else {
374 doSyslogd();
375 }
376 384
377#ifdef BB_KLOGD 385#ifdef BB_KLOGD
378 /* Start up the klogd process */ 386 /* Start up the klogd process */
379 if (startKlogd == TRUE) { 387 if (startKlogd == TRUE) {
380 klogd_pid = fork(); 388 klogd_pid = fork();
381 if (klogd_pid == 0 ) { 389 if (klogd_pid == 0) {
382 strncpy(argv[0], "klogd", strlen(argv[0])); 390 strncpy(argv[0], "klogd", strlen(argv[0]));
383 doKlogd(); 391 doKlogd();
392 }
384 } 393 }
385 }
386#endif 394#endif
387 395
388 exit( TRUE); 396 exit(TRUE);
389} 397}
390
391
diff --git a/tail.c b/tail.c
index 0ab8f11b0..31705afa2 100644
--- a/tail.c
+++ b/tail.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1#include "internal.h" 2#include "internal.h"
2/* This file contains _two_ implementations of tail. One is 3/* This file contains _two_ implementations of tail. One is
3 * a bit more full featured, but costs 6k. The other (i.e. the 4 * a bit more full featured, but costs 6k. The other (i.e. the
@@ -68,22 +69,23 @@ static int forever;
68static int print_headers; 69static int print_headers;
69 70
70const char tail_usage[] = 71const char tail_usage[] =
71 "tail [OPTION] [FILE]...\n\n" 72 "tail [OPTION] [FILE]...\n\n"
72 "Print last 10 lines of each FILE to standard output.\n" 73 "Print last 10 lines of each FILE to standard output.\n"
73 "With more than one FILE, precede each with a header giving the\n" 74 "With more than one FILE, precede each with a header giving the\n"
74 "file name. With no FILE, or when FILE is -, read standard input.\n\n" 75 "file name. With no FILE, or when FILE is -, read standard input.\n\n"
75 "Options:\n" 76 "Options:\n"
76 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n" 77 "\t-n NUM\t\tPrint last NUM lines instead of first 10\n"
77 "\t-f\t\tOutput data as the file grows. This version\n" 78
78 "\t\t\tof 'tail -f' supports only one file at a time.\n"; 79 "\t-f\t\tOutput data as the file grows. This version\n"
80 "\t\t\tof 'tail -f' supports only one file at a time.\n";
79 81
80 82
81static void write_header(const char *filename) 83static void write_header(const char *filename)
82{ 84{
83 static int first_file = 1; 85 static int first_file = 1;
84 86
85 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename); 87 printf("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
86 first_file = 0; 88 first_file = 0;
87} 89}
88 90
89/* Print the last N_LINES lines from the end of file FD. 91/* Print the last N_LINES lines from the end of file FD.
@@ -97,57 +99,57 @@ static void write_header(const char *filename)
97static int 99static int
98file_lines(const char *filename, int fd, long int n_lines, off_t pos) 100file_lines(const char *filename, int fd, long int n_lines, off_t pos)
99{ 101{
100 char buffer[BUFSIZ]; 102 char buffer[BUFSIZ];
101 int bytes_read; 103 int bytes_read;
102 int i; /* Index into `buffer' for scanning. */ 104 int i; /* Index into `buffer' for scanning. */
103
104 if (n_lines == 0)
105 return 0;
106 105
107 /* Set `bytes_read' to the size of the last, probably partial, buffer; 106 if (n_lines == 0)
108 0 < `bytes_read' <= `BUFSIZ'. */
109 bytes_read = pos % BUFSIZ;
110 if (bytes_read == 0)
111 bytes_read = BUFSIZ;
112 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
113 reads will be on block boundaries, which might increase efficiency. */
114 pos -= bytes_read;
115 lseek(fd, pos, SEEK_SET);
116 bytes_read = fullRead(fd, buffer, bytes_read);
117 if (bytes_read == -1)
118 error("read error");
119
120 /* Count the incomplete line on files that don't end with a newline. */
121 if (bytes_read && buffer[bytes_read - 1] != '\n')
122 --n_lines;
123
124 do {
125 /* Scan backward, counting the newlines in this bufferfull. */
126 for (i = bytes_read - 1; i >= 0; i--) {
127 /* Have we counted the requested number of newlines yet? */
128 if (buffer[i] == '\n' && n_lines-- == 0) {
129 /* If this newline wasn't the last character in the buffer,
130 print the text after it. */
131 if (i != bytes_read - 1)
132 XWRITE(STDOUT_FILENO, &buffer[i + 1],
133 bytes_read - (i + 1));
134 return 0; 107 return 0;
135 } 108
136 } 109 /* Set `bytes_read' to the size of the last, probably partial, buffer;
137 /* Not enough newlines in that bufferfull. */ 110 0 < `bytes_read' <= `BUFSIZ'. */
138 if (pos == 0) { 111 bytes_read = pos % BUFSIZ;
139 /* Not enough lines in the file; print the entire file. */ 112 if (bytes_read == 0)
140 lseek(fd, (off_t) 0, SEEK_SET); 113 bytes_read = BUFSIZ;
141 return 0; 114 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
142 } 115 reads will be on block boundaries, which might increase efficiency. */
143 pos -= BUFSIZ; 116 pos -= bytes_read;
144 lseek(fd, pos, SEEK_SET); 117 lseek(fd, pos, SEEK_SET);
145 } 118 bytes_read = fullRead(fd, buffer, bytes_read);
146 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0); 119 if (bytes_read == -1)
147 if (bytes_read == -1) 120 error("read error");
148 error("read error"); 121
122 /* Count the incomplete line on files that don't end with a newline. */
123 if (bytes_read && buffer[bytes_read - 1] != '\n')
124 --n_lines;
125
126 do {
127 /* Scan backward, counting the newlines in this bufferfull. */
128 for (i = bytes_read - 1; i >= 0; i--) {
129 /* Have we counted the requested number of newlines yet? */
130 if (buffer[i] == '\n' && n_lines-- == 0) {
131 /* If this newline wasn't the last character in the buffer,
132 print the text after it. */
133 if (i != bytes_read - 1)
134 XWRITE(STDOUT_FILENO, &buffer[i + 1],
135 bytes_read - (i + 1));
136 return 0;
137 }
138 }
139 /* Not enough newlines in that bufferfull. */
140 if (pos == 0) {
141 /* Not enough lines in the file; print the entire file. */
142 lseek(fd, (off_t) 0, SEEK_SET);
143 return 0;
144 }
145 pos -= BUFSIZ;
146 lseek(fd, pos, SEEK_SET);
147 }
148 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
149 if (bytes_read == -1)
150 error("read error");
149 151
150 return 0; 152 return 0;
151} 153}
152 154
153/* Print the last N_LINES lines from the end of the standard input, 155/* Print the last N_LINES lines from the end of the standard input,
@@ -157,100 +159,100 @@ file_lines(const char *filename, int fd, long int n_lines, off_t pos)
157 159
158static int pipe_lines(const char *filename, int fd, long int n_lines) 160static int pipe_lines(const char *filename, int fd, long int n_lines)
159{ 161{
160 struct linebuffer { 162 struct linebuffer {
161 int nbytes, nlines; 163 int nbytes, nlines;
162 char buffer[BUFSIZ]; 164 char buffer[BUFSIZ];
163 struct linebuffer *next; 165 struct linebuffer *next;
164 }; 166 };
165 typedef struct linebuffer LBUFFER; 167 typedef struct linebuffer LBUFFER;
166 LBUFFER *first, *last, *tmp; 168 LBUFFER *first, *last, *tmp;
167 int i; /* Index into buffers. */ 169 int i; /* Index into buffers. */
168 int total_lines = 0; /* Total number of newlines in all buffers. */ 170 int total_lines = 0; /* Total number of newlines in all buffers. */
169 int errors = 0; 171 int errors = 0;
170 172
171 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 173 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
172 first->nbytes = first->nlines = 0; 174 first->nbytes = first->nlines = 0;
173 first->next = NULL; 175 first->next = NULL;
174 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 176 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
175 177
176 /* Input is always read into a fresh buffer. */ 178 /* Input is always read into a fresh buffer. */
177 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) { 179 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
178 tmp->nlines = 0; 180 tmp->nlines = 0;
179 tmp->next = NULL; 181 tmp->next = NULL;
180 182
181 /* Count the number of newlines just read. */ 183 /* Count the number of newlines just read. */
182 for (i = 0; i < tmp->nbytes; i++) 184 for (i = 0; i < tmp->nbytes; i++)
183 if (tmp->buffer[i] == '\n') 185 if (tmp->buffer[i] == '\n')
184 ++tmp->nlines; 186 ++tmp->nlines;
185 total_lines += tmp->nlines; 187 total_lines += tmp->nlines;
186 188
187 /* If there is enough room in the last buffer read, just append the new 189 /* If there is enough room in the last buffer read, just append the new
188 one to it. This is because when reading from a pipe, `nbytes' can 190 one to it. This is because when reading from a pipe, `nbytes' can
189 often be very small. */ 191 often be very small. */
190 if (tmp->nbytes + last->nbytes < BUFSIZ) { 192 if (tmp->nbytes + last->nbytes < BUFSIZ) {
191 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 193 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
192 last->nbytes += tmp->nbytes; 194 last->nbytes += tmp->nbytes;
193 last->nlines += tmp->nlines; 195 last->nlines += tmp->nlines;
194 } else { 196 } else {
195 /* If there's not enough room, link the new buffer onto the end of 197 /* If there's not enough room, link the new buffer onto the end of
196 the list, then either free up the oldest buffer for the next 198 the list, then either free up the oldest buffer for the next
197 read if that would leave enough lines, or else malloc a new one. 199 read if that would leave enough lines, or else malloc a new one.
198 Some compaction mechanism is possible but probably not 200 Some compaction mechanism is possible but probably not
199 worthwhile. */ 201 worthwhile. */
200 last = last->next = tmp; 202 last = last->next = tmp;
201 if (total_lines - first->nlines > n_lines) { 203 if (total_lines - first->nlines > n_lines) {
202 tmp = first; 204 tmp = first;
203 total_lines -= first->nlines; 205 total_lines -= first->nlines;
204 first = first->next; 206 first = first->next;
205 } else 207 } else
206 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER)); 208 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
209 }
207 } 210 }
208 } 211 if (tmp->nbytes == -1)
209 if (tmp->nbytes == -1) 212 error("read error");
210 error("read error"); 213
211 214 free((char *) tmp);
212 free((char *) tmp); 215
213 216 /* This prevents a core dump when the pipe contains no newlines. */
214 /* This prevents a core dump when the pipe contains no newlines. */ 217 if (n_lines == 0)
215 if (n_lines == 0) 218 goto free_lbuffers;
216 goto free_lbuffers; 219
217 220 /* Count the incomplete line on files that don't end with a newline. */
218 /* Count the incomplete line on files that don't end with a newline. */ 221 if (last->buffer[last->nbytes - 1] != '\n') {
219 if (last->buffer[last->nbytes - 1] != '\n') { 222 ++last->nlines;
220 ++last->nlines; 223 ++total_lines;
221 ++total_lines; 224 }
222 } 225
223 226 /* Run through the list, printing lines. First, skip over unneeded
224 /* Run through the list, printing lines. First, skip over unneeded 227 buffers. */
225 buffers. */ 228 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
226 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next) 229 total_lines -= tmp->nlines;
227 total_lines -= tmp->nlines; 230
228 231 /* Find the correct beginning, then print the rest of the file. */
229 /* Find the correct beginning, then print the rest of the file. */ 232 if (total_lines > n_lines) {
230 if (total_lines > n_lines) { 233 char *cp;
231 char *cp; 234
232 235 /* Skip `total_lines' - `n_lines' newlines. We made sure that
233 /* Skip `total_lines' - `n_lines' newlines. We made sure that 236 `total_lines' - `n_lines' <= `tmp->nlines'. */
234 `total_lines' - `n_lines' <= `tmp->nlines'. */ 237 cp = tmp->buffer;
235 cp = tmp->buffer; 238 for (i = total_lines - n_lines; i; --i)
236 for (i = total_lines - n_lines; i; --i) 239 while (*cp++ != '\n')
237 while (*cp++ != '\n') 240 /* Do nothing. */ ;
238 /* Do nothing. */ ; 241 i = cp - tmp->buffer;
239 i = cp - tmp->buffer; 242 } else
240 } else 243 i = 0;
241 i = 0; 244 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
242 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i); 245
243 246 for (tmp = tmp->next; tmp; tmp = tmp->next)
244 for (tmp = tmp->next; tmp; tmp = tmp->next) 247 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
245 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
246 248
247 free_lbuffers: 249 free_lbuffers:
248 while (first) { 250 while (first) {
249 tmp = first->next; 251 tmp = first->next;
250 free((char *) first); 252 free((char *) first);
251 first = tmp; 253 first = tmp;
252 } 254 }
253 return errors; 255 return errors;
254} 256}
255 257
256/* Display file FILENAME from the current position in FD to the end. 258/* Display file FILENAME from the current position in FD to the end.
@@ -259,25 +261,25 @@ static int pipe_lines(const char *filename, int fd, long int n_lines)
259 261
260static long dump_remainder(const char *filename, int fd) 262static long dump_remainder(const char *filename, int fd)
261{ 263{
262 char buffer[BUFSIZ]; 264 char buffer[BUFSIZ];
263 int bytes_read; 265 int bytes_read;
264 long total; 266 long total;
265 267
266 total = 0; 268 total = 0;
267 output: 269 output:
268 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) { 270 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
269 XWRITE(STDOUT_FILENO, buffer, bytes_read); 271 XWRITE(STDOUT_FILENO, buffer, bytes_read);
270 total += bytes_read; 272 total += bytes_read;
271 } 273 }
272 if (bytes_read == -1) 274 if (bytes_read == -1)
273 error("read error"); 275 error("read error");
274 if (forever) { 276 if (forever) {
275 fflush(stdout); 277 fflush(stdout);
276 sleep(1); 278 sleep(1);
277 goto output; 279 goto output;
278 } 280 }
279 281
280 return total; 282 return total;
281} 283}
282 284
283/* Output the last N_LINES lines of file FILENAME open for reading in FD. 285/* Output the last N_LINES lines of file FILENAME open for reading in FD.
@@ -285,31 +287,31 @@ static long dump_remainder(const char *filename, int fd)
285 287
286static int tail_lines(const char *filename, int fd, long int n_lines) 288static int tail_lines(const char *filename, int fd, long int n_lines)
287{ 289{
288 struct stat stats; 290 struct stat stats;
289 off_t length; 291 off_t length;
290 292
291 if (print_headers) 293 if (print_headers)
292 write_header(filename); 294 write_header(filename);
293 295
294 if (fstat(fd, &stats)) 296 if (fstat(fd, &stats))
295 error("fstat error"); 297 error("fstat error");
296 298
297 /* Use file_lines only if FD refers to a regular file with 299 /* Use file_lines only if FD refers to a regular file with
298 its file pointer positioned at beginning of file. */ 300 its file pointer positioned at beginning of file. */
299 /* FIXME: adding the lseek conjunct is a kludge. 301 /* FIXME: adding the lseek conjunct is a kludge.
300 Once there's a reasonable test suite, fix the true culprit: 302 Once there's a reasonable test suite, fix the true culprit:
301 file_lines. file_lines shouldn't presume that the input 303 file_lines. file_lines shouldn't presume that the input
302 file pointer is initially positioned to beginning of file. */ 304 file pointer is initially positioned to beginning of file. */
303 if (S_ISREG(stats.st_mode) 305 if (S_ISREG(stats.st_mode)
304 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) { 306 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
305 length = lseek(fd, (off_t) 0, SEEK_END); 307 length = lseek(fd, (off_t) 0, SEEK_END);
306 if (length != 0 && file_lines(filename, fd, n_lines, length)) 308 if (length != 0 && file_lines(filename, fd, n_lines, length))
307 return 1; 309 return 1;
308 dump_remainder(filename, fd); 310 dump_remainder(filename, fd);
309 } else 311 } else
310 return pipe_lines(filename, fd, n_lines); 312 return pipe_lines(filename, fd, n_lines);
311 313
312 return 0; 314 return 0;
313} 315}
314 316
315/* Display the last N_UNITS lines of file FILENAME. 317/* Display the last N_UNITS lines of file FILENAME.
@@ -318,78 +320,78 @@ static int tail_lines(const char *filename, int fd, long int n_lines)
318 320
319static int tail_file(const char *filename, off_t n_units) 321static int tail_file(const char *filename, off_t n_units)
320{ 322{
321 int fd, errors; 323 int fd, errors;
322 324
323 if (!strcmp(filename, "-")) { 325 if (!strcmp(filename, "-")) {
324 filename = "standard input"; 326 filename = "standard input";
325 errors = tail_lines(filename, 0, (long) n_units); 327 errors = tail_lines(filename, 0, (long) n_units);
326 } else { 328 } else {
327 /* Not standard input. */ 329 /* Not standard input. */
328 fd = open(filename, O_RDONLY); 330 fd = open(filename, O_RDONLY);
329 if (fd == -1) 331 if (fd == -1)
330 error("open error"); 332 error("open error");
331 333
332 errors = tail_lines(filename, fd, (long) n_units); 334 errors = tail_lines(filename, fd, (long) n_units);
333 close(fd); 335 close(fd);
334 } 336 }
335 337
336 return errors; 338 return errors;
337} 339}
338 340
339extern int tail_main(int argc, char **argv) 341extern int tail_main(int argc, char **argv)
340{ 342{
341 int exit_status = 0; 343 int exit_status = 0;
342 int n_units = DEFAULT_N_LINES; 344 int n_units = DEFAULT_N_LINES;
343 int n_tmp, i; 345 int n_tmp, i;
344 char opt; 346 char opt;
345 347
346 forever = print_headers = 0; 348 forever = print_headers = 0;
347 349
348 /* parse argv[] */ 350 /* parse argv[] */
349 for (i = 1; i < argc; i++) { 351 for (i = 1; i < argc; i++) {
350 if (argv[i][0] == '-') { 352 if (argv[i][0] == '-') {
351 opt = argv[i][1]; 353 opt = argv[i][1];
352 switch (opt) { 354 switch (opt) {
353 case 'f': 355 case 'f':
354 forever = 1; 356 forever = 1;
355 break; 357 break;
356 case 'n': 358 case 'n':
357 n_tmp = 0; 359 n_tmp = 0;
358 if (++i < argc) 360 if (++i < argc)
359 n_tmp = atoi(argv[i]); 361 n_tmp = atoi(argv[i]);
360 if (n_tmp < 1) 362 if (n_tmp < 1)
361 usage(tail_usage); 363 usage(tail_usage);
362 n_units = n_tmp; 364 n_units = n_tmp;
363 break; 365 break;
364 case '-': 366 case '-':
365 case 'h': 367 case 'h':
366 usage(tail_usage); 368 usage(tail_usage);
367 default: 369 default:
368 fprintf(stderr, "tail: invalid option -- %c\n", opt); 370 fprintf(stderr, "tail: invalid option -- %c\n", opt);
369 usage(tail_usage); 371 usage(tail_usage);
370 } 372 }
371 } else { 373 } else {
372 break; 374 break;
375 }
373 } 376 }
374 }
375 377
376 if (i + 1 < argc) { 378 if (i + 1 < argc) {
377 if (forever) { 379 if (forever) {
378 fprintf(stderr, 380 fprintf(stderr,
379 "tail: option -f is invalid with multiple files\n"); 381 "tail: option -f is invalid with multiple files\n");
380 usage(tail_usage); 382 usage(tail_usage);
383 }
384 print_headers = 1;
381 } 385 }
382 print_headers = 1;
383 }
384 386
385 if (i >= argc) { 387 if (i >= argc) {
386 exit_status |= tail_file("-", n_units); 388 exit_status |= tail_file("-", n_units);
387 } else { 389 } else {
388 for (; i < argc; i++) 390 for (; i < argc; i++)
389 exit_status |= tail_file(argv[i], n_units); 391 exit_status |= tail_file(argv[i], n_units);
390 } 392 }
391 393
392 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 394 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
393} 395}
394 396
395 397
@@ -441,15 +443,15 @@ extern int tail_main(int argc, char **argv)
441#define NDEBUG 1 443#define NDEBUG 1
442 444
443 445
444static void detailed_error(int i, int errnum, char* fmt, ...) 446static void detailed_error(int i, int errnum, char *fmt, ...)
445{ 447{
446 va_list arguments; 448 va_list arguments;
447 449
448 va_start(arguments, fmt); 450 va_start(arguments, fmt);
449 vfprintf(stderr, fmt, arguments); 451 vfprintf(stderr, fmt, arguments);
450 fprintf(stderr, "\n%s\n", strerror( errnum)); 452 fprintf(stderr, "\n%s\n", strerror(errnum));
451 va_end(arguments); 453 va_end(arguments);
452 exit(i); 454 exit(i);
453} 455}
454 456
455 457
@@ -494,9 +496,8 @@ static int from_start;
494static int print_headers; 496static int print_headers;
495 497
496/* When to print the filename banners. */ 498/* When to print the filename banners. */
497enum header_mode 499enum header_mode {
498{ 500 multiple_files, always, never
499 multiple_files, always, never
500}; 501};
501 502
502/* The name this program was run with. */ 503/* The name this program was run with. */
@@ -506,8 +507,7 @@ char *program_name;
506static int have_read_stdin; 507static int have_read_stdin;
507 508
508 509
509static const char tail_usage[] = 510static const char tail_usage[] = "tail [OPTION]... [FILE]...\n\
510"tail [OPTION]... [FILE]...\n\
511\n\ 511\n\
512Print last 10 lines of each FILE to standard output.\n\ 512Print last 10 lines of each FILE to standard output.\n\
513With more than one FILE, precede each with a header giving the file name.\n\ 513With more than one FILE, precede each with a header giving the file name.\n\
@@ -524,15 +524,13 @@ If the first character of N (bytes or lines) is a `+', output begins with \n\
524the Nth item from the start of each file, otherwise, print the last N items\n\ 524the Nth item from the start of each file, otherwise, print the last N items\n\
525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n"; 525in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2).\n\n";
526 526
527static void 527static void write_header(const char *filename, const char *comment)
528write_header (const char *filename, const char *comment)
529{ 528{
530 static int first_file = 1; 529 static int first_file = 1;
531 530
532 printf ("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename, 531 printf("%s==> %s%s%s <==\n", (first_file ? "" : "\n"), filename,
533 (comment ? ": " : ""), 532 (comment ? ": " : ""), (comment ? comment : ""));
534 (comment ? comment : "")); 533 first_file = 0;
535 first_file = 0;
536} 534}
537 535
538/* Print the last N_LINES lines from the end of file FD. 536/* Print the last N_LINES lines from the end of file FD.
@@ -544,67 +542,62 @@ write_header (const char *filename, const char *comment)
544 Return 0 if successful, 1 if an error occurred. */ 542 Return 0 if successful, 1 if an error occurred. */
545 543
546static int 544static int
547file_lines (const char *filename, int fd, long int n_lines, off_t pos) 545file_lines(const char *filename, int fd, long int n_lines, off_t pos)
548{ 546{
549 char buffer[BUFSIZ]; 547 char buffer[BUFSIZ];
550 int bytes_read; 548 int bytes_read;
551 int i; /* Index into `buffer' for scanning. */ 549 int i; /* Index into `buffer' for scanning. */
552 550
553 if (n_lines == 0) 551 if (n_lines == 0)
554 return 0; 552 return 0;
555 553
556 /* Set `bytes_read' to the size of the last, probably partial, buffer; 554 /* Set `bytes_read' to the size of the last, probably partial, buffer;
557 0 < `bytes_read' <= `BUFSIZ'. */ 555 0 < `bytes_read' <= `BUFSIZ'. */
558 bytes_read = pos % BUFSIZ; 556 bytes_read = pos % BUFSIZ;
559 if (bytes_read == 0) 557 if (bytes_read == 0)
560 bytes_read = BUFSIZ; 558 bytes_read = BUFSIZ;
561 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all 559 /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
562 reads will be on block boundaries, which might increase efficiency. */ 560 reads will be on block boundaries, which might increase efficiency. */
563 pos -= bytes_read; 561 pos -= bytes_read;
564 lseek (fd, pos, SEEK_SET); 562 lseek(fd, pos, SEEK_SET);
565 bytes_read = fullRead (fd, buffer, bytes_read); 563 bytes_read = fullRead(fd, buffer, bytes_read);
566 if (bytes_read == -1) 564 if (bytes_read == -1) {
567 { 565 detailed_error(0, errno, "%s", filename);
568 detailed_error (0, errno, "%s", filename); 566 return 1;
569 return 1; 567 }
570 } 568
571 569 /* Count the incomplete line on files that don't end with a newline. */
572 /* Count the incomplete line on files that don't end with a newline. */ 570 if (bytes_read && buffer[bytes_read - 1] != '\n')
573 if (bytes_read && buffer[bytes_read - 1] != '\n') 571 --n_lines;
574 --n_lines; 572
575 573 do {
576 do 574 /* Scan backward, counting the newlines in this bufferfull. */
577 { 575 for (i = bytes_read - 1; i >= 0; i--) {
578 /* Scan backward, counting the newlines in this bufferfull. */ 576 /* Have we counted the requested number of newlines yet? */
579 for (i = bytes_read - 1; i >= 0; i--) 577 if (buffer[i] == '\n' && n_lines-- == 0) {
580 { 578 /* If this newline wasn't the last character in the buffer,
581 /* Have we counted the requested number of newlines yet? */ 579 print the text after it. */
582 if (buffer[i] == '\n' && n_lines-- == 0) 580 if (i != bytes_read - 1)
583 { 581 XWRITE(STDOUT_FILENO, &buffer[i + 1],
584 /* If this newline wasn't the last character in the buffer, 582 bytes_read - (i + 1));
585 print the text after it. */ 583 return 0;
586 if (i != bytes_read - 1) 584 }
587 XWRITE (STDOUT_FILENO, &buffer[i + 1], bytes_read - (i + 1)); 585 }
588 return 0; 586 /* Not enough newlines in that bufferfull. */
589 } 587 if (pos == 0) {
588 /* Not enough lines in the file; print the entire file. */
589 lseek(fd, (off_t) 0, SEEK_SET);
590 return 0;
591 }
592 pos -= BUFSIZ;
593 lseek(fd, pos, SEEK_SET);
590 } 594 }
591 /* Not enough newlines in that bufferfull. */ 595 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0);
592 if (pos == 0) 596 if (bytes_read == -1) {
593 { 597 detailed_error(0, errno, "%s", filename);
594 /* Not enough lines in the file; print the entire file. */ 598 return 1;
595 lseek (fd, (off_t) 0, SEEK_SET);
596 return 0;
597 } 599 }
598 pos -= BUFSIZ; 600 return 0;
599 lseek (fd, pos, SEEK_SET);
600 }
601 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0);
602 if (bytes_read == -1)
603 {
604 detailed_error (0, errno, "%s", filename);
605 return 1;
606 }
607 return 0;
608} 601}
609 602
610/* Print the last N_LINES lines from the end of the standard input, 603/* Print the last N_LINES lines from the end of the standard input,
@@ -612,301 +605,264 @@ file_lines (const char *filename, int fd, long int n_lines, off_t pos)
612 Buffer the text as a linked list of LBUFFERs, adding them as needed. 605 Buffer the text as a linked list of LBUFFERs, adding them as needed.
613 Return 0 if successful, 1 if an error occured. */ 606 Return 0 if successful, 1 if an error occured. */
614 607
615static int 608static int pipe_lines(const char *filename, int fd, long int n_lines)
616pipe_lines (const char *filename, int fd, long int n_lines)
617{ 609{
618 struct linebuffer 610 struct linebuffer {
619 { 611 int nbytes, nlines;
620 int nbytes, nlines; 612 char buffer[BUFSIZ];
621 char buffer[BUFSIZ]; 613 struct linebuffer *next;
622 struct linebuffer *next; 614 };
623 }; 615 typedef struct linebuffer LBUFFER;
624 typedef struct linebuffer LBUFFER; 616 LBUFFER *first, *last, *tmp;
625 LBUFFER *first, *last, *tmp; 617 int i; /* Index into buffers. */
626 int i; /* Index into buffers. */ 618 int total_lines = 0; /* Total number of newlines in all buffers. */
627 int total_lines = 0; /* Total number of newlines in all buffers. */ 619 int errors = 0;
628 int errors = 0; 620
629 621 first = last = (LBUFFER *) xmalloc(sizeof(LBUFFER));
630 first = last = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 622 first->nbytes = first->nlines = 0;
631 first->nbytes = first->nlines = 0; 623 first->next = NULL;
632 first->next = NULL; 624 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
633 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 625
634 626 /* Input is always read into a fresh buffer. */
635 /* Input is always read into a fresh buffer. */ 627 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
636 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 628 tmp->nlines = 0;
637 { 629 tmp->next = NULL;
638 tmp->nlines = 0; 630
639 tmp->next = NULL; 631 /* Count the number of newlines just read. */
640 632 for (i = 0; i < tmp->nbytes; i++)
641 /* Count the number of newlines just read. */ 633 if (tmp->buffer[i] == '\n')
642 for (i = 0; i < tmp->nbytes; i++) 634 ++tmp->nlines;
643 if (tmp->buffer[i] == '\n') 635 total_lines += tmp->nlines;
644 ++tmp->nlines; 636
645 total_lines += tmp->nlines; 637 /* If there is enough room in the last buffer read, just append the new
646 638 one to it. This is because when reading from a pipe, `nbytes' can
647 /* If there is enough room in the last buffer read, just append the new 639 often be very small. */
648 one to it. This is because when reading from a pipe, `nbytes' can 640 if (tmp->nbytes + last->nbytes < BUFSIZ) {
649 often be very small. */ 641 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
650 if (tmp->nbytes + last->nbytes < BUFSIZ) 642 last->nbytes += tmp->nbytes;
651 { 643 last->nlines += tmp->nlines;
652 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 644 } else {
653 last->nbytes += tmp->nbytes; 645 /* If there's not enough room, link the new buffer onto the end of
654 last->nlines += tmp->nlines; 646 the list, then either free up the oldest buffer for the next
647 read if that would leave enough lines, or else malloc a new one.
648 Some compaction mechanism is possible but probably not
649 worthwhile. */
650 last = last->next = tmp;
651 if (total_lines - first->nlines > n_lines) {
652 tmp = first;
653 total_lines -= first->nlines;
654 first = first->next;
655 } else
656 tmp = (LBUFFER *) xmalloc(sizeof(LBUFFER));
657 }
658 }
659 if (tmp->nbytes == -1) {
660 detailed_error(0, errno, "%s", filename);
661 errors = 1;
662 free((char *) tmp);
663 goto free_lbuffers;
655 } 664 }
656 else 665
657 { 666 free((char *) tmp);
658 /* If there's not enough room, link the new buffer onto the end of 667
659 the list, then either free up the oldest buffer for the next 668 /* This prevents a core dump when the pipe contains no newlines. */
660 read if that would leave enough lines, or else malloc a new one. 669 if (n_lines == 0)
661 Some compaction mechanism is possible but probably not 670 goto free_lbuffers;
662 worthwhile. */ 671
663 last = last->next = tmp; 672 /* Count the incomplete line on files that don't end with a newline. */
664 if (total_lines - first->nlines > n_lines) 673 if (last->buffer[last->nbytes - 1] != '\n') {
665 { 674 ++last->nlines;
666 tmp = first; 675 ++total_lines;
667 total_lines -= first->nlines; 676 }
668 first = first->next; 677
669 } 678 /* Run through the list, printing lines. First, skip over unneeded
670 else 679 buffers. */
671 tmp = (LBUFFER *) xmalloc (sizeof (LBUFFER)); 680 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
681 total_lines -= tmp->nlines;
682
683 /* Find the correct beginning, then print the rest of the file. */
684 if (total_lines > n_lines) {
685 char *cp;
686
687 /* Skip `total_lines' - `n_lines' newlines. We made sure that
688 `total_lines' - `n_lines' <= `tmp->nlines'. */
689 cp = tmp->buffer;
690 for (i = total_lines - n_lines; i; --i)
691 while (*cp++ != '\n')
692 /* Do nothing. */ ;
693 i = cp - tmp->buffer;
694 } else
695 i = 0;
696 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
697
698 for (tmp = tmp->next; tmp; tmp = tmp->next)
699 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
700
701 free_lbuffers:
702 while (first) {
703 tmp = first->next;
704 free((char *) first);
705 first = tmp;
672 } 706 }
673 } 707 return errors;
674 if (tmp->nbytes == -1)
675 {
676 detailed_error (0, errno, "%s", filename);
677 errors = 1;
678 free ((char *) tmp);
679 goto free_lbuffers;
680 }
681
682 free ((char *) tmp);
683
684 /* This prevents a core dump when the pipe contains no newlines. */
685 if (n_lines == 0)
686 goto free_lbuffers;
687
688 /* Count the incomplete line on files that don't end with a newline. */
689 if (last->buffer[last->nbytes - 1] != '\n')
690 {
691 ++last->nlines;
692 ++total_lines;
693 }
694
695 /* Run through the list, printing lines. First, skip over unneeded
696 buffers. */
697 for (tmp = first; total_lines - tmp->nlines > n_lines; tmp = tmp->next)
698 total_lines -= tmp->nlines;
699
700 /* Find the correct beginning, then print the rest of the file. */
701 if (total_lines > n_lines)
702 {
703 char *cp;
704
705 /* Skip `total_lines' - `n_lines' newlines. We made sure that
706 `total_lines' - `n_lines' <= `tmp->nlines'. */
707 cp = tmp->buffer;
708 for (i = total_lines - n_lines; i; --i)
709 while (*cp++ != '\n')
710 /* Do nothing. */ ;
711 i = cp - tmp->buffer;
712 }
713 else
714 i = 0;
715 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
716
717 for (tmp = tmp->next; tmp; tmp = tmp->next)
718 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
719
720free_lbuffers:
721 while (first)
722 {
723 tmp = first->next;
724 free ((char *) first);
725 first = tmp;
726 }
727 return errors;
728} 708}
729 709
730/* Print the last N_BYTES characters from the end of pipe FD. 710/* Print the last N_BYTES characters from the end of pipe FD.
731 This is a stripped down version of pipe_lines. 711 This is a stripped down version of pipe_lines.
732 Return 0 if successful, 1 if an error occurred. */ 712 Return 0 if successful, 1 if an error occurred. */
733 713
734static int 714static int pipe_bytes(const char *filename, int fd, off_t n_bytes)
735pipe_bytes (const char *filename, int fd, off_t n_bytes)
736{ 715{
737 struct charbuffer 716 struct charbuffer {
738 { 717 int nbytes;
739 int nbytes; 718 char buffer[BUFSIZ];
740 char buffer[BUFSIZ]; 719 struct charbuffer *next;
741 struct charbuffer *next; 720 };
742 }; 721 typedef struct charbuffer CBUFFER;
743 typedef struct charbuffer CBUFFER; 722 CBUFFER *first, *last, *tmp;
744 CBUFFER *first, *last, *tmp; 723 int i; /* Index into buffers. */
745 int i; /* Index into buffers. */ 724 int total_bytes = 0; /* Total characters in all buffers. */
746 int total_bytes = 0; /* Total characters in all buffers. */ 725 int errors = 0;
747 int errors = 0; 726
748 727 first = last = (CBUFFER *) xmalloc(sizeof(CBUFFER));
749 first = last = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 728 first->nbytes = 0;
750 first->nbytes = 0; 729 first->next = NULL;
751 first->next = NULL; 730 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
752 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 731
753 732 /* Input is always read into a fresh buffer. */
754 /* Input is always read into a fresh buffer. */ 733 while ((tmp->nbytes = fullRead(fd, tmp->buffer, BUFSIZ)) > 0) {
755 while ((tmp->nbytes = fullRead (fd, tmp->buffer, BUFSIZ)) > 0) 734 tmp->next = NULL;
756 { 735
757 tmp->next = NULL; 736 total_bytes += tmp->nbytes;
758 737 /* If there is enough room in the last buffer read, just append the new
759 total_bytes += tmp->nbytes; 738 one to it. This is because when reading from a pipe, `nbytes' can
760 /* If there is enough room in the last buffer read, just append the new 739 often be very small. */
761 one to it. This is because when reading from a pipe, `nbytes' can 740 if (tmp->nbytes + last->nbytes < BUFSIZ) {
762 often be very small. */ 741 memcpy(&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
763 if (tmp->nbytes + last->nbytes < BUFSIZ) 742 last->nbytes += tmp->nbytes;
764 { 743 } else {
765 memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); 744 /* If there's not enough room, link the new buffer onto the end of
766 last->nbytes += tmp->nbytes; 745 the list, then either free up the oldest buffer for the next
746 read if that would leave enough characters, or else malloc a new
747 one. Some compaction mechanism is possible but probably not
748 worthwhile. */
749 last = last->next = tmp;
750 if (total_bytes - first->nbytes > n_bytes) {
751 tmp = first;
752 total_bytes -= first->nbytes;
753 first = first->next;
754 } else {
755 tmp = (CBUFFER *) xmalloc(sizeof(CBUFFER));
756 }
757 }
767 } 758 }
768 else 759 if (tmp->nbytes == -1) {
769 { 760 detailed_error(0, errno, "%s", filename);
770 /* If there's not enough room, link the new buffer onto the end of 761 errors = 1;
771 the list, then either free up the oldest buffer for the next 762 free((char *) tmp);
772 read if that would leave enough characters, or else malloc a new 763 goto free_cbuffers;
773 one. Some compaction mechanism is possible but probably not 764 }
774 worthwhile. */ 765
775 last = last->next = tmp; 766 free((char *) tmp);
776 if (total_bytes - first->nbytes > n_bytes) 767
777 { 768 /* Run through the list, printing characters. First, skip over unneeded
778 tmp = first; 769 buffers. */
779 total_bytes -= first->nbytes; 770 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
780 first = first->next; 771 total_bytes -= tmp->nbytes;
781 } 772
782 else 773 /* Find the correct beginning, then print the rest of the file.
783 { 774 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
784 tmp = (CBUFFER *) xmalloc (sizeof (CBUFFER)); 775 if (total_bytes > n_bytes)
785 } 776 i = total_bytes - n_bytes;
777 else
778 i = 0;
779 XWRITE(STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
780
781 for (tmp = tmp->next; tmp; tmp = tmp->next)
782 XWRITE(STDOUT_FILENO, tmp->buffer, tmp->nbytes);
783
784 free_cbuffers:
785 while (first) {
786 tmp = first->next;
787 free((char *) first);
788 first = tmp;
786 } 789 }
787 } 790 return errors;
788 if (tmp->nbytes == -1)
789 {
790 detailed_error (0, errno, "%s", filename);
791 errors = 1;
792 free ((char *) tmp);
793 goto free_cbuffers;
794 }
795
796 free ((char *) tmp);
797
798 /* Run through the list, printing characters. First, skip over unneeded
799 buffers. */
800 for (tmp = first; total_bytes - tmp->nbytes > n_bytes; tmp = tmp->next)
801 total_bytes -= tmp->nbytes;
802
803 /* Find the correct beginning, then print the rest of the file.
804 We made sure that `total_bytes' - `n_bytes' <= `tmp->nbytes'. */
805 if (total_bytes > n_bytes)
806 i = total_bytes - n_bytes;
807 else
808 i = 0;
809 XWRITE (STDOUT_FILENO, &tmp->buffer[i], tmp->nbytes - i);
810
811 for (tmp = tmp->next; tmp; tmp = tmp->next)
812 XWRITE (STDOUT_FILENO, tmp->buffer, tmp->nbytes);
813
814free_cbuffers:
815 while (first)
816 {
817 tmp = first->next;
818 free ((char *) first);
819 first = tmp;
820 }
821 return errors;
822} 791}
823 792
824/* Skip N_BYTES characters from the start of pipe FD, and print 793/* Skip N_BYTES characters from the start of pipe FD, and print
825 any extra characters that were read beyond that. 794 any extra characters that were read beyond that.
826 Return 1 on error, 0 if ok. */ 795 Return 1 on error, 0 if ok. */
827 796
828static int 797static int start_bytes(const char *filename, int fd, off_t n_bytes)
829start_bytes (const char *filename, int fd, off_t n_bytes)
830{ 798{
831 char buffer[BUFSIZ]; 799 char buffer[BUFSIZ];
832 int bytes_read = 0; 800 int bytes_read = 0;
833 801
834 while (n_bytes > 0 && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 802 while (n_bytes > 0 && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0)
835 n_bytes -= bytes_read; 803 n_bytes -= bytes_read;
836 if (bytes_read == -1) 804 if (bytes_read == -1) {
837 { 805 detailed_error(0, errno, "%s", filename);
838 detailed_error (0, errno, "%s", filename); 806 return 1;
839 return 1; 807 } else if (n_bytes < 0)
840 } 808 XWRITE(STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
841 else if (n_bytes < 0) 809 return 0;
842 XWRITE (STDOUT_FILENO, &buffer[bytes_read + n_bytes], -n_bytes);
843 return 0;
844} 810}
845 811
846/* Skip N_LINES lines at the start of file or pipe FD, and print 812/* Skip N_LINES lines at the start of file or pipe FD, and print
847 any extra characters that were read beyond that. 813 any extra characters that were read beyond that.
848 Return 1 on error, 0 if ok. */ 814 Return 1 on error, 0 if ok. */
849 815
850static int 816static int start_lines(const char *filename, int fd, long int n_lines)
851start_lines (const char *filename, int fd, long int n_lines)
852{ 817{
853 char buffer[BUFSIZ]; 818 char buffer[BUFSIZ];
854 int bytes_read = 0; 819 int bytes_read = 0;
855 int bytes_to_skip = 0; 820 int bytes_to_skip = 0;
856 821
857 while (n_lines && (bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 822 while (n_lines && (bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
858 { 823 bytes_to_skip = 0;
859 bytes_to_skip = 0; 824 while (bytes_to_skip < bytes_read)
860 while (bytes_to_skip < bytes_read) 825 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0)
861 if (buffer[bytes_to_skip++] == '\n' && --n_lines == 0) 826 break;
862 break; 827 }
863 } 828 if (bytes_read == -1) {
864 if (bytes_read == -1) 829 detailed_error(0, errno, "%s", filename);
865 { 830 return 1;
866 detailed_error (0, errno, "%s", filename); 831 } else if (bytes_to_skip < bytes_read) {
867 return 1; 832 XWRITE(STDOUT_FILENO, &buffer[bytes_to_skip],
868 } 833 bytes_read - bytes_to_skip);
869 else if (bytes_to_skip < bytes_read) 834 }
870 { 835 return 0;
871 XWRITE (STDOUT_FILENO, &buffer[bytes_to_skip],
872 bytes_read - bytes_to_skip);
873 }
874 return 0;
875} 836}
876 837
877/* Display file FILENAME from the current position in FD to the end. 838/* Display file FILENAME from the current position in FD to the end.
878 If `forever' is nonzero, keep reading from the end of the file 839 If `forever' is nonzero, keep reading from the end of the file
879 until killed. Return the number of bytes read from the file. */ 840 until killed. Return the number of bytes read from the file. */
880 841
881static long 842static long dump_remainder(const char *filename, int fd)
882dump_remainder (const char *filename, int fd)
883{ 843{
884 char buffer[BUFSIZ]; 844 char buffer[BUFSIZ];
885 int bytes_read; 845 int bytes_read;
886 long total; 846 long total;
887 847
888 total = 0; 848 total = 0;
889output: 849 output:
890 while ((bytes_read = fullRead (fd, buffer, BUFSIZ)) > 0) 850 while ((bytes_read = fullRead(fd, buffer, BUFSIZ)) > 0) {
891 { 851 XWRITE(STDOUT_FILENO, buffer, bytes_read);
892 XWRITE (STDOUT_FILENO, buffer, bytes_read); 852 total += bytes_read;
893 total += bytes_read; 853 }
894 } 854 if (bytes_read == -1)
895 if (bytes_read == -1) 855 detailed_error(EXIT_FAILURE, errno, "%s", filename);
896 detailed_error (EXIT_FAILURE, errno, "%s", filename); 856 if (forever) {
897 if (forever) 857 fflush(stdout);
898 { 858 sleep(1);
899 fflush (stdout); 859 goto output;
900 sleep (1); 860 } else {
901 goto output; 861 if (forever_multiple)
902 } 862 fflush(stdout);
903 else 863 }
904 { 864
905 if (forever_multiple) 865 return total;
906 fflush (stdout);
907 }
908
909 return total;
910} 866}
911 867
912/* Tail NFILES (>1) files forever until killed. The file names are in 868/* Tail NFILES (>1) files forever until killed. The file names are in
@@ -916,186 +872,161 @@ output:
916 none of them have changed size in one iteration, we sleep for a 872 none of them have changed size in one iteration, we sleep for a
917 second and try again. We do this until the user interrupts us. */ 873 second and try again. We do this until the user interrupts us. */
918 874
919static void 875static void tail_forever(char **names, int nfiles)
920tail_forever (char **names, int nfiles)
921{ 876{
922 int last; 877 int last;
923 878
924 last = -1; 879 last = -1;
925 880
926 while (1) 881 while (1) {
927 { 882 int i;
928 int i; 883 int changed;
929 int changed; 884
930 885 changed = 0;
931 changed = 0; 886 for (i = 0; i < nfiles; i++) {
932 for (i = 0; i < nfiles; i++) 887 struct stat stats;
933 { 888
934 struct stat stats; 889 if (file_descs[i] < 0)
935 890 continue;
936 if (file_descs[i] < 0) 891 if (fstat(file_descs[i], &stats) < 0) {
937 continue; 892 detailed_error(0, errno, "%s", names[i]);
938 if (fstat (file_descs[i], &stats) < 0) 893 file_descs[i] = -1;
939 { 894 continue;
940 detailed_error (0, errno, "%s", names[i]); 895 }
941 file_descs[i] = -1; 896 if (stats.st_size == file_sizes[i])
942 continue; 897 continue;
943 } 898
944 if (stats.st_size == file_sizes[i]) 899 /* This file has changed size. Print out what we can, and
945 continue; 900 then keep looping. */
946 901
947 /* This file has changed size. Print out what we can, and 902 changed = 1;
948 then keep looping. */ 903
949 904 if (stats.st_size < file_sizes[i]) {
950 changed = 1; 905 write_header(names[i], "file truncated");
951 906 last = i;
952 if (stats.st_size < file_sizes[i]) 907 lseek(file_descs[i], stats.st_size, SEEK_SET);
953 { 908 file_sizes[i] = stats.st_size;
954 write_header (names[i], "file truncated"); 909 continue;
955 last = i; 910 }
956 lseek (file_descs[i], stats.st_size, SEEK_SET); 911
957 file_sizes[i] = stats.st_size; 912 if (i != last) {
958 continue; 913 if (print_headers)
959 } 914 write_header(names[i], NULL);
960 915 last = i;
961 if (i != last) 916 }
962 { 917 file_sizes[i] += dump_remainder(names[i], file_descs[i]);
963 if (print_headers) 918 }
964 write_header (names[i], NULL);
965 last = i;
966 }
967 file_sizes[i] += dump_remainder (names[i], file_descs[i]);
968 }
969 919
970 /* If none of the files changed size, sleep. */ 920 /* If none of the files changed size, sleep. */
971 if (! changed) 921 if (!changed)
972 sleep (1); 922 sleep(1);
973 } 923 }
974} 924}
975 925
976/* Output the last N_BYTES bytes of file FILENAME open for reading in FD. 926/* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
977 Return 0 if successful, 1 if an error occurred. */ 927 Return 0 if successful, 1 if an error occurred. */
978 928
979static int 929static int tail_bytes(const char *filename, int fd, off_t n_bytes)
980tail_bytes (const char *filename, int fd, off_t n_bytes)
981{ 930{
982 struct stat stats; 931 struct stat stats;
983 932
984 /* FIXME: resolve this like in dd.c. */ 933 /* FIXME: resolve this like in dd.c. */
985 /* Use fstat instead of checking for errno == ESPIPE because 934 /* Use fstat instead of checking for errno == ESPIPE because
986 lseek doesn't work on some special files but doesn't return an 935 lseek doesn't work on some special files but doesn't return an
987 error, either. */ 936 error, either. */
988 if (fstat (fd, &stats)) 937 if (fstat(fd, &stats)) {
989 { 938 detailed_error(0, errno, "%s", filename);
990 detailed_error (0, errno, "%s", filename); 939 return 1;
991 return 1; 940 }
992 } 941
993 942 if (from_start) {
994 if (from_start) 943 if (S_ISREG(stats.st_mode))
995 { 944 lseek(fd, n_bytes, SEEK_CUR);
996 if (S_ISREG (stats.st_mode)) 945 else if (start_bytes(filename, fd, n_bytes))
997 lseek (fd, n_bytes, SEEK_CUR); 946 return 1;
998 else if (start_bytes (filename, fd, n_bytes)) 947 dump_remainder(filename, fd);
999 return 1; 948 } else {
1000 dump_remainder (filename, fd); 949 if (S_ISREG(stats.st_mode)) {
1001 } 950 off_t current_pos, end_pos;
1002 else 951 size_t bytes_remaining;
1003 { 952
1004 if (S_ISREG (stats.st_mode)) 953 if ((current_pos = lseek(fd, (off_t) 0, SEEK_CUR)) != -1
1005 { 954 && (end_pos = lseek(fd, (off_t) 0, SEEK_END)) != -1) {
1006 off_t current_pos, end_pos; 955 off_t diff;
1007 size_t bytes_remaining; 956
1008 957 /* Be careful here. The current position may actually be
1009 if ((current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1 958 beyond the end of the file. */
1010 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1) 959 bytes_remaining = (diff =
1011 { 960 end_pos - current_pos) < 0 ? 0 : diff;
1012 off_t diff; 961 } else {
1013 /* Be careful here. The current position may actually be 962 detailed_error(0, errno, "%s", filename);
1014 beyond the end of the file. */ 963 return 1;
1015 bytes_remaining = (diff = end_pos - current_pos) < 0 ? 0 : diff; 964 }
1016 } 965
1017 else 966 if (bytes_remaining <= n_bytes) {
1018 { 967 /* From the current position to end of file, there are no
1019 detailed_error (0, errno, "%s", filename); 968 more bytes than have been requested. So reposition the
1020 return 1; 969 file pointer to the incoming current position and print
1021 } 970 everything after that. */
1022 971 lseek(fd, current_pos, SEEK_SET);
1023 if (bytes_remaining <= n_bytes) 972 } else {
1024 { 973 /* There are more bytes remaining than were requested.
1025 /* From the current position to end of file, there are no 974 Back up. */
1026 more bytes than have been requested. So reposition the 975 lseek(fd, -n_bytes, SEEK_END);
1027 file pointer to the incoming current position and print 976 }
1028 everything after that. */ 977 dump_remainder(filename, fd);
1029 lseek (fd, current_pos, SEEK_SET); 978 } else
1030 } 979 return pipe_bytes(filename, fd, n_bytes);
1031 else
1032 {
1033 /* There are more bytes remaining than were requested.
1034 Back up. */
1035 lseek (fd, -n_bytes, SEEK_END);
1036 }
1037 dump_remainder (filename, fd);
1038 } 980 }
1039 else 981 return 0;
1040 return pipe_bytes (filename, fd, n_bytes);
1041 }
1042 return 0;
1043} 982}
1044 983
1045/* Output the last N_LINES lines of file FILENAME open for reading in FD. 984/* Output the last N_LINES lines of file FILENAME open for reading in FD.
1046 Return 0 if successful, 1 if an error occurred. */ 985 Return 0 if successful, 1 if an error occurred. */
1047 986
1048static int 987static int tail_lines(const char *filename, int fd, long int n_lines)
1049tail_lines (const char *filename, int fd, long int n_lines)
1050{ 988{
1051 struct stat stats; 989 struct stat stats;
1052 off_t length; 990 off_t length;
1053 991
1054 if (fstat (fd, &stats)) 992 if (fstat(fd, &stats)) {
1055 { 993 detailed_error(0, errno, "%s", filename);
1056 detailed_error (0, errno, "%s", filename); 994 return 1;
1057 return 1; 995 }
1058 } 996
1059 997 if (from_start) {
1060 if (from_start) 998 if (start_lines(filename, fd, n_lines))
1061 { 999 return 1;
1062 if (start_lines (filename, fd, n_lines)) 1000 dump_remainder(filename, fd);
1063 return 1; 1001 } else {
1064 dump_remainder (filename, fd); 1002 /* Use file_lines only if FD refers to a regular file with
1065 } 1003 its file pointer positioned at beginning of file. */
1066 else 1004 /* FIXME: adding the lseek conjunct is a kludge.
1067 { 1005 Once there's a reasonable test suite, fix the true culprit:
1068 /* Use file_lines only if FD refers to a regular file with 1006 file_lines. file_lines shouldn't presume that the input
1069 its file pointer positioned at beginning of file. */ 1007 file pointer is initially positioned to beginning of file. */
1070 /* FIXME: adding the lseek conjunct is a kludge. 1008 if (S_ISREG(stats.st_mode)
1071 Once there's a reasonable test suite, fix the true culprit: 1009 && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
1072 file_lines. file_lines shouldn't presume that the input 1010 length = lseek(fd, (off_t) 0, SEEK_END);
1073 file pointer is initially positioned to beginning of file. */ 1011 if (length != 0 && file_lines(filename, fd, n_lines, length))
1074 if (S_ISREG (stats.st_mode) 1012 return 1;
1075 && lseek (fd, (off_t) 0, SEEK_CUR) == (off_t) 0) 1013 dump_remainder(filename, fd);
1076 { 1014 } else
1077 length = lseek (fd, (off_t) 0, SEEK_END); 1015 return pipe_lines(filename, fd, n_lines);
1078 if (length != 0 && file_lines (filename, fd, n_lines, length))
1079 return 1;
1080 dump_remainder (filename, fd);
1081 } 1016 }
1082 else 1017 return 0;
1083 return pipe_lines (filename, fd, n_lines);
1084 }
1085 return 0;
1086} 1018}
1087 1019
1088/* Display the last N_UNITS units of file FILENAME, open for reading 1020/* Display the last N_UNITS units of file FILENAME, open for reading
1089 in FD. 1021 in FD.
1090 Return 0 if successful, 1 if an error occurred. */ 1022 Return 0 if successful, 1 if an error occurred. */
1091 1023
1092static int 1024static int tail(const char *filename, int fd, off_t n_units)
1093tail (const char *filename, int fd, off_t n_units)
1094{ 1025{
1095 if (count_lines) 1026 if (count_lines)
1096 return tail_lines (filename, fd, (long) n_units); 1027 return tail_lines(filename, fd, (long) n_units);
1097 else 1028 else
1098 return tail_bytes (filename, fd, n_units); 1029 return tail_bytes(filename, fd, n_units);
1099} 1030}
1100 1031
1101/* Display the last N_UNITS units of file FILENAME. 1032/* Display the last N_UNITS units of file FILENAME.
@@ -1103,207 +1034,183 @@ tail (const char *filename, int fd, off_t n_units)
1103 FILENUM is this file's index in the list of files the user gave. 1034 FILENUM is this file's index in the list of files the user gave.
1104 Return 0 if successful, 1 if an error occurred. */ 1035 Return 0 if successful, 1 if an error occurred. */
1105 1036
1106static int 1037static int tail_file(const char *filename, off_t n_units, int filenum)
1107tail_file (const char *filename, off_t n_units, int filenum)
1108{ 1038{
1109 int fd, errors; 1039 int fd, errors;
1110 struct stat stats; 1040 struct stat stats;
1111 1041
1112 if (!strcmp (filename, "-")) 1042 if (!strcmp(filename, "-")) {
1113 { 1043 have_read_stdin = 1;
1114 have_read_stdin = 1; 1044 filename = "standard input";
1115 filename = "standard input"; 1045 if (print_headers)
1116 if (print_headers) 1046 write_header(filename, NULL);
1117 write_header (filename, NULL); 1047 errors = tail(filename, 0, n_units);
1118 errors = tail (filename, 0, n_units); 1048 if (forever_multiple) {
1119 if (forever_multiple) 1049 if (fstat(0, &stats) < 0) {
1120 { 1050 detailed_error(0, errno, "standard input");
1121 if (fstat (0, &stats) < 0) 1051 errors = 1;
1122 { 1052 } else if (!S_ISREG(stats.st_mode)) {
1123 detailed_error (0, errno, "standard input"); 1053 detailed_error(0, 0,
1124 errors = 1; 1054 "standard input: cannot follow end of non-regular file");
1125 } 1055 errors = 1;
1126 else if (!S_ISREG (stats.st_mode)) 1056 }
1127 { 1057 if (errors)
1128 detailed_error (0, 0, 1058 file_descs[filenum] = -1;
1129 "standard input: cannot follow end of non-regular file"); 1059 else {
1130 errors = 1; 1060 file_descs[filenum] = 0;
1131 } 1061 file_sizes[filenum] = stats.st_size;
1132 if (errors) 1062 }
1133 file_descs[filenum] = -1;
1134 else
1135 {
1136 file_descs[filenum] = 0;
1137 file_sizes[filenum] = stats.st_size;
1138 }
1139 }
1140 }
1141 else
1142 {
1143 /* Not standard input. */
1144 fd = open (filename, O_RDONLY);
1145 if (fd == -1)
1146 {
1147 if (forever_multiple)
1148 file_descs[filenum] = -1;
1149 detailed_error (0, errno, "%s", filename);
1150 errors = 1;
1151 }
1152 else
1153 {
1154 if (print_headers)
1155 write_header (filename, NULL);
1156 errors = tail (filename, fd, n_units);
1157 if (forever_multiple)
1158 {
1159 if (fstat (fd, &stats) < 0)
1160 {
1161 detailed_error (0, errno, "%s", filename);
1162 errors = 1;
1163 }
1164 else if (!S_ISREG (stats.st_mode))
1165 {
1166 detailed_error (0, 0, "%s: cannot follow end of non-regular file",
1167 filename);
1168 errors = 1;
1169 }
1170 if (errors)
1171 {
1172 close (fd);
1173 file_descs[filenum] = -1;
1174 }
1175 else
1176 {
1177 file_descs[filenum] = fd;
1178 file_sizes[filenum] = stats.st_size;
1179 } 1063 }
1180 } 1064 } else {
1181 else 1065 /* Not standard input. */
1182 { 1066 fd = open(filename, O_RDONLY);
1183 if (close (fd)) 1067 if (fd == -1) {
1184 { 1068 if (forever_multiple)
1185 detailed_error (0, errno, "%s", filename); 1069 file_descs[filenum] = -1;
1186 errors = 1; 1070 detailed_error(0, errno, "%s", filename);
1071 errors = 1;
1072 } else {
1073 if (print_headers)
1074 write_header(filename, NULL);
1075 errors = tail(filename, fd, n_units);
1076 if (forever_multiple) {
1077 if (fstat(fd, &stats) < 0) {
1078 detailed_error(0, errno, "%s", filename);
1079 errors = 1;
1080 } else if (!S_ISREG(stats.st_mode)) {
1081 detailed_error(0, 0,
1082 "%s: cannot follow end of non-regular file",
1083 filename);
1084 errors = 1;
1085 }
1086 if (errors) {
1087 close(fd);
1088 file_descs[filenum] = -1;
1089 } else {
1090 file_descs[filenum] = fd;
1091 file_sizes[filenum] = stats.st_size;
1092 }
1093 } else {
1094 if (close(fd)) {
1095 detailed_error(0, errno, "%s", filename);
1096 errors = 1;
1097 }
1098 }
1187 } 1099 }
1188 }
1189 } 1100 }
1190 }
1191 1101
1192 return errors; 1102 return errors;
1193} 1103}
1194 1104
1195extern int 1105extern int tail_main(int argc, char **argv)
1196tail_main (int argc, char **argv)
1197{ 1106{
1198 int stopit = 0; 1107 int stopit = 0;
1199 enum header_mode header_mode = multiple_files; 1108 enum header_mode header_mode = multiple_files;
1200 int exit_status = 0; 1109 int exit_status = 0;
1201 /* If from_start, the number of items to skip before printing; otherwise, 1110
1202 the number of items at the end of the file to print. Initially, -1 1111 /* If from_start, the number of items to skip before printing; otherwise,
1203 means the value has not been set. */ 1112 the number of items at the end of the file to print. Initially, -1
1204 off_t n_units = -1; 1113 means the value has not been set. */
1205 int n_files; 1114 off_t n_units = -1;
1206 char **file; 1115 int n_files;
1207 1116 char **file;
1208 program_name = argv[0]; 1117
1209 have_read_stdin = 0; 1118 program_name = argv[0];
1210 count_lines = 1; 1119 have_read_stdin = 0;
1211 forever = forever_multiple = from_start = print_headers = 0; 1120 count_lines = 1;
1212 1121 forever = forever_multiple = from_start = print_headers = 0;
1213 /* Parse any options */ 1122
1214 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 1123 /* Parse any options */
1215 while (--argc > 0 && ( **(++argv) == '-' || **argv == '+' )) { 1124 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
1216 if (**argv == '+') { 1125 while (--argc > 0 && (**(++argv) == '-' || **argv == '+')) {
1217 from_start = 1; 1126 if (**argv == '+') {
1127 from_start = 1;
1128 }
1129 stopit = 0;
1130 while (stopit == 0 && *(++(*argv))) {
1131 switch (**argv) {
1132 case 'c':
1133 count_lines = 0;
1134
1135 if (--argc < 1) {
1136 usage(tail_usage);
1137 }
1138 n_units = getNum(*(++argv));
1139 stopit = 1;
1140 break;
1141
1142 case 'f':
1143 forever = 1;
1144 break;
1145
1146 case 'n':
1147 count_lines = 1;
1148
1149 if (--argc < 1) {
1150 usage(tail_usage);
1151 }
1152 n_units = atol(*(++argv));
1153 stopit = 1;
1154 break;
1155
1156 case 'q':
1157 header_mode = never;
1158 break;
1159
1160 case 'v':
1161 header_mode = always;
1162 break;
1163
1164 default:
1165 usage(tail_usage);
1166 }
1167 }
1168 }
1169
1170
1171 if (n_units == -1)
1172 n_units = DEFAULT_N_LINES;
1173
1174 /* To start printing with item N_UNITS from the start of the file, skip
1175 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix
1176 compatibility it's treated the same as `tail +1'. */
1177 if (from_start) {
1178 if (n_units)
1179 --n_units;
1218 } 1180 }
1219 stopit = 0; 1181
1220 while (stopit == 0 && *(++(*argv))) { 1182 n_files = argc;
1221 switch (**argv) { 1183 file = argv;
1222 case 'c': 1184
1223 count_lines = 0; 1185 if (n_files > 1 && forever) {
1224 1186 forever_multiple = 1;
1225 if (--argc < 1) { 1187 forever = 0;
1226 usage(tail_usage); 1188 file_descs = (int *) xmalloc(n_files * sizeof(int));
1227 } 1189
1228 n_units = getNum(*(++argv)); 1190 file_sizes = (off_t *) xmalloc(n_files * sizeof(off_t));
1229 stopit = 1;
1230 break;
1231
1232 case 'f':
1233 forever = 1;
1234 break;
1235
1236 case 'n':
1237 count_lines = 1;
1238
1239 if (--argc < 1) {
1240 usage(tail_usage);
1241 }
1242 n_units = atol(*(++argv));
1243 stopit = 1;
1244 break;
1245
1246 case 'q':
1247 header_mode = never;
1248 break;
1249
1250 case 'v':
1251 header_mode = always;
1252 break;
1253
1254 default:
1255 usage (tail_usage);
1256 }
1257 } 1191 }
1258 } 1192
1259 1193 if (header_mode == always
1260 1194 || (header_mode == multiple_files && n_files > 1))
1261 if (n_units == -1) 1195 print_headers = 1;
1262 n_units = DEFAULT_N_LINES; 1196
1263 1197 if (n_files == 0) {
1264 /* To start printing with item N_UNITS from the start of the file, skip 1198 exit_status |= tail_file("-", n_units, 0);
1265 N_UNITS - 1 items. `tail +0' is actually meaningless, but for Unix 1199 } else {
1266 compatibility it's treated the same as `tail +1'. */ 1200 int i;
1267 if (from_start) 1201
1268 { 1202 for (i = 0; i < n_files; i++)
1269 if (n_units) 1203 exit_status |= tail_file(file[i], n_units, i);
1270 --n_units; 1204
1271 } 1205 if (forever_multiple)
1272 1206 tail_forever(file, n_files);
1273 n_files = argc; 1207 }
1274 file = argv; 1208
1275 1209 if (have_read_stdin && close(0) < 0)
1276 if (n_files > 1 && forever) 1210 detailed_error(EXIT_FAILURE, errno, "-");
1277 { 1211 if (fclose(stdout) == EOF)
1278 forever_multiple = 1; 1212 detailed_error(EXIT_FAILURE, errno, "write error");
1279 forever = 0; 1213 exit(exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1280 file_descs = (int *) xmalloc (n_files * sizeof (int));
1281 file_sizes = (off_t *) xmalloc (n_files * sizeof (off_t));
1282 }
1283
1284 if (header_mode == always
1285 || (header_mode == multiple_files && n_files > 1))
1286 print_headers = 1;
1287
1288 if (n_files == 0)
1289 {
1290 exit_status |= tail_file ("-", n_units, 0);
1291 }
1292 else
1293 {
1294 int i;
1295 for (i = 0; i < n_files; i++)
1296 exit_status |= tail_file (file[i], n_units, i);
1297
1298 if (forever_multiple)
1299 tail_forever (file, n_files);
1300 }
1301
1302 if (have_read_stdin && close (0) < 0)
1303 detailed_error (EXIT_FAILURE, errno, "-");
1304 if (fclose (stdout) == EOF)
1305 detailed_error (EXIT_FAILURE, errno, "write error");
1306 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1307} 1214}
1308 1215
1309 1216
diff --git a/tar.c b/tar.c
index 6496231ae..87b5d2176 100644
--- a/tar.c
+++ b/tar.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tar implementation for busybox based on code taken from sash. 3 * Mini tar implementation for busybox based on code taken from sash.
3 * 4 *
@@ -40,27 +41,29 @@
40#include <utime.h> 41#include <utime.h>
41#include <sys/types.h> 42#include <sys/types.h>
42#include <sys/sysmacros.h> 43#include <sys/sysmacros.h>
43#include <sys/param.h> /* for PATH_MAX */ 44#include <sys/param.h> /* for PATH_MAX */
44 45
45 46
46#ifdef BB_FEATURE_TAR_CREATE 47#ifdef BB_FEATURE_TAR_CREATE
47 48
48static const char tar_usage[] = 49static const char tar_usage[] =
49"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" 50 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
50"Create, extract, or list files from a tar file.\n\n" 51 "Create, extract, or list files from a tar file.\n\n"
51"Options:\n" 52 "Options:\n"
52"\tc=create, x=extract, t=list contents, v=verbose,\n" 53
53"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 54 "\tc=create, x=extract, t=list contents, v=verbose,\n"
55 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
54 56
55#else 57#else
56 58
57static const char tar_usage[] = 59static const char tar_usage[] =
58"tar -[xtvOf] [tarFileName] [FILE] ...\n\n" 60 "tar -[xtvOf] [tarFileName] [FILE] ...\n\n"
59"Extract, or list files stored in a tar file. This\n" 61 "Extract, or list files stored in a tar file. This\n"
60"version of tar does not support creation of tar files.\n\n" 62 "version of tar does not support creation of tar files.\n\n"
61"Options:\n" 63 "Options:\n"
62"\tx=extract, t=list contents, v=verbose,\n" 64
63"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 65 "\tx=extract, t=list contents, v=verbose,\n"
66 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
64 67
65#endif 68#endif
66 69
@@ -78,22 +81,22 @@ static const char tar_usage[] =
78 * with zero padding. We only process this information minimally. 81 * with zero padding. We only process this information minimally.
79 */ 82 */
80typedef struct { 83typedef struct {
81 char name[TAR_NAME_SIZE]; 84 char name[TAR_NAME_SIZE];
82 char mode[8]; 85 char mode[8];
83 char uid[8]; 86 char uid[8];
84 char gid[8]; 87 char gid[8];
85 char size[12]; 88 char size[12];
86 char mtime[12]; 89 char mtime[12];
87 char checkSum[8]; 90 char checkSum[8];
88 char typeFlag; 91 char typeFlag;
89 char linkName[TAR_NAME_SIZE]; 92 char linkName[TAR_NAME_SIZE];
90 char magic[6]; 93 char magic[6];
91 char version[2]; 94 char version[2];
92 char uname[32]; 95 char uname[32];
93 char gname[32]; 96 char gname[32];
94 char devMajor[8]; 97 char devMajor[8];
95 char devMinor[8]; 98 char devMinor[8];
96 char prefix[155]; 99 char prefix[155];
97} TarHeader; 100} TarHeader;
98 101
99#define TAR_MAGIC "ustar" 102#define TAR_MAGIC "ustar"
@@ -113,7 +116,7 @@ static int createFlag;
113static int verboseFlag; 116static int verboseFlag;
114static int tostdoutFlag; 117static int tostdoutFlag;
115 118
116static int inHeader; // <- check me 119static int inHeader; // <- check me
117static int badHeader; 120static int badHeader;
118static int errorFlag; 121static int errorFlag;
119static int skipFileFlag; 122static int skipFileFlag;
@@ -140,141 +143,145 @@ static ino_t tarInode;
140/* 143/*
141 * Local procedures to restore files from a tar file. 144 * Local procedures to restore files from a tar file.
142 */ 145 */
143static void readTarFile (int fileCount, char **fileTable); 146static void readTarFile(int fileCount, char **fileTable);
144static void readData (const char *cp, int count); 147static void readData(const char *cp, int count);
145static long getOctal (const char *cp, int len); 148static long getOctal(const char *cp, int len);
149
150static void readHeader(const TarHeader * hp,
146 151
147static void readHeader (const TarHeader * hp, 152 int fileCount, char **fileTable);
148 int fileCount, char **fileTable);
149 153
150static int wantFileName (const char *fileName, 154static int wantFileName(const char *fileName,
151 int fileCount, char **fileTable); 155
156 int fileCount, char **fileTable);
152 157
153#ifdef BB_FEATURE_TAR_CREATE 158#ifdef BB_FEATURE_TAR_CREATE
154/* 159/*
155 * Local procedures to save files into a tar file. 160 * Local procedures to save files into a tar file.
156 */ 161 */
157static void saveFile (const char *fileName, int seeLinks); 162static void saveFile(const char *fileName, int seeLinks);
163
164static void saveRegularFile(const char *fileName,
158 165
159static void saveRegularFile (const char *fileName, 166 const struct stat *statbuf);
160 const struct stat *statbuf);
161 167
162static void saveDirectory (const char *fileName, 168static void saveDirectory(const char *fileName,
163 const struct stat *statbuf);
164 169
165static void writeHeader (const char *fileName, const struct stat *statbuf); 170 const struct stat *statbuf);
166 171
167static void writeTarFile (int fileCount, char **fileTable); 172static void writeHeader(const char *fileName, const struct stat *statbuf);
168static void writeTarBlock (const char *buf, int len); 173
169static int putOctal (char *cp, int len, long value); 174static void writeTarFile(int fileCount, char **fileTable);
175static void writeTarBlock(const char *buf, int len);
176static int putOctal(char *cp, int len, long value);
170 177
171#endif 178#endif
172 179
173 180
174extern int tar_main (int argc, char **argv) 181extern int tar_main(int argc, char **argv)
175{ 182{
176 const char *options; 183 const char *options;
177 184
178 argc--; 185 argc--;
179 argv++; 186 argv++;
180 187
181 if (argc < 1) 188 if (argc < 1)
182 usage( tar_usage); 189 usage(tar_usage);
183 190
184 191
185 errorFlag = FALSE; 192 errorFlag = FALSE;
186 extractFlag = FALSE; 193 extractFlag = FALSE;
187 createFlag = FALSE; 194 createFlag = FALSE;
188 listFlag = FALSE; 195 listFlag = FALSE;
189 verboseFlag = FALSE; 196 verboseFlag = FALSE;
190 tostdoutFlag = FALSE; 197 tostdoutFlag = FALSE;
191 tarName = NULL; 198 tarName = NULL;
192 tarDev = 0; 199 tarDev = 0;
193 tarInode = 0; 200 tarInode = 0;
194 tarFd = -1; 201 tarFd = -1;
195 202
196 /* 203 /*
197 * Parse the options. 204 * Parse the options.
198 */ 205 */
199 if (**argv == '-') 206 if (**argv == '-')
200 options = (*argv++) + 1; 207 options = (*argv++) + 1;
201 else 208 else
202 options = (*argv++); 209 options = (*argv++);
203 argc--; 210 argc--;
204 211
205 for (; *options; options++) { 212 for (; *options; options++) {
206 switch (*options) { 213 switch (*options) {
207 case 'f': 214 case 'f':
208 if (tarName != NULL) { 215 if (tarName != NULL) {
209 fprintf (stderr, "Only one 'f' option allowed\n"); 216 fprintf(stderr, "Only one 'f' option allowed\n");
210 217
211 exit (FALSE); 218 exit(FALSE);
212 } 219 }
213 220
214 tarName = *argv++; 221 tarName = *argv++;
215 argc--; 222 argc--;
216 223
217 break; 224 break;
218 225
219 case 't': 226 case 't':
220 if (extractFlag == TRUE || createFlag == TRUE ) 227 if (extractFlag == TRUE || createFlag == TRUE)
221 goto flagError; 228 goto flagError;
222 listFlag = TRUE; 229 listFlag = TRUE;
223 break; 230 break;
224 231
225 case 'x': 232 case 'x':
226 if (listFlag == TRUE || createFlag == TRUE ) 233 if (listFlag == TRUE || createFlag == TRUE)
227 goto flagError; 234 goto flagError;
228 extractFlag = TRUE; 235 extractFlag = TRUE;
229 break; 236 break;
230 case 'c': 237 case 'c':
231 if (extractFlag == TRUE || listFlag == TRUE) 238 if (extractFlag == TRUE || listFlag == TRUE)
232 goto flagError; 239 goto flagError;
233 createFlag = TRUE; 240 createFlag = TRUE;
234 break; 241 break;
235 242
236 case 'v': 243 case 'v':
237 verboseFlag = TRUE; 244 verboseFlag = TRUE;
238 break; 245 break;
239 246
240 case 'O': 247 case 'O':
241 tostdoutFlag = TRUE; 248 tostdoutFlag = TRUE;
242 break; 249 break;
243 250
244 case '-': 251 case '-':
245 usage( tar_usage); 252 usage(tar_usage);
246 break; 253 break;
247 254
248 default: 255 default:
249 fprintf (stderr, "Unknown tar flag '%c'\n" 256 fprintf(stderr, "Unknown tar flag '%c'\n"
250 "Try `tar --help' for more information\n", 257 "Try `tar --help' for more information\n", *options);
251 *options); 258 exit(FALSE);
252 exit (FALSE); 259 }
253 } 260 }
254 }
255 261
256 /* 262 /*
257 * Do the correct type of action supplying the rest of the 263 * Do the correct type of action supplying the rest of the
258 * command line arguments as the list of files to process. 264 * command line arguments as the list of files to process.
259 */ 265 */
260 if (createFlag==TRUE) { 266 if (createFlag == TRUE) {
261#ifndef BB_FEATURE_TAR_CREATE 267#ifndef BB_FEATURE_TAR_CREATE
262 fprintf (stderr, "This version of tar was not compiled with tar creation support.\n" ); 268 fprintf(stderr,
263 exit (FALSE); 269 "This version of tar was not compiled with tar creation support.\n");
270 exit(FALSE);
264#else 271#else
265 writeTarFile (argc, argv); 272 writeTarFile(argc, argv);
266#endif 273#endif
267 } else { 274 } else {
268 readTarFile (argc, argv); 275 readTarFile(argc, argv);
269 } 276 }
270 if (errorFlag==TRUE) { 277 if (errorFlag == TRUE) {
271 fprintf (stderr, "\n"); 278 fprintf(stderr, "\n");
272 } 279 }
273 exit (!errorFlag); 280 exit(!errorFlag);
274 281
275flagError: 282 flagError:
276 fprintf (stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); 283 fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n");
277 exit (FALSE); 284 exit(FALSE);
278} 285}
279 286
280 287
@@ -282,120 +289,120 @@ flagError:
282 * Read a tar file and extract or list the specified files within it. 289 * Read a tar file and extract or list the specified files within it.
283 * If the list is empty than all files are extracted or listed. 290 * If the list is empty than all files are extracted or listed.
284 */ 291 */
285static void readTarFile (int fileCount, char **fileTable) 292static void readTarFile(int fileCount, char **fileTable)
286{ 293{
287 const char *cp; 294 const char *cp;
288 int cc; 295 int cc;
289 int inCc; 296 int inCc;
290 int blockSize; 297 int blockSize;
291 char buf[BUF_SIZE]; 298 char buf[BUF_SIZE];
292 299
293 skipFileFlag = FALSE; 300 skipFileFlag = FALSE;
294 badHeader = FALSE; 301 badHeader = FALSE;
295 warnedRoot = FALSE; 302 warnedRoot = FALSE;
296 eofFlag = FALSE; 303 eofFlag = FALSE;
297 inHeader = TRUE; 304 inHeader = TRUE;
298 inCc = 0; 305 inCc = 0;
299 dataCc = 0; 306 dataCc = 0;
300 outFd = -1; 307 outFd = -1;
301 blockSize = sizeof (buf); 308 blockSize = sizeof(buf);
302 cp = buf; 309 cp = buf;
303 310
304 /*
305 * Open the tar file for reading.
306 */
307 if ((tarName == NULL) || !strcmp (tarName, "-")) {
308 tarFd = fileno(stdin);
309 } else
310 tarFd = open (tarName, O_RDONLY);
311
312 if (tarFd < 0) {
313 perror (tarName);
314 errorFlag = TRUE;
315 return;
316 }
317
318 /*
319 * Read blocks from the file until an end of file header block
320 * has been seen. (A real end of file from a read is an error.)
321 */
322 while (eofFlag==FALSE) {
323 /* 311 /*
324 * Read the next block of data if necessary. 312 * Open the tar file for reading.
325 * This will be a large block if possible, which we will
326 * then process in the small tar blocks.
327 */ 313 */
328 if (inCc <= 0) { 314 if ((tarName == NULL) || !strcmp(tarName, "-")) {
329 cp = buf; 315 tarFd = fileno(stdin);
330 inCc = fullRead (tarFd, buf, blockSize); 316 } else
331 317 tarFd = open(tarName, O_RDONLY);
332 if (inCc < 0) {
333 perror (tarName);
334 errorFlag = TRUE;
335 goto done;
336 }
337 318
338 if (inCc == 0) { 319 if (tarFd < 0) {
339 fprintf (stderr, 320 perror(tarName);
340 "Unexpected end of file from \"%s\"", tarName);
341 errorFlag = TRUE; 321 errorFlag = TRUE;
342 goto done; 322 return;
343 }
344 } 323 }
345 324
346 /* 325 /*
347 * If we are expecting a header block then examine it. 326 * Read blocks from the file until an end of file header block
327 * has been seen. (A real end of file from a read is an error.)
348 */ 328 */
349 if (inHeader==TRUE) { 329 while (eofFlag == FALSE) {
350 readHeader ((const TarHeader *) cp, fileCount, fileTable); 330 /*
351 331 * Read the next block of data if necessary.
352 cp += TAR_BLOCK_SIZE; 332 * This will be a large block if possible, which we will
353 inCc -= TAR_BLOCK_SIZE; 333 * then process in the small tar blocks.
354 334 */
355 continue; 335 if (inCc <= 0) {
336 cp = buf;
337 inCc = fullRead(tarFd, buf, blockSize);
338
339 if (inCc < 0) {
340 perror(tarName);
341 errorFlag = TRUE;
342 goto done;
343 }
344
345 if (inCc == 0) {
346 fprintf(stderr,
347 "Unexpected end of file from \"%s\"", tarName);
348 errorFlag = TRUE;
349 goto done;
350 }
351 }
352
353 /*
354 * If we are expecting a header block then examine it.
355 */
356 if (inHeader == TRUE) {
357 readHeader((const TarHeader *) cp, fileCount, fileTable);
358
359 cp += TAR_BLOCK_SIZE;
360 inCc -= TAR_BLOCK_SIZE;
361
362 continue;
363 }
364
365 /*
366 * We are currently handling the data for a file.
367 * Process the minimum of the amount of data we have available
368 * and the amount left to be processed for the file.
369 */
370 cc = inCc;
371
372 if (cc > dataCc)
373 cc = dataCc;
374
375 readData(cp, cc);
376
377 /*
378 * If the amount left isn't an exact multiple of the tar block
379 * size then round it up to the next block boundary since there
380 * is padding at the end of the file.
381 */
382 if (cc % TAR_BLOCK_SIZE)
383 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
384
385 cp += cc;
386 inCc -= cc;
356 } 387 }
357 388
389 done:
358 /* 390 /*
359 * We are currently handling the data for a file. 391 * Close the tar file if needed.
360 * Process the minimum of the amount of data we have available
361 * and the amount left to be processed for the file.
362 */ 392 */
363 cc = inCc; 393 if ((tarFd >= 0) && (close(tarFd) < 0))
364 394 perror(tarName);
365 if (cc > dataCc)
366 cc = dataCc;
367
368 readData (cp, cc);
369 395
370 /* 396 /*
371 * If the amount left isn't an exact multiple of the tar block 397 * Close the output file if needed.
372 * size then round it up to the next block boundary since there 398 * This is only done here on a previous error and so no
373 * is padding at the end of the file. 399 * message is required on errors.
374 */ 400 */
375 if (cc % TAR_BLOCK_SIZE) 401 if (tostdoutFlag == FALSE) {
376 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE); 402 if (outFd >= 0) {
377 403 close(outFd);
378 cp += cc; 404 }
379 inCc -= cc;
380 }
381
382 done:
383 /*
384 * Close the tar file if needed.
385 */
386 if ((tarFd >= 0) && (close (tarFd) < 0))
387 perror (tarName);
388
389 /*
390 * Close the output file if needed.
391 * This is only done here on a previous error and so no
392 * message is required on errors.
393 */
394 if (tostdoutFlag == FALSE) {
395 if (outFd >= 0) {
396 close (outFd);
397 } 405 }
398 }
399} 406}
400 407
401 408
@@ -405,304 +412,305 @@ static void readTarFile (int fileCount, char **fileTable)
405 * the end of the tar file. 412 * the end of the tar file.
406 */ 413 */
407static void 414static void
408readHeader (const TarHeader * hp, int fileCount, char **fileTable) 415readHeader(const TarHeader * hp, int fileCount, char **fileTable)
409{ 416{
410 int checkSum; 417 int checkSum;
411 int cc; 418 int cc;
412 int hardLink; 419 int hardLink;
413 int softLink; 420 int softLink;
414 int devFileFlag; 421 int devFileFlag;
415 unsigned int major; 422 unsigned int major;
416 unsigned int minor; 423 unsigned int minor;
417 long size; 424 long size;
418 struct utimbuf utb; 425 struct utimbuf utb;
419 426
420 /* 427 /*
421 * If the block is completely empty, then this is the end of the 428 * If the block is completely empty, then this is the end of the
422 * archive file. If the name is null, then just skip this header. 429 * archive file. If the name is null, then just skip this header.
423 */ 430 */
424 outName = hp->name; 431 outName = hp->name;
425 432
426 if (*outName == '\0') { 433 if (*outName == '\0') {
427 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { 434 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
428 if (*outName++) 435 if (*outName++)
436 return;
437 }
438
439 eofFlag = TRUE;
440
429 return; 441 return;
430 } 442 }
431 443
432 eofFlag = TRUE; 444 /*
433 445 * There is another file in the archive to examine.
434 return; 446 * Extract the encoded information and check it.
435 } 447 */
436 448 mode = getOctal(hp->mode, sizeof(hp->mode));
437 /* 449 uid = getOctal(hp->uid, sizeof(hp->uid));
438 * There is another file in the archive to examine. 450 gid = getOctal(hp->gid, sizeof(hp->gid));
439 * Extract the encoded information and check it. 451 size = getOctal(hp->size, sizeof(hp->size));
440 */ 452 mtime = getOctal(hp->mtime, sizeof(hp->mtime));
441 mode = getOctal (hp->mode, sizeof (hp->mode)); 453 checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum));
442 uid = getOctal (hp->uid, sizeof (hp->uid)); 454 major = getOctal(hp->devMajor, sizeof(hp->devMajor));
443 gid = getOctal (hp->gid, sizeof (hp->gid)); 455 minor = getOctal(hp->devMinor, sizeof(hp->devMinor));
444 size = getOctal (hp->size, sizeof (hp->size));
445 mtime = getOctal (hp->mtime, sizeof (hp->mtime));
446 checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum));
447 major = getOctal (hp->devMajor, sizeof (hp->devMajor));
448 minor = getOctal (hp->devMinor, sizeof (hp->devMinor));
449
450 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
451 if (badHeader==FALSE)
452 fprintf (stderr, "Bad tar header, skipping\n");
453
454 badHeader = TRUE;
455
456 return;
457 }
458
459 badHeader = FALSE;
460 skipFileFlag = FALSE;
461 devFileFlag = FALSE;
462
463 /*
464 * Check for the file modes.
465 */
466 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
467 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
468
469 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
470 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
471
472 /*
473 * Check for a directory.
474 */
475 if (outName[strlen (outName) - 1] == '/')
476 mode |= S_IFDIR;
477
478 /*
479 * Check for absolute paths in the file.
480 * If we find any, then warn the user and make them relative.
481 */
482 if (*outName == '/') {
483 while (*outName == '/')
484 outName++;
485
486 if (warnedRoot==FALSE) {
487 fprintf (stderr,
488 "Absolute path detected, removing leading slashes\n");
489 }
490 456
491 warnedRoot = TRUE; 457 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
492 } 458 if (badHeader == FALSE)
493 459 fprintf(stderr, "Bad tar header, skipping\n");
494 /*
495 * See if we want this file to be restored.
496 * If not, then set up to skip it.
497 */
498 if (wantFileName (outName, fileCount, fileTable) == FALSE) {
499 if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode)
500 || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) {
501 inHeader = (size == 0)? TRUE : FALSE;
502 dataCc = size;
503 }
504 460
505 skipFileFlag = TRUE; 461 badHeader = TRUE;
506 462
507 return; 463 return;
508 }
509
510 /*
511 * This file is to be handled.
512 * If we aren't extracting then just list information about the file.
513 */
514 if (extractFlag==FALSE) {
515 if (verboseFlag==TRUE) {
516 printf ("%s %3d/%-d ", modeString (mode), uid, gid);
517 if( S_ISCHR (mode) || S_ISBLK (mode) )
518 printf ("%4d,%4d %s ", major,minor, timeString (mtime));
519 else
520 printf ("%9ld %s ", size, timeString (mtime));
521 }
522 printf ("%s", outName);
523
524 if (hardLink)
525 printf (" (link to \"%s\")", hp->linkName);
526 else if (softLink)
527 printf (" (symlink to \"%s\")", hp->linkName);
528 else if (S_ISREG (mode) || S_ISCHR (mode) || S_ISBLK (mode) ||
529 S_ISSOCK(mode) || S_ISFIFO(mode) ) {
530 inHeader = (size == 0)? TRUE : FALSE;
531 dataCc = size;
532 } 464 }
533 465
534 printf ("\n"); 466 badHeader = FALSE;
467 skipFileFlag = FALSE;
468 devFileFlag = FALSE;
535 469
536 return; 470 /*
537 } 471 * Check for the file modes.
472 */
473 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
474 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
475
476 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
477 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
478
479 /*
480 * Check for a directory.
481 */
482 if (outName[strlen(outName) - 1] == '/')
483 mode |= S_IFDIR;
484
485 /*
486 * Check for absolute paths in the file.
487 * If we find any, then warn the user and make them relative.
488 */
489 if (*outName == '/') {
490 while (*outName == '/')
491 outName++;
538 492
539 /* 493 if (warnedRoot == FALSE) {
540 * We really want to extract the file. 494 fprintf(stderr,
541 */ 495 "Absolute path detected, removing leading slashes\n");
542 if (verboseFlag==TRUE) 496 }
543 printf ("x %s\n", outName);
544 497
545 if (hardLink) { 498 warnedRoot = TRUE;
546 if (link (hp->linkName, outName) < 0) {
547 perror (outName);
548 return;
549 } 499 }
550 /* Set the file time */ 500
551 utb.actime = mtime; 501 /*
552 utb.modtime = mtime; 502 * See if we want this file to be restored.
553 utime (outName, &utb); 503 * If not, then set up to skip it.
554 /* Set the file permissions */ 504 */
555 chown(outName, uid, gid); 505 if (wantFileName(outName, fileCount, fileTable) == FALSE) {
556 chmod(outName, mode); 506 if (!hardLink && !softLink && (S_ISREG(mode) || S_ISCHR(mode)
557 return; 507 || S_ISBLK(mode) || S_ISSOCK(mode)
558 } 508 || S_ISFIFO(mode))) {
559 509 inHeader = (size == 0) ? TRUE : FALSE;
560 if (softLink) { 510 dataCc = size;
561#ifdef S_ISLNK 511 }
562 if (symlink (hp->linkName, outName) < 0) { 512
563 perror (outName); 513 skipFileFlag = TRUE;
564 return; 514
515 return;
565 } 516 }
566 /* Try to change ownership of the symlink. 517
567 * If libs doesn't support that, don't bother. 518 /*
568 * Changing the pointed-to file is the Wrong Thing(tm). 519 * This file is to be handled.
520 * If we aren't extracting then just list information about the file.
569 */ 521 */
522 if (extractFlag == FALSE) {
523 if (verboseFlag == TRUE) {
524 printf("%s %3d/%-d ", modeString(mode), uid, gid);
525 if (S_ISCHR(mode) || S_ISBLK(mode))
526 printf("%4d,%4d %s ", major, minor, timeString(mtime));
527 else
528 printf("%9ld %s ", size, timeString(mtime));
529 }
530 printf("%s", outName);
531
532 if (hardLink)
533 printf(" (link to \"%s\")", hp->linkName);
534 else if (softLink)
535 printf(" (symlink to \"%s\")", hp->linkName);
536 else if (S_ISREG(mode) || S_ISCHR(mode) || S_ISBLK(mode) ||
537 S_ISSOCK(mode) || S_ISFIFO(mode)) {
538 inHeader = (size == 0) ? TRUE : FALSE;
539 dataCc = size;
540 }
541
542 printf("\n");
543
544 return;
545 }
546
547 /*
548 * We really want to extract the file.
549 */
550 if (verboseFlag == TRUE)
551 printf("x %s\n", outName);
552
553 if (hardLink) {
554 if (link(hp->linkName, outName) < 0) {
555 perror(outName);
556 return;
557 }
558 /* Set the file time */
559 utb.actime = mtime;
560 utb.modtime = mtime;
561 utime(outName, &utb);
562 /* Set the file permissions */
563 chown(outName, uid, gid);
564 chmod(outName, mode);
565 return;
566 }
567
568 if (softLink) {
569#ifdef S_ISLNK
570 if (symlink(hp->linkName, outName) < 0) {
571 perror(outName);
572 return;
573 }
574 /* Try to change ownership of the symlink.
575 * If libs doesn't support that, don't bother.
576 * Changing the pointed-to file is the Wrong Thing(tm).
577 */
570#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 578#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
571 lchown(outName, uid, gid); 579 lchown(outName, uid, gid);
572#endif 580#endif
573 581
574 /* Do not change permissions or date on symlink, 582 /* Do not change permissions or date on symlink,
575 * since it changes the pointed to file instead. duh. */ 583 * since it changes the pointed to file instead. duh. */
576#else 584#else
577 fprintf (stderr, "Cannot create symbolic links\n"); 585 fprintf(stderr, "Cannot create symbolic links\n");
578#endif 586#endif
579 return; 587 return;
580 }
581
582 /* Set the umask for this process so it doesn't
583 * screw things up. */
584 umask(0);
585
586 /*
587 * If the file is a directory, then just create the path.
588 */
589 if (S_ISDIR (mode)) {
590 if (createPath (outName, mode)==TRUE) {
591 /* Set the file time */
592 utb.actime = mtime;
593 utb.modtime = mtime;
594 utime (outName, &utb);
595 /* Set the file permissions */
596 chown(outName, uid, gid);
597 chmod(outName, mode);
598 return;
599 } 588 }
600 return; 589
601 } 590 /* Set the umask for this process so it doesn't
602 591 * screw things up. */
603 /* 592 umask(0);
604 * There is a file to write. 593
605 * First create the path to it if necessary with default permissions. 594 /*
606 */ 595 * If the file is a directory, then just create the path.
607 createPath (outName, 0777); 596 */
608 597 if (S_ISDIR(mode)) {
609 inHeader = (size == 0)? TRUE : FALSE; 598 if (createPath(outName, mode) == TRUE) {
610 dataCc = size; 599 /* Set the file time */
611 600 utb.actime = mtime;
612 /* 601 utb.modtime = mtime;
613 * Start the output file. 602 utime(outName, &utb);
614 */ 603 /* Set the file permissions */
615 if (tostdoutFlag == TRUE) 604 chown(outName, uid, gid);
616 outFd = fileno(stdout); 605 chmod(outName, mode);
617 else { 606 return;
618 if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { 607 }
619 devFileFlag = TRUE; 608 return;
620 outFd = mknod (outName, mode, makedev(major, minor) );
621 } 609 }
622 else if (S_ISFIFO(mode) ) { 610
623 devFileFlag = TRUE; 611 /*
624 outFd = mkfifo(outName, mode); 612 * There is a file to write.
625 } else { 613 * First create the path to it if necessary with default permissions.
626 outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode); 614 */
615 createPath(outName, 0777);
616
617 inHeader = (size == 0) ? TRUE : FALSE;
618 dataCc = size;
619
620 /*
621 * Start the output file.
622 */
623 if (tostdoutFlag == TRUE)
624 outFd = fileno(stdout);
625 else {
626 if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode)) {
627 devFileFlag = TRUE;
628 outFd = mknod(outName, mode, makedev(major, minor));
629 } else if (S_ISFIFO(mode)) {
630 devFileFlag = TRUE;
631 outFd = mkfifo(outName, mode);
632 } else {
633 outFd = open(outName, O_WRONLY | O_CREAT | O_TRUNC, mode);
634 }
635 if (outFd < 0) {
636 perror(outName);
637 skipFileFlag = TRUE;
638 return;
639 }
640 /* Set the file time */
641 utb.actime = mtime;
642 utb.modtime = mtime;
643 utime(outName, &utb);
644 /* Set the file permissions */
645 chown(outName, uid, gid);
646 chmod(outName, mode);
627 } 647 }
628 if (outFd < 0) { 648
629 perror (outName); 649
630 skipFileFlag = TRUE; 650 /*
631 return; 651 * If the file is empty, then that's all we need to do.
652 */
653 if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
654 close(outFd);
655 outFd = -1;
632 } 656 }
633 /* Set the file time */
634 utb.actime = mtime;
635 utb.modtime = mtime;
636 utime (outName, &utb);
637 /* Set the file permissions */
638 chown(outName, uid, gid);
639 chmod(outName, mode);
640 }
641
642
643 /*
644 * If the file is empty, then that's all we need to do.
645 */
646 if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
647 close (outFd);
648 outFd = -1;
649 }
650} 657}
651 658
652 659
653/* 660/*
654 * Handle a data block of some specified size that was read. 661 * Handle a data block of some specified size that was read.
655 */ 662 */
656static void readData (const char *cp, int count) 663static void readData(const char *cp, int count)
657{ 664{
658 /* 665 /*
659 * Reduce the amount of data left in this file. 666 * Reduce the amount of data left in this file.
660 * If there is no more data left, then we need to read 667 * If there is no more data left, then we need to read
661 * the header again. 668 * the header again.
662 */ 669 */
663 dataCc -= count; 670 dataCc -= count;
664
665 if (dataCc <= 0)
666 inHeader = TRUE;
667 671
668 /* 672 if (dataCc <= 0)
669 * If we aren't extracting files or this file is being 673 inHeader = TRUE;
670 * skipped then do nothing more. 674
671 */ 675 /*
672 if (extractFlag==FALSE || skipFileFlag==TRUE) 676 * If we aren't extracting files or this file is being
673 return; 677 * skipped then do nothing more.
674 678 */
675 /* 679 if (extractFlag == FALSE || skipFileFlag == TRUE)
676 * Write the data to the output file. 680 return;
677 */ 681
678 if (fullWrite (outFd, cp, count) < 0) { 682 /*
679 perror (outName); 683 * Write the data to the output file.
680 if (tostdoutFlag == FALSE) { 684 */
681 close (outFd); 685 if (fullWrite(outFd, cp, count) < 0) {
682 outFd = -1; 686 perror(outName);
687 if (tostdoutFlag == FALSE) {
688 close(outFd);
689 outFd = -1;
690 }
691 skipFileFlag = TRUE;
692 return;
683 } 693 }
684 skipFileFlag = TRUE;
685 return;
686 }
687
688 /*
689 * Check if we are done writing to the file now.
690 */
691 if (dataCc <= 0 && tostdoutFlag == FALSE) {
692 struct utimbuf utb;
693 if (close (outFd))
694 perror (outName);
695 694
696 /* Set the file time */ 695 /*
697 utb.actime = mtime; 696 * Check if we are done writing to the file now.
698 utb.modtime = mtime; 697 */
699 utime (outName, &utb); 698 if (dataCc <= 0 && tostdoutFlag == FALSE) {
700 /* Set the file permissions */ 699 struct utimbuf utb;
701 chown(outName, uid, gid); 700
702 chmod(outName, mode); 701 if (close(outFd))
702 perror(outName);
703 703
704 outFd = -1; 704 /* Set the file time */
705 } 705 utb.actime = mtime;
706 utb.modtime = mtime;
707 utime(outName, &utb);
708 /* Set the file permissions */
709 chown(outName, uid, gid);
710 chmod(outName, mode);
711
712 outFd = -1;
713 }
706} 714}
707 715
708 716
@@ -712,40 +720,40 @@ static void readData (const char *cp, int count)
712 * Returns TRUE if the file is selected. 720 * Returns TRUE if the file is selected.
713 */ 721 */
714static int 722static int
715wantFileName (const char *fileName, int fileCount, char **fileTable) 723wantFileName(const char *fileName, int fileCount, char **fileTable)
716{ 724{
717 const char *pathName; 725 const char *pathName;
718 int fileLength; 726 int fileLength;
719 int pathLength; 727 int pathLength;
720 728
721 /* 729 /*
722 * If there are no files in the list, then the file is wanted. 730 * If there are no files in the list, then the file is wanted.
723 */ 731 */
724 if (fileCount == 0) 732 if (fileCount == 0)
725 return TRUE; 733 return TRUE;
726 734
727 fileLength = strlen (fileName); 735 fileLength = strlen(fileName);
728 736
729 /* 737 /*
730 * Check each of the test paths. 738 * Check each of the test paths.
731 */ 739 */
732 while (fileCount-- > 0) { 740 while (fileCount-- > 0) {
733 pathName = *fileTable++; 741 pathName = *fileTable++;
734 742
735 pathLength = strlen (pathName); 743 pathLength = strlen(pathName);
736 744
737 if (fileLength < pathLength) 745 if (fileLength < pathLength)
738 continue; 746 continue;
739 747
740 if (memcmp (fileName, pathName, pathLength) != 0) 748 if (memcmp(fileName, pathName, pathLength) != 0)
741 continue; 749 continue;
742 750
743 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) { 751 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) {
744 return TRUE; 752 return TRUE;
753 }
745 } 754 }
746 }
747 755
748 return FALSE; 756 return FALSE;
749} 757}
750 758
751/* 759/*
@@ -753,34 +761,34 @@ wantFileName (const char *fileName, int fileCount, char **fileTable)
753 * spaces on both sides of the number and with an optional null character 761 * spaces on both sides of the number and with an optional null character
754 * at the end. Returns -1 on an illegal format. 762 * at the end. Returns -1 on an illegal format.
755 */ 763 */
756static long getOctal (const char *cp, int len) 764static long getOctal(const char *cp, int len)
757{ 765{
758 long val; 766 long val;
759 767
760 while ((len > 0) && (*cp == ' ')) { 768 while ((len > 0) && (*cp == ' ')) {
761 cp++; 769 cp++;
762 len--; 770 len--;
763 } 771 }
764 772
765 if ((len == 0) || !isOctal (*cp)) 773 if ((len == 0) || !isOctal(*cp))
766 return -1; 774 return -1;
767 775
768 val = 0; 776 val = 0;
769 777
770 while ((len > 0) && isOctal (*cp)) { 778 while ((len > 0) && isOctal(*cp)) {
771 val = val * 8 + *cp++ - '0'; 779 val = val * 8 + *cp++ - '0';
772 len--; 780 len--;
773 } 781 }
774 782
775 while ((len > 0) && (*cp == ' ')) { 783 while ((len > 0) && (*cp == ' ')) {
776 cp++; 784 cp++;
777 len--; 785 len--;
778 } 786 }
779 787
780 if ((len > 0) && *cp) 788 if ((len > 0) && *cp)
781 return -1; 789 return -1;
782 790
783 return val; 791 return val;
784} 792}
785 793
786 794
@@ -795,65 +803,65 @@ static long getOctal (const char *cp, int len)
795/* 803/*
796 * Write a tar file containing the specified files. 804 * Write a tar file containing the specified files.
797 */ 805 */
798static void writeTarFile (int fileCount, char **fileTable) 806static void writeTarFile(int fileCount, char **fileTable)
799{ 807{
800 struct stat statbuf; 808 struct stat statbuf;
801 809
802 /* 810 /*
803 * Make sure there is at least one file specified. 811 * Make sure there is at least one file specified.
804 */ 812 */
805 if (fileCount <= 0) { 813 if (fileCount <= 0) {
806 fprintf (stderr, "No files specified to be saved\n"); 814 fprintf(stderr, "No files specified to be saved\n");
807 errorFlag = TRUE; 815 errorFlag = TRUE;
808 } 816 }
809 817
810 /* 818 /*
811 * Create the tar file for writing. 819 * Create the tar file for writing.
812 */ 820 */
813 if ((tarName == NULL) || !strcmp (tarName, "-")) { 821 if ((tarName == NULL) || !strcmp(tarName, "-")) {
814 tostdoutFlag = TRUE; 822 tostdoutFlag = TRUE;
815 tarFd = fileno(stdout); 823 tarFd = fileno(stdout);
816 } else 824 } else
817 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); 825 tarFd = open(tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
818 826
819 if (tarFd < 0) { 827 if (tarFd < 0) {
820 perror (tarName); 828 perror(tarName);
821 errorFlag = TRUE; 829 errorFlag = TRUE;
822 return; 830 return;
823 } 831 }
824 832
825 /* 833 /*
826 * Get the device and inode of the tar file for checking later. 834 * Get the device and inode of the tar file for checking later.
827 */ 835 */
828 if (fstat (tarFd, &statbuf) < 0) { 836 if (fstat(tarFd, &statbuf) < 0) {
829 perror (tarName); 837 perror(tarName);
830 errorFlag = TRUE; 838 errorFlag = TRUE;
831 goto done; 839 goto done;
832 } 840 }
833 841
834 tarDev = statbuf.st_dev; 842 tarDev = statbuf.st_dev;
835 tarInode = statbuf.st_ino; 843 tarInode = statbuf.st_ino;
836 844
837 /* 845 /*
838 * Append each file name into the archive file. 846 * Append each file name into the archive file.
839 * Follow symbolic links for these top level file names. 847 * Follow symbolic links for these top level file names.
840 */ 848 */
841 while (errorFlag==FALSE && (fileCount-- > 0)) { 849 while (errorFlag == FALSE && (fileCount-- > 0)) {
842 saveFile (*fileTable++, FALSE); 850 saveFile(*fileTable++, FALSE);
843 } 851 }
844 852
845 /* 853 /*
846 * Now write an empty block of zeroes to end the archive. 854 * Now write an empty block of zeroes to end the archive.
847 */ 855 */
848 writeTarBlock ("", 1); 856 writeTarBlock("", 1);
849 857
850 858
851 done: 859 done:
852 /* 860 /*
853 * Close the tar file and check for errors if it was opened. 861 * Close the tar file and check for errors if it was opened.
854 */ 862 */
855 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0)) 863 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close(tarFd) < 0))
856 perror (tarName); 864 perror(tarName);
857} 865}
858 866
859/* 867/*
@@ -863,73 +871,73 @@ static void writeTarFile (int fileCount, char **fileTable)
863 * flag indicates whether or not we want to see symbolic links as 871 * flag indicates whether or not we want to see symbolic links as
864 * they really are, instead of blindly following them. 872 * they really are, instead of blindly following them.
865 */ 873 */
866static void saveFile (const char *fileName, int seeLinks) 874static void saveFile(const char *fileName, int seeLinks)
867{ 875{
868 int status; 876 int status;
869 struct stat statbuf; 877 struct stat statbuf;
870 878
871 if (verboseFlag==TRUE) 879 if (verboseFlag == TRUE)
872 printf ("a %s\n", fileName); 880 printf("a %s\n", fileName);
873 881
874 /* 882 /*
875 * Check that the file name will fit in the header. 883 * Check that the file name will fit in the header.
876 */ 884 */
877 if (strlen (fileName) >= TAR_NAME_SIZE) { 885 if (strlen(fileName) >= TAR_NAME_SIZE) {
878 fprintf (stderr, "%s: File name is too long\n", fileName); 886 fprintf(stderr, "%s: File name is too long\n", fileName);
879 887
880 return; 888 return;
881 } 889 }
882 890
883 /* 891 /*
884 * Find out about the file. 892 * Find out about the file.
885 */ 893 */
886#ifdef S_ISLNK 894#ifdef S_ISLNK
887 if (seeLinks==TRUE) 895 if (seeLinks == TRUE)
888 status = lstat (fileName, &statbuf); 896 status = lstat(fileName, &statbuf);
889 else 897 else
890#endif 898#endif
891 status = stat (fileName, &statbuf); 899 status = stat(fileName, &statbuf);
892 900
893 if (status < 0) { 901 if (status < 0) {
894 perror (fileName); 902 perror(fileName);
903
904 return;
905 }
895 906
896 return; 907 /*
897 } 908 * Make sure we aren't trying to save our file into itself.
909 */
910 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
911 fprintf(stderr, "Skipping saving of archive file itself\n");
898 912
899 /* 913 return;
900 * Make sure we aren't trying to save our file into itself. 914 }
901 */
902 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
903 fprintf (stderr, "Skipping saving of archive file itself\n");
904 915
905 return; 916 /*
906 } 917 * Check the type of file.
918 */
919 mode = statbuf.st_mode;
907 920
908 /* 921 if (S_ISDIR(mode)) {
909 * Check the type of file. 922 saveDirectory(fileName, &statbuf);
910 */
911 mode = statbuf.st_mode;
912 923
913 if (S_ISDIR (mode)) { 924 return;
914 saveDirectory (fileName, &statbuf); 925 }
926 if (S_ISREG(mode)) {
927 saveRegularFile(fileName, &statbuf);
915 928
916 return; 929 return;
917 } 930 }
918 if (S_ISREG (mode)) {
919 saveRegularFile (fileName, &statbuf);
920 931
921 return; 932 /* Some day add support for tarring these up... but not today. :) */
922 }
923
924 /* Some day add support for tarring these up... but not today. :) */
925// if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) { 933// if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) {
926// fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName); 934// fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName);
927// } 935// }
928 936
929 /* 937 /*
930 * The file is a strange type of file, ignore it. 938 * The file is a strange type of file, ignore it.
931 */ 939 */
932 fprintf (stderr, "%s: not a directory or regular file\n", fileName); 940 fprintf(stderr, "%s: not a directory or regular file\n", fileName);
933} 941}
934 942
935 943
@@ -937,173 +945,172 @@ static void saveFile (const char *fileName, int seeLinks)
937 * Save a regular file to the tar file. 945 * Save a regular file to the tar file.
938 */ 946 */
939static void 947static void
940saveRegularFile (const char *fileName, const struct stat *statbuf) 948saveRegularFile(const char *fileName, const struct stat *statbuf)
941{ 949{
942 int sawEof; 950 int sawEof;
943 int fileFd; 951 int fileFd;
944 int cc; 952 int cc;
945 int dataCount; 953 int dataCount;
946 long fullDataCount; 954 long fullDataCount;
947 char data[TAR_BLOCK_SIZE * 16]; 955 char data[TAR_BLOCK_SIZE * 16];
948
949 /*
950 * Open the file for reading.
951 */
952 fileFd = open (fileName, O_RDONLY);
953
954 if (fileFd < 0) {
955 perror (fileName);
956
957 return;
958 }
959
960 /*
961 * Write out the header for the file.
962 */
963 writeHeader (fileName, statbuf);
964
965 /*
966 * Write the data blocks of the file.
967 * We must be careful to write the amount of data that the stat
968 * buffer indicated, even if the file has changed size. Otherwise
969 * the tar file will be incorrect.
970 */
971 fullDataCount = statbuf->st_size;
972 sawEof = FALSE;
973
974 while (fullDataCount > 0) {
975 /*
976 * Get the amount to write this iteration which is
977 * the minumum of the amount left to write and the
978 * buffer size.
979 */
980 dataCount = sizeof (data);
981
982 if (dataCount > fullDataCount)
983 dataCount = (int) fullDataCount;
984 956
985 /* 957 /*
986 * Read the data from the file if we haven't seen the 958 * Open the file for reading.
987 * end of file yet.
988 */ 959 */
989 cc = 0; 960 fileFd = open(fileName, O_RDONLY);
990
991 if (sawEof==FALSE) {
992 cc = fullRead (fileFd, data, dataCount);
993 961
994 if (cc < 0) { 962 if (fileFd < 0) {
995 perror (fileName); 963 perror(fileName);
996
997 (void) close (fileFd);
998 errorFlag = TRUE;
999 964
1000 return; 965 return;
1001 }
1002
1003 /*
1004 * If the file ended too soon, complain and set
1005 * a flag so we will zero fill the rest of it.
1006 */
1007 if (cc < dataCount) {
1008 fprintf (stderr,
1009 "%s: Short read - zero filling", fileName);
1010
1011 sawEof = TRUE;
1012 }
1013 } 966 }
1014 967
1015 /* 968 /*
1016 * Zero fill the rest of the data if necessary. 969 * Write out the header for the file.
1017 */ 970 */
1018 if (cc < dataCount) 971 writeHeader(fileName, statbuf);
1019 memset (data + cc, 0, dataCount - cc);
1020 972
1021 /* 973 /*
1022 * Write the buffer to the TAR file. 974 * Write the data blocks of the file.
975 * We must be careful to write the amount of data that the stat
976 * buffer indicated, even if the file has changed size. Otherwise
977 * the tar file will be incorrect.
1023 */ 978 */
1024 writeTarBlock (data, dataCount); 979 fullDataCount = statbuf->st_size;
1025 980 sawEof = FALSE;
1026 fullDataCount -= dataCount; 981
1027 } 982 while (fullDataCount > 0) {
983 /*
984 * Get the amount to write this iteration which is
985 * the minumum of the amount left to write and the
986 * buffer size.
987 */
988 dataCount = sizeof(data);
989
990 if (dataCount > fullDataCount)
991 dataCount = (int) fullDataCount;
992
993 /*
994 * Read the data from the file if we haven't seen the
995 * end of file yet.
996 */
997 cc = 0;
998
999 if (sawEof == FALSE) {
1000 cc = fullRead(fileFd, data, dataCount);
1001
1002 if (cc < 0) {
1003 perror(fileName);
1004
1005 (void) close(fileFd);
1006 errorFlag = TRUE;
1007
1008 return;
1009 }
1010
1011 /*
1012 * If the file ended too soon, complain and set
1013 * a flag so we will zero fill the rest of it.
1014 */
1015 if (cc < dataCount) {
1016 fprintf(stderr, "%s: Short read - zero filling", fileName);
1017
1018 sawEof = TRUE;
1019 }
1020 }
1021
1022 /*
1023 * Zero fill the rest of the data if necessary.
1024 */
1025 if (cc < dataCount)
1026 memset(data + cc, 0, dataCount - cc);
1027
1028 /*
1029 * Write the buffer to the TAR file.
1030 */
1031 writeTarBlock(data, dataCount);
1032
1033 fullDataCount -= dataCount;
1034 }
1028 1035
1029 /* 1036 /*
1030 * Close the file. 1037 * Close the file.
1031 */ 1038 */
1032 if ((tostdoutFlag == FALSE) && close (fileFd) < 0) 1039 if ((tostdoutFlag == FALSE) && close(fileFd) < 0)
1033 fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno)); 1040 fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno));
1034} 1041}
1035 1042
1036 1043
1037/* 1044/*
1038 * Save a directory and all of its files to the tar file. 1045 * Save a directory and all of its files to the tar file.
1039 */ 1046 */
1040static void saveDirectory (const char *dirName, const struct stat *statbuf) 1047static void saveDirectory(const char *dirName, const struct stat *statbuf)
1041{ 1048{
1042 DIR *dir; 1049 DIR *dir;
1043 struct dirent *entry; 1050 struct dirent *entry;
1044 int needSlash; 1051 int needSlash;
1045 char fullName[PATH_MAX + 1]; 1052 char fullName[PATH_MAX + 1];
1046 1053
1047 /* 1054 /*
1048 * Construct the directory name as used in the tar file by appending 1055 * Construct the directory name as used in the tar file by appending
1049 * a slash character to it. 1056 * a slash character to it.
1050 */ 1057 */
1051 strcpy (fullName, dirName); 1058 strcpy(fullName, dirName);
1052 strcat (fullName, "/"); 1059 strcat(fullName, "/");
1053 1060
1054 /* 1061 /*
1055 * Write out the header for the directory entry. 1062 * Write out the header for the directory entry.
1056 */ 1063 */
1057 writeHeader (fullName, statbuf); 1064 writeHeader(fullName, statbuf);
1058
1059 /*
1060 * Open the directory.
1061 */
1062 dir = opendir (dirName);
1063
1064 if (dir == NULL) {
1065 fprintf (stderr, "Cannot read directory \"%s\": %s\n",
1066 dirName, strerror (errno));
1067
1068 return;
1069 }
1070
1071 /*
1072 * See if a slash is needed.
1073 */
1074 needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/'));
1075
1076 /*
1077 * Read all of the directory entries and check them,
1078 * except for the current and parent directory entries.
1079 */
1080 while (errorFlag==FALSE && ((entry = readdir (dir)) != NULL)) {
1081 if ((strcmp (entry->d_name, ".") == 0) ||
1082 (strcmp (entry->d_name, "..") == 0)) {
1083 continue;
1084 }
1085 1065
1086 /* 1066 /*
1087 * Build the full path name to the file. 1067 * Open the directory.
1088 */ 1068 */
1089 strcpy (fullName, dirName); 1069 dir = opendir(dirName);
1070
1071 if (dir == NULL) {
1072 fprintf(stderr, "Cannot read directory \"%s\": %s\n",
1073 dirName, strerror(errno));
1090 1074
1091 if (needSlash) 1075 return;
1092 strcat (fullName, "/"); 1076 }
1093 1077
1094 strcat (fullName, entry->d_name); 1078 /*
1079 * See if a slash is needed.
1080 */
1081 needSlash = (*dirName && (dirName[strlen(dirName) - 1] != '/'));
1095 1082
1096 /* 1083 /*
1097 * Write this file to the tar file, noticing whether or not 1084 * Read all of the directory entries and check them,
1098 * the file is a symbolic link. 1085 * except for the current and parent directory entries.
1099 */ 1086 */
1100 saveFile (fullName, TRUE); 1087 while (errorFlag == FALSE && ((entry = readdir(dir)) != NULL)) {
1101 } 1088 if ((strcmp(entry->d_name, ".") == 0) ||
1089 (strcmp(entry->d_name, "..") == 0)) {
1090 continue;
1091 }
1092
1093 /*
1094 * Build the full path name to the file.
1095 */
1096 strcpy(fullName, dirName);
1097
1098 if (needSlash)
1099 strcat(fullName, "/");
1100
1101 strcat(fullName, entry->d_name);
1102
1103 /*
1104 * Write this file to the tar file, noticing whether or not
1105 * the file is a symbolic link.
1106 */
1107 saveFile(fullName, TRUE);
1108 }
1102 1109
1103 /* 1110 /*
1104 * All done, close the directory. 1111 * All done, close the directory.
1105 */ 1112 */
1106 closedir (dir); 1113 closedir(dir);
1107} 1114}
1108 1115
1109 1116
@@ -1111,54 +1118,54 @@ static void saveDirectory (const char *dirName, const struct stat *statbuf)
1111 * Write a tar header for the specified file name and status. 1118 * Write a tar header for the specified file name and status.
1112 * It is assumed that the file name fits. 1119 * It is assumed that the file name fits.
1113 */ 1120 */
1114static void writeHeader (const char *fileName, const struct stat *statbuf) 1121static void writeHeader(const char *fileName, const struct stat *statbuf)
1115{ 1122{
1116 long checkSum; 1123 long checkSum;
1117 const unsigned char *cp; 1124 const unsigned char *cp;
1118 int len; 1125 int len;
1119 TarHeader header; 1126 TarHeader header;
1120 1127
1121 /* 1128 /*
1122 * Zero the header block in preparation for filling it in. 1129 * Zero the header block in preparation for filling it in.
1123 */ 1130 */
1124 memset ((char *) &header, 0, sizeof (header)); 1131 memset((char *) &header, 0, sizeof(header));
1125 1132
1126 /* 1133 /*
1127 * Fill in the header. 1134 * Fill in the header.
1128 */ 1135 */
1129 strcpy (header.name, fileName); 1136 strcpy(header.name, fileName);
1130 1137
1131 strncpy (header.magic, TAR_MAGIC, sizeof (header.magic)); 1138 strncpy(header.magic, TAR_MAGIC, sizeof(header.magic));
1132 strncpy (header.version, TAR_VERSION, sizeof (header.version)); 1139 strncpy(header.version, TAR_VERSION, sizeof(header.version));
1133 1140
1134 putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777); 1141 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777);
1135 putOctal (header.uid, sizeof (header.uid), statbuf->st_uid); 1142 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
1136 putOctal (header.gid, sizeof (header.gid), statbuf->st_gid); 1143 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
1137 putOctal (header.size, sizeof (header.size), statbuf->st_size); 1144 putOctal(header.size, sizeof(header.size), statbuf->st_size);
1138 putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime); 1145 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
1139 1146
1140 header.typeFlag = TAR_TYPE_REGULAR; 1147 header.typeFlag = TAR_TYPE_REGULAR;
1141 1148
1142 /* 1149 /*
1143 * Calculate and store the checksum. 1150 * Calculate and store the checksum.
1144 * This is the sum of all of the bytes of the header, 1151 * This is the sum of all of the bytes of the header,
1145 * with the checksum field itself treated as blanks. 1152 * with the checksum field itself treated as blanks.
1146 */ 1153 */
1147 memset (header.checkSum, ' ', sizeof (header.checkSum)); 1154 memset(header.checkSum, ' ', sizeof(header.checkSum));
1148 1155
1149 cp = (const unsigned char *) &header; 1156 cp = (const unsigned char *) &header;
1150 len = sizeof (header); 1157 len = sizeof(header);
1151 checkSum = 0; 1158 checkSum = 0;
1152 1159
1153 while (len-- > 0) 1160 while (len-- > 0)
1154 checkSum += *cp++; 1161 checkSum += *cp++;
1155 1162
1156 putOctal (header.checkSum, sizeof (header.checkSum), checkSum); 1163 putOctal(header.checkSum, sizeof(header.checkSum), checkSum);
1157 1164
1158 /* 1165 /*
1159 * Write the tar header. 1166 * Write the tar header.
1160 */ 1167 */
1161 writeTarBlock ((const char *) &header, sizeof (header)); 1168 writeTarBlock((const char *) &header, sizeof(header));
1162} 1169}
1163 1170
1164 1171
@@ -1167,56 +1174,56 @@ static void writeHeader (const char *fileName, const struct stat *statbuf)
1167 * The data is always padded out to a multiple of TAR_BLOCK_SIZE. 1174 * The data is always padded out to a multiple of TAR_BLOCK_SIZE.
1168 * The errorFlag static variable is set on an error. 1175 * The errorFlag static variable is set on an error.
1169 */ 1176 */
1170static void writeTarBlock (const char *buf, int len) 1177static void writeTarBlock(const char *buf, int len)
1171{ 1178{
1172 int partialLength; 1179 int partialLength;
1173 int completeLength; 1180 int completeLength;
1174 char fullBlock[TAR_BLOCK_SIZE]; 1181 char fullBlock[TAR_BLOCK_SIZE];
1175 1182
1176 /* 1183 /*
1177 * If we had a write error before, then do nothing more. 1184 * If we had a write error before, then do nothing more.
1178 */ 1185 */
1179 if (errorFlag==TRUE) 1186 if (errorFlag == TRUE)
1180 return; 1187 return;
1181 1188
1182 /* 1189 /*
1183 * Get the amount of complete and partial blocks. 1190 * Get the amount of complete and partial blocks.
1184 */ 1191 */
1185 partialLength = len % TAR_BLOCK_SIZE; 1192 partialLength = len % TAR_BLOCK_SIZE;
1186 completeLength = len - partialLength; 1193 completeLength = len - partialLength;
1187 1194
1188 /* 1195 /*
1189 * Write all of the complete blocks. 1196 * Write all of the complete blocks.
1190 */ 1197 */
1191 if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) { 1198 if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) {
1192 perror (tarName); 1199 perror(tarName);
1193 1200
1194 errorFlag = TRUE; 1201 errorFlag = TRUE;
1195 1202
1196 return; 1203 return;
1197 } 1204 }
1198 1205
1199 /* 1206 /*
1200 * If there are no partial blocks left, we are done. 1207 * If there are no partial blocks left, we are done.
1201 */ 1208 */
1202 if (partialLength == 0) 1209 if (partialLength == 0)
1203 return; 1210 return;
1204 1211
1205 /* 1212 /*
1206 * Copy the partial data into a complete block, and pad the rest 1213 * Copy the partial data into a complete block, and pad the rest
1207 * of it with zeroes. 1214 * of it with zeroes.
1208 */ 1215 */
1209 memcpy (fullBlock, buf + completeLength, partialLength); 1216 memcpy(fullBlock, buf + completeLength, partialLength);
1210 memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); 1217 memset(fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength);
1211 1218
1212 /* 1219 /*
1213 * Write the last complete block. 1220 * Write the last complete block.
1214 */ 1221 */
1215 if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) { 1222 if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) {
1216 perror (tarName); 1223 perror(tarName);
1217 1224
1218 errorFlag = TRUE; 1225 errorFlag = TRUE;
1219 } 1226 }
1220} 1227}
1221 1228
1222 1229
@@ -1225,48 +1232,48 @@ static void writeTarBlock (const char *buf, int len)
1225 * The number is zero and space padded and possibly null padded. 1232 * The number is zero and space padded and possibly null padded.
1226 * Returns TRUE if successful. 1233 * Returns TRUE if successful.
1227 */ 1234 */
1228static int putOctal (char *cp, int len, long value) 1235static int putOctal(char *cp, int len, long value)
1229{ 1236{
1230 int tempLength; 1237 int tempLength;
1231 char *tempString; 1238 char *tempString;
1232 char tempBuffer[32]; 1239 char tempBuffer[32];
1233
1234 /*
1235 * Create a string of the specified length with an initial space,
1236 * leading zeroes and the octal number, and a trailing null.
1237 */
1238 tempString = tempBuffer;
1239
1240 sprintf (tempString, " %0*lo", len - 2, value);
1241
1242 tempLength = strlen (tempString) + 1;
1243
1244 /*
1245 * If the string is too large, suppress the leading space.
1246 */
1247 if (tempLength > len) {
1248 tempLength--;
1249 tempString++;
1250 }
1251
1252 /*
1253 * If the string is still too large, suppress the trailing null.
1254 */
1255 if (tempLength > len)
1256 tempLength--;
1257
1258 /*
1259 * If the string is still too large, fail.
1260 */
1261 if (tempLength > len)
1262 return FALSE;
1263 1240
1264 /* 1241 /*
1265 * Copy the string to the field. 1242 * Create a string of the specified length with an initial space,
1266 */ 1243 * leading zeroes and the octal number, and a trailing null.
1267 memcpy (cp, tempString, len); 1244 */
1245 tempString = tempBuffer;
1268 1246
1269 return TRUE; 1247 sprintf(tempString, " %0*lo", len - 2, value);
1248
1249 tempLength = strlen(tempString) + 1;
1250
1251 /*
1252 * If the string is too large, suppress the leading space.
1253 */
1254 if (tempLength > len) {
1255 tempLength--;
1256 tempString++;
1257 }
1258
1259 /*
1260 * If the string is still too large, suppress the trailing null.
1261 */
1262 if (tempLength > len)
1263 tempLength--;
1264
1265 /*
1266 * If the string is still too large, fail.
1267 */
1268 if (tempLength > len)
1269 return FALSE;
1270
1271 /*
1272 * Copy the string to the field.
1273 */
1274 memcpy(cp, tempString, len);
1275
1276 return TRUE;
1270} 1277}
1271#endif 1278#endif
1272 1279
diff --git a/tee.c b/tee.c
index 4c5c691c6..2f746f96d 100644
--- a/tee.c
+++ b/tee.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tee implementation for busybox 3 * Mini tee implementation for busybox
3 * 4 *
@@ -25,102 +26,100 @@
25#include <stdio.h> 26#include <stdio.h>
26 27
27static const char tee_usage[] = 28static const char tee_usage[] =
28 "tee [OPTION]... [FILE]...\n\n" 29 "tee [OPTION]... [FILE]...\n\n"
29 "Copy standard input to each FILE, and also to standard output.\n\n" 30 "Copy standard input to each FILE, and also to standard output.\n\n"
30 "Options:\n" 31 "Options:\n" "\t-a\tappend to the given FILEs, do not overwrite\n"
31 "\t-a\tappend to the given FILEs, do not overwrite\n"
32#if 0 32#if 0
33 "\t-i\tignore interrupt signals\n" 33 "\t-i\tignore interrupt signals\n"
34#endif 34#endif
35 ; 35;
36 36
37 37
38/* FileList _______________________________________________________________ */ 38/* FileList _______________________________________________________________ */
39 39
40#define FL_MAX 1024 40#define FL_MAX 1024
41static FILE *FileList[FL_MAX]; 41static FILE *FileList[FL_MAX];
42static int FL_end; 42static int FL_end;
43
44typedef void (FL_Function) (FILE * file, char c);
43 45
44typedef void (FL_Function)(FILE *file, char c);
45
46 46
47/* apply a function to everything in FileList */ 47/* apply a function to everything in FileList */
48static void 48static void FL_apply(FL_Function * f, char c)
49FL_apply(FL_Function *f, char c)
50{ 49{
51 int i; 50 int i;
52 for (i = 0; i <= FL_end; i++) { 51
53 f(FileList[i], c); 52 for (i = 0; i <= FL_end; i++) {
54 } 53 f(FileList[i], c);
54 }
55} 55}
56 56
57/* FL_Function for writing to files*/ 57/* FL_Function for writing to files*/
58static void 58static void tee_fwrite(FILE * file, char c)
59tee_fwrite(FILE *file, char c)
60{ 59{
61 fputc(c, file); 60 fputc(c, file);
62} 61}
63 62
64/* FL_Function for closing files */ 63/* FL_Function for closing files */
65static void 64static void tee_fclose(FILE * file, char c)
66tee_fclose(FILE *file, char c)
67{ 65{
68 fclose(file); 66 fclose(file);
69} 67}
70 68
71/* ________________________________________________________________________ */ 69/* ________________________________________________________________________ */
72 70
73/* BusyBoxed tee(1) */ 71/* BusyBoxed tee(1) */
74int 72int tee_main(int argc, char **argv)
75tee_main(int argc, char **argv)
76{ 73{
77 int i; 74 int i;
78 char c; 75 char c;
79 char opt; 76 char opt;
80 char opt_fopen[2] = "w"; 77 char opt_fopen[2] = "w";
81 FILE *file; 78 FILE *file;
82 79
83 /* parse argv[] */ 80 /* parse argv[] */
84 for (i = 1; i < argc; i++) { 81 for (i = 1; i < argc; i++) {
85 if (argv[i][0] == '-') { 82 if (argv[i][0] == '-') {
86 opt = argv[i][1]; 83 opt = argv[i][1];
87 switch (opt) { 84 switch (opt) {
88 case 'a': 85 case 'a':
89 opt_fopen[0] = 'a'; 86 opt_fopen[0] = 'a';
90 break; 87 break;
91#if 0 88#if 0
92 case 'i': 89 case 'i':
93 fprintf(stderr, "ignore interrupt not implemented\n"); 90 fprintf(stderr, "ignore interrupt not implemented\n");
94 break; 91 break;
95#endif 92#endif
96 default: 93 default:
97 usage(tee_usage); 94 usage(tee_usage);
98 } 95 }
99 } else { 96 } else {
100 break; 97 break;
98 }
101 } 99 }
102 } 100
103 101 /* init FILE pointers */
104 /* init FILE pointers */ 102 FL_end = 0;
105 FL_end = 0; 103 FileList[0] = stdout;
106 FileList[0] = stdout; 104 for (; i < argc; i++) {
107 for ( ; i < argc; i++) { 105 /* add a file to FileList */
108 /* add a file to FileList */ 106 file = fopen(argv[i], opt_fopen);
109 file = fopen(argv[i], opt_fopen); 107 if (!file) {
110 if (!file) { continue; } 108 continue;
111 if (FL_end < FL_MAX) { 109 }
112 FileList[++FL_end] = file; 110 if (FL_end < FL_MAX) {
111 FileList[++FL_end] = file;
112 }
113 } 113 }
114 }
115 114
116 /* read and redirect */ 115 /* read and redirect */
117 while ((c = (char) getchar()) && (!feof(stdin))) { 116 while ((c = (char) getchar()) && (!feof(stdin))) {
118 FL_apply(tee_fwrite, c); 117 FL_apply(tee_fwrite, c);
119 } 118 }
120 119
121 /* clean up */ 120 /* clean up */
122 FL_apply(tee_fclose, 0); 121 FL_apply(tee_fclose, 0);
123 exit(0); 122 exit(0);
124} 123}
125 124
126/* $Id: tee.c,v 1.5 2000/02/07 05:29:42 erik Exp $ */ 125/* $Id: tee.c,v 1.6 2000/02/08 19:58:47 erik Exp $ */
diff --git a/touch.c b/touch.c
index d2d3e9484..a0f21acdd 100644
--- a/touch.c
+++ b/touch.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini touch implementation for busybox 3 * Mini touch implementation for busybox
3 * 4 *
@@ -31,56 +32,50 @@
31 32
32 33
33static const char touch_usage[] = "touch [-c] file [file ...]\n\n" 34static const char touch_usage[] = "touch [-c] file [file ...]\n\n"
34"Update the last-modified date on the given file[s].\n";
35 35
36 "Update the last-modified date on the given file[s].\n";
36 37
37 38
38extern int
39touch_main(int argc, char **argv)
40{
41 int fd;
42 int create=TRUE;
43 39
44 if (argc < 2) { 40extern int touch_main(int argc, char **argv)
45 usage( touch_usage); 41{
46 } 42 int fd;
47 argc--; 43 int create = TRUE;
48 argv++;
49 44
50 /* Parse options */ 45 if (argc < 2) {
51 while (**argv == '-') { 46 usage(touch_usage);
52 while (*++(*argv)) switch (**argv) {
53 case 'c':
54 create = FALSE;
55 break;
56 default:
57 usage( touch_usage);
58 exit( FALSE);
59 } 47 }
60 argc--; 48 argc--;
61 argv++; 49 argv++;
62 }
63 50
64 fd = open (*argv, (create==FALSE)? O_RDWR : O_RDWR | O_CREAT, 0644); 51 /* Parse options */
65 if (fd < 0 ) { 52 while (**argv == '-') {
66 if (create==FALSE && errno == ENOENT) 53 while (*++(*argv))
67 exit( TRUE); 54 switch (**argv) {
68 else { 55 case 'c':
69 perror("touch"); 56 create = FALSE;
70 exit( FALSE); 57 break;
58 default:
59 usage(touch_usage);
60 exit(FALSE);
61 }
62 argc--;
63 argv++;
71 } 64 }
72 }
73 close( fd);
74 if (utime (*argv, NULL)) {
75 perror("touch");
76 exit( FALSE);
77 }
78 else
79 exit( TRUE);
80}
81
82
83
84
85
86 65
66 fd = open(*argv, (create == FALSE) ? O_RDWR : O_RDWR | O_CREAT, 0644);
67 if (fd < 0) {
68 if (create == FALSE && errno == ENOENT)
69 exit(TRUE);
70 else {
71 perror("touch");
72 exit(FALSE);
73 }
74 }
75 close(fd);
76 if (utime(*argv, NULL)) {
77 perror("touch");
78 exit(FALSE);
79 } else
80 exit(TRUE);
81}
diff --git a/true_false.c b/true_false.c
index eb9466b7b..7829673e0 100644
--- a/true_false.c
+++ b/true_false.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini true/false implementation for busybox 3 * Mini true/false implementation for busybox
3 * 4 *
@@ -24,15 +25,12 @@
24#include "internal.h" 25#include "internal.h"
25 26
26 27
27extern int 28extern int true_main(int argc, char **argv)
28true_main(int argc, char** argv)
29{ 29{
30 exit( TRUE); 30 exit(TRUE);
31} 31}
32 32
33extern int 33extern int false_main(int argc, char **argv)
34false_main(int argc, char** argv)
35{ 34{
36 exit( FALSE); 35 exit(FALSE);
37} 36}
38
diff --git a/tty.c b/tty.c
index 83abaffb5..8ac1c1fcd 100644
--- a/tty.c
+++ b/tty.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini tty implementation for busybox 3 * Mini tty implementation for busybox
3 * 4 *
@@ -24,19 +25,23 @@
24#include <sys/types.h> 25#include <sys/types.h>
25 26
26static const char tty_usage[] = "tty\n\n" 27static const char tty_usage[] = "tty\n\n"
27"Print the file name of the terminal connected to standard input.\n" 28 "Print the file name of the terminal connected to standard input.\n"
28"\t-s\tprint nothing, only return an exit status\n";
29 29
30extern int tty_main(int argc, char **argv) { 30 "\t-s\tprint nothing, only return an exit status\n";
31
32extern int tty_main(int argc, char **argv)
33{
31 char *tty; 34 char *tty;
32 35
33 if (argc > 1) { 36 if (argc > 1) {
34 if (argv[1][0] != '-' || argv[1][1] != 's') usage (tty_usage); 37 if (argv[1][0] != '-' || argv[1][1] != 's')
35 } 38 usage(tty_usage);
36 else { 39 } else {
37 tty = ttyname (0); 40 tty = ttyname(0);
38 if (tty) puts (tty); 41 if (tty)
39 else puts ("not a tty"); 42 puts(tty);
43 else
44 puts("not a tty");
40 } 45 }
41 exit (isatty (0) ? TRUE : FALSE); 46 exit(isatty(0) ? TRUE : FALSE);
42} 47}
diff --git a/umount.c b/umount.c
index b65caf76e..a2ca8c74a 100644
--- a/umount.c
+++ b/umount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini umount implementation for busybox 3 * Mini umount implementation for busybox
3 * 4 *
@@ -28,24 +29,23 @@
28#include <fstab.h> 29#include <fstab.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char umount_usage[] = 32static const char umount_usage[] =
32"umount [flags] filesystem|directory\n\n" 33 "umount [flags] filesystem|directory\n\n"
33"Flags:\n" 34 "Flags:\n" "\t-a:\tUnmount all file systems"
34"\t-a:\tUnmount all file systems"
35#ifdef BB_MTAB 35#ifdef BB_MTAB
36" in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n" 36 " in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n"
37#else 37#else
38"\n" 38 "\n"
39#endif 39#endif
40#ifdef BB_FEATURE_REMOUNT 40#ifdef BB_FEATURE_REMOUNT
41"\t-r:\tTry to remount devices as read-only if mount is busy\n" 41 "\t-r:\tTry to remount devices as read-only if mount is busy\n"
42#endif 42#endif
43; 43;
44 44
45struct _mtab_entry_t { 45struct _mtab_entry_t {
46 char *device; 46 char *device;
47 char *mountpt; 47 char *mountpt;
48 struct _mtab_entry_t *next; 48 struct _mtab_entry_t *next;
49}; 49};
50 50
51static struct _mtab_entry_t *mtab_cache = NULL; 51static struct _mtab_entry_t *mtab_cache = NULL;
@@ -55,113 +55,112 @@ static struct _mtab_entry_t *mtab_cache = NULL;
55static int useMtab = TRUE; 55static int useMtab = TRUE;
56static int umountAll = FALSE; 56static int umountAll = FALSE;
57static int doRemount = FALSE; 57static int doRemount = FALSE;
58extern const char mtab_file[]; /* Defined in utility.c */ 58extern const char mtab_file[]; /* Defined in utility.c */
59 59
60#define MIN(x,y) (x > y ? x : y) 60#define MIN(x,y) (x > y ? x : y)
61 61
62static int 62static int do_umount(const char *name, int useMtab)
63do_umount(const char* name, int useMtab)
64{ 63{
65 int status; 64 int status;
66 char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE); 65 char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
67 66
68 if (blockDevice && strcmp(blockDevice, name) == 0) 67 if (blockDevice && strcmp(blockDevice, name) == 0)
69 name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT); 68 name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
70 69
71 status = umount(name); 70 status = umount(name);
72 71
73#if defined BB_FEATURE_MOUNT_LOOP 72#if defined BB_FEATURE_MOUNT_LOOP
74 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) 73 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
75 /* this was a loop device, delete it */ 74 /* this was a loop device, delete it */
76 del_loop(blockDevice); 75 del_loop(blockDevice);
77#endif 76#endif
78#if defined BB_FEATURE_REMOUNT 77#if defined BB_FEATURE_REMOUNT
79 if ( status != 0 && doRemount == TRUE && errno == EBUSY ) { 78 if (status != 0 && doRemount == TRUE && errno == EBUSY) {
80 status = mount(blockDevice, name, NULL, 79 status = mount(blockDevice, name, NULL,
81 MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); 80 MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
82 if (status == 0) { 81 if (status == 0) {
83 fprintf(stderr, "umount: %s busy - remounted read-only\n", 82 fprintf(stderr, "umount: %s busy - remounted read-only\n",
84 blockDevice); 83 blockDevice);
85 /* TODO: update mtab if BB_MTAB is defined */ 84 /* TODO: update mtab if BB_MTAB is defined */
86 } else { 85 } else {
87 fprintf(stderr, "umount: Cannot remount %s read-only\n", 86 fprintf(stderr, "umount: Cannot remount %s read-only\n",
88 blockDevice); 87 blockDevice);
88 }
89 } 89 }
90 }
91#endif 90#endif
92 if ( status == 0 ) { 91 if (status == 0) {
93#if defined BB_MTAB 92#if defined BB_MTAB
94 if ( useMtab==TRUE ) 93 if (useMtab == TRUE)
95 erase_mtab(name); 94 erase_mtab(name);
96#endif 95#endif
97 return( TRUE); 96 return (TRUE);
98 } 97 }
99 return(FALSE); 98 return (FALSE);
100} 99}
101 100
102static int 101static int umount_all(int useMtab)
103umount_all(int useMtab)
104{ 102{
105 int status = TRUE; 103 int status = TRUE;
106 char *mountpt; 104 char *mountpt;
107 void *iter; 105 void *iter;
108 106
109 for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) { 107 for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
110 status=do_umount (mountpt, useMtab); 108 status = do_umount(mountpt, useMtab);
111 if (status != 0) {
112 /* Don't bother retrying the umount on busy devices */
113 if (errno == EBUSY) {
114 perror(mountpt);
115 continue;
116 }
117 status = do_umount (mountpt, useMtab);
118 if (status != 0) { 109 if (status != 0) {
119 printf ("Couldn't umount %s on %s: %s\n", 110 /* Don't bother retrying the umount on busy devices */
120 mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), strerror(errno)); 111 if (errno == EBUSY) {
112 perror(mountpt);
113 continue;
114 }
115 status = do_umount(mountpt, useMtab);
116 if (status != 0) {
117 printf("Couldn't umount %s on %s: %s\n",
118 mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
119 strerror(errno));
120 }
121 } 121 }
122 } 122 }
123 } 123 return (status);
124 return (status);
125} 124}
126 125
127extern int 126extern int umount_main(int argc, char **argv)
128umount_main(int argc, char** argv)
129{ 127{
130 if (argc < 2) { 128 if (argc < 2) {
131 usage( umount_usage); 129 usage(umount_usage);
132 } 130 }
133 131
134 /* Parse any options */ 132 /* Parse any options */
135 while (--argc > 0 && **(++argv) == '-') { 133 while (--argc > 0 && **(++argv) == '-') {
136 while (*++(*argv)) switch (**argv) { 134 while (*++(*argv))
137 case 'a': 135 switch (**argv) {
138 umountAll = TRUE; 136 case 'a':
139 break; 137 umountAll = TRUE;
138 break;
140#ifdef BB_MTAB 139#ifdef BB_MTAB
141 case 'n': 140 case 'n':
142 useMtab = FALSE; 141 useMtab = FALSE;
143 break; 142 break;
144#endif 143#endif
145#ifdef BB_FEATURE_REMOUNT 144#ifdef BB_FEATURE_REMOUNT
146 case 'r': 145 case 'r':
147 doRemount = TRUE; 146 doRemount = TRUE;
148 break; 147 break;
149#endif 148#endif
150 default: 149 default:
151 usage( umount_usage); 150 usage(umount_usage);
151 }
152 }
153
154 mtab_read();
155 if (umountAll == TRUE) {
156 exit(umount_all(useMtab));
157 }
158 if (do_umount(*argv, useMtab) == 0)
159 exit(TRUE);
160 else {
161 perror("umount");
162 exit(FALSE);
152 } 163 }
153 }
154
155 mtab_read();
156 if (umountAll==TRUE) {
157 exit(umount_all(useMtab));
158 }
159 if ( do_umount(*argv,useMtab) == 0 )
160 exit (TRUE);
161 else {
162 perror("umount");
163 exit(FALSE);
164 }
165} 164}
166 165
167 166
@@ -172,79 +171,89 @@ umount_main(int argc, char** argv)
172 */ 171 */
173void mtab_read(void) 172void mtab_read(void)
174{ 173{
175 struct _mtab_entry_t *entry = NULL; 174 struct _mtab_entry_t *entry = NULL;
176 struct mntent *e; 175 struct mntent *e;
177 FILE *fp; 176 FILE *fp;
178 177
179 if (mtab_cache != NULL) return; 178 if (mtab_cache != NULL)
180 179 return;
181 if ((fp = setmntent(mtab_file, "r")) == NULL) { 180
182 fprintf(stderr, "Cannot open %s\n", mtab_file); 181 if ((fp = setmntent(mtab_file, "r")) == NULL) {
183 return; 182 fprintf(stderr, "Cannot open %s\n", mtab_file);
184 } 183 return;
185 while ((e = getmntent(fp))) { 184 }
186 entry = malloc(sizeof(struct _mtab_entry_t)); 185 while ((e = getmntent(fp))) {
187 entry->device = strdup(e->mnt_fsname); 186 entry = malloc(sizeof(struct _mtab_entry_t));
188 entry->mountpt = strdup(e->mnt_dir); 187
189 entry->next = mtab_cache; 188 entry->device = strdup(e->mnt_fsname);
190 mtab_cache = entry; 189 entry->mountpt = strdup(e->mnt_dir);
191 } 190 entry->next = mtab_cache;
192 endmntent(fp); 191 mtab_cache = entry;
192 }
193 endmntent(fp);
193} 194}
194 195
195char *mtab_getinfo(const char *match, const char which) 196char *mtab_getinfo(const char *match, const char which)
196{ 197{
197 struct _mtab_entry_t *cur = mtab_cache; 198 struct _mtab_entry_t *cur = mtab_cache;
198 while (cur) { 199
199 if (strcmp(cur->mountpt, match) == 0 || 200 while (cur) {
200 strcmp(cur->device, match) == 0) { 201 if (strcmp(cur->mountpt, match) == 0 ||
201 if (which == MTAB_GETMOUNTPT) { 202 strcmp(cur->device, match) == 0) {
202 return cur->mountpt; 203 if (which == MTAB_GETMOUNTPT) {
203 } else { 204 return cur->mountpt;
205 } else {
204#if !defined BB_MTAB 206#if !defined BB_MTAB
205 if (strcmp(cur->device, "/dev/root") == 0) { 207 if (strcmp(cur->device, "/dev/root") == 0) {
206 struct fstab* fstabItem; 208 struct fstab *fstabItem;
207 fstabItem = getfsfile ("/"); 209
208 if (fstabItem != NULL) return fstabItem->fs_spec; 210 fstabItem = getfsfile("/");
209 } 211 if (fstabItem != NULL)
212 return fstabItem->fs_spec;
213 }
210#endif 214#endif
211 return cur->device; 215 return cur->device;
212 } 216 }
217 }
218 cur = cur->next;
213 } 219 }
214 cur = cur->next; 220 return NULL;
215 }
216 return NULL;
217} 221}
218 222
219char *mtab_first(void **iter) 223char *mtab_first(void **iter)
220{ 224{
221 struct _mtab_entry_t *mtab_iter; 225 struct _mtab_entry_t *mtab_iter;
222 if (!iter) return NULL; 226
223 mtab_iter = mtab_cache; 227 if (!iter)
224 *iter = (void *)mtab_iter; 228 return NULL;
225 return mtab_next(iter); 229 mtab_iter = mtab_cache;
230 *iter = (void *) mtab_iter;
231 return mtab_next(iter);
226} 232}
227 233
228char *mtab_next(void **iter) 234char *mtab_next(void **iter)
229{ 235{
230 char *mp; 236 char *mp;
231 if (iter == NULL || *iter == NULL) return NULL; 237
232 mp = ((struct _mtab_entry_t *)(*iter))->mountpt; 238 if (iter == NULL || *iter == NULL)
233 *iter = (void *)((struct _mtab_entry_t *)(*iter))->next; 239 return NULL;
234 return mp; 240 mp = ((struct _mtab_entry_t *) (*iter))->mountpt;
241 *iter = (void *) ((struct _mtab_entry_t *) (*iter))->next;
242 return mp;
235} 243}
236 244
237void mtab_free(void) 245void mtab_free(void)
238{ 246{
239 struct _mtab_entry_t *this, *next; 247 struct _mtab_entry_t *this, *next;
240
241 this = mtab_cache;
242 while (this) {
243 next = this->next;
244 if (this->device) free(this->device);
245 if (this->mountpt) free(this->mountpt);
246 free(this);
247 this = next;
248 }
249}
250 248
249 this = mtab_cache;
250 while (this) {
251 next = this->next;
252 if (this->device)
253 free(this->device);
254 if (this->mountpt)
255 free(this->mountpt);
256 free(this);
257 this = next;
258 }
259}
diff --git a/uname.c b/uname.c
index 9083edb04..9a1cb808a 100644
--- a/uname.c
+++ b/uname.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* uname -- print system information 2/* uname -- print system information
2 Copyright (C) 1989-1999 Free Software Foundation, Inc. 3 Copyright (C) 1989-1999 Free Software Foundation, Inc.
3 4
@@ -41,16 +42,17 @@
41 42
42 43
43static const char uname_usage[] = 44static const char uname_usage[] =
44 "uname [OPTION]...\n\n" 45 "uname [OPTION]...\n\n"
45 "Print certain system information. With no OPTION, same as -s.\n\n" 46 "Print certain system information. With no OPTION, same as -s.\n\n"
46 "Options:\n" 47 "Options:\n"
47 "\t-a\tprint all information\n" 48 "\t-a\tprint all information\n"
48 "\t-m\tthe machine (hardware) type\n" 49 "\t-m\tthe machine (hardware) type\n"
49 "\t-n\tprint the machine's network node hostname\n" 50 "\t-n\tprint the machine's network node hostname\n"
50 "\t-r\tprint the operating system release\n" 51 "\t-r\tprint the operating system release\n"
51 "\t-s\tprint the operating system name\n" 52 "\t-s\tprint the operating system name\n"
52 "\t-p\tprint the host processor type\n" 53
53 "\t-v\tprint the operating system version\n"; 54 "\t-p\tprint the host processor type\n"
55 "\t-v\tprint the operating system version\n";
54 56
55 57
56static void print_element(unsigned int mask, char *element); 58static void print_element(unsigned int mask, char *element);
@@ -80,77 +82,78 @@ static unsigned char toprint;
80 82
81int uname_main(int argc, char **argv) 83int uname_main(int argc, char **argv)
82{ 84{
83 struct utsname name; 85 struct utsname name;
84 char processor[256]; 86 char processor[256];
87
85#if defined(__sparc__) && defined(__linux__) 88#if defined(__sparc__) && defined(__linux__)
86 char *fake_sparc = getenv("FAKE_SPARC"); 89 char *fake_sparc = getenv("FAKE_SPARC");
87#endif 90#endif
88 91
89 toprint = 0; 92 toprint = 0;
90 93
91 /* Parse any options */ 94 /* Parse any options */
92 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); 95 //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv);
93 while (--argc > 0 && **(++argv) == '-') { 96 while (--argc > 0 && **(++argv) == '-') {
94 while (*(++(*argv))) { 97 while (*(++(*argv))) {
95 switch (**argv) { 98 switch (**argv) {
96 case 's': 99 case 's':
97 toprint |= PRINT_SYSNAME; 100 toprint |= PRINT_SYSNAME;
98 break; 101 break;
99 case 'n': 102 case 'n':
100 toprint |= PRINT_NODENAME; 103 toprint |= PRINT_NODENAME;
101 break; 104 break;
102 case 'r': 105 case 'r':
103 toprint |= PRINT_RELEASE; 106 toprint |= PRINT_RELEASE;
104 break; 107 break;
105 case 'v': 108 case 'v':
106 toprint |= PRINT_VERSION; 109 toprint |= PRINT_VERSION;
107 break; 110 break;
108 case 'm': 111 case 'm':
109 toprint |= PRINT_MACHINE; 112 toprint |= PRINT_MACHINE;
110 break; 113 break;
111 case 'p': 114 case 'p':
112 toprint |= PRINT_PROCESSOR; 115 toprint |= PRINT_PROCESSOR;
113 break; 116 break;
114 case 'a': 117 case 'a':
115 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE | 118 toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE |
116 PRINT_PROCESSOR | PRINT_VERSION | 119 PRINT_PROCESSOR | PRINT_VERSION |
117 PRINT_MACHINE); 120 PRINT_MACHINE);
118 break; 121 break;
119 default: 122 default:
120 usage(uname_usage); 123 usage(uname_usage);
121 } 124 }
125 }
122 } 126 }
123 }
124 127
125 if (toprint == 0) 128 if (toprint == 0)
126 toprint = PRINT_SYSNAME; 129 toprint = PRINT_SYSNAME;
127 130
128 if (uname(&name) == -1) 131 if (uname(&name) == -1)
129 perror("cannot get system name"); 132 perror("cannot get system name");
130 133
131#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE) 134#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE)
132 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1) 135 if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1)
133 perror("cannot get processor type"); 136 perror("cannot get processor type");
134} 137}
135 138
136#else 139#else
137 strcpy(processor, "unknown"); 140 strcpy(processor, "unknown");
138#endif 141#endif
139 142
140#if defined(__sparc__) && defined(__linux__) 143#if defined(__sparc__) && defined(__linux__)
141 if (fake_sparc != NULL 144 if (fake_sparc != NULL
142 && (fake_sparc[0] == 'y' 145 && (fake_sparc[0] == 'y'
143 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc"); 146 || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc");
144#endif 147#endif
145 148
146 print_element(PRINT_SYSNAME, name.sysname); 149 print_element(PRINT_SYSNAME, name.sysname);
147 print_element(PRINT_NODENAME, name.nodename); 150 print_element(PRINT_NODENAME, name.nodename);
148 print_element(PRINT_RELEASE, name.release); 151 print_element(PRINT_RELEASE, name.release);
149 print_element(PRINT_VERSION, name.version); 152 print_element(PRINT_VERSION, name.version);
150 print_element(PRINT_MACHINE, name.machine); 153 print_element(PRINT_MACHINE, name.machine);
151 print_element(PRINT_PROCESSOR, processor); 154 print_element(PRINT_PROCESSOR, processor);
152 155
153 exit(TRUE); 156 exit(TRUE);
154} 157}
155 158
156/* If the name element set in MASK is selected for printing in `toprint', 159/* If the name element set in MASK is selected for printing in `toprint',
@@ -159,8 +162,8 @@ int uname_main(int argc, char **argv)
159 162
160static void print_element(unsigned int mask, char *element) 163static void print_element(unsigned int mask, char *element)
161{ 164{
162 if (toprint & mask) { 165 if (toprint & mask) {
163 toprint &= ~mask; 166 toprint &= ~mask;
164 printf("%s%c", element, toprint ? ' ' : '\n'); 167 printf("%s%c", element, toprint ? ' ' : '\n');
165 } 168 }
166} 169}
diff --git a/uniq.c b/uniq.c
index 965d290c2..1e41eaacd 100644
--- a/uniq.c
+++ b/uniq.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini uniq implementation for busybox 3 * Mini uniq implementation for busybox
3 * 4 *
@@ -27,119 +28,116 @@
27#include <errno.h> 28#include <errno.h>
28 29
29static const char uniq_usage[] = 30static const char uniq_usage[] =
30"uniq [OPTION]... [INPUT [OUTPUT]]\n" 31 "uniq [OPTION]... [INPUT [OUTPUT]]\n"
31"Discard all but one of successive identical lines from INPUT (or\n" 32 "Discard all but one of successive identical lines from INPUT (or\n"
32"standard input), writing to OUTPUT (or standard output).\n" 33 "standard input), writing to OUTPUT (or standard output).\n"
33"\n" 34 "\n"
34"\t-h\tdisplay this help and exit\n" 35 "\t-h\tdisplay this help and exit\n"
35"\n" 36
36"A field is a run of whitespace, then non-whitespace characters.\n" 37 "\n"
37"Fields are skipped before chars.\n" 38 "A field is a run of whitespace, then non-whitespace characters.\n"
38; 39 "Fields are skipped before chars.\n";
39 40
40/* max chars in line */ 41/* max chars in line */
41#define UNIQ_MAX 4096 42#define UNIQ_MAX 4096
42 43
43typedef void (Print)(FILE *, const char *); 44typedef void (Print) (FILE *, const char *);
44 45
45typedef int (Decide)(const char *, const char *); 46typedef int (Decide) (const char *, const char *);
46 47
47/* container for two lines to be compared */ 48/* container for two lines to be compared */
48typedef struct { 49typedef struct {
49 char *a; 50 char *a;
50 char *b; 51 char *b;
51 int recurrence; 52 int recurrence;
52 FILE *in; 53 FILE *in;
53 FILE *out; 54 FILE *out;
54 void *func; 55 void *func;
55} Subject; 56} Subject;
56 57
57/* set up all the variables of a uniq operation */ 58/* set up all the variables of a uniq operation */
58static Subject * 59static Subject *subject_init(Subject * self, FILE * in, FILE * out,
59subject_init(Subject *self, FILE *in, FILE *out, void *func) 60 void *func)
60{ 61{
61 self->a = NULL; 62 self->a = NULL;
62 self->b = NULL; 63 self->b = NULL;
63 self->in = in; 64 self->in = in;
64 self->out = out; 65 self->out = out;
65 self->func = func; 66 self->func = func;
66 self->recurrence = 0; 67 self->recurrence = 0;
67 return self; 68 return self;
68} 69}
69 70
70/* point a and b to the appropriate lines; 71/* point a and b to the appropriate lines;
71 * count the recurrences (if any) of a string; 72 * count the recurrences (if any) of a string;
72 */ 73 */
73static Subject * 74static Subject *subject_next(Subject * self)
74subject_next(Subject *self)
75{ 75{
76 /* tmp line holders */ 76 /* tmp line holders */
77 static char line[2][UNIQ_MAX]; 77 static char line[2][UNIQ_MAX];
78 static int alternator = 0; 78 static int alternator = 0;
79 79
80 if (fgets(line[alternator], UNIQ_MAX, self->in)) { 80 if (fgets(line[alternator], UNIQ_MAX, self->in)) {
81 self->a = self->b; 81 self->a = self->b;
82 self->b = line[alternator]; 82 self->b = line[alternator];
83 alternator ^= 1; 83 alternator ^= 1;
84 return self; 84 return self;
85 } 85 }
86 86
87 return NULL; 87 return NULL;
88} 88}
89 89
90static Subject * 90static Subject *subject_last(Subject * self)
91subject_last(Subject *self)
92{ 91{
93 self->a = self->b; 92 self->a = self->b;
94 self->b = NULL; 93 self->b = NULL;
95 return self; 94 return self;
96} 95}
97 96
98static Subject * 97static Subject *subject_study(Subject * self)
99subject_study(Subject *self)
100{ 98{
101 if (self->a == NULL) { 99 if (self->a == NULL) {
102 return self; 100 return self;
103 } 101 }
104 if (self->b == NULL) { 102 if (self->b == NULL) {
105 fprintf(self->out, "%s", self->a); 103 fprintf(self->out, "%s", self->a);
104 return self;
105 }
106 if (strcmp(self->a, self->b) == 0) {
107 self->recurrence++;
108 } else {
109 fprintf(self->out, "%s", self->a);
110 self->recurrence = 0;
111 }
106 return self; 112 return self;
107 }
108 if (strcmp(self->a, self->b) == 0) {
109 self->recurrence++;
110 } else {
111 fprintf(self->out, "%s", self->a);
112 self->recurrence = 0;
113 }
114 return self;
115} 113}
116 114
117static int 115static int
118set_file_pointers(int schema, FILE **in, FILE **out, char **argv) 116set_file_pointers(int schema, FILE ** in, FILE ** out, char **argv)
119{ 117{
120 switch (schema) { 118 switch (schema) {
121 case 0: 119 case 0:
122 *in = stdin; 120 *in = stdin;
123 *out = stdout; 121 *out = stdout;
124 break; 122 break;
125 case 1: 123 case 1:
126 *in = fopen(argv[0], "r"); 124 *in = fopen(argv[0], "r");
127 *out = stdout; 125 *out = stdout;
128 break; 126 break;
129 case 2: 127 case 2:
130 *in = fopen(argv[0], "r"); 128 *in = fopen(argv[0], "r");
131 *out = fopen(argv[1], "w"); 129 *out = fopen(argv[1], "w");
132 break; 130 break;
133 } 131 }
134 if (*in == NULL) { 132 if (*in == NULL) {
135 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno)); 133 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno));
136 return errno; 134 return errno;
137 } 135 }
138 if (*out == NULL) { 136 if (*out == NULL) {
139 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno)); 137 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno));
140 return errno; 138 return errno;
141 } 139 }
142 return 0; 140 return 0;
143} 141}
144 142
145 143
@@ -152,45 +150,44 @@ set_file_pointers(int schema, FILE **in, FILE **out, char **argv)
152/* it seems like GNU/uniq only takes one or two files as an option */ 150/* it seems like GNU/uniq only takes one or two files as an option */
153 151
154/* ________________________________________________________________________ */ 152/* ________________________________________________________________________ */
155int 153int uniq_main(int argc, char **argv)
156uniq_main(int argc, char **argv)
157{ 154{
158 int i; 155 int i;
159 char opt; 156 char opt;
160 FILE *in, *out; 157 FILE *in, *out;
161 Subject s; 158 Subject s;
162 159
163 /* parse argv[] */ 160 /* parse argv[] */
164 for (i = 1; i < argc; i++) { 161 for (i = 1; i < argc; i++) {
165 if (argv[i][0] == '-') { 162 if (argv[i][0] == '-') {
166 opt = argv[i][1]; 163 opt = argv[i][1];
167 switch (opt) { 164 switch (opt) {
168 case '-': 165 case '-':
169 case 'h': 166 case 'h':
170 usage(uniq_usage); 167 usage(uniq_usage);
171 default: 168 default:
172 usage(uniq_usage); 169 usage(uniq_usage);
173 } 170 }
174 } else { 171 } else {
175 break; 172 break;
173 }
176 } 174 }
177 }
178 175
179 /* 0 src: stdin; dst: stdout */ 176 /* 0 src: stdin; dst: stdout */
180 /* 1 src: file; dst: stdout */ 177 /* 1 src: file; dst: stdout */
181 /* 2 src: file; dst: file */ 178 /* 2 src: file; dst: file */
182 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) { 179 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) {
183 exit(1); 180 exit(1);
184 } 181 }
185 182
186 subject_init(&s, in, out, NULL); 183 subject_init(&s, in, out, NULL);
187 while (subject_next(&s)) { 184 while (subject_next(&s)) {
185 subject_study(&s);
186 }
187 subject_last(&s);
188 subject_study(&s); 188 subject_study(&s);
189 }
190 subject_last(&s);
191 subject_study(&s);
192 189
193 exit(0); 190 exit(0);
194} 191}
195 192
196/* $Id: uniq.c,v 1.6 2000/02/07 05:29:42 erik Exp $ */ 193/* $Id: uniq.c,v 1.7 2000/02/08 19:58:47 erik Exp $ */
diff --git a/update.c b/update.c
index 5a7c755ff..fef188bba 100644
--- a/update.c
+++ b/update.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini update implementation for busybox 3 * Mini update implementation for busybox
3 * 4 *
@@ -27,20 +28,19 @@
27#include <sys/kdaemon.h> 28#include <sys/kdaemon.h>
28#else 29#else
29_syscall2(int, bdflush, int, func, int, data); 30_syscall2(int, bdflush, int, func, int, data);
30#endif /* __GLIBC__ */ 31#endif /* __GLIBC__ */
31 32
32extern int 33extern int update_main(int argc, char **argv)
33update_main(int argc, char** argv)
34{ 34{
35 /* 35 /*
36 * Update is actually two daemons, bdflush and update. 36 * Update is actually two daemons, bdflush and update.
37 */ 37 */
38 int pid; 38 int pid;
39 39
40 pid = fork(); 40 pid = fork();
41 if ( pid < 0 ) 41 if (pid < 0)
42 return pid; 42 return pid;
43 else if ( pid == 0 ) { 43 else if (pid == 0) {
44 /* 44 /*
45 * This is no longer necessary since 1.3.5x, but it will harmlessly 45 * This is no longer necessary since 1.3.5x, but it will harmlessly
46 * exit if that is the case. 46 * exit if that is the case.
@@ -52,11 +52,11 @@ update_main(int argc, char** argv)
52 _exit(0); 52 _exit(0);
53 } 53 }
54 pid = fork(); 54 pid = fork();
55 if ( pid < 0 ) 55 if (pid < 0)
56 return pid; 56 return pid;
57 else if ( pid == 0 ) { 57 else if (pid == 0) {
58 argv[0] = "update"; 58 argv[0] = "update";
59 for ( ; ; ) { 59 for (;;) {
60 sync(); 60 sync();
61 sleep(30); 61 sleep(30);
62 } 62 }
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index e38fd5555..bbed8221a 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* dmesg.c -- Print out the contents of the kernel ring buffer 2/* dmesg.c -- Print out the contents of the kernel ring buffer
2 * Created: Sat Oct 9 16:19:47 1993 3 * Created: Sat Oct 9 16:19:47 1993
3 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu 4 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu
@@ -24,8 +25,8 @@
24 25
25#ifndef __alpha__ 26#ifndef __alpha__
26# define __NR_klogctl __NR_syslog 27# define __NR_klogctl __NR_syslog
27 static inline _syscall3(int, klogctl, int, type, char *, b, int, len); 28static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
28#else /* __alpha__ */ 29#else /* __alpha__ */
29#define klogctl syslog 30#define klogctl syslog
30#endif 31#endif
31 32
@@ -35,90 +36,91 @@
35 36
36static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n"; 37static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n";
37 38
38int dmesg_main( int argc, char** argv ) 39int dmesg_main(int argc, char **argv)
39{ 40{
40 char *buf; 41 char *buf;
41 int bufsize=8196; 42 int bufsize = 8196;
42 int i; 43 int i;
43 int n; 44 int n;
44 int level = 0; 45 int level = 0;
45 int lastc; 46 int lastc;
46 int cmd = 3; 47 int cmd = 3;
47 int stopDoingThat; 48 int stopDoingThat;
48 49
49 argc--; 50 argc--;
50 argv++; 51 argv++;
51 52
52 /* Parse any options */ 53 /* Parse any options */
53 while (argc && **argv == '-') { 54 while (argc && **argv == '-') {
54 stopDoingThat = FALSE; 55 stopDoingThat = FALSE;
55 while (stopDoingThat == FALSE && *++(*argv)) { 56 while (stopDoingThat == FALSE && *++(*argv)) {
56 switch (**argv) { 57 switch (**argv) {
57 case 'c': 58 case 'c':
58 cmd = 4; 59 cmd = 4;
59 break; 60 break;
60 case 'n': 61 case 'n':
61 cmd = 8; 62 cmd = 8;
62 if (--argc == 0) 63 if (--argc == 0)
63 goto end; 64 goto end;
64 level = atoi (*(++argv)); 65 level = atoi(*(++argv));
65 if (--argc > 0) 66 if (--argc > 0)
66 ++argv; 67 ++argv;
67 stopDoingThat = TRUE; 68 stopDoingThat = TRUE;
68 break; 69 break;
69 case 's': 70 case 's':
70 if (--argc == 0) 71 if (--argc == 0)
71 goto end; 72 goto end;
72 bufsize = atoi (*(++argv)); 73 bufsize = atoi(*(++argv));
73 if (--argc > 0) 74 if (--argc > 0)
74 ++argv; 75 ++argv;
75 stopDoingThat = TRUE; 76 stopDoingThat = TRUE;
76 break; 77 break;
77 default: 78 default:
79 goto end;
80 }
81 }
82 }
83
84 if (argc > 1) {
78 goto end; 85 goto end;
79 }
80 } 86 }
81 }
82
83 if (argc > 1) {
84 goto end;
85 }
86 87
87 if (cmd == 8) { 88 if (cmd == 8) {
88 n = klogctl( cmd, NULL, level ); 89 n = klogctl(cmd, NULL, level);
89 if (n < 0) { 90 if (n < 0) {
90 goto klogctl_error; 91 goto klogctl_error;
91 } 92 }
92 exit( TRUE ); 93 exit(TRUE);
93 } 94 }
94 95
95 if (bufsize < 4096) bufsize = 4096; 96 if (bufsize < 4096)
96 buf = (char*)malloc(bufsize); 97 bufsize = 4096;
97 n = klogctl( cmd, buf, bufsize ); 98 buf = (char *) malloc(bufsize);
98 if (n < 0) { 99 n = klogctl(cmd, buf, bufsize);
99 goto klogctl_error; 100 if (n < 0) {
100 } 101 goto klogctl_error;
102 }
101 103
102 lastc = '\n'; 104 lastc = '\n';
103 for (i = 0; i < n; i++) { 105 for (i = 0; i < n; i++) {
104 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 106 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
105 i++; 107 i++;
106 while (buf[i] >= '0' && buf[i] <= '9') 108 while (buf[i] >= '0' && buf[i] <= '9')
107 i++; 109 i++;
108 if (buf[i] == '>') 110 if (buf[i] == '>')
109 i++; 111 i++;
110 } 112 }
111 lastc = buf[i]; 113 lastc = buf[i];
112 putchar( lastc ); 114 putchar(lastc);
113 } 115 }
114 if (lastc != '\n') 116 if (lastc != '\n')
115 putchar( '\n' ); 117 putchar('\n');
116 exit( TRUE); 118 exit(TRUE);
117end: 119 end:
118 usage( dmesg_usage); 120 usage(dmesg_usage);
119 exit (FALSE); 121 exit(FALSE);
120klogctl_error: 122 klogctl_error:
121 perror( "klogctl" ); 123 perror("klogctl");
122 exit( FALSE ); 124 exit(FALSE);
123 125
124} 126}
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index c29145e51..a75e431db 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini fbset implementation for busybox 3 * Mini fbset implementation for busybox
3 * 4 *
@@ -48,7 +49,7 @@
48#define OPT_READMODE (1 << 2) 49#define OPT_READMODE (1 << 2)
49 50
50#define CMD_HELP 0 51#define CMD_HELP 0
51#define CMD_FB 1 52#define CMD_FB 1
52#define CMD_DB 2 53#define CMD_DB 2
53#define CMD_GEOMETRY 3 54#define CMD_GEOMETRY 3
54#define CMD_TIMING 4 55#define CMD_TIMING 4
@@ -87,213 +88,242 @@
87static unsigned int g_options = 0; 88static unsigned int g_options = 0;
88 89
89struct cmdoptions_t { 90struct cmdoptions_t {
90 char *name; 91 char *name;
91 unsigned char param_count; 92 unsigned char param_count;
92 unsigned char code; 93 unsigned char code;
93} g_cmdoptions[] = { 94} g_cmdoptions[] = {
94 { "-h", 0, CMD_HELP }, 95 {
95 { "-fb", 1, CMD_FB }, 96 "-h", 0, CMD_HELP}, {
96 { "-db", 1, CMD_DB }, 97 "-fb", 1, CMD_FB}, {
97 { "-a", 0, CMD_ALL }, 98 "-db", 1, CMD_DB}, {
98 { "-i", 0, CMD_INFO }, 99 "-a", 0, CMD_ALL}, {
99 { "-g", 5, CMD_GEOMETRY }, 100 "-i", 0, CMD_INFO}, {
100 { "-t", 7, CMD_TIMING }, 101 "-g", 5, CMD_GEOMETRY}, {
101 { "-accel", 1, CMD_ACCEL }, 102 "-t", 7, CMD_TIMING}, {
102 { "-hsync", 1, CMD_HSYNC }, 103 "-accel", 1, CMD_ACCEL}, {
103 { "-vsync", 1, CMD_VSYNC }, 104 "-hsync", 1, CMD_HSYNC}, {
104 { "-laced", 1, CMD_LACED }, 105 "-vsync", 1, CMD_VSYNC}, {
105 { "-double", 1, CMD_DOUBLE }, 106 "-laced", 1, CMD_LACED}, {
106 107 "-double", 1, CMD_DOUBLE},
107#ifdef BB_FBSET_FANCY 108#ifdef BB_FBSET_FANCY
108 { "--help", 0, CMD_HELP }, 109 {
109 { "-all", 0, CMD_ALL }, 110 "--help", 0, CMD_HELP}, {
110 { "-xres", 1, CMD_XRES }, 111 "-all", 0, CMD_ALL}, {
111 { "-yres", 1, CMD_YRES }, 112 "-xres", 1, CMD_XRES}, {
112 { "-vxres", 1, CMD_VXRES }, 113 "-yres", 1, CMD_YRES}, {
113 { "-vyres", 1, CMD_VYRES }, 114 "-vxres", 1, CMD_VXRES}, {
114 { "-depth", 1, CMD_DEPTH }, 115 "-vyres", 1, CMD_VYRES}, {
115 { "-match", 0, CMD_MATCH }, 116 "-depth", 1, CMD_DEPTH}, {
116 { "--geometry", 5, CMD_GEOMETRY }, 117 "-match", 0, CMD_MATCH}, {
117 118 "--geometry", 5, CMD_GEOMETRY}, {
118 { "-pixclock", 1, CMD_PIXCLOCK }, 119 "-pixclock", 1, CMD_PIXCLOCK}, {
119 { "-left", 1, CMD_LEFT }, 120 "-left", 1, CMD_LEFT}, {
120 { "-right", 1, CMD_RIGHT }, 121 "-right", 1, CMD_RIGHT}, {
121 { "-upper", 1, CMD_UPPER }, 122 "-upper", 1, CMD_UPPER}, {
122 { "-lower", 1, CMD_LOWER }, 123 "-lower", 1, CMD_LOWER}, {
123 { "-hslen", 1, CMD_HSLEN }, 124 "-hslen", 1, CMD_HSLEN}, {
124 { "-vslen", 1, CMD_VSLEN }, 125 "-vslen", 1, CMD_VSLEN}, {
125 { "--timings", 7, CMD_TIMING }, 126 "--timings", 7, CMD_TIMING}, {
126 127 "-csync", 1, CMD_CSYNC}, {
127 { "-csync", 1, CMD_CSYNC }, 128 "-gsync", 1, CMD_GSYNC}, {
128 { "-gsync", 1, CMD_GSYNC }, 129 "-extsync", 1, CMD_EXTSYNC}, {
129 { "-extsync", 1, CMD_EXTSYNC }, 130 "-bcast", 1, CMD_BCAST}, {
130 { "-bcast", 1, CMD_BCAST }, 131 "-rgba", 1, CMD_RGBA}, {
131 { "-rgba", 1, CMD_RGBA }, 132 "-step", 1, CMD_STEP}, {
132 { "-step", 1, CMD_STEP }, 133 "-move", 1, CMD_MOVE},
133 { "-move", 1, CMD_MOVE },
134#endif 134#endif
135 { 0, 0, 0 } 135 {
136 0, 0, 0}
136}; 137};
137 138
138static int readmode(struct fb_var_screeninfo *base, const char *fn, 139static int readmode(struct fb_var_screeninfo *base, const char *fn,
139 const char *mode) 140 const char *mode)
140{ 141{
141#ifdef BB_FBSET_READMODE 142#ifdef BB_FBSET_READMODE
142 FILE *f; 143 FILE *f;
143 char buf[256]; 144 char buf[256];
144 char *p = buf; 145 char *p = buf;
145 146
146 if ((f = fopen(fn, "r")) == NULL) PERROR("readmode(fopen)"); 147 if ((f = fopen(fn, "r")) == NULL)
147 while (!feof(f)) { 148 PERROR("readmode(fopen)");
148 fgets(buf, sizeof(buf), f); 149 while (!feof(f)) {
149 if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { 150 fgets(buf, sizeof(buf), f);
150 p += 5; 151 if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) {
151 if ((p = strstr(buf, mode))) { 152 p += 5;
152 p += strlen(mode); 153 if ((p = strstr(buf, mode))) {
153 if (!isspace(*p) && (*p != 0) && (*p != '"') && (*p != '\r') 154 p += strlen(mode);
154 && (*p != '\n')) continue; /* almost, but not quite */ 155 if (!isspace(*p) && (*p != 0) && (*p != '"')
155 while (!feof(f)) { 156 && (*p != '\r') && (*p != '\n'))
156 fgets(buf, sizeof(buf), f); 157 continue; /* almost, but not quite */
157 if (!strstr(buf, "endmode")) return 1; 158 while (!feof(f)) {
159 fgets(buf, sizeof(buf), f);
160 if (!strstr(buf, "endmode"))
161 return 1;
162 }
163 }
158 } 164 }
159 }
160 } 165 }
161 }
162#else 166#else
163 fprintf(stderr, "W: mode reading was disabled on this copy of fbset; ignoring request\n"); 167 fprintf(stderr,
168 "W: mode reading was disabled on this copy of fbset; ignoring request\n");
164#endif 169#endif
165 return 0; 170 return 0;
166} 171}
167 172
168static void setmode(struct fb_var_screeninfo *base, 173static void setmode(struct fb_var_screeninfo *base,
169 struct fb_var_screeninfo *set) 174 struct fb_var_screeninfo *set)
170{ 175{
171 if ((int)set->xres > 0) base->xres = set->xres; 176 if ((int) set->xres > 0)
172 if ((int)set->yres > 0) base->yres = set->yres; 177 base->xres = set->xres;
173 if ((int)set->xres_virtual > 0) base->xres_virtual = set->xres_virtual; 178 if ((int) set->yres > 0)
174 if ((int)set->yres_virtual > 0) base->yres_virtual = set->yres_virtual; 179 base->yres = set->yres;
175 if ((int)set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel; 180 if ((int) set->xres_virtual > 0)
181 base->xres_virtual = set->xres_virtual;
182 if ((int) set->yres_virtual > 0)
183 base->yres_virtual = set->yres_virtual;
184 if ((int) set->bits_per_pixel > 0)
185 base->bits_per_pixel = set->bits_per_pixel;
176} 186}
177 187
178static void showmode(struct fb_var_screeninfo *v) 188static void showmode(struct fb_var_screeninfo *v)
179{ 189{
180 double drate = 0, hrate = 0, vrate = 0; 190 double drate = 0, hrate = 0, vrate = 0;
181 if (v->pixclock) { 191
182 drate = 1e12 / v->pixclock; 192 if (v->pixclock) {
183 hrate = drate / (v->left_margin+v->xres+v->right_margin+v->hsync_len); 193 drate = 1e12 / v->pixclock;
184 vrate = hrate / (v->upper_margin+v->yres+v->lower_margin+v->vsync_len); 194 hrate =
185 } 195 drate / (v->left_margin + v->xres + v->right_margin +
186 printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int)(vrate+0.5)); 196 v->hsync_len);
197 vrate =
198 hrate / (v->upper_margin + v->yres + v->lower_margin +
199 v->vsync_len);
200 }
201 printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5));
187#ifdef BB_FBSET_FANCY 202#ifdef BB_FBSET_FANCY
188 printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate/1e6, hrate/1e3, 203 printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6,
189 vrate); 204 hrate / 1e3, vrate);
190#endif 205#endif
191 printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, 206 printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres,
192 v->xres_virtual, v->yres_virtual, v->bits_per_pixel); 207 v->xres_virtual, v->yres_virtual, v->bits_per_pixel);
193#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 208#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
194 printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, 209 printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin,
195 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, 210 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len,
196 v->vsync_len); 211 v->vsync_len);
197 printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); 212 printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false"));
198#else 213#else
199 printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock, v->left_margin, 214 printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock,
200 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, 215 v->left_margin, v->right_margin, v->upper_margin,
201 v->vsync_len); 216 v->lower_margin, v->hsync_len, v->vsync_len);
202#endif 217#endif
203 printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, v->red.offset, 218 printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length,
204 v->green.length, v->green.offset, v->blue.length, v->blue.offset, 219 v->red.offset, v->green.length, v->green.offset, v->blue.length,
205 v->transp.length, v->transp.offset); 220 v->blue.offset, v->transp.length, v->transp.offset);
206 printf("endmode\n"); 221 printf("endmode\n");
207} 222}
208 223
209static void fbset_usage(void) 224static void fbset_usage(void)
210{ 225{
211 int i; 226 int i;
227
212#ifndef STANDALONE 228#ifndef STANDALONE
213 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 229 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
230 BB_VER, BB_BT);
214#endif 231#endif
215 fprintf(stderr, "Usage: fbset [options] [mode]\n"); 232 fprintf(stderr, "Usage: fbset [options] [mode]\n");
216 fprintf(stderr, "\tThe following options are recognized:\n"); 233 fprintf(stderr, "\tThe following options are recognized:\n");
217 for (i = 0; g_cmdoptions[i].name; i++) 234 for (i = 0; g_cmdoptions[i].name; i++)
218 fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name); 235 fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name);
219 exit(-1); 236 exit(-1);
220} 237}
221 238
222#ifdef STANDALONE 239#ifdef STANDALONE
223int main(int argc, char **argv) 240int main(int argc, char **argv)
224#else 241#else
225extern int fbset_main(int argc, char **argv) 242extern int fbset_main(int argc, char **argv)
226#endif 243#endif
227{ 244{
228 struct fb_var_screeninfo var, varset; 245 struct fb_var_screeninfo var, varset;
229 int fh, i; 246 int fh, i;
230 char *fbdev = DEFAULTFBDEV; 247 char *fbdev = DEFAULTFBDEV;
231 char *modefile = DEFAULTFBMODE; 248 char *modefile = DEFAULTFBMODE;
232 char *thisarg, *mode = NULL; 249 char *thisarg, *mode = NULL;
250
251 memset(&varset, 0xFF, sizeof(varset));
233 252
234 memset(&varset, 0xFF, sizeof(varset)); 253 /* parse cmd args.... why do they have to make things so difficult? */
235 254 argv++;
236 /* parse cmd args.... why do they have to make things so difficult? */ 255 argc--;
237 argv++; argc--; 256 for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
238 for (; argc > 0 && (thisarg = *argv); argc--, argv++) { 257 for (i = 0; g_cmdoptions[i].name; i++) {
239 for (i = 0; g_cmdoptions[i].name; i++) { 258 if (!strcmp(thisarg, g_cmdoptions[i].name)) {
240 if (!strcmp(thisarg, g_cmdoptions[i].name)) { 259 if (argc - 1 < g_cmdoptions[i].param_count)
241 if (argc - 1 < g_cmdoptions[i].param_count) fbset_usage(); 260 fbset_usage();
242 switch (g_cmdoptions[i].code) { 261 switch (g_cmdoptions[i].code) {
243 case CMD_HELP: fbset_usage(); 262 case CMD_HELP:
244 case CMD_FB: fbdev = argv[1]; break; 263 fbset_usage();
245 case CMD_DB: modefile = argv[1]; break; 264 case CMD_FB:
246 case CMD_GEOMETRY: 265 fbdev = argv[1];
247 varset.xres = strtoul(argv[1],0,0); 266 break;
248 varset.yres = strtoul(argv[2],0,0); 267 case CMD_DB:
249 varset.xres_virtual = strtoul(argv[3],0,0); 268 modefile = argv[1];
250 varset.yres_virtual = strtoul(argv[4],0,0); 269 break;
251 varset.bits_per_pixel = strtoul(argv[5],0,0); 270 case CMD_GEOMETRY:
252 break; 271 varset.xres = strtoul(argv[1], 0, 0);
253 case CMD_TIMING: 272 varset.yres = strtoul(argv[2], 0, 0);
254 varset.pixclock = strtoul(argv[1],0,0); 273 varset.xres_virtual = strtoul(argv[3], 0, 0);
255 varset.left_margin = strtoul(argv[2],0,0); 274 varset.yres_virtual = strtoul(argv[4], 0, 0);
256 varset.right_margin = strtoul(argv[3],0,0); 275 varset.bits_per_pixel = strtoul(argv[5], 0, 0);
257 varset.upper_margin = strtoul(argv[4],0,0); 276 break;
258 varset.lower_margin = strtoul(argv[5],0,0); 277 case CMD_TIMING:
259 varset.hsync_len = strtoul(argv[6],0,0); 278 varset.pixclock = strtoul(argv[1], 0, 0);
260 varset.vsync_len = strtoul(argv[7],0,0); 279 varset.left_margin = strtoul(argv[2], 0, 0);
261 break; 280 varset.right_margin = strtoul(argv[3], 0, 0);
281 varset.upper_margin = strtoul(argv[4], 0, 0);
282 varset.lower_margin = strtoul(argv[5], 0, 0);
283 varset.hsync_len = strtoul(argv[6], 0, 0);
284 varset.vsync_len = strtoul(argv[7], 0, 0);
285 break;
262#ifdef BB_FBSET_FANCY 286#ifdef BB_FBSET_FANCY
263 case CMD_XRES: varset.xres = strtoul(argv[1],0,0); break; 287 case CMD_XRES:
264 case CMD_YRES: varset.yres = strtoul(argv[1],0,0); break; 288 varset.xres = strtoul(argv[1], 0, 0);
289 break;
290 case CMD_YRES:
291 varset.yres = strtoul(argv[1], 0, 0);
292 break;
265#endif 293#endif
294 }
295 argc -= g_cmdoptions[i].param_count;
296 argv += g_cmdoptions[i].param_count;
297 break;
298 }
299 }
300 if (!g_cmdoptions[i].name) {
301 if (argc == 1) {
302 mode = *argv;
303 g_options |= OPT_READMODE;
304 } else {
305 fbset_usage();
306 }
266 } 307 }
267 argc -= g_cmdoptions[i].param_count;
268 argv += g_cmdoptions[i].param_count;
269 break;
270 }
271 }
272 if (!g_cmdoptions[i].name) {
273 if (argc == 1) {
274 mode = *argv;
275 g_options |= OPT_READMODE;
276 } else {
277 fbset_usage();
278 }
279 } 308 }
280 }
281 309
282 if ((fh = open(fbdev, O_RDONLY)) < 0) PERROR("fbset(open)"); 310 if ((fh = open(fbdev, O_RDONLY)) < 0)
283 if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); 311 PERROR("fbset(open)");
284 if (g_options & OPT_READMODE) { 312 if (ioctl(fh, FBIOGET_VSCREENINFO, &var))
285 if (!readmode(&var, modefile, mode)) { 313 PERROR("fbset(ioctl)");
286 fprintf(stderr, "Unknown video mode `%s'\n", mode); 314 if (g_options & OPT_READMODE) {
287 exit(1); 315 if (!readmode(&var, modefile, mode)) {
316 fprintf(stderr, "Unknown video mode `%s'\n", mode);
317 exit(1);
318 }
288 } 319 }
289 }
290 320
291 setmode(&var, &varset); 321 setmode(&var, &varset);
292 if (g_options & OPT_CHANGE) 322 if (g_options & OPT_CHANGE)
293 if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); 323 if (ioctl(fh, FBIOPUT_VSCREENINFO, &var))
294 showmode(&var); 324 PERROR("fbset(ioctl)");
295 close(fh); 325 showmode(&var);
296 326 close(fh);
297 return(TRUE);
298}
299 327
328 return (TRUE);
329}
diff --git a/util-linux/fdflush.c b/util-linux/fdflush.c
index a244e8def..0b154c8a6 100644
--- a/util-linux/fdflush.c
+++ b/util-linux/fdflush.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini fdflush implementation for busybox 3 * Mini fdflush implementation for busybox
3 * 4 *
@@ -29,24 +30,25 @@
29 30
30extern int fdflush_main(int argc, char **argv) 31extern int fdflush_main(int argc, char **argv)
31{ 32{
32 int value; 33 int value;
33 int fd; 34 int fd;
34 if ( argc <= 1 || **(argv++) == '-' ) {
35 usage( "fdflush device\n");
36 }
37 35
38 fd = open(*argv, 0); 36 if (argc <= 1 || **(argv++) == '-') {
39 if ( fd < 0 ) { 37 usage("fdflush device\n");
40 perror(*argv); 38 }
41 exit(FALSE);
42 }
43 39
44 value = ioctl(fd, FDFLUSH, 0); 40 fd = open(*argv, 0);
45 close(fd); 41 if (fd < 0) {
42 perror(*argv);
43 exit(FALSE);
44 }
46 45
47 if ( value ) { 46 value = ioctl(fd, FDFLUSH, 0);
48 perror(*argv); 47 close(fd);
49 exit(FALSE); 48
50 } 49 if (value) {
51 exit (TRUE); 50 perror(*argv);
51 exit(FALSE);
52 }
53 exit(TRUE);
52} 54}
diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c
index 09111c5dc..084c76d36 100644
--- a/util-linux/fsck_minix.c
+++ b/util-linux/fsck_minix.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * fsck.c - a file system consistency checker for Linux. 3 * fsck.c - a file system consistency checker for Linux.
3 * 4 *
@@ -96,7 +97,7 @@
96#include <termios.h> 97#include <termios.h>
97#include <mntent.h> 98#include <mntent.h>
98#include <sys/stat.h> 99#include <sys/stat.h>
99#include <sys/param.h> /* for PATH_MAX */ 100#include <sys/param.h> /* for PATH_MAX */
100 101
101#include <linux/fs.h> 102#include <linux/fs.h>
102#include <linux/minix_fs.h> 103#include <linux/minix_fs.h>
@@ -124,17 +125,17 @@
124 125
125#define BITS_PER_BLOCK (BLOCK_SIZE<<3) 126#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
126 127
127static char * program_name = "fsck.minix"; 128static char *program_name = "fsck.minix";
128static char * program_version = "1.2 - 11/11/96"; 129static char *program_version = "1.2 - 11/11/96";
129static char * device_name = NULL; 130static char *device_name = NULL;
130static int IN; 131static int IN;
131static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0, 132static int repair = 0, automatic = 0, verbose = 0, list = 0, show =
132 force=0; 133 0, warn_mode = 0, force = 0;
133static int directory=0, regular=0, blockdev=0, chardev=0, links=0, 134static int directory = 0, regular = 0, blockdev = 0, chardev = 0, links =
134 symlinks=0, total=0; 135 0, symlinks = 0, total = 0;
135 136
136static int changed = 0; /* flags if the filesystem has been changed */ 137static int changed = 0; /* flags if the filesystem has been changed */
137static int errors_uncorrected = 0; /* flag if some error was not corrected */ 138static int errors_uncorrected = 0; /* flag if some error was not corrected */
138static int dirsize = 16; 139static int dirsize = 16;
139static int namelen = 14; 140static int namelen = 14;
140static int version2 = 0; 141static int version2 = 0;
@@ -146,10 +147,12 @@ static int termios_set = 0;
146static int name_depth = 0; 147static int name_depth = 0;
147static char name_list[MAX_DEPTH][PATH_MAX + 1]; 148static char name_list[MAX_DEPTH][PATH_MAX + 1];
148 149
149static char * inode_buffer = NULL; 150static char *inode_buffer = NULL;
151
150#define Inode (((struct minix_inode *) inode_buffer)-1) 152#define Inode (((struct minix_inode *) inode_buffer)-1)
151#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 153#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
152static char super_block_buffer[BLOCK_SIZE]; 154static char super_block_buffer[BLOCK_SIZE];
155
153#define Super (*(struct minix_super_block *)super_block_buffer) 156#define Super (*(struct minix_super_block *)super_block_buffer)
154#define INODES ((unsigned long)Super.s_ninodes) 157#define INODES ((unsigned long)Super.s_ninodes)
155#ifdef HAVE_MINIX2 158#ifdef HAVE_MINIX2
@@ -168,8 +171,8 @@ static char super_block_buffer[BLOCK_SIZE];
168static char *inode_map; 171static char *inode_map;
169static char *zone_map; 172static char *zone_map;
170 173
171static unsigned char * inode_count = NULL; 174static unsigned char *inode_count = NULL;
172static unsigned char * zone_count = NULL; 175static unsigned char *zone_count = NULL;
173 176
174static void recursive_check(unsigned int ino); 177static void recursive_check(unsigned int ino);
175static void recursive_check2(unsigned int ino); 178static void recursive_check2(unsigned int ino);
@@ -191,22 +194,27 @@ static void leave(int status)
191 exit(status); 194 exit(status);
192} 195}
193 196
194static void show_usage(void) { 197static void show_usage(void)
195 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 198{
199 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
200 BB_VER, BB_BT);
196 fprintf(stderr, "Usage: %s [-larvsmf] /dev/name\n\n", program_name); 201 fprintf(stderr, "Usage: %s [-larvsmf] /dev/name\n\n", program_name);
197 fprintf(stderr, "Performs a consistency check for MINIX filesystems.\n\n"); 202 fprintf(stderr,
203 "Performs a consistency check for MINIX filesystems.\n\n");
198 fprintf(stderr, "OPTIONS:\n"); 204 fprintf(stderr, "OPTIONS:\n");
199 fprintf(stderr, "\t-l\tLists all filenames\n"); 205 fprintf(stderr, "\t-l\tLists all filenames\n");
200 fprintf(stderr, "\t-r\tPerform interactive repairs\n"); 206 fprintf(stderr, "\t-r\tPerform interactive repairs\n");
201 fprintf(stderr, "\t-a\tPerform automatic repairs\n"); 207 fprintf(stderr, "\t-a\tPerform automatic repairs\n");
202 fprintf(stderr, "\t-v\tverbose\n"); 208 fprintf(stderr, "\t-v\tverbose\n");
203 fprintf(stderr, "\t-s\tOutputs super-block information\n"); 209 fprintf(stderr, "\t-s\tOutputs super-block information\n");
204 fprintf(stderr, "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n"); 210 fprintf(stderr,
211 "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n");
205 fprintf(stderr, "\t-f\tForce file system check.\n\n"); 212 fprintf(stderr, "\t-f\tForce file system check.\n\n");
206 leave(16); 213 leave(16);
207} 214}
208 215
209static void die(const char *str) { 216static void die(const char *str)
217{
210 fprintf(stderr, "%s: %s\n", program_name, str); 218 fprintf(stderr, "%s: %s\n", program_name, str);
211 leave(8); 219 leave(8);
212} 220}
@@ -217,15 +225,15 @@ static void die(const char *str) {
217 */ 225 */
218static void print_current_name(void) 226static void print_current_name(void)
219{ 227{
220 int i=0; 228 int i = 0;
221 229
222 while (i<name_depth) 230 while (i < name_depth)
223 printf("/%.*s",namelen,name_list[i++]); 231 printf("/%.*s", namelen, name_list[i++]);
224 if (i == 0) 232 if (i == 0)
225 printf ("/"); 233 printf("/");
226} 234}
227 235
228static int ask(const char * string, int def) 236static int ask(const char *string, int def)
229{ 237{
230 int c; 238 int c;
231 239
@@ -237,18 +245,18 @@ static int ask(const char * string, int def)
237 if (automatic) { 245 if (automatic) {
238 printf("\n"); 246 printf("\n");
239 if (!def) 247 if (!def)
240 errors_uncorrected = 1; 248 errors_uncorrected = 1;
241 return def; 249 return def;
242 } 250 }
243 printf(def?"%s (y/n)? ":"%s (n/y)? ",string); 251 printf(def ? "%s (y/n)? " : "%s (n/y)? ", string);
244 for (;;) { 252 for (;;) {
245 fflush(stdout); 253 fflush(stdout);
246 if ((c=getchar())==EOF) { 254 if ((c = getchar()) == EOF) {
247 if (!def) 255 if (!def)
248 errors_uncorrected = 1; 256 errors_uncorrected = 1;
249 return def; 257 return def;
250 } 258 }
251 c=toupper(c); 259 c = toupper(c);
252 if (c == 'Y') { 260 if (c == 'Y') {
253 def = 1; 261 def = 1;
254 break; 262 break;
@@ -263,7 +271,7 @@ static int ask(const char * string, int def)
263 else { 271 else {
264 printf("n\n"); 272 printf("n\n");
265 errors_uncorrected = 1; 273 errors_uncorrected = 1;
266 } 274 }
267 return def; 275 return def;
268} 276}
269 277
@@ -274,17 +282,17 @@ static int ask(const char * string, int def)
274 */ 282 */
275static void check_mount(void) 283static void check_mount(void)
276{ 284{
277 FILE * f; 285 FILE *f;
278 struct mntent * mnt; 286 struct mntent *mnt;
279 int cont; 287 int cont;
280 int fd; 288 int fd;
281 289
282 if ((f = setmntent (MOUNTED, "r")) == NULL) 290 if ((f = setmntent(MOUNTED, "r")) == NULL)
283 return; 291 return;
284 while ((mnt = getmntent (f)) != NULL) 292 while ((mnt = getmntent(f)) != NULL)
285 if (strcmp (device_name, mnt->mnt_fsname) == 0) 293 if (strcmp(device_name, mnt->mnt_fsname) == 0)
286 break; 294 break;
287 endmntent (f); 295 endmntent(f);
288 if (!mnt) 296 if (!mnt)
289 return; 297 return;
290 298
@@ -298,15 +306,15 @@ static void check_mount(void)
298 return; 306 return;
299 else 307 else
300 close(fd); 308 close(fd);
301 309
302 printf ("%s is mounted. ", device_name); 310 printf("%s is mounted. ", device_name);
303 if (isatty(0) && isatty(1)) 311 if (isatty(0) && isatty(1))
304 cont = ask("Do you really want to continue", 0); 312 cont = ask("Do you really want to continue", 0);
305 else 313 else
306 cont = 0; 314 cont = 0;
307 if (!cont) { 315 if (!cont) {
308 printf ("check aborted.\n"); 316 printf("check aborted.\n");
309 exit (0); 317 exit(0);
310 } 318 }
311 return; 319 return;
312} 320}
@@ -317,7 +325,7 @@ static void check_mount(void)
317 * if an error was corrected, and returns the zone (0 for no zone 325 * if an error was corrected, and returns the zone (0 for no zone
318 * or a bad zone-number). 326 * or a bad zone-number).
319 */ 327 */
320static int check_zone_nr(unsigned short * nr, int * corrected) 328static int check_zone_nr(unsigned short *nr, int *corrected)
321{ 329{
322 if (!*nr) 330 if (!*nr)
323 return 0; 331 return 0;
@@ -329,7 +337,7 @@ static int check_zone_nr(unsigned short * nr, int * corrected)
329 return *nr; 337 return *nr;
330 print_current_name(); 338 print_current_name();
331 printf("'."); 339 printf("'.");
332 if (ask("Remove block",1)) { 340 if (ask("Remove block", 1)) {
333 *nr = 0; 341 *nr = 0;
334 *corrected = 1; 342 *corrected = 1;
335 } 343 }
@@ -337,19 +345,19 @@ static int check_zone_nr(unsigned short * nr, int * corrected)
337} 345}
338 346
339#ifdef HAVE_MINIX2 347#ifdef HAVE_MINIX2
340static int check_zone_nr2 (unsigned int *nr, int *corrected) 348static int check_zone_nr2(unsigned int *nr, int *corrected)
341{ 349{
342 if (!*nr) 350 if (!*nr)
343 return 0; 351 return 0;
344 if (*nr < FIRSTZONE) 352 if (*nr < FIRSTZONE)
345 printf ("Zone nr < FIRSTZONE in file `"); 353 printf("Zone nr < FIRSTZONE in file `");
346 else if (*nr >= ZONES) 354 else if (*nr >= ZONES)
347 printf ("Zone nr >= ZONES in file `"); 355 printf("Zone nr >= ZONES in file `");
348 else 356 else
349 return *nr; 357 return *nr;
350 print_current_name (); 358 print_current_name();
351 printf ("'."); 359 printf("'.");
352 if (ask ("Remove block", 1)) { 360 if (ask("Remove block", 1)) {
353 *nr = 0; 361 *nr = 0;
354 *corrected = 1; 362 *corrected = 1;
355 } 363 }
@@ -360,23 +368,23 @@ static int check_zone_nr2 (unsigned int *nr, int *corrected)
360/* 368/*
361 * read-block reads block nr into the buffer at addr. 369 * read-block reads block nr into the buffer at addr.
362 */ 370 */
363static void read_block(unsigned int nr, char * addr) 371static void read_block(unsigned int nr, char *addr)
364{ 372{
365 if (!nr) { 373 if (!nr) {
366 memset(addr,0,BLOCK_SIZE); 374 memset(addr, 0, BLOCK_SIZE);
367 return; 375 return;
368 } 376 }
369 if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) { 377 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) {
370 printf("Read error: unable to seek to block in file '"); 378 printf("Read error: unable to seek to block in file '");
371 print_current_name(); 379 print_current_name();
372 printf("'\n"); 380 printf("'\n");
373 memset(addr,0,BLOCK_SIZE); 381 memset(addr, 0, BLOCK_SIZE);
374 errors_uncorrected = 1; 382 errors_uncorrected = 1;
375 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { 383 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
376 printf("Read error: bad block in file '"); 384 printf("Read error: bad block in file '");
377 print_current_name(); 385 print_current_name();
378 printf("'\n"); 386 printf("'\n");
379 memset(addr,0,BLOCK_SIZE); 387 memset(addr, 0, BLOCK_SIZE);
380 errors_uncorrected = 1; 388 errors_uncorrected = 1;
381 } 389 }
382} 390}
@@ -384,17 +392,17 @@ static void read_block(unsigned int nr, char * addr)
384/* 392/*
385 * write_block writes block nr to disk. 393 * write_block writes block nr to disk.
386 */ 394 */
387static void write_block(unsigned int nr, char * addr) 395static void write_block(unsigned int nr, char *addr)
388{ 396{
389 if (!nr) 397 if (!nr)
390 return; 398 return;
391 if (nr < FIRSTZONE || nr >= ZONES) { 399 if (nr < FIRSTZONE || nr >= ZONES) {
392 printf("Internal error: trying to write bad block\n" 400 printf("Internal error: trying to write bad block\n"
393 "Write request ignored\n"); 401 "Write request ignored\n");
394 errors_uncorrected = 1; 402 errors_uncorrected = 1;
395 return; 403 return;
396 } 404 }
397 if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) 405 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET))
398 die("seek failed in write_block"); 406 die("seek failed in write_block");
399 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { 407 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
400 printf("Write error: bad block in file '"); 408 printf("Write error: bad block in file '");
@@ -409,16 +417,16 @@ static void write_block(unsigned int nr, char * addr)
409 * It sets 'changed' if the inode has needed changing, and re-writes 417 * It sets 'changed' if the inode has needed changing, and re-writes
410 * any indirect blocks with errors. 418 * any indirect blocks with errors.
411 */ 419 */
412static int map_block(struct minix_inode * inode, unsigned int blknr) 420static int map_block(struct minix_inode *inode, unsigned int blknr)
413{ 421{
414 unsigned short ind[BLOCK_SIZE>>1]; 422 unsigned short ind[BLOCK_SIZE >> 1];
415 unsigned short dind[BLOCK_SIZE>>1]; 423 unsigned short dind[BLOCK_SIZE >> 1];
416 int blk_chg, block, result; 424 int blk_chg, block, result;
417 425
418 if (blknr<7) 426 if (blknr < 7)
419 return check_zone_nr(inode->i_zone + blknr, &changed); 427 return check_zone_nr(inode->i_zone + blknr, &changed);
420 blknr -= 7; 428 blknr -= 7;
421 if (blknr<512) { 429 if (blknr < 512) {
422 block = check_zone_nr(inode->i_zone + 7, &changed); 430 block = check_zone_nr(inode->i_zone + 7, &changed);
423 read_block(block, (char *) ind); 431 read_block(block, (char *) ind);
424 blk_chg = 0; 432 blk_chg = 0;
@@ -431,73 +439,73 @@ static int map_block(struct minix_inode * inode, unsigned int blknr)
431 block = check_zone_nr(inode->i_zone + 8, &changed); 439 block = check_zone_nr(inode->i_zone + 8, &changed);
432 read_block(block, (char *) dind); 440 read_block(block, (char *) dind);
433 blk_chg = 0; 441 blk_chg = 0;
434 result = check_zone_nr(dind + (blknr/512), &blk_chg); 442 result = check_zone_nr(dind + (blknr / 512), &blk_chg);
435 if (blk_chg) 443 if (blk_chg)
436 write_block(block, (char *) dind); 444 write_block(block, (char *) dind);
437 block = result; 445 block = result;
438 read_block(block, (char *) ind); 446 read_block(block, (char *) ind);
439 blk_chg = 0; 447 blk_chg = 0;
440 result = check_zone_nr(ind + (blknr%512), &blk_chg); 448 result = check_zone_nr(ind + (blknr % 512), &blk_chg);
441 if (blk_chg) 449 if (blk_chg)
442 write_block(block, (char *) ind); 450 write_block(block, (char *) ind);
443 return result; 451 return result;
444} 452}
445 453
446#ifdef HAVE_MINIX2 454#ifdef HAVE_MINIX2
447static int map_block2 (struct minix2_inode *inode, unsigned int blknr) 455static int map_block2(struct minix2_inode *inode, unsigned int blknr)
448{ 456{
449 unsigned int ind[BLOCK_SIZE >> 2]; 457 unsigned int ind[BLOCK_SIZE >> 2];
450 unsigned int dind[BLOCK_SIZE >> 2]; 458 unsigned int dind[BLOCK_SIZE >> 2];
451 unsigned int tind[BLOCK_SIZE >> 2]; 459 unsigned int tind[BLOCK_SIZE >> 2];
452 int blk_chg, block, result; 460 int blk_chg, block, result;
453 461
454 if (blknr < 7) 462 if (blknr < 7)
455 return check_zone_nr2 (inode->i_zone + blknr, &changed); 463 return check_zone_nr2(inode->i_zone + blknr, &changed);
456 blknr -= 7; 464 blknr -= 7;
457 if (blknr < 256) { 465 if (blknr < 256) {
458 block = check_zone_nr2 (inode->i_zone + 7, &changed); 466 block = check_zone_nr2(inode->i_zone + 7, &changed);
459 read_block (block, (char *) ind); 467 read_block(block, (char *) ind);
460 blk_chg = 0; 468 blk_chg = 0;
461 result = check_zone_nr2 (blknr + ind, &blk_chg); 469 result = check_zone_nr2(blknr + ind, &blk_chg);
462 if (blk_chg) 470 if (blk_chg)
463 write_block (block, (char *) ind); 471 write_block(block, (char *) ind);
464 return result; 472 return result;
465 } 473 }
466 blknr -= 256; 474 blknr -= 256;
467 if (blknr >= 256 * 256) { 475 if (blknr >= 256 * 256) {
468 block = check_zone_nr2 (inode->i_zone + 8, &changed); 476 block = check_zone_nr2(inode->i_zone + 8, &changed);
469 read_block (block, (char *) dind); 477 read_block(block, (char *) dind);
470 blk_chg = 0; 478 blk_chg = 0;
471 result = check_zone_nr2 (dind + blknr / 256, &blk_chg); 479 result = check_zone_nr2(dind + blknr / 256, &blk_chg);
472 if (blk_chg) 480 if (blk_chg)
473 write_block (block, (char *) dind); 481 write_block(block, (char *) dind);
474 block = result; 482 block = result;
475 read_block (block, (char *) ind); 483 read_block(block, (char *) ind);
476 blk_chg = 0; 484 blk_chg = 0;
477 result = check_zone_nr2 (ind + blknr % 256, &blk_chg); 485 result = check_zone_nr2(ind + blknr % 256, &blk_chg);
478 if (blk_chg) 486 if (blk_chg)
479 write_block (block, (char *) ind); 487 write_block(block, (char *) ind);
480 return result; 488 return result;
481 } 489 }
482 blknr -= 256 * 256; 490 blknr -= 256 * 256;
483 block = check_zone_nr2 (inode->i_zone + 9, &changed); 491 block = check_zone_nr2(inode->i_zone + 9, &changed);
484 read_block (block, (char *) tind); 492 read_block(block, (char *) tind);
485 blk_chg = 0; 493 blk_chg = 0;
486 result = check_zone_nr2 (tind + blknr / (256 * 256), &blk_chg); 494 result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg);
487 if (blk_chg) 495 if (blk_chg)
488 write_block (block, (char *) tind); 496 write_block(block, (char *) tind);
489 block = result; 497 block = result;
490 read_block (block, (char *) dind); 498 read_block(block, (char *) dind);
491 blk_chg = 0; 499 blk_chg = 0;
492 result = check_zone_nr2 (dind + (blknr / 256) % 256, &blk_chg); 500 result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg);
493 if (blk_chg) 501 if (blk_chg)
494 write_block (block, (char *) dind); 502 write_block(block, (char *) dind);
495 block = result; 503 block = result;
496 read_block (block, (char *) ind); 504 read_block(block, (char *) ind);
497 blk_chg = 0; 505 blk_chg = 0;
498 result = check_zone_nr2 (ind + blknr % 256, &blk_chg); 506 result = check_zone_nr2(ind + blknr % 256, &blk_chg);
499 if (blk_chg) 507 if (blk_chg)
500 write_block (block, (char *) ind); 508 write_block(block, (char *) ind);
501 return result; 509 return result;
502} 510}
503#endif 511#endif
@@ -510,11 +518,11 @@ static void write_super_block(void)
510 * unconditionally set if we get this far. 518 * unconditionally set if we get this far.
511 */ 519 */
512 Super.s_state |= MINIX_VALID_FS; 520 Super.s_state |= MINIX_VALID_FS;
513 if ( errors_uncorrected ) 521 if (errors_uncorrected)
514 Super.s_state |= MINIX_ERROR_FS; 522 Super.s_state |= MINIX_ERROR_FS;
515 else 523 else
516 Super.s_state &= ~MINIX_ERROR_FS; 524 Super.s_state &= ~MINIX_ERROR_FS;
517 525
518 if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) 526 if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
519 die("seek failed in write_super_block"); 527 die("seek failed in write_super_block");
520 if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) 528 if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
@@ -527,15 +535,15 @@ static void write_tables(void)
527{ 535{
528 write_super_block(); 536 write_super_block();
529 537
530 if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE)) 538 if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE))
531 die("Unable to write inode map"); 539 die("Unable to write inode map");
532 if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE)) 540 if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE))
533 die("Unable to write zone map"); 541 die("Unable to write zone map");
534 if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE)) 542 if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE))
535 die("Unable to write inodes"); 543 die("Unable to write inodes");
536} 544}
537 545
538static void get_dirsize (void) 546static void get_dirsize(void)
539{ 547{
540 int block; 548 int block;
541 char blk[BLOCK_SIZE]; 549 char blk[BLOCK_SIZE];
@@ -547,9 +555,9 @@ static void get_dirsize (void)
547 else 555 else
548#endif 556#endif
549 block = Inode[ROOT_INO].i_zone[0]; 557 block = Inode[ROOT_INO].i_zone[0];
550 read_block (block, blk); 558 read_block(block, blk);
551 for (size = 16; size < BLOCK_SIZE; size <<= 1) { 559 for (size = 16; size < BLOCK_SIZE; size <<= 1) {
552 if (strcmp (blk + size + 2, "..") == 0) { 560 if (strcmp(blk + size + 2, "..") == 0) {
553 dirsize = size; 561 dirsize = size;
554 namelen = size - 2; 562 namelen = size - 2;
555 return; 563 return;
@@ -600,8 +608,8 @@ static void read_tables(void)
600 zone_map = malloc(ZMAPS * BLOCK_SIZE); 608 zone_map = malloc(ZMAPS * BLOCK_SIZE);
601 if (!inode_map) 609 if (!inode_map)
602 die("Unable to allocate buffer for zone map"); 610 die("Unable to allocate buffer for zone map");
603 memset(inode_map,0,sizeof(inode_map)); 611 memset(inode_map, 0, sizeof(inode_map));
604 memset(zone_map,0,sizeof(zone_map)); 612 memset(zone_map, 0, sizeof(zone_map));
605 inode_buffer = malloc(INODE_BUFFER_SIZE); 613 inode_buffer = malloc(INODE_BUFFER_SIZE);
606 if (!inode_buffer) 614 if (!inode_buffer)
607 die("Unable to allocate buffer for inodes"); 615 die("Unable to allocate buffer for inodes");
@@ -611,31 +619,31 @@ static void read_tables(void)
611 zone_count = malloc(ZONES); 619 zone_count = malloc(ZONES);
612 if (!zone_count) 620 if (!zone_count)
613 die("Unable to allocate buffer for zone count"); 621 die("Unable to allocate buffer for zone count");
614 if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE)) 622 if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE))
615 die("Unable to read inode map"); 623 die("Unable to read inode map");
616 if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE)) 624 if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE))
617 die("Unable to read zone map"); 625 die("Unable to read zone map");
618 if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE)) 626 if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE))
619 die("Unable to read inodes"); 627 die("Unable to read inodes");
620 if (NORM_FIRSTZONE != FIRSTZONE) { 628 if (NORM_FIRSTZONE != FIRSTZONE) {
621 printf("Warning: Firstzone != Norm_firstzone\n"); 629 printf("Warning: Firstzone != Norm_firstzone\n");
622 errors_uncorrected = 1; 630 errors_uncorrected = 1;
623 } 631 }
624 get_dirsize (); 632 get_dirsize();
625 if (show) { 633 if (show) {
626 printf("%ld inodes\n",INODES); 634 printf("%ld inodes\n", INODES);
627 printf("%ld blocks\n",ZONES); 635 printf("%ld blocks\n", ZONES);
628 printf("Firstdatazone=%ld (%ld)\n",FIRSTZONE,NORM_FIRSTZONE); 636 printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE);
629 printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); 637 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
630 printf("Maxsize=%ld\n",MAXSIZE); 638 printf("Maxsize=%ld\n", MAXSIZE);
631 printf("Filesystem state=%d\n", Super.s_state); 639 printf("Filesystem state=%d\n", Super.s_state);
632 printf("namelen=%d\n\n",namelen); 640 printf("namelen=%d\n\n", namelen);
633 } 641 }
634} 642}
635 643
636struct minix_inode * get_inode(unsigned int nr) 644struct minix_inode *get_inode(unsigned int nr)
637{ 645{
638 struct minix_inode * inode; 646 struct minix_inode *inode;
639 647
640 if (!nr || nr > INODES) 648 if (!nr || nr > INODES)
641 return NULL; 649 return NULL;
@@ -643,15 +651,14 @@ struct minix_inode * get_inode(unsigned int nr)
643 inode = Inode + nr; 651 inode = Inode + nr;
644 if (!inode_count[nr]) { 652 if (!inode_count[nr]) {
645 if (!inode_in_use(nr)) { 653 if (!inode_in_use(nr)) {
646 printf("Inode %d marked not used, but used for file '", 654 printf("Inode %d marked not used, but used for file '", nr);
647 nr);
648 print_current_name(); 655 print_current_name();
649 printf("'\n"); 656 printf("'\n");
650 if (repair) { 657 if (repair) {
651 if (ask("Mark in use",1)) 658 if (ask("Mark in use", 1))
652 mark_inode(nr); 659 mark_inode(nr);
653 } else { 660 } else {
654 errors_uncorrected = 1; 661 errors_uncorrected = 1;
655 } 662 }
656 } 663 }
657 if (S_ISDIR(inode->i_mode)) 664 if (S_ISDIR(inode->i_mode))
@@ -664,14 +671,12 @@ struct minix_inode * get_inode(unsigned int nr)
664 blockdev++; 671 blockdev++;
665 else if (S_ISLNK(inode->i_mode)) 672 else if (S_ISLNK(inode->i_mode))
666 symlinks++; 673 symlinks++;
667 else if (S_ISSOCK(inode->i_mode)) 674 else if (S_ISSOCK(inode->i_mode));
668 ; 675 else if (S_ISFIFO(inode->i_mode));
669 else if (S_ISFIFO(inode->i_mode))
670 ;
671 else { 676 else {
672 print_current_name(); 677 print_current_name();
673 printf(" has mode %05o\n",inode->i_mode); 678 printf(" has mode %05o\n", inode->i_mode);
674 } 679 }
675 680
676 } else 681 } else
677 links++; 682 links++;
@@ -684,8 +689,7 @@ struct minix_inode * get_inode(unsigned int nr)
684} 689}
685 690
686#ifdef HAVE_MINIX2 691#ifdef HAVE_MINIX2
687struct minix2_inode * 692struct minix2_inode *get_inode2(unsigned int nr)
688get_inode2 (unsigned int nr)
689{ 693{
690 struct minix2_inode *inode; 694 struct minix2_inode *inode;
691 695
@@ -694,37 +698,37 @@ get_inode2 (unsigned int nr)
694 total++; 698 total++;
695 inode = Inode2 + nr; 699 inode = Inode2 + nr;
696 if (!inode_count[nr]) { 700 if (!inode_count[nr]) {
697 if (!inode_in_use (nr)) { 701 if (!inode_in_use(nr)) {
698 printf ("Inode %d marked not used, but used for file '", nr); 702 printf("Inode %d marked not used, but used for file '", nr);
699 print_current_name (); 703 print_current_name();
700 printf ("'\n"); 704 printf("'\n");
701 if (repair) { 705 if (repair) {
702 if (ask ("Mark in use", 1)) 706 if (ask("Mark in use", 1))
703 mark_inode (nr); 707 mark_inode(nr);
704 else 708 else
705 errors_uncorrected = 1; 709 errors_uncorrected = 1;
706 } 710 }
707 } 711 }
708 if (S_ISDIR (inode->i_mode)) 712 if (S_ISDIR(inode->i_mode))
709 directory++; 713 directory++;
710 else if (S_ISREG (inode->i_mode)) 714 else if (S_ISREG(inode->i_mode))
711 regular++; 715 regular++;
712 else if (S_ISCHR (inode->i_mode)) 716 else if (S_ISCHR(inode->i_mode))
713 chardev++; 717 chardev++;
714 else if (S_ISBLK (inode->i_mode)) 718 else if (S_ISBLK(inode->i_mode))
715 blockdev++; 719 blockdev++;
716 else if (S_ISLNK (inode->i_mode)) 720 else if (S_ISLNK(inode->i_mode))
717 symlinks++; 721 symlinks++;
718 else if (S_ISSOCK (inode->i_mode)); 722 else if (S_ISSOCK(inode->i_mode));
719 else if (S_ISFIFO (inode->i_mode)); 723 else if (S_ISFIFO(inode->i_mode));
720 else { 724 else {
721 print_current_name (); 725 print_current_name();
722 printf (" has mode %05o\n", inode->i_mode); 726 printf(" has mode %05o\n", inode->i_mode);
723 } 727 }
724 } else 728 } else
725 links++; 729 links++;
726 if (!++inode_count[nr]) { 730 if (!++inode_count[nr]) {
727 printf ("Warning: inode count too big.\n"); 731 printf("Warning: inode count too big.\n");
728 inode_count[nr]--; 732 inode_count[nr]--;
729 errors_uncorrected = 1; 733 errors_uncorrected = 1;
730 } 734 }
@@ -734,23 +738,23 @@ get_inode2 (unsigned int nr)
734 738
735static void check_root(void) 739static void check_root(void)
736{ 740{
737 struct minix_inode * inode = Inode + ROOT_INO; 741 struct minix_inode *inode = Inode + ROOT_INO;
738 742
739 if (!inode || !S_ISDIR(inode->i_mode)) 743 if (!inode || !S_ISDIR(inode->i_mode))
740 die("root inode isn't a directory"); 744 die("root inode isn't a directory");
741} 745}
742 746
743#ifdef HAVE_MINIX2 747#ifdef HAVE_MINIX2
744static void check_root2 (void) 748static void check_root2(void)
745{ 749{
746 struct minix2_inode *inode = Inode2 + ROOT_INO; 750 struct minix2_inode *inode = Inode2 + ROOT_INO;
747 751
748 if (!inode || !S_ISDIR (inode->i_mode)) 752 if (!inode || !S_ISDIR(inode->i_mode))
749 die ("root inode isn't a directory"); 753 die("root inode isn't a directory");
750} 754}
751#endif 755#endif
752 756
753static int add_zone(unsigned short * znr, int * corrected) 757static int add_zone(unsigned short *znr, int *corrected)
754{ 758{
755 int result; 759 int result;
756 int block; 760 int block;
@@ -763,7 +767,7 @@ static int add_zone(unsigned short * znr, int * corrected)
763 printf("Block has been used before. Now in file `"); 767 printf("Block has been used before. Now in file `");
764 print_current_name(); 768 print_current_name();
765 printf("'."); 769 printf("'.");
766 if (ask("Clear",1)) { 770 if (ask("Clear", 1)) {
767 *znr = 0; 771 *znr = 0;
768 block = 0; 772 block = 0;
769 *corrected = 1; 773 *corrected = 1;
@@ -772,10 +776,10 @@ static int add_zone(unsigned short * znr, int * corrected)
772 if (!block) 776 if (!block)
773 return 0; 777 return 0;
774 if (!zone_in_use(block)) { 778 if (!zone_in_use(block)) {
775 printf("Block %d in file `",block); 779 printf("Block %d in file `", block);
776 print_current_name(); 780 print_current_name();
777 printf("' is marked not in use."); 781 printf("' is marked not in use.");
778 if (ask("Correct",1)) 782 if (ask("Correct", 1))
779 mark_zone(block); 783 mark_zone(block);
780 } 784 }
781 if (!++zone_count[block]) 785 if (!++zone_count[block])
@@ -784,20 +788,20 @@ static int add_zone(unsigned short * znr, int * corrected)
784} 788}
785 789
786#ifdef HAVE_MINIX2 790#ifdef HAVE_MINIX2
787static int add_zone2 (unsigned int *znr, int *corrected) 791static int add_zone2(unsigned int *znr, int *corrected)
788{ 792{
789 int result; 793 int result;
790 int block; 794 int block;
791 795
792 result = 0; 796 result = 0;
793 block = check_zone_nr2 (znr, corrected); 797 block = check_zone_nr2(znr, corrected);
794 if (!block) 798 if (!block)
795 return 0; 799 return 0;
796 if (zone_count[block]) { 800 if (zone_count[block]) {
797 printf ("Block has been used before. Now in file `"); 801 printf("Block has been used before. Now in file `");
798 print_current_name (); 802 print_current_name();
799 printf ("'."); 803 printf("'.");
800 if (ask ("Clear", 1)) { 804 if (ask("Clear", 1)) {
801 *znr = 0; 805 *znr = 0;
802 block = 0; 806 block = 0;
803 *corrected = 1; 807 *corrected = 1;
@@ -805,12 +809,12 @@ static int add_zone2 (unsigned int *znr, int *corrected)
805 } 809 }
806 if (!block) 810 if (!block)
807 return 0; 811 return 0;
808 if (!zone_in_use (block)) { 812 if (!zone_in_use(block)) {
809 printf ("Block %d in file `", block); 813 printf("Block %d in file `", block);
810 print_current_name (); 814 print_current_name();
811 printf ("' is marked not in use."); 815 printf("' is marked not in use.");
812 if (ask ("Correct", 1)) 816 if (ask("Correct", 1))
813 mark_zone (block); 817 mark_zone(block);
814 } 818 }
815 if (!++zone_count[block]) 819 if (!++zone_count[block])
816 zone_count[block]--; 820 zone_count[block]--;
@@ -818,182 +822,179 @@ static int add_zone2 (unsigned int *znr, int *corrected)
818} 822}
819#endif 823#endif
820 824
821static void add_zone_ind(unsigned short * znr, int * corrected) 825static void add_zone_ind(unsigned short *znr, int *corrected)
822{ 826{
823 static char blk[BLOCK_SIZE]; 827 static char blk[BLOCK_SIZE];
824 int i, chg_blk=0; 828 int i, chg_blk = 0;
825 int block; 829 int block;
826 830
827 block = add_zone(znr, corrected); 831 block = add_zone(znr, corrected);
828 if (!block) 832 if (!block)
829 return; 833 return;
830 read_block(block, blk); 834 read_block(block, blk);
831 for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) 835 for (i = 0; i < (BLOCK_SIZE >> 1); i++)
832 add_zone(i + (unsigned short *) blk, &chg_blk); 836 add_zone(i + (unsigned short *) blk, &chg_blk);
833 if (chg_blk) 837 if (chg_blk)
834 write_block(block, blk); 838 write_block(block, blk);
835} 839}
836 840
837#ifdef HAVE_MINIX2 841#ifdef HAVE_MINIX2
838static void 842static void add_zone_ind2(unsigned int *znr, int *corrected)
839add_zone_ind2 (unsigned int *znr, int *corrected)
840{ 843{
841 static char blk[BLOCK_SIZE]; 844 static char blk[BLOCK_SIZE];
842 int i, chg_blk = 0; 845 int i, chg_blk = 0;
843 int block; 846 int block;
844 847
845 block = add_zone2 (znr, corrected); 848 block = add_zone2(znr, corrected);
846 if (!block) 849 if (!block)
847 return; 850 return;
848 read_block (block, blk); 851 read_block(block, blk);
849 for (i = 0; i < BLOCK_SIZE >> 2; i++) 852 for (i = 0; i < BLOCK_SIZE >> 2; i++)
850 add_zone2 (i + (unsigned int *) blk, &chg_blk); 853 add_zone2(i + (unsigned int *) blk, &chg_blk);
851 if (chg_blk) 854 if (chg_blk)
852 write_block (block, blk); 855 write_block(block, blk);
853} 856}
854#endif 857#endif
855 858
856static void add_zone_dind(unsigned short * znr, int * corrected) 859static void add_zone_dind(unsigned short *znr, int *corrected)
857{ 860{
858 static char blk[BLOCK_SIZE]; 861 static char blk[BLOCK_SIZE];
859 int i, blk_chg=0; 862 int i, blk_chg = 0;
860 int block; 863 int block;
861 864
862 block = add_zone(znr, corrected); 865 block = add_zone(znr, corrected);
863 if (!block) 866 if (!block)
864 return; 867 return;
865 read_block(block, blk); 868 read_block(block, blk);
866 for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) 869 for (i = 0; i < (BLOCK_SIZE >> 1); i++)
867 add_zone_ind(i + (unsigned short *) blk, &blk_chg); 870 add_zone_ind(i + (unsigned short *) blk, &blk_chg);
868 if (blk_chg) 871 if (blk_chg)
869 write_block(block, blk); 872 write_block(block, blk);
870} 873}
871 874
872#ifdef HAVE_MINIX2 875#ifdef HAVE_MINIX2
873static void 876static void add_zone_dind2(unsigned int *znr, int *corrected)
874add_zone_dind2 (unsigned int *znr, int *corrected)
875{ 877{
876 static char blk[BLOCK_SIZE]; 878 static char blk[BLOCK_SIZE];
877 int i, blk_chg = 0; 879 int i, blk_chg = 0;
878 int block; 880 int block;
879 881
880 block = add_zone2 (znr, corrected); 882 block = add_zone2(znr, corrected);
881 if (!block) 883 if (!block)
882 return; 884 return;
883 read_block (block, blk); 885 read_block(block, blk);
884 for (i = 0; i < BLOCK_SIZE >> 2; i++) 886 for (i = 0; i < BLOCK_SIZE >> 2; i++)
885 add_zone_ind2 (i + (unsigned int *) blk, &blk_chg); 887 add_zone_ind2(i + (unsigned int *) blk, &blk_chg);
886 if (blk_chg) 888 if (blk_chg)
887 write_block (block, blk); 889 write_block(block, blk);
888} 890}
889 891
890static void 892static void add_zone_tind2(unsigned int *znr, int *corrected)
891add_zone_tind2 (unsigned int *znr, int *corrected)
892{ 893{
893 static char blk[BLOCK_SIZE]; 894 static char blk[BLOCK_SIZE];
894 int i, blk_chg = 0; 895 int i, blk_chg = 0;
895 int block; 896 int block;
896 897
897 block = add_zone2 (znr, corrected); 898 block = add_zone2(znr, corrected);
898 if (!block) 899 if (!block)
899 return; 900 return;
900 read_block (block, blk); 901 read_block(block, blk);
901 for (i = 0; i < BLOCK_SIZE >> 2; i++) 902 for (i = 0; i < BLOCK_SIZE >> 2; i++)
902 add_zone_dind2 (i + (unsigned int *) blk, &blk_chg); 903 add_zone_dind2(i + (unsigned int *) blk, &blk_chg);
903 if (blk_chg) 904 if (blk_chg)
904 write_block (block, blk); 905 write_block(block, blk);
905} 906}
906#endif 907#endif
907 908
908static void check_zones(unsigned int i) 909static void check_zones(unsigned int i)
909{ 910{
910 struct minix_inode * inode; 911 struct minix_inode *inode;
911 912
912 if (!i || i > INODES) 913 if (!i || i > INODES)
913 return; 914 return;
914 if (inode_count[i] > 1) /* have we counted this file already? */ 915 if (inode_count[i] > 1) /* have we counted this file already? */
915 return; 916 return;
916 inode = Inode + i; 917 inode = Inode + i;
917 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && 918 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
918 !S_ISLNK(inode->i_mode)) 919 !S_ISLNK(inode->i_mode)) return;
919 return; 920 for (i = 0; i < 7; i++)
920 for (i=0 ; i<7 ; i++)
921 add_zone(i + inode->i_zone, &changed); 921 add_zone(i + inode->i_zone, &changed);
922 add_zone_ind(7 + inode->i_zone, &changed); 922 add_zone_ind(7 + inode->i_zone, &changed);
923 add_zone_dind(8 + inode->i_zone, &changed); 923 add_zone_dind(8 + inode->i_zone, &changed);
924} 924}
925 925
926#ifdef HAVE_MINIX2 926#ifdef HAVE_MINIX2
927static void 927static void check_zones2(unsigned int i)
928check_zones2 (unsigned int i)
929{ 928{
930 struct minix2_inode *inode; 929 struct minix2_inode *inode;
931 930
932 if (!i || i > INODES) 931 if (!i || i > INODES)
933 return; 932 return;
934 if (inode_count[i] > 1) /* have we counted this file already? */ 933 if (inode_count[i] > 1) /* have we counted this file already? */
935 return; 934 return;
936 inode = Inode2 + i; 935 inode = Inode2 + i;
937 if (!S_ISDIR (inode->i_mode) && !S_ISREG (inode->i_mode) 936 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode)
938 && !S_ISLNK (inode->i_mode)) 937 && !S_ISLNK(inode->i_mode))
939 return; 938 return;
940 for (i = 0; i < 7; i++) 939 for (i = 0; i < 7; i++)
941 add_zone2 (i + inode->i_zone, &changed); 940 add_zone2(i + inode->i_zone, &changed);
942 add_zone_ind2 (7 + inode->i_zone, &changed); 941 add_zone_ind2(7 + inode->i_zone, &changed);
943 add_zone_dind2 (8 + inode->i_zone, &changed); 942 add_zone_dind2(8 + inode->i_zone, &changed);
944 add_zone_tind2 (9 + inode->i_zone, &changed); 943 add_zone_tind2(9 + inode->i_zone, &changed);
945} 944}
946#endif 945#endif
947 946
948static void check_file(struct minix_inode * dir, unsigned int offset) 947static void check_file(struct minix_inode *dir, unsigned int offset)
949{ 948{
950 static char blk[BLOCK_SIZE]; 949 static char blk[BLOCK_SIZE];
951 struct minix_inode * inode; 950 struct minix_inode *inode;
952 int ino; 951 int ino;
953 char * name; 952 char *name;
954 int block; 953 int block;
955 954
956 block = map_block(dir,offset/BLOCK_SIZE); 955 block = map_block(dir, offset / BLOCK_SIZE);
957 read_block(block, blk); 956 read_block(block, blk);
958 name = blk + (offset % BLOCK_SIZE) + 2; 957 name = blk + (offset % BLOCK_SIZE) + 2;
959 ino = * (unsigned short *) (name-2); 958 ino = *(unsigned short *) (name - 2);
960 if (ino > INODES) { 959 if (ino > INODES) {
961 print_current_name(); 960 print_current_name();
962 printf(" contains a bad inode number for file '"); 961 printf(" contains a bad inode number for file '");
963 printf("%.*s'.",namelen,name); 962 printf("%.*s'.", namelen, name);
964 if (ask(" Remove",1)) { 963 if (ask(" Remove", 1)) {
965 *(unsigned short *)(name-2) = 0; 964 *(unsigned short *) (name - 2) = 0;
966 write_block(block, blk); 965 write_block(block, blk);
967 } 966 }
968 ino = 0; 967 ino = 0;
969 } 968 }
970 if (name_depth < MAX_DEPTH) 969 if (name_depth < MAX_DEPTH)
971 strncpy (name_list[name_depth], name, namelen); 970 strncpy(name_list[name_depth], name, namelen);
972 name_depth++; 971 name_depth++;
973 inode = get_inode(ino); 972 inode = get_inode(ino);
974 name_depth--; 973 name_depth--;
975 if (!offset) { 974 if (!offset) {
976 if (!inode || strcmp(".",name)) { 975 if (!inode || strcmp(".", name)) {
977 print_current_name(); 976 print_current_name();
978 printf(": bad directory: '.' isn't first\n"); 977 printf(": bad directory: '.' isn't first\n");
979 errors_uncorrected = 1; 978 errors_uncorrected = 1;
980 } else return; 979 } else
980 return;
981 } 981 }
982 if (offset == dirsize) { 982 if (offset == dirsize) {
983 if (!inode || strcmp("..",name)) { 983 if (!inode || strcmp("..", name)) {
984 print_current_name(); 984 print_current_name();
985 printf(": bad directory: '..' isn't second\n"); 985 printf(": bad directory: '..' isn't second\n");
986 errors_uncorrected = 1; 986 errors_uncorrected = 1;
987 } else return; 987 } else
988 return;
988 } 989 }
989 if (!inode) 990 if (!inode)
990 return; 991 return;
991 if (name_depth < MAX_DEPTH) 992 if (name_depth < MAX_DEPTH)
992 strncpy(name_list[name_depth],name,namelen); 993 strncpy(name_list[name_depth], name, namelen);
993 name_depth++; 994 name_depth++;
994 if (list) { 995 if (list) {
995 if (verbose) 996 if (verbose)
996 printf("%6d %07o %3d ",ino,inode->i_mode,inode->i_nlinks); 997 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
997 print_current_name(); 998 print_current_name();
998 if (S_ISDIR(inode->i_mode)) 999 if (S_ISDIR(inode->i_mode))
999 printf(":\n"); 1000 printf(":\n");
@@ -1008,8 +1009,7 @@ static void check_file(struct minix_inode * dir, unsigned int offset)
1008} 1009}
1009 1010
1010#ifdef HAVE_MINIX2 1011#ifdef HAVE_MINIX2
1011static void 1012static void check_file2(struct minix2_inode *dir, unsigned int offset)
1012check_file2 (struct minix2_inode *dir, unsigned int offset)
1013{ 1013{
1014 static char blk[BLOCK_SIZE]; 1014 static char blk[BLOCK_SIZE];
1015 struct minix2_inode *inode; 1015 struct minix2_inode *inode;
@@ -1017,37 +1017,37 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1017 char *name; 1017 char *name;
1018 int block; 1018 int block;
1019 1019
1020 block = map_block2 (dir, offset / BLOCK_SIZE); 1020 block = map_block2(dir, offset / BLOCK_SIZE);
1021 read_block (block, blk); 1021 read_block(block, blk);
1022 name = blk + (offset % BLOCK_SIZE) + 2; 1022 name = blk + (offset % BLOCK_SIZE) + 2;
1023 ino = *(unsigned short *) (name - 2); 1023 ino = *(unsigned short *) (name - 2);
1024 if (ino > INODES) { 1024 if (ino > INODES) {
1025 print_current_name (); 1025 print_current_name();
1026 printf (" contains a bad inode number for file '"); 1026 printf(" contains a bad inode number for file '");
1027 printf ("%.*s'.", namelen, name); 1027 printf("%.*s'.", namelen, name);
1028 if (ask (" Remove", 1)) { 1028 if (ask(" Remove", 1)) {
1029 *(unsigned short *) (name - 2) = 0; 1029 *(unsigned short *) (name - 2) = 0;
1030 write_block (block, blk); 1030 write_block(block, blk);
1031 } 1031 }
1032 ino = 0; 1032 ino = 0;
1033 } 1033 }
1034 if (name_depth < MAX_DEPTH) 1034 if (name_depth < MAX_DEPTH)
1035 strncpy (name_list[name_depth], name, namelen); 1035 strncpy(name_list[name_depth], name, namelen);
1036 name_depth++; 1036 name_depth++;
1037 inode = get_inode2 (ino); 1037 inode = get_inode2(ino);
1038 name_depth--; 1038 name_depth--;
1039 if (!offset) { 1039 if (!offset) {
1040 if (!inode || strcmp (".", name)) { 1040 if (!inode || strcmp(".", name)) {
1041 print_current_name (); 1041 print_current_name();
1042 printf (": bad directory: '.' isn't first\n"); 1042 printf(": bad directory: '.' isn't first\n");
1043 errors_uncorrected = 1; 1043 errors_uncorrected = 1;
1044 } else 1044 } else
1045 return; 1045 return;
1046 } 1046 }
1047 if (offset == dirsize) { 1047 if (offset == dirsize) {
1048 if (!inode || strcmp ("..", name)) { 1048 if (!inode || strcmp("..", name)) {
1049 print_current_name (); 1049 print_current_name();
1050 printf (": bad directory: '..' isn't second\n"); 1050 printf(": bad directory: '..' isn't second\n");
1051 errors_uncorrected = 1; 1051 errors_uncorrected = 1;
1052 } else 1052 } else
1053 return; 1053 return;
@@ -1057,16 +1057,16 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1057 name_depth++; 1057 name_depth++;
1058 if (list) { 1058 if (list) {
1059 if (verbose) 1059 if (verbose)
1060 printf ("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); 1060 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
1061 print_current_name (); 1061 print_current_name();
1062 if (S_ISDIR (inode->i_mode)) 1062 if (S_ISDIR(inode->i_mode))
1063 printf (":\n"); 1063 printf(":\n");
1064 else 1064 else
1065 printf ("\n"); 1065 printf("\n");
1066 } 1066 }
1067 check_zones2 (ino); 1067 check_zones2(ino);
1068 if (inode && S_ISDIR (inode->i_mode)) 1068 if (inode && S_ISDIR(inode->i_mode))
1069 recursive_check2 (ino); 1069 recursive_check2(ino);
1070 name_depth--; 1070 name_depth--;
1071 return; 1071 return;
1072} 1072}
@@ -1074,7 +1074,7 @@ check_file2 (struct minix2_inode *dir, unsigned int offset)
1074 1074
1075static void recursive_check(unsigned int ino) 1075static void recursive_check(unsigned int ino)
1076{ 1076{
1077 struct minix_inode * dir; 1077 struct minix_inode *dir;
1078 unsigned int offset; 1078 unsigned int offset;
1079 1079
1080 dir = Inode + ino; 1080 dir = Inode + ino;
@@ -1085,27 +1085,26 @@ static void recursive_check(unsigned int ino)
1085 printf(": bad directory: size<32"); 1085 printf(": bad directory: size<32");
1086 errors_uncorrected = 1; 1086 errors_uncorrected = 1;
1087 } 1087 }
1088 for (offset = 0 ; offset < dir->i_size ; offset += dirsize) 1088 for (offset = 0; offset < dir->i_size; offset += dirsize)
1089 check_file(dir,offset); 1089 check_file(dir, offset);
1090} 1090}
1091 1091
1092#ifdef HAVE_MINIX2 1092#ifdef HAVE_MINIX2
1093static void 1093static void recursive_check2(unsigned int ino)
1094recursive_check2 (unsigned int ino)
1095{ 1094{
1096 struct minix2_inode *dir; 1095 struct minix2_inode *dir;
1097 unsigned int offset; 1096 unsigned int offset;
1098 1097
1099 dir = Inode2 + ino; 1098 dir = Inode2 + ino;
1100 if (!S_ISDIR (dir->i_mode)) 1099 if (!S_ISDIR(dir->i_mode))
1101 die ("internal error"); 1100 die("internal error");
1102 if (dir->i_size < 2 * dirsize) { 1101 if (dir->i_size < 2 * dirsize) {
1103 print_current_name (); 1102 print_current_name();
1104 printf (": bad directory: size < 32"); 1103 printf(": bad directory: size < 32");
1105 errors_uncorrected = 1; 1104 errors_uncorrected = 1;
1106 } 1105 }
1107 for (offset = 0; offset < dir->i_size; offset += dirsize) 1106 for (offset = 0; offset < dir->i_size; offset += dirsize)
1108 check_file2 (dir, offset); 1107 check_file2(dir, offset);
1109} 1108}
1110#endif 1109#endif
1111 1110
@@ -1113,7 +1112,7 @@ static int bad_zone(int i)
1113{ 1112{
1114 char buffer[1024]; 1113 char buffer[1024];
1115 1114
1116 if (BLOCK_SIZE*i != lseek(IN, BLOCK_SIZE*i, SEEK_SET)) 1115 if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET))
1117 die("seek failed in bad_zone"); 1116 die("seek failed in bad_zone");
1118 return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); 1117 return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
1119} 1118}
@@ -1122,10 +1121,10 @@ static void check_counts(void)
1122{ 1121{
1123 int i; 1122 int i;
1124 1123
1125 for (i=1 ; i <= INODES ; i++) { 1124 for (i = 1; i <= INODES; i++) {
1126 if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) { 1125 if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) {
1127 printf("Inode %d mode not cleared.",i); 1126 printf("Inode %d mode not cleared.", i);
1128 if (ask("Clear",1)) { 1127 if (ask("Clear", 1)) {
1129 Inode[i].i_mode = 0; 1128 Inode[i].i_mode = 0;
1130 changed = 1; 1129 changed = 1;
1131 } 1130 }
@@ -1133,117 +1132,115 @@ static void check_counts(void)
1133 if (!inode_count[i]) { 1132 if (!inode_count[i]) {
1134 if (!inode_in_use(i)) 1133 if (!inode_in_use(i))
1135 continue; 1134 continue;
1136 printf("Inode %d not used, marked used in the bitmap.",i); 1135 printf("Inode %d not used, marked used in the bitmap.", i);
1137 if (ask("Clear",1)) 1136 if (ask("Clear", 1))
1138 unmark_inode(i); 1137 unmark_inode(i);
1139 continue; 1138 continue;
1140 } 1139 }
1141 if (!inode_in_use(i)) { 1140 if (!inode_in_use(i)) {
1142 printf("Inode %d used, marked unused in the bitmap.", i); 1141 printf("Inode %d used, marked unused in the bitmap.", i);
1143 if (ask("Set",1)) 1142 if (ask("Set", 1))
1144 mark_inode(i); 1143 mark_inode(i);
1145 } 1144 }
1146 if (Inode[i].i_nlinks != inode_count[i]) { 1145 if (Inode[i].i_nlinks != inode_count[i]) {
1147 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", 1146 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.",
1148 i,Inode[i].i_mode,Inode[i].i_nlinks,inode_count[i]); 1147 i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]);
1149 if (ask("Set i_nlinks to count",1)) { 1148 if (ask("Set i_nlinks to count", 1)) {
1150 Inode[i].i_nlinks=inode_count[i]; 1149 Inode[i].i_nlinks = inode_count[i];
1151 changed=1; 1150 changed = 1;
1152 } 1151 }
1153 } 1152 }
1154 } 1153 }
1155 for (i=FIRSTZONE ; i < ZONES ; i++) { 1154 for (i = FIRSTZONE; i < ZONES; i++) {
1156 if (zone_in_use(i) == zone_count[i]) 1155 if (zone_in_use(i) == zone_count[i])
1157 continue; 1156 continue;
1158 if (!zone_count[i]) { 1157 if (!zone_count[i]) {
1159 if (bad_zone(i)) 1158 if (bad_zone(i))
1160 continue; 1159 continue;
1161 printf("Zone %d: marked in use, no file uses it.",i); 1160 printf("Zone %d: marked in use, no file uses it.", i);
1162 if (ask("Unmark",1)) 1161 if (ask("Unmark", 1))
1163 unmark_zone(i); 1162 unmark_zone(i);
1164 continue; 1163 continue;
1165 } 1164 }
1166 printf("Zone %d: %sin use, counted=%d\n", 1165 printf("Zone %d: %sin use, counted=%d\n",
1167 i,zone_in_use(i)?"":"not ",zone_count[i]); 1166 i, zone_in_use(i) ? "" : "not ", zone_count[i]);
1168 } 1167 }
1169} 1168}
1170 1169
1171#ifdef HAVE_MINIX2 1170#ifdef HAVE_MINIX2
1172static void 1171static void check_counts2(void)
1173check_counts2 (void)
1174{ 1172{
1175 int i; 1173 int i;
1176 1174
1177 for (i = 1; i <= INODES; i++) { 1175 for (i = 1; i <= INODES; i++) {
1178 if (!inode_in_use (i) && Inode2[i].i_mode && warn_mode) { 1176 if (!inode_in_use(i) && Inode2[i].i_mode && warn_mode) {
1179 printf ("Inode %d mode not cleared.", i); 1177 printf("Inode %d mode not cleared.", i);
1180 if (ask ("Clear", 1)) { 1178 if (ask("Clear", 1)) {
1181 Inode2[i].i_mode = 0; 1179 Inode2[i].i_mode = 0;
1182 changed = 1; 1180 changed = 1;
1183 } 1181 }
1184 } 1182 }
1185 if (!inode_count[i]) { 1183 if (!inode_count[i]) {
1186 if (!inode_in_use (i)) 1184 if (!inode_in_use(i))
1187 continue; 1185 continue;
1188 printf ("Inode %d not used, marked used in the bitmap.", i); 1186 printf("Inode %d not used, marked used in the bitmap.", i);
1189 if (ask ("Clear", 1)) 1187 if (ask("Clear", 1))
1190 unmark_inode (i); 1188 unmark_inode(i);
1191 continue; 1189 continue;
1192 } 1190 }
1193 if (!inode_in_use (i)) { 1191 if (!inode_in_use(i)) {
1194 printf ("Inode %d used, marked unused in the bitmap.", i); 1192 printf("Inode %d used, marked unused in the bitmap.", i);
1195 if (ask ("Set", 1)) 1193 if (ask("Set", 1))
1196 mark_inode (i); 1194 mark_inode(i);
1197 } 1195 }
1198 if (Inode2[i].i_nlinks != inode_count[i]) { 1196 if (Inode2[i].i_nlinks != inode_count[i]) {
1199 printf ("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", 1197 printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.",
1200 i, Inode2[i].i_mode, Inode2[i].i_nlinks, inode_count[i]); 1198 i, Inode2[i].i_mode, Inode2[i].i_nlinks,
1201 if (ask ("Set i_nlinks to count", 1)) { 1199 inode_count[i]);
1200 if (ask("Set i_nlinks to count", 1)) {
1202 Inode2[i].i_nlinks = inode_count[i]; 1201 Inode2[i].i_nlinks = inode_count[i];
1203 changed = 1; 1202 changed = 1;
1204 } 1203 }
1205 } 1204 }
1206 } 1205 }
1207 for (i = FIRSTZONE; i < ZONES; i++) { 1206 for (i = FIRSTZONE; i < ZONES; i++) {
1208 if (zone_in_use (i) == zone_count[i]) 1207 if (zone_in_use(i) == zone_count[i])
1209 continue; 1208 continue;
1210 if (!zone_count[i]) { 1209 if (!zone_count[i]) {
1211 if (bad_zone (i)) 1210 if (bad_zone(i))
1212 continue; 1211 continue;
1213 printf ("Zone %d: marked in use, no file uses it.", i); 1212 printf("Zone %d: marked in use, no file uses it.", i);
1214 if (ask ("Unmark", 1)) 1213 if (ask("Unmark", 1))
1215 unmark_zone (i); 1214 unmark_zone(i);
1216 continue; 1215 continue;
1217 } 1216 }
1218 printf ("Zone %d: %sin use, counted=%d\n", 1217 printf("Zone %d: %sin use, counted=%d\n",
1219 i, zone_in_use (i) ? "" : "not ", zone_count[i]); 1218 i, zone_in_use(i) ? "" : "not ", zone_count[i]);
1220 } 1219 }
1221} 1220}
1222#endif 1221#endif
1223 1222
1224static void check(void) 1223static void check(void)
1225{ 1224{
1226 memset(inode_count,0,(INODES + 1) * sizeof(*inode_count)); 1225 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
1227 memset(zone_count,0,ZONES*sizeof(*zone_count)); 1226 memset(zone_count, 0, ZONES * sizeof(*zone_count));
1228 check_zones(ROOT_INO); 1227 check_zones(ROOT_INO);
1229 recursive_check(ROOT_INO); 1228 recursive_check(ROOT_INO);
1230 check_counts(); 1229 check_counts();
1231} 1230}
1232 1231
1233#ifdef HAVE_MINIX2 1232#ifdef HAVE_MINIX2
1234static void 1233static void check2(void)
1235check2 (void)
1236{ 1234{
1237 memset (inode_count, 0, (INODES + 1) * sizeof (*inode_count)); 1235 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
1238 memset (zone_count, 0, ZONES * sizeof (*zone_count)); 1236 memset(zone_count, 0, ZONES * sizeof(*zone_count));
1239 check_zones2 (ROOT_INO); 1237 check_zones2(ROOT_INO);
1240 recursive_check2 (ROOT_INO); 1238 recursive_check2(ROOT_INO);
1241 check_counts2 (); 1239 check_counts2();
1242} 1240}
1243#endif 1241#endif
1244 1242
1245extern int 1243extern int fsck_minix_main(int argc, char **argv)
1246fsck_minix_main(int argc, char ** argv)
1247{ 1244{
1248 struct termios tmp; 1245 struct termios tmp;
1249 int count; 1246 int count;
@@ -1264,29 +1261,47 @@ fsck_minix_main(int argc, char ** argv)
1264 show_usage(); 1261 show_usage();
1265 else 1262 else
1266 device_name = argv[0]; 1263 device_name = argv[0];
1267 } else while (*++argv[0]) 1264 } else
1268 switch (argv[0][0]) { 1265 while (*++argv[0])
1269 case 'l': list=1; break; 1266 switch (argv[0][0]) {
1270 case 'a': automatic=1; repair=1; break; 1267 case 'l':
1271 case 'r': automatic=0; repair=1; break; 1268 list = 1;
1272 case 'v': verbose=1; break; 1269 break;
1273 case 's': show=1; break; 1270 case 'a':
1274 case 'm': warn_mode=1; break; 1271 automatic = 1;
1275 case 'f': force=1; break; 1272 repair = 1;
1276 default: show_usage(); 1273 break;
1277 } 1274 case 'r':
1275 automatic = 0;
1276 repair = 1;
1277 break;
1278 case 'v':
1279 verbose = 1;
1280 break;
1281 case 's':
1282 show = 1;
1283 break;
1284 case 'm':
1285 warn_mode = 1;
1286 break;
1287 case 'f':
1288 force = 1;
1289 break;
1290 default:
1291 show_usage();
1292 }
1278 } 1293 }
1279 if (!device_name) 1294 if (!device_name)
1280 show_usage(); 1295 show_usage();
1281 check_mount(); /* trying to check a mounted filesystem? */ 1296 check_mount(); /* trying to check a mounted filesystem? */
1282 if (repair && !automatic) { 1297 if (repair && !automatic) {
1283 if (!isatty(0) || !isatty(1)) 1298 if (!isatty(0) || !isatty(1))
1284 die("need terminal for interactive repairs"); 1299 die("need terminal for interactive repairs");
1285 } 1300 }
1286 IN = open(device_name,repair?O_RDWR:O_RDONLY); 1301 IN = open(device_name, repair ? O_RDWR : O_RDONLY);
1287 if (IN < 0) 1302 if (IN < 0)
1288 die("unable to open '%s'"); 1303 die("unable to open '%s'");
1289 for (count=0 ; count<3 ; count++) 1304 for (count = 0; count < 3; count++)
1290 sync(); 1305 sync();
1291 read_superblock(); 1306 read_superblock();
1292 1307
@@ -1297,80 +1312,77 @@ fsck_minix_main(int argc, char ** argv)
1297 * command line. 1312 * command line.
1298 */ 1313 */
1299 printf("%s, %s\n", program_name, program_version); 1314 printf("%s, %s\n", program_name, program_version);
1300 if ( !(Super.s_state & MINIX_ERROR_FS) && 1315 if (!(Super.s_state & MINIX_ERROR_FS) &&
1301 (Super.s_state & MINIX_VALID_FS) && 1316 (Super.s_state & MINIX_VALID_FS) && !force) {
1302 !force ) {
1303 if (repair) 1317 if (repair)
1304 printf("%s is clean, no check.\n", device_name); 1318 printf("%s is clean, no check.\n", device_name);
1305 return retcode; 1319 return retcode;
1306 } 1320 } else if (force)
1307 else if (force)
1308 printf("Forcing filesystem check on %s.\n", device_name); 1321 printf("Forcing filesystem check on %s.\n", device_name);
1309 else if (repair) 1322 else if (repair)
1310 printf("Filesystem on %s is dirty, needs checking.\n",\ 1323 printf("Filesystem on %s is dirty, needs checking.\n",
1311 device_name); 1324 device_name);
1312 1325
1313 read_tables(); 1326 read_tables();
1314 1327
1315 if (repair && !automatic) { 1328 if (repair && !automatic) {
1316 tcgetattr(0,&termios); 1329 tcgetattr(0, &termios);
1317 tmp = termios; 1330 tmp = termios;
1318 tmp.c_lflag &= ~(ICANON|ECHO); 1331 tmp.c_lflag &= ~(ICANON | ECHO);
1319 tcsetattr(0,TCSANOW,&tmp); 1332 tcsetattr(0, TCSANOW, &tmp);
1320 termios_set = 1; 1333 termios_set = 1;
1321 } 1334 }
1322
1323#if HAVE_MINIX2 1335#if HAVE_MINIX2
1324 if (version2) { 1336 if (version2) {
1325 check_root2 (); 1337 check_root2();
1326 check2 (); 1338 check2();
1327 } else 1339 } else
1328#endif 1340#endif
1329 { 1341 {
1330 check_root(); 1342 check_root();
1331 check(); 1343 check();
1332 } 1344 }
1333 if (verbose) { 1345 if (verbose) {
1334 int i, free; 1346 int i, free;
1335 1347
1336 for (i=1,free=0 ; i <= INODES ; i++) 1348 for (i = 1, free = 0; i <= INODES; i++)
1337 if (!inode_in_use(i)) 1349 if (!inode_in_use(i))
1338 free++; 1350 free++;
1339 printf("\n%6ld inodes used (%ld%%)\n",(INODES-free), 1351 printf("\n%6ld inodes used (%ld%%)\n", (INODES - free),
1340 100*(INODES-free)/INODES); 1352 100 * (INODES - free) / INODES);
1341 for (i=FIRSTZONE,free=0 ; i < ZONES ; i++) 1353 for (i = FIRSTZONE, free = 0; i < ZONES; i++)
1342 if (!zone_in_use(i)) 1354 if (!zone_in_use(i))
1343 free++; 1355 free++;
1344 printf("%6ld zones used (%ld%%)\n",(ZONES-free), 1356 printf("%6ld zones used (%ld%%)\n", (ZONES - free),
1345 100*(ZONES-free)/ZONES); 1357 100 * (ZONES - free) / ZONES);
1346 printf("\n%6d regular files\n" 1358 printf("\n%6d regular files\n"
1347 "%6d directories\n" 1359 "%6d directories\n"
1348 "%6d character device files\n" 1360 "%6d character device files\n"
1349 "%6d block device files\n" 1361 "%6d block device files\n"
1350 "%6d links\n" 1362 "%6d links\n"
1351 "%6d symbolic links\n" 1363 "%6d symbolic links\n"
1352 "------\n" 1364 "------\n"
1353 "%6d files\n", 1365 "%6d files\n",
1354 regular,directory,chardev,blockdev, 1366 regular, directory, chardev, blockdev,
1355 links-2*directory+1,symlinks,total-2*directory+1); 1367 links - 2 * directory + 1, symlinks,
1368 total - 2 * directory + 1);
1356 } 1369 }
1357 if (changed) { 1370 if (changed) {
1358 write_tables(); 1371 write_tables();
1359 printf( "----------------------------\n" 1372 printf("----------------------------\n"
1360 "FILE SYSTEM HAS BEEN CHANGED\n" 1373 "FILE SYSTEM HAS BEEN CHANGED\n"
1361 "----------------------------\n"); 1374 "----------------------------\n");
1362 for (count=0 ; count<3 ; count++) 1375 for (count = 0; count < 3; count++)
1363 sync(); 1376 sync();
1364 } 1377 } else if (repair)
1365 else if ( repair )
1366 write_super_block(); 1378 write_super_block();
1367 1379
1368 if (repair && !automatic) 1380 if (repair && !automatic)
1369 tcsetattr(0,TCSANOW,&termios); 1381 tcsetattr(0, TCSANOW, &termios);
1370 1382
1371 if (changed) 1383 if (changed)
1372 retcode += 3; 1384 retcode += 3;
1373 if (errors_uncorrected) 1385 if (errors_uncorrected)
1374 retcode += 4; 1386 retcode += 4;
1375 return retcode; 1387 return retcode;
1376} 1388}
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index b90d3a700..4435cb64a 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * mkfs.c - make a linux (minix) file-system. 3 * mkfs.c - make a linux (minix) file-system.
3 * 4 *
@@ -107,27 +108,30 @@
107 108
108#define BITS_PER_BLOCK (BLOCK_SIZE<<3) 109#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
109 110
110static char * program_name = "mkfs"; 111static char *program_name = "mkfs";
111static char * device_name = NULL; 112static char *device_name = NULL;
112static int DEV = -1; 113static int DEV = -1;
113static long BLOCKS = 0; 114static long BLOCKS = 0;
114static int check = 0; 115static int check = 0;
115static int badblocks = 0; 116static int badblocks = 0;
116static int namelen = 30; /* default (changed to 30, per Linus's 117static int namelen = 30; /* default (changed to 30, per Linus's
117 suggestion, Sun Nov 21 08:05:07 1993) */ 118
119 suggestion, Sun Nov 21 08:05:07 1993) */
118static int dirsize = 32; 120static int dirsize = 32;
119static int magic = MINIX_SUPER_MAGIC2; 121static int magic = MINIX_SUPER_MAGIC2;
120static int version2 = 0; 122static int version2 = 0;
121 123
122static char root_block[BLOCK_SIZE] = "\0"; 124static char root_block[BLOCK_SIZE] = "\0";
123 125
124static char * inode_buffer = NULL; 126static char *inode_buffer = NULL;
127
125#define Inode (((struct minix_inode *) inode_buffer)-1) 128#define Inode (((struct minix_inode *) inode_buffer)-1)
126#ifdef HAVE_MINIX2 129#ifdef HAVE_MINIX2
127#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 130#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
128#endif 131#endif
129static char super_block_buffer[BLOCK_SIZE]; 132static char super_block_buffer[BLOCK_SIZE];
130static char boot_block_buffer[512]; 133static char boot_block_buffer[512];
134
131#define Super (*(struct minix_super_block *)super_block_buffer) 135#define Super (*(struct minix_super_block *)super_block_buffer)
132#define INODES ((unsigned long)Super.s_ninodes) 136#define INODES ((unsigned long)Super.s_ninodes)
133#ifdef HAVE_MINIX2 137#ifdef HAVE_MINIX2
@@ -164,21 +168,28 @@ static unsigned long req_nr_inodes = 0;
164 * to compile this under minix, volatile gives a warning, as 168 * to compile this under minix, volatile gives a warning, as
165 * exit() isn't defined as volatile under minix. 169 * exit() isn't defined as volatile under minix.
166 */ 170 */
167static volatile void die(char *str) { 171static volatile void die(char *str)
172{
168 fprintf(stderr, "%s: %s\n", program_name, str); 173 fprintf(stderr, "%s: %s\n", program_name, str);
169 exit(8); 174 exit(8);
170} 175}
171 176
172static volatile void show_usage() 177static volatile void show_usage()
173{ 178{
174 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); 179 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
175 fprintf(stderr, "Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n\n", program_name); 180 BB_VER, BB_BT);
181 fprintf(stderr,
182 "Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n\n",
183 program_name);
176 fprintf(stderr, "Make a MINIX filesystem.\n\n"); 184 fprintf(stderr, "Make a MINIX filesystem.\n\n");
177 fprintf(stderr, "OPTIONS:\n"); 185 fprintf(stderr, "OPTIONS:\n");
178 fprintf(stderr, "\t-c\t\tCheck the device for bad blocks\n"); 186 fprintf(stderr, "\t-c\t\tCheck the device for bad blocks\n");
179 fprintf(stderr, "\t-n [14|30]\tSpecify the maximum length of filenames\n"); 187 fprintf(stderr,
180 fprintf(stderr, "\t-i\t\tSpecify the number of inodes for the filesystem\n"); 188 "\t-n [14|30]\tSpecify the maximum length of filenames\n");
181 fprintf(stderr, "\t-l FILENAME\tRead the bad blocks list from FILENAME\n"); 189 fprintf(stderr,
190 "\t-i\t\tSpecify the number of inodes for the filesystem\n");
191 fprintf(stderr,
192 "\t-l FILENAME\tRead the bad blocks list from FILENAME\n");
182 fprintf(stderr, "\t-v\t\tMake a Minix version 2 filesystem\n\n"); 193 fprintf(stderr, "\t-v\t\tMake a Minix version 2 filesystem\n\n");
183 exit(16); 194 exit(16);
184} 195}
@@ -190,56 +201,55 @@ static volatile void show_usage()
190 */ 201 */
191static void check_mount(void) 202static void check_mount(void)
192{ 203{
193 FILE * f; 204 FILE *f;
194 struct mntent * mnt; 205 struct mntent *mnt;
195 206
196 if ((f = setmntent (MOUNTED, "r")) == NULL) 207 if ((f = setmntent(MOUNTED, "r")) == NULL)
197 return; 208 return;
198 while ((mnt = getmntent (f)) != NULL) 209 while ((mnt = getmntent(f)) != NULL)
199 if (strcmp (device_name, mnt->mnt_fsname) == 0) 210 if (strcmp(device_name, mnt->mnt_fsname) == 0)
200 break; 211 break;
201 endmntent (f); 212 endmntent(f);
202 if (!mnt) 213 if (!mnt)
203 return; 214 return;
204 215
205 die("%s is mounted; will not make a filesystem here!"); 216 die("%s is mounted; will not make a filesystem here!");
206} 217}
207 218
208static long valid_offset (int fd, int offset) 219static long valid_offset(int fd, int offset)
209{ 220{
210 char ch; 221 char ch;
211 222
212 if (lseek (fd, offset, 0) < 0) 223 if (lseek(fd, offset, 0) < 0)
213 return 0; 224 return 0;
214 if (read (fd, &ch, 1) < 1) 225 if (read(fd, &ch, 1) < 1)
215 return 0; 226 return 0;
216 return 1; 227 return 1;
217} 228}
218 229
219static int count_blocks (int fd) 230static int count_blocks(int fd)
220{ 231{
221 int high, low; 232 int high, low;
222 233
223 low = 0; 234 low = 0;
224 for (high = 1; valid_offset (fd, high); high *= 2) 235 for (high = 1; valid_offset(fd, high); high *= 2)
225 low = high; 236 low = high;
226 while (low < high - 1) 237 while (low < high - 1) {
227 {
228 const int mid = (low + high) / 2; 238 const int mid = (low + high) / 2;
229 239
230 if (valid_offset (fd, mid)) 240 if (valid_offset(fd, mid))
231 low = mid; 241 low = mid;
232 else 242 else
233 high = mid; 243 high = mid;
234 } 244 }
235 valid_offset (fd, 0); 245 valid_offset(fd, 0);
236 return (low + 1); 246 return (low + 1);
237} 247}
238 248
239static int get_size(const char *file) 249static int get_size(const char *file)
240{ 250{
241 int fd; 251 int fd;
242 long size; 252 long size;
243 253
244 fd = open(file, O_RDWR); 254 fd = open(file, O_RDWR);
245 if (fd < 0) { 255 if (fd < 0) {
@@ -250,7 +260,7 @@ static int get_size(const char *file)
250 close(fd); 260 close(fd);
251 return (size * 512); 261 return (size * 512);
252 } 262 }
253 263
254 size = count_blocks(fd); 264 size = count_blocks(fd);
255 close(fd); 265 close(fd);
256 return size; 266 return size;
@@ -270,18 +280,18 @@ static void write_tables(void)
270 die("seek failed in write_tables"); 280 die("seek failed in write_tables");
271 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) 281 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
272 die("unable to write super-block"); 282 die("unable to write super-block");
273 if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE)) 283 if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE))
274 die("unable to write inode map"); 284 die("unable to write inode map");
275 if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE)) 285 if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE))
276 die("unable to write zone map"); 286 die("unable to write zone map");
277 if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE)) 287 if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE))
278 die("unable to write inodes"); 288 die("unable to write inodes");
279 289
280} 290}
281 291
282static void write_block(int blk, char * buffer) 292static void write_block(int blk, char *buffer)
283{ 293{
284 if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET)) 294 if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET))
285 die("seek failed in write_block"); 295 die("seek failed in write_block");
286 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) 296 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
287 die("write failed in write_block"); 297 die("write failed in write_block");
@@ -291,10 +301,10 @@ static int get_free_block(void)
291{ 301{
292 int blk; 302 int blk;
293 303
294 if (used_good_blocks+1 >= MAX_GOOD_BLOCKS) 304 if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
295 die("too many bad blocks"); 305 die("too many bad blocks");
296 if (used_good_blocks) 306 if (used_good_blocks)
297 blk = good_blocks_table[used_good_blocks-1]+1; 307 blk = good_blocks_table[used_good_blocks - 1] + 1;
298 else 308 else
299 blk = FIRSTZONE; 309 blk = FIRSTZONE;
300 while (blk < ZONES && zone_in_use(blk)) 310 while (blk < ZONES && zone_in_use(blk))
@@ -310,14 +320,14 @@ static void mark_good_blocks(void)
310{ 320{
311 int blk; 321 int blk;
312 322
313 for (blk=0 ; blk < used_good_blocks ; blk++) 323 for (blk = 0; blk < used_good_blocks; blk++)
314 mark_zone(good_blocks_table[blk]); 324 mark_zone(good_blocks_table[blk]);
315} 325}
316 326
317inline int next(int zone) 327inline int next(int zone)
318{ 328{
319 if (!zone) 329 if (!zone)
320 zone = FIRSTZONE-1; 330 zone = FIRSTZONE - 1;
321 while (++zone < ZONES) 331 while (++zone < ZONES)
322 if (zone_in_use(zone)) 332 if (zone_in_use(zone))
323 return zone; 333 return zone;
@@ -326,11 +336,11 @@ inline int next(int zone)
326 336
327static void make_bad_inode(void) 337static void make_bad_inode(void)
328{ 338{
329 struct minix_inode * inode = &Inode[MINIX_BAD_INO]; 339 struct minix_inode *inode = &Inode[MINIX_BAD_INO];
330 int i,j,zone; 340 int i, j, zone;
331 int ind=0,dind=0; 341 int ind = 0, dind = 0;
332 unsigned short ind_block[BLOCK_SIZE>>1]; 342 unsigned short ind_block[BLOCK_SIZE >> 1];
333 unsigned short dind_block[BLOCK_SIZE>>1]; 343 unsigned short dind_block[BLOCK_SIZE >> 1];
334 344
335#define NEXT_BAD (zone = next(zone)) 345#define NEXT_BAD (zone = next(zone))
336 346
@@ -340,34 +350,34 @@ static void make_bad_inode(void)
340 inode->i_nlinks = 1; 350 inode->i_nlinks = 1;
341 inode->i_time = time(NULL); 351 inode->i_time = time(NULL);
342 inode->i_mode = S_IFREG + 0000; 352 inode->i_mode = S_IFREG + 0000;
343 inode->i_size = badblocks*BLOCK_SIZE; 353 inode->i_size = badblocks * BLOCK_SIZE;
344 zone = next(0); 354 zone = next(0);
345 for (i=0 ; i<7 ; i++) { 355 for (i = 0; i < 7; i++) {
346 inode->i_zone[i] = zone; 356 inode->i_zone[i] = zone;
347 if (!NEXT_BAD) 357 if (!NEXT_BAD)
348 goto end_bad; 358 goto end_bad;
349 } 359 }
350 inode->i_zone[7] = ind = get_free_block(); 360 inode->i_zone[7] = ind = get_free_block();
351 memset(ind_block,0,BLOCK_SIZE); 361 memset(ind_block, 0, BLOCK_SIZE);
352 for (i=0 ; i<512 ; i++) { 362 for (i = 0; i < 512; i++) {
353 ind_block[i] = zone; 363 ind_block[i] = zone;
354 if (!NEXT_BAD) 364 if (!NEXT_BAD)
355 goto end_bad; 365 goto end_bad;
356 } 366 }
357 inode->i_zone[8] = dind = get_free_block(); 367 inode->i_zone[8] = dind = get_free_block();
358 memset(dind_block,0,BLOCK_SIZE); 368 memset(dind_block, 0, BLOCK_SIZE);
359 for (i=0 ; i<512 ; i++) { 369 for (i = 0; i < 512; i++) {
360 write_block(ind,(char *) ind_block); 370 write_block(ind, (char *) ind_block);
361 dind_block[i] = ind = get_free_block(); 371 dind_block[i] = ind = get_free_block();
362 memset(ind_block,0,BLOCK_SIZE); 372 memset(ind_block, 0, BLOCK_SIZE);
363 for (j=0 ; j<512 ; j++) { 373 for (j = 0; j < 512; j++) {
364 ind_block[j] = zone; 374 ind_block[j] = zone;
365 if (!NEXT_BAD) 375 if (!NEXT_BAD)
366 goto end_bad; 376 goto end_bad;
367 } 377 }
368 } 378 }
369 die("too many bad blocks"); 379 die("too many bad blocks");
370end_bad: 380 end_bad:
371 if (ind) 381 if (ind)
372 write_block(ind, (char *) ind_block); 382 write_block(ind, (char *) ind_block);
373 if (dind) 383 if (dind)
@@ -375,8 +385,7 @@ end_bad:
375} 385}
376 386
377#ifdef HAVE_MINIX2 387#ifdef HAVE_MINIX2
378static void 388static void make_bad_inode2(void)
379make_bad_inode2 (void)
380{ 389{
381 struct minix2_inode *inode = &Inode2[MINIX_BAD_INO]; 390 struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
382 int i, j, zone; 391 int i, j, zone;
@@ -386,30 +395,30 @@ make_bad_inode2 (void)
386 395
387 if (!badblocks) 396 if (!badblocks)
388 return; 397 return;
389 mark_inode (MINIX_BAD_INO); 398 mark_inode(MINIX_BAD_INO);
390 inode->i_nlinks = 1; 399 inode->i_nlinks = 1;
391 inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL); 400 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
392 inode->i_mode = S_IFREG + 0000; 401 inode->i_mode = S_IFREG + 0000;
393 inode->i_size = badblocks * BLOCK_SIZE; 402 inode->i_size = badblocks * BLOCK_SIZE;
394 zone = next (0); 403 zone = next(0);
395 for (i = 0; i < 7; i++) { 404 for (i = 0; i < 7; i++) {
396 inode->i_zone[i] = zone; 405 inode->i_zone[i] = zone;
397 if (!NEXT_BAD) 406 if (!NEXT_BAD)
398 goto end_bad; 407 goto end_bad;
399 } 408 }
400 inode->i_zone[7] = ind = get_free_block (); 409 inode->i_zone[7] = ind = get_free_block();
401 memset (ind_block, 0, BLOCK_SIZE); 410 memset(ind_block, 0, BLOCK_SIZE);
402 for (i = 0; i < 256; i++) { 411 for (i = 0; i < 256; i++) {
403 ind_block[i] = zone; 412 ind_block[i] = zone;
404 if (!NEXT_BAD) 413 if (!NEXT_BAD)
405 goto end_bad; 414 goto end_bad;
406 } 415 }
407 inode->i_zone[8] = dind = get_free_block (); 416 inode->i_zone[8] = dind = get_free_block();
408 memset (dind_block, 0, BLOCK_SIZE); 417 memset(dind_block, 0, BLOCK_SIZE);
409 for (i = 0; i < 256; i++) { 418 for (i = 0; i < 256; i++) {
410 write_block (ind, (char *) ind_block); 419 write_block(ind, (char *) ind_block);
411 dind_block[i] = ind = get_free_block (); 420 dind_block[i] = ind = get_free_block();
412 memset (ind_block, 0, BLOCK_SIZE); 421 memset(ind_block, 0, BLOCK_SIZE);
413 for (j = 0; j < 256; j++) { 422 for (j = 0; j < 256; j++) {
414 ind_block[j] = zone; 423 ind_block[j] = zone;
415 if (!NEXT_BAD) 424 if (!NEXT_BAD)
@@ -417,47 +426,46 @@ make_bad_inode2 (void)
417 } 426 }
418 } 427 }
419 /* Could make triple indirect block here */ 428 /* Could make triple indirect block here */
420 die ("too many bad blocks"); 429 die("too many bad blocks");
421 end_bad: 430 end_bad:
422 if (ind) 431 if (ind)
423 write_block (ind, (char *) ind_block); 432 write_block(ind, (char *) ind_block);
424 if (dind) 433 if (dind)
425 write_block (dind, (char *) dind_block); 434 write_block(dind, (char *) dind_block);
426} 435}
427#endif 436#endif
428 437
429static void make_root_inode(void) 438static void make_root_inode(void)
430{ 439{
431 struct minix_inode * inode = &Inode[MINIX_ROOT_INO]; 440 struct minix_inode *inode = &Inode[MINIX_ROOT_INO];
432 441
433 mark_inode(MINIX_ROOT_INO); 442 mark_inode(MINIX_ROOT_INO);
434 inode->i_zone[0] = get_free_block(); 443 inode->i_zone[0] = get_free_block();
435 inode->i_nlinks = 2; 444 inode->i_nlinks = 2;
436 inode->i_time = time(NULL); 445 inode->i_time = time(NULL);
437 if (badblocks) 446 if (badblocks)
438 inode->i_size = 3*dirsize; 447 inode->i_size = 3 * dirsize;
439 else { 448 else {
440 root_block[2*dirsize] = '\0'; 449 root_block[2 * dirsize] = '\0';
441 root_block[2*dirsize+1] = '\0'; 450 root_block[2 * dirsize + 1] = '\0';
442 inode->i_size = 2*dirsize; 451 inode->i_size = 2 * dirsize;
443 } 452 }
444 inode->i_mode = S_IFDIR + 0755; 453 inode->i_mode = S_IFDIR + 0755;
445 inode->i_uid = getuid(); 454 inode->i_uid = getuid();
446 if (inode->i_uid) 455 if (inode->i_uid)
447 inode->i_gid = getgid(); 456 inode->i_gid = getgid();
448 write_block(inode->i_zone[0],root_block); 457 write_block(inode->i_zone[0], root_block);
449} 458}
450 459
451#ifdef HAVE_MINIX2 460#ifdef HAVE_MINIX2
452static void 461static void make_root_inode2(void)
453make_root_inode2 (void)
454{ 462{
455 struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO]; 463 struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO];
456 464
457 mark_inode (MINIX_ROOT_INO); 465 mark_inode(MINIX_ROOT_INO);
458 inode->i_zone[0] = get_free_block (); 466 inode->i_zone[0] = get_free_block();
459 inode->i_nlinks = 2; 467 inode->i_nlinks = 2;
460 inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL); 468 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
461 if (badblocks) 469 if (badblocks)
462 inode->i_size = 3 * dirsize; 470 inode->i_size = 3 * dirsize;
463 else { 471 else {
@@ -469,7 +477,7 @@ make_root_inode2 (void)
469 inode->i_uid = getuid(); 477 inode->i_uid = getuid();
470 if (inode->i_uid) 478 if (inode->i_uid)
471 inode->i_gid = getgid(); 479 inode->i_gid = getgid();
472 write_block (inode->i_zone[0], root_block); 480 write_block(inode->i_zone[0], root_block);
473} 481}
474#endif 482#endif
475 483
@@ -478,34 +486,38 @@ static void setup_tables(void)
478 int i; 486 int i;
479 unsigned long inodes; 487 unsigned long inodes;
480 488
481 memset(super_block_buffer,0,BLOCK_SIZE); 489 memset(super_block_buffer, 0, BLOCK_SIZE);
482 memset(boot_block_buffer,0,512); 490 memset(boot_block_buffer, 0, 512);
483 MAGIC = magic; 491 MAGIC = magic;
484 ZONESIZE = 0; 492 ZONESIZE = 0;
485 MAXSIZE = version2 ? 0x7fffffff : (7+512+512*512)*1024; 493 MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
486 ZONES = BLOCKS; 494 ZONES = BLOCKS;
487/* some magic nrs: 1 inode / 3 blocks */ 495/* some magic nrs: 1 inode / 3 blocks */
488 if ( req_nr_inodes == 0 ) 496 if (req_nr_inodes == 0)
489 inodes = BLOCKS/3; 497 inodes = BLOCKS / 3;
490 else 498 else
491 inodes = req_nr_inodes; 499 inodes = req_nr_inodes;
492 /* Round up inode count to fill block size */ 500 /* Round up inode count to fill block size */
493#ifdef HAVE_MINIX2 501#ifdef HAVE_MINIX2
494 if (version2) 502 if (version2)
495 inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & 503 inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
496 ~(MINIX2_INODES_PER_BLOCK - 1)); 504 ~(MINIX2_INODES_PER_BLOCK - 1));
497 else 505 else
498#endif 506#endif
499 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & 507 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
500 ~(MINIX_INODES_PER_BLOCK - 1)); 508 ~(MINIX_INODES_PER_BLOCK - 1));
501 if (inodes > 65535) 509 if (inodes > 65535)
502 inodes = 65535; 510 inodes = 65535;
503 INODES = inodes; 511 INODES = inodes;
504 IMAPS = UPPER(INODES + 1,BITS_PER_BLOCK); 512 IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK);
505 ZMAPS = 0; 513 ZMAPS = 0;
506 i=0; 514 i = 0;
507 while (ZMAPS != UPPER(BLOCKS - (2+IMAPS+ZMAPS+INODE_BLOCKS) + 1,BITS_PER_BLOCK) && i<1000) { 515 while (ZMAPS !=
508 ZMAPS = UPPER(BLOCKS - (2+IMAPS+ZMAPS+INODE_BLOCKS) + 1,BITS_PER_BLOCK); 516 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
517 BITS_PER_BLOCK) && i < 1000) {
518 ZMAPS =
519 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
520 BITS_PER_BLOCK);
509 i++; 521 i++;
510 } 522 }
511 /* Real bad hack but overwise mkfs.minix can be thrown 523 /* Real bad hack but overwise mkfs.minix can be thrown
@@ -514,50 +526,51 @@ static void setup_tables(void)
514 * dd if=/dev/zero of=test.fs count=10 bs=1024 526 * dd if=/dev/zero of=test.fs count=10 bs=1024
515 * /sbin/mkfs.minix -i 200 test.fs 527 * /sbin/mkfs.minix -i 200 test.fs
516 * */ 528 * */
517 if (i>=999) { 529 if (i >= 999) {
518 die ("unable to allocate buffers for maps"); 530 die("unable to allocate buffers for maps");
519 } 531 }
520 FIRSTZONE = NORM_FIRSTZONE; 532 FIRSTZONE = NORM_FIRSTZONE;
521 inode_map = malloc(IMAPS * BLOCK_SIZE); 533 inode_map = malloc(IMAPS * BLOCK_SIZE);
522 zone_map = malloc(ZMAPS * BLOCK_SIZE); 534 zone_map = malloc(ZMAPS * BLOCK_SIZE);
523 if (!inode_map || !zone_map) 535 if (!inode_map || !zone_map)
524 die("unable to allocate buffers for maps"); 536 die("unable to allocate buffers for maps");
525 memset(inode_map,0xff,IMAPS * BLOCK_SIZE); 537 memset(inode_map, 0xff, IMAPS * BLOCK_SIZE);
526 memset(zone_map,0xff,ZMAPS * BLOCK_SIZE); 538 memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE);
527 for (i = FIRSTZONE ; i<ZONES ; i++) 539 for (i = FIRSTZONE; i < ZONES; i++)
528 unmark_zone(i); 540 unmark_zone(i);
529 for (i = MINIX_ROOT_INO ; i<=INODES ; i++) 541 for (i = MINIX_ROOT_INO; i <= INODES; i++)
530 unmark_inode(i); 542 unmark_inode(i);
531 inode_buffer = malloc(INODE_BUFFER_SIZE); 543 inode_buffer = malloc(INODE_BUFFER_SIZE);
532 if (!inode_buffer) 544 if (!inode_buffer)
533 die("unable to allocate buffer for inodes"); 545 die("unable to allocate buffer for inodes");
534 memset(inode_buffer,0,INODE_BUFFER_SIZE); 546 memset(inode_buffer, 0, INODE_BUFFER_SIZE);
535 printf("%ld inodes\n",INODES); 547 printf("%ld inodes\n", INODES);
536 printf("%ld blocks\n",ZONES); 548 printf("%ld blocks\n", ZONES);
537 printf("Firstdatazone=%ld (%ld)\n",FIRSTZONE,NORM_FIRSTZONE); 549 printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE);
538 printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); 550 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
539 printf("Maxsize=%ld\n\n",MAXSIZE); 551 printf("Maxsize=%ld\n\n", MAXSIZE);
540} 552}
541 553
542/* 554/*
543 * Perform a test of a block; return the number of 555 * Perform a test of a block; return the number of
544 * blocks readable/writeable. 556 * blocks readable/writeable.
545 */ 557 */
546long do_check(char * buffer, int try, unsigned int current_block) 558long do_check(char *buffer, int try, unsigned int current_block)
547{ 559{
548 long got; 560 long got;
549 561
550 /* Seek to the correct loc. */ 562 /* Seek to the correct loc. */
551 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != 563 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
552 current_block * BLOCK_SIZE ) { 564 current_block * BLOCK_SIZE) {
553 die("seek failed during testing of blocks"); 565 die("seek failed during testing of blocks");
554 } 566 }
555 567
556 568
557 /* Try the read */ 569 /* Try the read */
558 got = read(DEV, buffer, try * BLOCK_SIZE); 570 got = read(DEV, buffer, try * BLOCK_SIZE);
559 if (got < 0) got = 0; 571 if (got < 0)
560 if (got & (BLOCK_SIZE - 1 )) { 572 got = 0;
573 if (got & (BLOCK_SIZE - 1)) {
561 printf("Weird values in do_check: probably bugs\n"); 574 printf("Weird values in do_check: probably bugs\n");
562 } 575 }
563 got /= BLOCK_SIZE; 576 got /= BLOCK_SIZE;
@@ -570,7 +583,7 @@ static void alarm_intr(int alnum)
570{ 583{
571 if (currently_testing >= ZONES) 584 if (currently_testing >= ZONES)
572 return; 585 return;
573 signal(SIGALRM,alarm_intr); 586 signal(SIGALRM, alarm_intr);
574 alarm(5); 587 alarm(5);
575 if (!currently_testing) 588 if (!currently_testing)
576 return; 589 return;
@@ -580,19 +593,19 @@ static void alarm_intr(int alnum)
580 593
581static void check_blocks(void) 594static void check_blocks(void)
582{ 595{
583 int try,got; 596 int try, got;
584 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 597 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
585 598
586 currently_testing=0; 599 currently_testing = 0;
587 signal(SIGALRM,alarm_intr); 600 signal(SIGALRM, alarm_intr);
588 alarm(5); 601 alarm(5);
589 while (currently_testing < ZONES) { 602 while (currently_testing < ZONES) {
590 if (lseek(DEV,currently_testing*BLOCK_SIZE,SEEK_SET) != 603 if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) !=
591 currently_testing*BLOCK_SIZE) 604 currently_testing * BLOCK_SIZE)
592 die("seek failed in check_blocks"); 605 die("seek failed in check_blocks");
593 try = TEST_BUFFER_BLOCKS; 606 try = TEST_BUFFER_BLOCKS;
594 if (currently_testing + try > ZONES) 607 if (currently_testing + try > ZONES)
595 try = ZONES-currently_testing; 608 try = ZONES - currently_testing;
596 got = do_check(buffer, try, currently_testing); 609 got = do_check(buffer, try, currently_testing);
597 currently_testing += got; 610 currently_testing += got;
598 if (got == try) 611 if (got == try)
@@ -613,139 +626,141 @@ static void get_list_blocks(filename)
613char *filename; 626char *filename;
614 627
615{ 628{
616 FILE *listfile; 629 FILE *listfile;
617 unsigned long blockno; 630 unsigned long blockno;
618 631
619 listfile=fopen(filename,"r"); 632 listfile = fopen(filename, "r");
620 if(listfile == (FILE *)NULL) { 633 if (listfile == (FILE *) NULL) {
621 die("can't open file of bad blocks"); 634 die("can't open file of bad blocks");
622 } 635 }
623 while(!feof(listfile)) { 636 while (!feof(listfile)) {
624 fscanf(listfile,"%ld\n", &blockno); 637 fscanf(listfile, "%ld\n", &blockno);
625 mark_zone(blockno); 638 mark_zone(blockno);
626 badblocks++; 639 badblocks++;
627 } 640 }
628 if(badblocks > 1) 641 if (badblocks > 1)
629 printf("%d bad blocks\n", badblocks); 642 printf("%d bad blocks\n", badblocks);
630 else if (badblocks == 1) 643 else if (badblocks == 1)
631 printf("one bad block\n"); 644 printf("one bad block\n");
632} 645}
633 646
634extern int 647extern int mkfs_minix_main(int argc, char **argv)
635mkfs_minix_main(int argc, char ** argv)
636{ 648{
637 int i; 649 int i;
638 char * tmp; 650 char *tmp;
639 struct stat statbuf; 651 struct stat statbuf;
640 char * listfile = NULL; 652 char *listfile = NULL;
641 653
642 if (argc && *argv) 654 if (argc && *argv)
643 program_name = *argv; 655 program_name = *argv;
644 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 656 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
645 die("bad inode size"); 657 die("bad inode size");
646#ifdef HAVE_MINIX2 658#ifdef HAVE_MINIX2
647 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 659 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
648 die("bad inode size"); 660 die("bad inode size");
649#endif 661#endif
650 opterr = 0; 662 opterr = 0;
651 while ((i = getopt(argc, argv, "ci:l:n:v")) != EOF) 663 while ((i = getopt(argc, argv, "ci:l:n:v")) != EOF)
652 switch (i) { 664 switch (i) {
653 case 'c': 665 case 'c':
654 check=1; break; 666 check = 1;
655 case 'i': 667 break;
656 req_nr_inodes = (unsigned long) atol(optarg); 668 case 'i':
657 break; 669 req_nr_inodes = (unsigned long) atol(optarg);
658 case 'l': 670 break;
659 listfile = optarg; break; 671 case 'l':
660 case 'n': 672 listfile = optarg;
661 i = strtoul(optarg,&tmp,0); 673 break;
662 if (*tmp) 674 case 'n':
663 show_usage(); 675 i = strtoul(optarg, &tmp, 0);
664 if (i == 14) 676 if (*tmp)
665 magic = MINIX_SUPER_MAGIC; 677 show_usage();
666 else if (i == 30) 678 if (i == 14)
667 magic = MINIX_SUPER_MAGIC2; 679 magic = MINIX_SUPER_MAGIC;
668 else 680 else if (i == 30)
669 show_usage(); 681 magic = MINIX_SUPER_MAGIC2;
670 namelen = i; 682 else
671 dirsize = i+2; 683 show_usage();
672 break; 684 namelen = i;
673 case 'v': 685 dirsize = i + 2;
686 break;
687 case 'v':
674#ifdef HAVE_MINIX2 688#ifdef HAVE_MINIX2
675 version2 = 1; 689 version2 = 1;
676#else 690#else
677 fprintf(stderr,"%s: not compiled with minix v2 support\n",program_name,device_name); 691 fprintf(stderr, "%s: not compiled with minix v2 support\n",
678 exit(-1); 692 program_name, device_name);
693 exit(-1);
679#endif 694#endif
680 break; 695 break;
681 default: 696 default:
682 show_usage(); 697 show_usage();
683 } 698 }
684 argc -= optind; 699 argc -= optind;
685 argv += optind; 700 argv += optind;
686 if (argc > 0 && !device_name) { 701 if (argc > 0 && !device_name) {
687 device_name = argv[0]; 702 device_name = argv[0];
688 argc--; 703 argc--;
689 argv++; 704 argv++;
690 } 705 }
691 if (argc > 0) { 706 if (argc > 0) {
692 BLOCKS = strtol(argv[0],&tmp,0); 707 BLOCKS = strtol(argv[0], &tmp, 0);
693 if (*tmp) { 708 if (*tmp) {
694 printf("strtol error: number of blocks not specified"); 709 printf("strtol error: number of blocks not specified");
695 show_usage(); 710 show_usage();
696 } 711 }
697 } 712 }
698 713
699 if (device_name && !BLOCKS) 714 if (device_name && !BLOCKS)
700 BLOCKS = get_size (device_name) / 1024; 715 BLOCKS = get_size(device_name) / 1024;
701 if (!device_name || BLOCKS<10) { 716 if (!device_name || BLOCKS < 10) {
702 show_usage(); 717 show_usage();
703 } 718 }
704#ifdef HAVE_MINIX2 719#ifdef HAVE_MINIX2
705 if (version2) { 720 if (version2) {
706 if (namelen == 14) 721 if (namelen == 14)
707 magic = MINIX2_SUPER_MAGIC; 722 magic = MINIX2_SUPER_MAGIC;
708 else 723 else
709 magic = MINIX2_SUPER_MAGIC2; 724 magic = MINIX2_SUPER_MAGIC2;
710 } else 725 } else
711#endif 726#endif
712 if (BLOCKS > 65535) 727 if (BLOCKS > 65535)
713 BLOCKS = 65535; 728 BLOCKS = 65535;
714 check_mount(); /* is it already mounted? */ 729 check_mount(); /* is it already mounted? */
715 tmp = root_block; 730 tmp = root_block;
716 *(short *)tmp = 1; 731 *(short *) tmp = 1;
717 strcpy(tmp+2,"."); 732 strcpy(tmp + 2, ".");
718 tmp += dirsize; 733 tmp += dirsize;
719 *(short *)tmp = 1; 734 *(short *) tmp = 1;
720 strcpy(tmp+2,".."); 735 strcpy(tmp + 2, "..");
721 tmp += dirsize; 736 tmp += dirsize;
722 *(short *)tmp = 2; 737 *(short *) tmp = 2;
723 strcpy(tmp+2,".badblocks"); 738 strcpy(tmp + 2, ".badblocks");
724 DEV = open(device_name,O_RDWR ); 739 DEV = open(device_name, O_RDWR);
725 if (DEV<0) 740 if (DEV < 0)
726 die("unable to open %s"); 741 die("unable to open %s");
727 if (fstat(DEV,&statbuf)<0) 742 if (fstat(DEV, &statbuf) < 0)
728 die("unable to stat %s"); 743 die("unable to stat %s");
729 if (!S_ISBLK(statbuf.st_mode)) 744 if (!S_ISBLK(statbuf.st_mode))
730 check=0; 745 check = 0;
731 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 746 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
732 die("will not try to make filesystem on '%s'"); 747 die("will not try to make filesystem on '%s'");
733 setup_tables(); 748 setup_tables();
734 if (check) 749 if (check)
735 check_blocks(); 750 check_blocks();
736 else if (listfile) 751 else if (listfile)
737 get_list_blocks(listfile); 752 get_list_blocks(listfile);
738#ifdef HAVE_MINIX2 753#ifdef HAVE_MINIX2
739 if (version2) { 754 if (version2) {
740 make_root_inode2 (); 755 make_root_inode2();
741 make_bad_inode2 (); 756 make_bad_inode2();
742 } else 757 } else
743#endif 758#endif
744 { 759 {
745 make_root_inode(); 760 make_root_inode();
746 make_bad_inode(); 761 make_bad_inode();
747 } 762 }
748 mark_good_blocks(); 763 mark_good_blocks();
749 write_tables(); 764 write_tables();
750 return 0; 765 return 0;
751} 766}
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index 601188f86..130d24162 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * mkswap.c - set up a linux swap device 3 * mkswap.c - set up a linux swap device
3 * 4 *
@@ -40,20 +41,21 @@
40#include <string.h> 41#include <string.h>
41#include <fcntl.h> 42#include <fcntl.h>
42#include <stdlib.h> 43#include <stdlib.h>
43#include <sys/ioctl.h> /* for _IO */ 44#include <sys/ioctl.h> /* for _IO */
44#include <sys/utsname.h> 45#include <sys/utsname.h>
45#include <sys/stat.h> 46#include <sys/stat.h>
46#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ 47#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
47 /* we also get PAGE_SIZE via getpagesize() */ 48 /* we also get PAGE_SIZE via getpagesize() */
48 49
49 50
50static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n\n" 51static const char mkswap_usage[] =
51"Prepare a disk partition to be used as a swap partition.\n\n" 52 "mkswap [-c] [-v0|-v1] device [block-count]\n\n"
52"Options:\n" 53 "Prepare a disk partition to be used as a swap partition.\n\n"
53"\t-c\t\tCheck for read-ability.\n" 54 "Options:\n" "\t-c\t\tCheck for read-ability.\n"
54"\t-v0\t\tMake version 0 swap [max 128 Megs].\n" 55 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
55"\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n" 56 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
56"\tblock-count\tNumber of block to use (default is entire partition).\n"; 57
58 "\tblock-count\tNumber of block to use (default is entire partition).\n";
57 59
58 60
59#ifndef _IO 61#ifndef _IO
@@ -64,8 +66,8 @@ static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n
64#define BLKGETSIZE _IO(0x12,96) 66#define BLKGETSIZE _IO(0x12,96)
65#endif 67#endif
66 68
67static char * program_name = "mkswap"; 69static char *program_name = "mkswap";
68static char * device_name = NULL; 70static char *device_name = NULL;
69static int DEV = -1; 71static int DEV = -1;
70static long PAGES = 0; 72static long PAGES = 0;
71static int check = 0; 73static int check = 0;
@@ -74,8 +76,8 @@ static int version = -1;
74 76
75#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) 77#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
76 78
77static int 79static int linux_version_code(void)
78linux_version_code(void) { 80{
79 struct utsname my_utsname; 81 struct utsname my_utsname;
80 int p, q, r; 82 int p, q, r;
81 83
@@ -83,7 +85,7 @@ linux_version_code(void) {
83 p = atoi(strtok(my_utsname.release, ".")); 85 p = atoi(strtok(my_utsname.release, "."));
84 q = atoi(strtok(NULL, ".")); 86 q = atoi(strtok(NULL, "."));
85 r = atoi(strtok(NULL, ".")); 87 r = atoi(strtok(NULL, "."));
86 return MAKE_VERSION(p,q,r); 88 return MAKE_VERSION(p, q, r);
87 } 89 }
88 return 0; 90 return 0;
89} 91}
@@ -98,7 +100,7 @@ static int pagesize;
98static int *signature_page; 100static int *signature_page;
99 101
100struct swap_header_v1 { 102struct swap_header_v1 {
101 char bootbits[1024]; /* Space for disklabel etc. */ 103 char bootbits[1024]; /* Space for disklabel etc. */
102 unsigned int version; 104 unsigned int version;
103 unsigned int last_page; 105 unsigned int last_page;
104 unsigned int nr_badpages; 106 unsigned int nr_badpages;
@@ -106,8 +108,8 @@ struct swap_header_v1 {
106 unsigned int badpages[1]; 108 unsigned int badpages[1];
107} *p; 109} *p;
108 110
109static void 111static void init_signature_page()
110init_signature_page() { 112{
111 pagesize = getpagesize(); 113 pagesize = getpagesize();
112 114
113#ifdef PAGE_SIZE 115#ifdef PAGE_SIZE
@@ -115,15 +117,15 @@ init_signature_page() {
115 fprintf(stderr, "Assuming pages of size %d\n", pagesize); 117 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
116#endif 118#endif
117 signature_page = (int *) malloc(pagesize); 119 signature_page = (int *) malloc(pagesize);
118 memset(signature_page,0,pagesize); 120 memset(signature_page, 0, pagesize);
119 p = (struct swap_header_v1 *) signature_page; 121 p = (struct swap_header_v1 *) signature_page;
120} 122}
121 123
122static void 124static void write_signature(char *sig)
123write_signature(char *sig) { 125{
124 char *sp = (char *) signature_page; 126 char *sp = (char *) signature_page;
125 127
126 strncpy(sp+pagesize-10, sig, 10); 128 strncpy(sp + pagesize - 10, sig, 10);
127} 129}
128 130
129#define V0_MAX_PAGES (8 * (pagesize - 10)) 131#define V0_MAX_PAGES (8 * (pagesize - 10))
@@ -172,42 +174,46 @@ It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
172 174
173#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) 175#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
174 176
175static void bit_set (unsigned int *addr, unsigned int nr) 177static void bit_set(unsigned int *addr, unsigned int nr)
176{ 178{
177 unsigned int r, m; 179 unsigned int r, m;
178 180
179 addr += nr / (8 * sizeof(int)); 181 addr += nr / (8 * sizeof(int));
182
180 r = *addr; 183 r = *addr;
181 m = 1 << (nr & (8 * sizeof(int) - 1)); 184 m = 1 << (nr & (8 * sizeof(int) - 1));
185
182 *addr = r | m; 186 *addr = r | m;
183} 187}
184 188
185static int bit_test_and_clear (unsigned int *addr, unsigned int nr) 189static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
186{ 190{
187 unsigned int r, m; 191 unsigned int r, m;
188 192
189 addr += nr / (8 * sizeof(int)); 193 addr += nr / (8 * sizeof(int));
194
190 r = *addr; 195 r = *addr;
191 m = 1 << (nr & (8 * sizeof(int) - 1)); 196 m = 1 << (nr & (8 * sizeof(int) - 1));
197
192 *addr = r & ~m; 198 *addr = r & ~m;
193 return (r & m) != 0; 199 return (r & m) != 0;
194} 200}
195 201
196 202
197void 203void die(const char *str)
198die(const char *str) { 204{
199 fprintf(stderr, "%s: %s\n", program_name, str); 205 fprintf(stderr, "%s: %s\n", program_name, str);
200 exit( FALSE); 206 exit(FALSE);
201} 207}
202 208
203void 209void page_ok(int page)
204page_ok(int page) { 210{
205 if (version==0) 211 if (version == 0)
206 bit_set(signature_page, page); 212 bit_set(signature_page, page);
207} 213}
208 214
209void 215void page_bad(int page)
210page_bad(int page) { 216{
211 if (version == 0) 217 if (version == 0)
212 bit_test_and_clear(signature_page, page); 218 bit_test_and_clear(signature_page, page);
213 else { 219 else {
@@ -218,8 +224,8 @@ page_bad(int page) {
218 badpages++; 224 badpages++;
219} 225}
220 226
221void 227void check_blocks(void)
222check_blocks(void) { 228{
223 unsigned int current_page; 229 unsigned int current_page;
224 int do_seek = 1; 230 int do_seek = 1;
225 char *buffer; 231 char *buffer;
@@ -233,8 +239,8 @@ check_blocks(void) {
233 page_ok(current_page++); 239 page_ok(current_page++);
234 continue; 240 continue;
235 } 241 }
236 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != 242 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
237 current_page*pagesize) 243 current_page * pagesize)
238 die("seek failed in check_blocks"); 244 die("seek failed in check_blocks");
239 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { 245 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
240 page_bad(current_page++); 246 page_bad(current_page++);
@@ -248,30 +254,28 @@ check_blocks(void) {
248 printf("%d bad pages\n", badpages); 254 printf("%d bad pages\n", badpages);
249} 255}
250 256
251static long valid_offset (int fd, int offset) 257static long valid_offset(int fd, int offset)
252{ 258{
253 char ch; 259 char ch;
254 260
255 if (lseek (fd, offset, 0) < 0) 261 if (lseek(fd, offset, 0) < 0)
256 return 0; 262 return 0;
257 if (read (fd, &ch, 1) < 1) 263 if (read(fd, &ch, 1) < 1)
258 return 0; 264 return 0;
259 return 1; 265 return 1;
260} 266}
261 267
262static int 268static int find_size(int fd)
263find_size (int fd)
264{ 269{
265 unsigned int high, low; 270 unsigned int high, low;
266 271
267 low = 0; 272 low = 0;
268 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2) 273 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
269 low = high; 274 low = high;
270 while (low < high - 1) 275 while (low < high - 1) {
271 {
272 const int mid = (low + high) / 2; 276 const int mid = (low + high) / 2;
273 277
274 if (valid_offset (fd, mid)) 278 if (valid_offset(fd, mid))
275 low = mid; 279 low = mid;
276 else 280 else
277 high = mid; 281 high = mid;
@@ -280,11 +284,10 @@ find_size (int fd)
280} 284}
281 285
282/* return size in pages, to avoid integer overflow */ 286/* return size in pages, to avoid integer overflow */
283static long 287static long get_size(const char *file)
284get_size(const char *file)
285{ 288{
286 int fd; 289 int fd;
287 long size; 290 long size;
288 291
289 fd = open(file, O_RDONLY); 292 fd = open(file, O_RDONLY);
290 if (fd < 0) { 293 if (fd < 0) {
@@ -292,7 +295,8 @@ get_size(const char *file)
292 exit(1); 295 exit(1);
293 } 296 }
294 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 297 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
295 int sectors_per_page = pagesize/512; 298 int sectors_per_page = pagesize / 512;
299
296 size /= sectors_per_page; 300 size /= sectors_per_page;
297 } else { 301 } else {
298 size = find_size(fd) / pagesize; 302 size = find_size(fd) / pagesize;
@@ -301,9 +305,9 @@ get_size(const char *file)
301 return size; 305 return size;
302} 306}
303 307
304int mkswap_main(int argc, char ** argv) 308int mkswap_main(int argc, char **argv)
305{ 309{
306 char * tmp; 310 char *tmp;
307 struct stat statbuf; 311 struct stat statbuf;
308 int sz; 312 int sz;
309 int maxpages; 313 int maxpages;
@@ -314,56 +318,56 @@ int mkswap_main(int argc, char ** argv)
314 if (argc && *argv) 318 if (argc && *argv)
315 program_name = *argv; 319 program_name = *argv;
316 320
317 init_signature_page(); /* get pagesize */ 321 init_signature_page(); /* get pagesize */
318 322
319 while (argc-- > 1) { 323 while (argc-- > 1) {
320 argv++; 324 argv++;
321 if (argv[0][0] != '-') { 325 if (argv[0][0] != '-') {
322 if (device_name) { 326 if (device_name) {
323 int blocks_per_page = pagesize/1024; 327 int blocks_per_page = pagesize / 1024;
324 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; 328
329 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
325 if (*tmp) 330 if (*tmp)
326 usage( mkswap_usage); 331 usage(mkswap_usage);
327 } else 332 } else
328 device_name = argv[0]; 333 device_name = argv[0];
329 } else { 334 } else {
330 switch (argv[0][1]) { 335 switch (argv[0][1]) {
331 case 'c': 336 case 'c':
332 check=1; 337 check = 1;
333 break; 338 break;
334 case 'f': 339 case 'f':
335 force=1; 340 force = 1;
336 break; 341 break;
337 case 'v': 342 case 'v':
338 version=atoi(argv[0]+2); 343 version = atoi(argv[0] + 2);
339 break; 344 break;
340 default: 345 default:
341 usage( mkswap_usage); 346 usage(mkswap_usage);
342 } 347 }
343 } 348 }
344 } 349 }
345 if (!device_name) { 350 if (!device_name) {
346 fprintf(stderr, 351 fprintf(stderr,
347 "%s: error: Nowhere to set up swap on?\n", 352 "%s: error: Nowhere to set up swap on?\n", program_name);
348 program_name); 353 usage(mkswap_usage);
349 usage( mkswap_usage);
350 } 354 }
351 sz = get_size(device_name); 355 sz = get_size(device_name);
352 if (!PAGES) { 356 if (!PAGES) {
353 PAGES = sz; 357 PAGES = sz;
354 } else if (PAGES > sz && !force) { 358 } else if (PAGES > sz && !force) {
355 fprintf(stderr, 359 fprintf(stderr,
356 "%s: error: " 360 "%s: error: "
357 "size %ld is larger than device size %d\n", 361 "size %ld is larger than device size %d\n",
358 program_name, 362 program_name,
359 PAGES*(pagesize/1024), sz*(pagesize/1024)); 363 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
360 exit( FALSE); 364 exit(FALSE);
361 } 365 }
362 366
363 if (version == -1) { 367 if (version == -1) {
364 if (PAGES <= V0_MAX_PAGES) 368 if (PAGES <= V0_MAX_PAGES)
365 version = 0; 369 version = 0;
366 else if (linux_version_code() < MAKE_VERSION(2,1,117)) 370 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
367 version = 0; 371 version = 0;
368 else if (pagesize < 2048) 372 else if (pagesize < 2048)
369 version = 0; 373 version = 0;
@@ -372,21 +376,21 @@ int mkswap_main(int argc, char ** argv)
372 } 376 }
373 if (version != 0 && version != 1) { 377 if (version != 0 && version != 1) {
374 fprintf(stderr, "%s: error: unknown version %d\n", 378 fprintf(stderr, "%s: error: unknown version %d\n",
375 program_name, version); 379 program_name, version);
376 usage( mkswap_usage); 380 usage(mkswap_usage);
377 } 381 }
378 if (PAGES < 10) { 382 if (PAGES < 10) {
379 fprintf(stderr, 383 fprintf(stderr,
380 "%s: error: swap area needs to be at least %ldkB\n", 384 "%s: error: swap area needs to be at least %ldkB\n",
381 program_name, (long)(10 * pagesize / 1024)); 385 program_name, (long) (10 * pagesize / 1024));
382 usage( mkswap_usage); 386 usage(mkswap_usage);
383 } 387 }
384#if 0 388#if 0
385 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); 389 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
386#else 390#else
387 if (!version) 391 if (!version)
388 maxpages = V0_MAX_PAGES; 392 maxpages = V0_MAX_PAGES;
389 else if (linux_version_code() >= MAKE_VERSION(2,2,1)) 393 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
390 maxpages = V1_MAX_PAGES; 394 maxpages = V1_MAX_PAGES;
391 else { 395 else {
392 maxpages = V1_OLD_MAX_PAGES; 396 maxpages = V1_OLD_MAX_PAGES;
@@ -397,29 +401,29 @@ int mkswap_main(int argc, char ** argv)
397 if (PAGES > maxpages) { 401 if (PAGES > maxpages) {
398 PAGES = maxpages; 402 PAGES = maxpages;
399 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", 403 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
400 program_name, PAGES * pagesize / 1024); 404 program_name, PAGES * pagesize / 1024);
401 } 405 }
402 406
403 DEV = open(device_name,O_RDWR); 407 DEV = open(device_name, O_RDWR);
404 if (DEV < 0 || fstat(DEV, &statbuf) < 0) { 408 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
405 perror(device_name); 409 perror(device_name);
406 exit( FALSE); 410 exit(FALSE);
407 } 411 }
408 if (!S_ISBLK(statbuf.st_mode)) 412 if (!S_ISBLK(statbuf.st_mode))
409 check=0; 413 check = 0;
410 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 414 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
411 die("Will not try to make swapdevice on '%s'"); 415 die("Will not try to make swapdevice on '%s'");
412 416
413#ifdef __sparc__ 417#ifdef __sparc__
414 if (!force && version == 0) { 418 if (!force && version == 0) {
415 /* Don't overwrite partition table unless forced */ 419 /* Don't overwrite partition table unless forced */
416 unsigned char *buffer = (unsigned char *)signature_page; 420 unsigned char *buffer = (unsigned char *) signature_page;
417 unsigned short *q, sum; 421 unsigned short *q, sum;
418 422
419 if (read(DEV, buffer, 512) != 512) 423 if (read(DEV, buffer, 512) != 512)
420 die("fatal: first page unreadable"); 424 die("fatal: first page unreadable");
421 if (buffer[508] == 0xDA && buffer[509] == 0xBE) { 425 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
422 q = (unsigned short *)(buffer + 510); 426 q = (unsigned short *) (buffer + 510);
423 for (sum = 0; q >= (unsigned short *) buffer;) 427 for (sum = 0; q >= (unsigned short *) buffer;)
424 sum ^= *q--; 428 sum ^= *q--;
425 if (!sum) { 429 if (!sum) {
@@ -427,9 +431,8 @@ int mkswap_main(int argc, char ** argv)
427%s: Device '%s' contains a valid Sun disklabel.\n\ 431%s: Device '%s' contains a valid Sun disklabel.\n\
428This probably means creating v0 swap would destroy your partition table\n\ 432This probably means creating v0 swap would destroy your partition table\n\
429No swap created. If you really want to create swap v0 on that device, use\n\ 433No swap created. If you really want to create swap v0 on that device, use\n\
430the -f option to force it.\n", 434the -f option to force it.\n", program_name, device_name);
431 program_name, device_name); 435 exit(FALSE);
432 exit( FALSE);
433 } 436 }
434 } 437 }
435 } 438 }
@@ -437,11 +440,11 @@ the -f option to force it.\n",
437 440
438 if (version == 0 || check) 441 if (version == 0 || check)
439 check_blocks(); 442 check_blocks();
440 if (version == 0 && !bit_test_and_clear(signature_page,0)) 443 if (version == 0 && !bit_test_and_clear(signature_page, 0))
441 die("fatal: first page unreadable"); 444 die("fatal: first page unreadable");
442 if (version == 1) { 445 if (version == 1) {
443 p->version = version; 446 p->version = version;
444 p->last_page = PAGES-1; 447 p->last_page = PAGES - 1;
445 p->nr_badpages = badpages; 448 p->nr_badpages = badpages;
446 } 449 }
447 450
@@ -449,14 +452,14 @@ the -f option to force it.\n",
449 if (goodpages <= 0) 452 if (goodpages <= 0)
450 die("Unable to set up swap-space: unreadable"); 453 die("Unable to set up swap-space: unreadable");
451 printf("Setting up swapspace version %d, size = %ld bytes\n", 454 printf("Setting up swapspace version %d, size = %ld bytes\n",
452 version, (long)(goodpages*pagesize)); 455 version, (long) (goodpages * pagesize));
453 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); 456 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
454 457
455 offset = ((version == 0) ? 0 : 1024); 458 offset = ((version == 0) ? 0 : 1024);
456 if (lseek(DEV, offset, SEEK_SET) != offset) 459 if (lseek(DEV, offset, SEEK_SET) != offset)
457 die("unable to rewind swap-device"); 460 die("unable to rewind swap-device");
458 if (write(DEV,(char*)signature_page+offset, pagesize-offset) 461 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
459 != pagesize-offset) 462 != pagesize - offset)
460 die("unable to write signature page"); 463 die("unable to write signature page");
461 464
462 /* 465 /*
@@ -464,6 +467,6 @@ the -f option to force it.\n",
464 * is not actually on disk. (This is a kernel bug.) 467 * is not actually on disk. (This is a kernel bug.)
465 */ 468 */
466 if (fsync(DEV)) 469 if (fsync(DEV))
467 die("fsync failed"); 470 die("fsync failed");
468 exit ( TRUE); 471 exit(TRUE);
469} 472}
diff --git a/util-linux/more.c b/util-linux/more.c
index 821427dda..d5711aa2f 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini more implementation for busybox 3 * Mini more implementation for busybox
3 * 4 *
@@ -45,19 +46,20 @@ static const char more_usage[] = "more [file ...]\n";
45# define stty(fd,argp) tcsetattr(fd,TCSANOW,argp) 46# define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
46#endif 47#endif
47 48
48 FILE *cin; 49FILE *cin;
49 struct termios initial_settings, new_settings; 50struct termios initial_settings, new_settings;
50 51
51 void gotsig(int sig) { 52void gotsig(int sig)
52 stty(fileno(cin), &initial_settings); 53{
53 fprintf(stdout, "\n"); 54 stty(fileno(cin), &initial_settings);
54 exit( TRUE); 55 fprintf(stdout, "\n");
55 } 56 exit(TRUE);
57}
56#endif 58#endif
57 59
58 60
59 61
60#define TERMINAL_WIDTH 79 /* not 80 in case terminal has linefold bug */ 62#define TERMINAL_WIDTH 79 /* not 80 in case terminal has linefold bug */
61#define TERMINAL_HEIGHT 24 63#define TERMINAL_HEIGHT 24
62 64
63 65
@@ -72,118 +74,121 @@ static int terminal_width = 0, terminal_height = 0;
72 74
73extern int more_main(int argc, char **argv) 75extern int more_main(int argc, char **argv)
74{ 76{
75 int c, lines=0, input=0; 77 int c, lines = 0, input = 0;
76 int next_page=0; 78 int next_page = 0;
77 struct stat st; 79 struct stat st;
78 FILE *file; 80 FILE *file;
81
79#ifdef BB_FEATURE_AUTOWIDTH 82#ifdef BB_FEATURE_AUTOWIDTH
80 struct winsize win = {0,0}; 83 struct winsize win = { 0, 0 };
81#endif 84#endif
82 85
83 argc--; 86 argc--;
84 argv++; 87 argv++;
85
86 if ( argc > 0 && (strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0) ) {
87 usage (more_usage);
88 }
89 do {
90 if (argc==0) {
91 file = stdin;
92 }
93 else
94 file = fopen(*argv, "r");
95 88
96 if (file == NULL) { 89 if (argc > 0
97 perror(*argv); 90 && (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0)) {
98 exit(FALSE); 91 usage(more_usage);
99 } 92 }
100 fstat(fileno(file), &st); 93 do {
94 if (argc == 0) {
95 file = stdin;
96 } else
97 file = fopen(*argv, "r");
98
99 if (file == NULL) {
100 perror(*argv);
101 exit(FALSE);
102 }
103 fstat(fileno(file), &st);
101 104
102#ifdef BB_FEATURE_USE_TERMIOS 105#ifdef BB_FEATURE_USE_TERMIOS
103 cin = fopen("/dev/tty", "r"); 106 cin = fopen("/dev/tty", "r");
104 if (!cin) 107 if (!cin)
105 cin = fopen("/dev/console", "r"); 108 cin = fopen("/dev/console", "r");
106#ifdef USE_OLD_TERMIO 109#ifdef USE_OLD_TERMIO
107 ioctl(fileno(cin),TCGETA,&initial_settings); 110 ioctl(fileno(cin), TCGETA, &initial_settings);
108#else 111#else
109 tcgetattr(fileno(cin),&initial_settings); 112 tcgetattr(fileno(cin), &initial_settings);
110#endif 113#endif
111 new_settings = initial_settings; 114 new_settings = initial_settings;
112 new_settings.c_lflag &= ~ICANON; 115 new_settings.c_lflag &= ~ICANON;
113 new_settings.c_lflag &= ~ECHO; 116 new_settings.c_lflag &= ~ECHO;
114 stty(fileno(cin), &new_settings); 117 stty(fileno(cin), &new_settings);
115 118
116#ifdef BB_FEATURE_AUTOWIDTH 119#ifdef BB_FEATURE_AUTOWIDTH
117 ioctl(fileno(stdout), TIOCGWINSZ, &win); 120 ioctl(fileno(stdout), TIOCGWINSZ, &win);
118 if (win.ws_row > 4) 121 if (win.ws_row > 4)
119 terminal_height = win.ws_row - 2; 122 terminal_height = win.ws_row - 2;
120 if (win.ws_col > 0) 123 if (win.ws_col > 0)
121 terminal_width = win.ws_col - 1; 124 terminal_width = win.ws_col - 1;
122#endif 125#endif
123 126
124 (void) signal(SIGINT, gotsig); 127 (void) signal(SIGINT, gotsig);
125 (void) signal(SIGQUIT, gotsig); 128 (void) signal(SIGQUIT, gotsig);
126 (void) signal(SIGTERM, gotsig); 129 (void) signal(SIGTERM, gotsig);
127 130
128#endif 131#endif
129 while ((c = getc(file)) != EOF) { 132 while ((c = getc(file)) != EOF) {
130 if ( next_page ) { 133 if (next_page) {
131 int len=0; 134 int len = 0;
132 next_page = 0; 135
133 lines=0; 136 next_page = 0;
134 len = fprintf(stdout, "--More-- "); 137 lines = 0;
135 if (file != stdin) { 138 len = fprintf(stdout, "--More-- ");
136 len += fprintf(stdout, "(%d%% of %ld bytes)", 139 if (file != stdin) {
137 (int) (100*( (double) ftell(file) / (double) st.st_size )), 140 len += fprintf(stdout, "(%d%% of %ld bytes)",
138 st.st_size); 141 (int) (100 *
139 } 142 ((double) ftell(file) /
140 len += fprintf(stdout, "%s", 143 (double) st.st_size)),
144 st.st_size);
145 }
146 len += fprintf(stdout, "%s",
141#ifdef BB_FEATURE_USE_TERMIOS 147#ifdef BB_FEATURE_USE_TERMIOS
142 "" 148 ""
143#else 149#else
144 "\n" 150 "\n"
145#endif 151#endif
146 ); 152 );
147 153
148 fflush(stdout); 154 fflush(stdout);
149 input = getc( cin); 155 input = getc(cin);
150 156
151#ifdef BB_FEATURE_USE_TERMIOS 157#ifdef BB_FEATURE_USE_TERMIOS
152 /* Erase the "More" message */ 158 /* Erase the "More" message */
153 while(--len >= 0) 159 while (--len >= 0)
154 putc('\b', stdout); 160 putc('\b', stdout);
155 while(++len <= terminal_width) 161 while (++len <= terminal_width)
156 putc(' ', stdout); 162 putc(' ', stdout);
157 while(--len >= 0) 163 while (--len >= 0)
158 putc('\b', stdout); 164 putc('\b', stdout);
159 fflush(stdout); 165 fflush(stdout);
160#endif 166#endif
161 167
162 } 168 }
163 if (c == '\n' ) { 169 if (c == '\n') {
164 switch(input) { 170 switch (input) {
165 case 'q': 171 case 'q':
166 goto end; 172 goto end;
167 case '\n': 173 case '\n':
168 /* increment by just one line if we are at 174 /* increment by just one line if we are at
169 * the end of this line*/ 175 * the end of this line*/
170 next_page = 1; 176 next_page = 1;
171 break; 177 break;
178 }
179 if (++lines == terminal_height)
180 next_page = 1;
181 }
182 putc(c, stdout);
172 } 183 }
173 if ( ++lines == terminal_height ) 184 fclose(file);
174 next_page = 1; 185 fflush(stdout);
175 }
176 putc(c, stdout);
177 }
178 fclose(file);
179 fflush(stdout);
180 186
181 argv++; 187 argv++;
182 } while (--argc > 0); 188 } while (--argc > 0);
183end: 189 end:
184#ifdef BB_FEATURE_USE_TERMIOS 190#ifdef BB_FEATURE_USE_TERMIOS
185 gotsig(0); 191 gotsig(0);
186#endif 192#endif
187 exit(TRUE); 193 exit(TRUE);
188} 194}
189
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 4c9e77be0..c3e3bbd75 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mount implementation for busybox 3 * Mini mount implementation for busybox
3 * 4 *
@@ -55,357 +56,371 @@
55static int use_loop = 0; 56static int use_loop = 0;
56#endif 57#endif
57 58
58extern const char mtab_file[]; /* Defined in utility.c */ 59extern const char mtab_file[]; /* Defined in utility.c */
59 60
60static const char mount_usage[] = "\tmount [flags]\n" 61static const char mount_usage[] = "\tmount [flags]\n"
61 "\tmount [flags] device directory [-o options,more-options]\n" 62 "\tmount [flags] device directory [-o options,more-options]\n"
62 "\n" 63 "\n" "Flags:\n" "\t-a:\tMount all file systems in fstab.\n"
63 "Flags:\n"
64 "\t-a:\tMount all file systems in fstab.\n"
65#ifdef BB_MTAB 64#ifdef BB_MTAB
66 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" 65 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n"
67 "\t-n:\tDon't write a mount table entry.\n" 66 "\t-n:\tDon't write a mount table entry.\n"
68#endif 67#endif
69 "\t-o option:\tOne of many filesystem options, listed below.\n" 68 "\t-o option:\tOne of many filesystem options, listed below.\n"
70 "\t-r:\tMount the filesystem read-only.\n" 69 "\t-r:\tMount the filesystem read-only.\n"
71 "\t-t filesystem-type:\tSpecify the filesystem type.\n" 70 "\t-t filesystem-type:\tSpecify the filesystem type.\n"
72 "\t-w:\tMount for reading and writing (default).\n" 71 "\t-w:\tMount for reading and writing (default).\n"
73 "\n" 72 "\n"
74 "Options for use with the \"-o\" flag:\n" 73 "Options for use with the \"-o\" flag:\n"
75 "\tasync / sync:\tWrites are asynchronous / synchronous.\n" 74 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
76 "\tdev / nodev:\tAllow use of special device files / disallow them.\n" 75 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
77 "\texec / noexec:\tAllow use of executable files / disallow them.\n" 76 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
78#if defined BB_FEATURE_MOUNT_LOOP 77#if defined BB_FEATURE_MOUNT_LOOP
79 "\tloop: Mounts a file via loop device.\n" 78 "\tloop: Mounts a file via loop device.\n"
80#endif 79#endif
81 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" 80 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
82 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" 81 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
83 "\tro / rw: Mount for read-only / read-write.\n" 82 "\tro / rw: Mount for read-only / read-write.\n"
84 "\t" 83 "\t"
85 "There are EVEN MORE flags that are specific to each filesystem.\n" 84
86 "You'll have to see the written documentation for those.\n"; 85 "There are EVEN MORE flags that are specific to each filesystem.\n"
86 "You'll have to see the written documentation for those.\n";
87 87
88 88
89struct mount_options { 89struct mount_options {
90 const char *name; 90 const char *name;
91 unsigned long and; 91 unsigned long and;
92 unsigned long or; 92 unsigned long or;
93}; 93};
94 94
95static const struct mount_options mount_options[] = { 95static const struct mount_options mount_options[] = {
96 {"async", ~MS_SYNCHRONOUS, 0}, 96 {"async", ~MS_SYNCHRONOUS, 0},
97 {"defaults", ~0, 0}, 97 {"defaults", ~0, 0},
98 {"dev", ~MS_NODEV, 0}, 98 {"dev", ~MS_NODEV, 0},
99 {"exec", ~MS_NOEXEC, 0}, 99 {"exec", ~MS_NOEXEC, 0},
100 {"nodev", ~0, MS_NODEV}, 100 {"nodev", ~0, MS_NODEV},
101 {"noexec", ~0, MS_NOEXEC}, 101 {"noexec", ~0, MS_NOEXEC},
102 {"nosuid", ~0, MS_NOSUID}, 102 {"nosuid", ~0, MS_NOSUID},
103 {"remount", ~0, MS_REMOUNT}, 103 {"remount", ~0, MS_REMOUNT},
104 {"ro", ~0, MS_RDONLY}, 104 {"ro", ~0, MS_RDONLY},
105 {"rw", ~MS_RDONLY, 0}, 105 {"rw", ~MS_RDONLY, 0},
106 {"suid", ~MS_NOSUID, 0}, 106 {"suid", ~MS_NOSUID, 0},
107 {"sync", ~0, MS_SYNCHRONOUS}, 107 {"sync", ~0, MS_SYNCHRONOUS},
108 {0, 0, 0} 108 {0, 0, 0}
109}; 109};
110 110
111static int 111static int
112do_mount(char* specialfile, char* dir, char* filesystemtype, 112do_mount(char *specialfile, char *dir, char *filesystemtype,
113 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts) 113 long flags, void *string_flags, int useMtab, int fakeIt,
114 char *mtab_opts)
114{ 115{
115 int status=0; 116 int status = 0;
116 117
117#if defined BB_MTAB 118#if defined BB_MTAB
118 if (fakeIt==FALSE) 119 if (fakeIt == FALSE)
119#endif 120#endif
120 { 121 {
121#if defined BB_FEATURE_MOUNT_LOOP 122#if defined BB_FEATURE_MOUNT_LOOP
122 if (use_loop) { 123 if (use_loop) {
123 int loro = flags & MS_RDONLY; 124 int loro = flags & MS_RDONLY;
124 char *lofile = specialfile; 125 char *lofile = specialfile;
125 specialfile = find_unused_loop_device(); 126
126 if (specialfile == NULL) { 127 specialfile = find_unused_loop_device();
127 fprintf(stderr, "Could not find a spare loop device\n"); 128 if (specialfile == NULL) {
128 return( FALSE); 129 fprintf(stderr, "Could not find a spare loop device\n");
129 } 130 return (FALSE);
130 if (set_loop (specialfile, lofile, 0, &loro)) { 131 }
131 fprintf(stderr, "Could not setup loop device\n"); 132 if (set_loop(specialfile, lofile, 0, &loro)) {
132 return( FALSE); 133 fprintf(stderr, "Could not setup loop device\n");
133 } 134 return (FALSE);
134 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ 135 }
135 fprintf(stderr, "WARNING: loop device is read-only\n"); 136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
136 flags &= ~MS_RDONLY; 137 fprintf(stderr, "WARNING: loop device is read-only\n");
137 } 138 flags &= ~MS_RDONLY;
138 } 139 }
140 }
139#endif 141#endif
140 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 142 status =
141 } 143 mount(specialfile, dir, filesystemtype, flags, string_flags);
144 }
142 145
143 146
144 /* If the mount was sucessful, do anything needed, then return TRUE */ 147 /* If the mount was sucessful, do anything needed, then return TRUE */
145 if (status == 0) { 148 if (status == 0) {
146 149
147#if defined BB_MTAB 150#if defined BB_MTAB
148 if (useMtab==TRUE) { 151 if (useMtab == TRUE) {
149 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 152 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
150 } 153 }
151#endif 154#endif
152 return( TRUE); 155 return (TRUE);
153 } 156 }
154 157
155 /* Bummer. mount failed. Clean up */ 158 /* Bummer. mount failed. Clean up */
156#if defined BB_FEATURE_MOUNT_LOOP 159#if defined BB_FEATURE_MOUNT_LOOP
157 if (specialfile != NULL) { 160 if (specialfile != NULL) {
158 del_loop(specialfile); 161 del_loop(specialfile);
159 } 162 }
160#endif 163#endif
161 return( FALSE); 164 return (FALSE);
162} 165}
163 166
164 167
165 168
166#if defined BB_MTAB 169#if defined BB_MTAB
167#define whine_if_fstab_is_missing() {} 170#define whine_if_fstab_is_missing() {}
168#else 171#else
169extern void whine_if_fstab_is_missing() 172extern void whine_if_fstab_is_missing()
170{ 173{
171 struct stat statBuf; 174 struct stat statBuf;
172 if (stat("/etc/fstab", &statBuf) < 0) 175
173 fprintf(stderr, "/etc/fstab file missing -- install one to name /dev/root.\n\n"); 176 if (stat("/etc/fstab", &statBuf) < 0)
177 fprintf(stderr,
178 "/etc/fstab file missing -- install one to name /dev/root.\n\n");
174} 179}
175#endif 180#endif
176 181
177 182
178/* Seperate standard mount options from the nonstandard string options */ 183/* Seperate standard mount options from the nonstandard string options */
179static void 184static void
180parse_mount_options ( char *options, unsigned long *flags, char *strflags) 185parse_mount_options(char *options, unsigned long *flags, char *strflags)
181{ 186{
182 while (options) { 187 while (options) {
183 int gotone=FALSE; 188 int gotone = FALSE;
184 char *comma = strchr (options, ','); 189 char *comma = strchr(options, ',');
185 const struct mount_options* f = mount_options; 190 const struct mount_options *f = mount_options;
186 if (comma) 191
187 *comma = '\0'; 192 if (comma)
188 193 *comma = '\0';
189 while (f->name != 0) { 194
190 if (strcasecmp (f->name, options) == 0) { 195 while (f->name != 0) {
191 196 if (strcasecmp(f->name, options) == 0) {
192 *flags &= f->and; 197
193 *flags |= f->or; 198 *flags &= f->and;
194 gotone=TRUE; 199 *flags |= f->or;
195 break; 200 gotone = TRUE;
196 } 201 break;
197 f++; 202 }
198 } 203 f++;
204 }
199#if defined BB_FEATURE_MOUNT_LOOP 205#if defined BB_FEATURE_MOUNT_LOOP
200 if (gotone==FALSE && !strcasecmp ("loop", options)) { /* loop device support */ 206 if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */
201 use_loop = 1; 207 use_loop = 1;
202 gotone=TRUE; 208 gotone = TRUE;
203 } 209 }
204#endif 210#endif
205 if (*strflags && strflags!= '\0' && gotone==FALSE) { 211 if (*strflags && strflags != '\0' && gotone == FALSE) {
206 char *temp=strflags; 212 char *temp = strflags;
207 temp += strlen (strflags); 213
208 *temp++ = ','; 214 temp += strlen(strflags);
209 *temp++ = '\0'; 215 *temp++ = ',';
210 } 216 *temp++ = '\0';
211 if (gotone==FALSE) 217 }
212 strcat (strflags, options); 218 if (gotone == FALSE)
213 if (comma) { 219 strcat(strflags, options);
214 *comma = ','; 220 if (comma) {
215 options = ++comma; 221 *comma = ',';
216 } else { 222 options = ++comma;
217 break; 223 } else {
224 break;
225 }
218 } 226 }
219 }
220} 227}
221 228
222int 229int
223mount_one(char *blockDevice, char *directory, char *filesystemType, 230mount_one(char *blockDevice, char *directory, char *filesystemType,
224 unsigned long flags, char *string_flags, int useMtab, int fakeIt, char *mtab_opts) 231 unsigned long flags, char *string_flags, int useMtab, int fakeIt,
232 char *mtab_opts)
225{ 233{
226 int status = 0; 234 int status = 0;
227 235
228 char buf[255]; 236 char buf[255];
229 237
230#if defined BB_FEATURE_USE_PROCFS 238#if defined BB_FEATURE_USE_PROCFS
231 if (strcmp(filesystemType, "auto") == 0) { 239 if (strcmp(filesystemType, "auto") == 0) {
232 FILE *f = fopen ("/proc/filesystems", "r"); 240 FILE *f = fopen("/proc/filesystems", "r");
233 241
234 if (f == NULL) 242 if (f == NULL)
235 return( FALSE); 243 return (FALSE);
236 244
237 while (fgets (buf, sizeof (buf), f) != NULL) { 245 while (fgets(buf, sizeof(buf), f) != NULL) {
238 filesystemType = buf; 246 filesystemType = buf;
239 if (*filesystemType == '\t') { // Not a nodev filesystem 247 if (*filesystemType == '\t') { // Not a nodev filesystem
240 248
241 // Add NULL termination to each line 249 // Add NULL termination to each line
242 while (*filesystemType && *filesystemType != '\n') 250 while (*filesystemType && *filesystemType != '\n')
243 filesystemType++; 251 filesystemType++;
244 *filesystemType = '\0'; 252 *filesystemType = '\0';
245 253
246 filesystemType = buf; 254 filesystemType = buf;
247 filesystemType++; // hop past tab 255 filesystemType++; // hop past tab
248 256
249 status = do_mount (blockDevice, directory, filesystemType, 257 status = do_mount(blockDevice, directory, filesystemType,
250 flags | MS_MGC_VAL, string_flags, useMtab, 258 flags | MS_MGC_VAL, string_flags,
251 fakeIt, mtab_opts); 259 useMtab, fakeIt, mtab_opts);
252 if (status == TRUE) 260 if (status == TRUE)
253 break; 261 break;
254 } 262 }
255 } 263 }
256 fclose (f); 264 fclose(f);
257 } else 265 } else
258#endif 266#endif
259 { 267 {
260 status = do_mount (blockDevice, directory, filesystemType, 268 status = do_mount(blockDevice, directory, filesystemType,
261 flags | MS_MGC_VAL, string_flags, useMtab, 269 flags | MS_MGC_VAL, string_flags, useMtab,
262 fakeIt, mtab_opts); 270 fakeIt, mtab_opts);
263 } 271 }
264 272
265 if (status==FALSE) { 273 if (status == FALSE) {
266 fprintf (stderr, "Mounting %s on %s failed: %s\n", 274 fprintf(stderr, "Mounting %s on %s failed: %s\n",
267 blockDevice, directory, strerror(errno)); 275 blockDevice, directory, strerror(errno));
268 return (FALSE); 276 return (FALSE);
269 } 277 }
270 return (TRUE); 278 return (TRUE);
271} 279}
272 280
273extern int mount_main (int argc, char **argv) 281extern int mount_main(int argc, char **argv)
274{ 282{
275 char string_flags_buf[1024]=""; 283 char string_flags_buf[1024] = "";
276 char *string_flags = string_flags_buf; 284 char *string_flags = string_flags_buf;
277 char *extra_opts = string_flags_buf; 285 char *extra_opts = string_flags_buf;
278 unsigned long flags = 0; 286 unsigned long flags = 0;
279 char *filesystemType = "auto"; 287 char *filesystemType = "auto";
280 char *device = NULL; 288 char *device = NULL;
281 char *directory = NULL; 289 char *directory = NULL;
282 int all = FALSE; 290 int all = FALSE;
283 int fakeIt = FALSE; 291 int fakeIt = FALSE;
284 int useMtab = TRUE; 292 int useMtab = TRUE;
285 int i; 293 int i;
286 294
287 /* Only compiled in if BB_MTAB is not defined */ 295 /* Only compiled in if BB_MTAB is not defined */
288 whine_if_fstab_is_missing(); 296 whine_if_fstab_is_missing();
289 297
290 if (argc == 1) { 298 if (argc == 1) {
291 FILE *mountTable = setmntent (mtab_file, "r"); 299 FILE *mountTable = setmntent(mtab_file, "r");
292 if (mountTable) { 300
293 struct mntent *m; 301 if (mountTable) {
294 while ((m = getmntent (mountTable)) != 0) { 302 struct mntent *m;
295 struct fstab* fstabItem; 303
296 char *blockDevice = m->mnt_fsname; 304 while ((m = getmntent(mountTable)) != 0) {
297 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */ 305 struct fstab *fstabItem;
298 if (strcmp (blockDevice, "/dev/root") == 0) { 306 char *blockDevice = m->mnt_fsname;
299 fstabItem = getfsfile ("/"); 307
300 if (fstabItem != NULL) 308 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
301 blockDevice = fstabItem->fs_spec; 309 if (strcmp(blockDevice, "/dev/root") == 0) {
310 fstabItem = getfsfile("/");
311 if (fstabItem != NULL)
312 blockDevice = fstabItem->fs_spec;
313 }
314 printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
315 m->mnt_type, m->mnt_opts);
316 }
317 endmntent(mountTable);
318 } else {
319 perror(mtab_file);
302 } 320 }
303 printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, 321 exit(TRUE);
304 m->mnt_type, m->mnt_opts);
305 }
306 endmntent (mountTable);
307 } else {
308 perror(mtab_file);
309 } 322 }
310 exit( TRUE); 323
311 } 324
312 325 /* Parse options */
313 326 i = --argc;
314 /* Parse options */ 327 argv++;
315 i = --argc; 328 while (i > 0 && **argv) {
316 argv++; 329 if (**argv == '-') {
317 while (i > 0 && **argv) { 330 char *opt = *argv;
318 if (**argv == '-') { 331
319 char *opt = *argv; 332 while (i > 0 && *++opt)
320 while (i>0 && *++opt) switch (*opt) { 333 switch (*opt) {
321 case 'o': 334 case 'o':
322 if (--i == 0) { 335 if (--i == 0) {
323 goto goodbye; 336 goto goodbye;
324 } 337 }
325 parse_mount_options (*(++argv), &flags, string_flags); 338 parse_mount_options(*(++argv), &flags, string_flags);
326 break; 339 break;
327 case 'r': 340 case 'r':
328 flags |= MS_RDONLY; 341 flags |= MS_RDONLY;
329 break; 342 break;
330 case 't': 343 case 't':
331 if (--i == 0) { 344 if (--i == 0) {
332 goto goodbye; 345 goto goodbye;
333 } 346 }
334 filesystemType = *(++argv); 347 filesystemType = *(++argv);
335 break; 348 break;
336 case 'w': 349 case 'w':
337 flags &= ~MS_RDONLY; 350 flags &= ~MS_RDONLY;
338 break; 351 break;
339 case 'a': 352 case 'a':
340 all = TRUE; 353 all = TRUE;
341 break; 354 break;
342#ifdef BB_MTAB 355#ifdef BB_MTAB
343 case 'f': 356 case 'f':
344 fakeIt = TRUE; 357 fakeIt = TRUE;
345 break; 358 break;
346 case 'n': 359 case 'n':
347 useMtab = FALSE; 360 useMtab = FALSE;
348 break; 361 break;
349#endif 362#endif
350 case 'v': 363 case 'v':
351 case 'h': 364 case 'h':
352 case '-': 365 case '-':
353 goto goodbye; 366 goto goodbye;
354 } 367 }
355 } else { 368 } else {
356 if (device == NULL) 369 if (device == NULL)
357 device = *argv; 370 device = *argv;
358 else if (directory == NULL) 371 else if (directory == NULL)
359 directory = *argv; 372 directory = *argv;
360 else { 373 else {
361 goto goodbye; 374 goto goodbye;
362 } 375 }
376 }
377 i--;
378 argv++;
363 } 379 }
364 i--;
365 argv++;
366 }
367 380
368 if (all == TRUE) { 381 if (all == TRUE) {
369 struct mntent *m; 382 struct mntent *m;
370 FILE *f = setmntent ("/etc/fstab", "r"); 383 FILE *f = setmntent("/etc/fstab", "r");
371 384
372 if (f == NULL) { 385 if (f == NULL) {
373 perror("/etc/fstab"); 386 perror("/etc/fstab");
374 exit( FALSE); 387 exit(FALSE);
375 } 388 }
376 while ((m = getmntent (f)) != NULL) { 389 while ((m = getmntent(f)) != NULL) {
377 // If the file system isn't noauto, and isn't mounted on /, 390 // If the file system isn't noauto, and isn't mounted on /,
378 // and isn't swap or nfs, then mount it 391 // and isn't swap or nfs, then mount it
379 if ((!strstr (m->mnt_opts, "noauto")) && 392 if ((!strstr(m->mnt_opts, "noauto")) &&
380 (m->mnt_dir[1] != '\0') && 393 (m->mnt_dir[1] != '\0') &&
381 (!strstr (m->mnt_type, "swap")) && 394 (!strstr(m->mnt_type, "swap")) &&
382 (!strstr (m->mnt_type, "nfs"))) 395 (!strstr(m->mnt_type, "nfs"))) {
383 { 396 flags = 0;
384 flags = 0; 397 *string_flags = '\0';
385 *string_flags = '\0'; 398 parse_mount_options(m->mnt_opts, &flags, string_flags);
386 parse_mount_options(m->mnt_opts, &flags, string_flags); 399 mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
387 mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, 400 flags, string_flags, useMtab, fakeIt,
388 flags, string_flags, useMtab, fakeIt, extra_opts); 401 extra_opts);
389 } 402 }
390 } 403 }
391 endmntent (f); 404 endmntent(f);
392 } else { 405 } else {
393 if (device && directory) { 406 if (device && directory) {
394#ifdef BB_NFSMOUNT 407#ifdef BB_NFSMOUNT
395 if (strcmp(filesystemType, "nfs") == 0) { 408 if (strcmp(filesystemType, "nfs") == 0) {
396 if (nfsmount(device, directory, &flags, &extra_opts, &string_flags, 1) != 0) 409 if (nfsmount
397 exit(FALSE); 410 (device, directory, &flags, &extra_opts, &string_flags,
398 } 411 1) != 0)
412 exit(FALSE);
413 }
399#endif 414#endif
400 exit (mount_one (device, directory, filesystemType, 415 exit(mount_one(device, directory, filesystemType,
401 flags, string_flags, useMtab, fakeIt, extra_opts)); 416 flags, string_flags, useMtab, fakeIt,
402 } else { 417 extra_opts));
403 goto goodbye; 418 } else {
419 goto goodbye;
420 }
404 } 421 }
405 } 422 exit(TRUE);
406 exit( TRUE);
407 423
408goodbye: 424 goodbye:
409 usage( mount_usage); 425 usage(mount_usage);
410} 426}
411
diff --git a/util-linux/nfsmount.c b/util-linux/nfsmount.c
index f2bd2f49c..03ce58447 100644
--- a/util-linux/nfsmount.c
+++ b/util-linux/nfsmount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * nfsmount.c -- Linux NFS mount 3 * nfsmount.c -- Linux NFS mount
3 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> 4 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
@@ -53,7 +54,7 @@
53 54
54#define _ 55#define _
55#define HAVE_inet_aton 56#define HAVE_inet_aton
56#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 57#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
57#define sloppy 0 58#define sloppy 0
58#define EX_FAIL 1 59#define EX_FAIL 1
59#define EX_BG 1 60#define EX_BG 1
@@ -65,8 +66,8 @@ static char *nfs_strerror(int stat);
65 66
66#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) 67#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
67 68
68static int 69static int linux_version_code(void)
69linux_version_code(void) { 70{
70 struct utsname my_utsname; 71 struct utsname my_utsname;
71 int p, q, r; 72 int p, q, r;
72 73
@@ -74,7 +75,7 @@ linux_version_code(void) {
74 p = atoi(strtok(my_utsname.release, ".")); 75 p = atoi(strtok(my_utsname.release, "."));
75 q = atoi(strtok(NULL, ".")); 76 q = atoi(strtok(NULL, "."));
76 r = atoi(strtok(NULL, ".")); 77 r = atoi(strtok(NULL, "."));
77 return MAKE_VERSION(p,q,r); 78 return MAKE_VERSION(p, q, r);
78 } 79 }
79 return 0; 80 return 0;
80} 81}
@@ -95,22 +96,22 @@ static int nfs_mount_version = NFS_MOUNT_VERSION;
95 * NFS_MOUNT_VERSION: these nfsmount sources at compile time 96 * NFS_MOUNT_VERSION: these nfsmount sources at compile time
96 * nfs_mount_version: version this source and running kernel can handle 97 * nfs_mount_version: version this source and running kernel can handle
97 */ 98 */
98static void 99static void find_kernel_nfs_mount_version(void)
99find_kernel_nfs_mount_version(void) { 100{
100 int kernel_version = linux_version_code(); 101 int kernel_version = linux_version_code();
101 102
102 if (kernel_version) { 103 if (kernel_version) {
103 if (kernel_version < MAKE_VERSION(2,1,32)) 104 if (kernel_version < MAKE_VERSION(2, 1, 32))
104 nfs_mount_version = 1; 105 nfs_mount_version = 1;
105 else 106 else
106 nfs_mount_version = 3; 107 nfs_mount_version = 3;
107 } 108 }
108 if (nfs_mount_version > NFS_MOUNT_VERSION) 109 if (nfs_mount_version > NFS_MOUNT_VERSION)
109 nfs_mount_version = NFS_MOUNT_VERSION; 110 nfs_mount_version = NFS_MOUNT_VERSION;
110} 111}
111 112
112int nfsmount(const char *spec, const char *node, unsigned long *flags, 113int nfsmount(const char *spec, const char *node, unsigned long *flags,
113 char **extra_opts, char **mount_opts, int running_bg) 114 char **extra_opts, char **mount_opts, int running_bg)
114{ 115{
115 static char *prev_bg_host; 116 static char *prev_bg_host;
116 char hostdir[1024]; 117 char hostdir[1024];
@@ -118,7 +119,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
118 char *hostname; 119 char *hostname;
119 char *dirname; 120 char *dirname;
120 char *old_opts; 121 char *old_opts;
121 char *mounthost=NULL; 122 char *mounthost = NULL;
122 char new_opts[1024]; 123 char new_opts[1024];
123 fhandle root_fhandle; 124 fhandle root_fhandle;
124 struct timeval total_timeout; 125 struct timeval total_timeout;
@@ -161,7 +162,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
161 mclient = NULL; 162 mclient = NULL;
162 if (strlen(spec) >= sizeof(hostdir)) { 163 if (strlen(spec) >= sizeof(hostdir)) {
163 fprintf(stderr, _("mount: " 164 fprintf(stderr, _("mount: "
164 "excessively long host:dir argument\n")); 165 "excessively long host:dir argument\n"));
165 goto fail; 166 goto fail;
166 } 167 }
167 strcpy(hostdir, spec); 168 strcpy(hostdir, spec);
@@ -174,11 +175,11 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
174 if ((s = strchr(hostdir, ','))) { 175 if ((s = strchr(hostdir, ','))) {
175 *s = '\0'; 176 *s = '\0';
176 fprintf(stderr, _("mount: warning: " 177 fprintf(stderr, _("mount: warning: "
177 "multiple hostnames not supported\n")); 178 "multiple hostnames not supported\n"));
178 } 179 }
179 } else { 180 } else {
180 fprintf(stderr, _("mount: " 181 fprintf(stderr, _("mount: "
181 "directory to mount not in host:dir format\n")); 182 "directory to mount not in host:dir format\n"));
182 goto fail; 183 goto fail;
183 } 184 }
184 185
@@ -189,20 +190,18 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
189 { 190 {
190 if ((hp = gethostbyname(hostname)) == NULL) { 191 if ((hp = gethostbyname(hostname)) == NULL) {
191 fprintf(stderr, _("mount: can't get address for %s\n"), 192 fprintf(stderr, _("mount: can't get address for %s\n"),
192 hostname); 193 hostname);
193 goto fail; 194 goto fail;
194 } else { 195 } else {
195 if (hp->h_length > sizeof(struct in_addr)) { 196 if (hp->h_length > sizeof(struct in_addr)) {
196 fprintf(stderr, 197 fprintf(stderr, _("mount: got bad hp->h_length\n"));
197 _("mount: got bad hp->h_length\n"));
198 hp->h_length = sizeof(struct in_addr); 198 hp->h_length = sizeof(struct in_addr);
199 } 199 }
200 memcpy(&server_addr.sin_addr, 200 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
201 hp->h_addr, hp->h_length);
202 } 201 }
203 } 202 }
204 203
205 memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); 204 memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr));
206 205
207 /* add IP address to mtab options for use when unmounting */ 206 /* add IP address to mtab options for use when unmounting */
208 207
@@ -211,12 +210,10 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
211 if (!old_opts) 210 if (!old_opts)
212 old_opts = ""; 211 old_opts = "";
213 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { 212 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
214 fprintf(stderr, _("mount: " 213 fprintf(stderr, _("mount: " "excessively long option argument\n"));
215 "excessively long option argument\n"));
216 goto fail; 214 goto fail;
217 } 215 }
218 sprintf(new_opts, "%s%saddr=%s", 216 sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s);
219 old_opts, *old_opts ? "," : "", s);
220 *extra_opts = xstrdup(new_opts); 217 *extra_opts = xstrdup(new_opts);
221 218
222 /* Set default options. 219 /* Set default options.
@@ -224,13 +221,13 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
224 * let the kernel decide. 221 * let the kernel decide.
225 * timeo is filled in after we know whether it'll be TCP or UDP. */ 222 * timeo is filled in after we know whether it'll be TCP or UDP. */
226 memset(&data, 0, sizeof(data)); 223 memset(&data, 0, sizeof(data));
227 data.retrans = 3; 224 data.retrans = 3;
228 data.acregmin = 3; 225 data.acregmin = 3;
229 data.acregmax = 60; 226 data.acregmax = 60;
230 data.acdirmin = 30; 227 data.acdirmin = 30;
231 data.acdirmax = 60; 228 data.acdirmax = 60;
232#if NFS_MOUNT_VERSION >= 2 229#if NFS_MOUNT_VERSION >= 2
233 data.namlen = NAME_MAX; 230 data.namlen = NAME_MAX;
234#endif 231#endif
235 232
236 bg = 0; 233 bg = 0;
@@ -240,7 +237,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
240 nocto = 0; 237 nocto = 0;
241 nolock = 0; 238 nolock = 0;
242 noac = 0; 239 noac = 0;
243 retry = 10000; /* 10000 minutes ~ 1 week */ 240 retry = 10000; /* 10000 minutes ~ 1 week */
244 tcp = 0; 241 tcp = 0;
245 242
246 mountprog = MOUNTPROG; 243 mountprog = MOUNTPROG;
@@ -254,7 +251,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
254 251
255 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { 252 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
256 if ((opteq = strchr(opt, '='))) { 253 if ((opteq = strchr(opt, '='))) {
257 val = atoi(opteq + 1); 254 val = atoi(opteq + 1);
258 *opteq = '\0'; 255 *opteq = '\0';
259 if (!strcmp(opt, "rsize")) 256 if (!strcmp(opt, "rsize"))
260 data.rsize = val; 257 data.rsize = val;
@@ -277,29 +274,27 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
277 data.acregmax = val; 274 data.acregmax = val;
278 data.acdirmin = val; 275 data.acdirmin = val;
279 data.acdirmax = val; 276 data.acdirmax = val;
280 } 277 } else if (!strcmp(opt, "retry"))
281 else if (!strcmp(opt, "retry"))
282 retry = val; 278 retry = val;
283 else if (!strcmp(opt, "port")) 279 else if (!strcmp(opt, "port"))
284 port = val; 280 port = val;
285 else if (!strcmp(opt, "mountport")) 281 else if (!strcmp(opt, "mountport"))
286 mountport = val; 282 mountport = val;
287 else if (!strcmp(opt, "mounthost")) 283 else if (!strcmp(opt, "mounthost"))
288 mounthost=xstrndup(opteq+1, 284 mounthost = xstrndup(opteq + 1,
289 strcspn(opteq+1," \t\n\r,")); 285 strcspn(opteq + 1, " \t\n\r,"));
290 else if (!strcmp(opt, "mountprog")) 286 else if (!strcmp(opt, "mountprog"))
291 mountprog = val; 287 mountprog = val;
292 else if (!strcmp(opt, "mountvers")) 288 else if (!strcmp(opt, "mountvers"))
293 mountvers = val; 289 mountvers = val;
294 else if (!strcmp(opt, "nfsprog")) 290 else if (!strcmp(opt, "nfsprog"))
295 nfsprog = val; 291 nfsprog = val;
296 else if (!strcmp(opt, "nfsvers") || 292 else if (!strcmp(opt, "nfsvers") || !strcmp(opt, "vers"))
297 !strcmp(opt, "vers"))
298 nfsvers = val; 293 nfsvers = val;
299 else if (!strcmp(opt, "proto")) { 294 else if (!strcmp(opt, "proto")) {
300 if (!strncmp(opteq+1, "tcp", 3)) 295 if (!strncmp(opteq + 1, "tcp", 3))
301 tcp = 1; 296 tcp = 1;
302 else if (!strncmp(opteq+1, "udp", 3)) 297 else if (!strncmp(opteq + 1, "udp", 3))
303 tcp = 0; 298 tcp = 0;
304 else 299 else
305 printf(_("Warning: Unrecognized proto= option.\n")); 300 printf(_("Warning: Unrecognized proto= option.\n"));
@@ -309,24 +304,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
309 data.namlen = val; 304 data.namlen = val;
310 else 305 else
311#endif 306#endif
312 printf(_("Warning: Option namlen is not supported.\n")); 307 printf(_
308 ("Warning: Option namlen is not supported.\n"));
313 } else if (!strcmp(opt, "addr")) 309 } else if (!strcmp(opt, "addr"))
314 /* ignore */; 310 /* ignore */ ;
315 else { 311 else {
316 printf(_("unknown nfs mount parameter: " 312 printf(_("unknown nfs mount parameter: "
317 "%s=%d\n"), opt, val); 313 "%s=%d\n"), opt, val);
318 goto fail; 314 goto fail;
319 } 315 }
320 } 316 } else {
321 else {
322 val = 1; 317 val = 1;
323 if (!strncmp(opt, "no", 2)) { 318 if (!strncmp(opt, "no", 2)) {
324 val = 0; 319 val = 0;
325 opt += 2; 320 opt += 2;
326 } 321 }
327 if (!strcmp(opt, "bg")) 322 if (!strcmp(opt, "bg"))
328 bg = val; 323 bg = val;
329 else if (!strcmp(opt, "fg")) 324 else if (!strcmp(opt, "fg"))
330 bg = !val; 325 bg = !val;
331 else if (!strcmp(opt, "soft")) 326 else if (!strcmp(opt, "soft"))
332 soft = val; 327 soft = val;
@@ -348,11 +343,12 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
348 if (nfs_mount_version >= 3) 343 if (nfs_mount_version >= 3)
349 nolock = !val; 344 nolock = !val;
350 else 345 else
351 printf(_("Warning: option nolock is not supported.\n")); 346 printf(_
347 ("Warning: option nolock is not supported.\n"));
352 } else { 348 } else {
353 if (!sloppy) { 349 if (!sloppy) {
354 printf(_("unknown nfs mount option: " 350 printf(_("unknown nfs mount option: "
355 "%s%s\n"), val ? "" : "no", opt); 351 "%s%s\n"), val ? "" : "no", opt);
356 goto fail; 352 goto fail;
357 } 353 }
358 } 354 }
@@ -378,22 +374,21 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
378 374
379#ifdef NFS_MOUNT_DEBUG 375#ifdef NFS_MOUNT_DEBUG
380 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", 376 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
381 data.rsize, data.wsize, data.timeo, data.retrans); 377 data.rsize, data.wsize, data.timeo, data.retrans);
382 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", 378 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
383 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); 379 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
384 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", 380 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
385 port, bg, retry, data.flags); 381 port, bg, retry, data.flags);
386 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", 382 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
387 mountprog, mountvers, nfsprog, nfsvers); 383 mountprog, mountvers, nfsprog, nfsvers);
388 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", 384 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
389 (data.flags & NFS_MOUNT_SOFT) != 0, 385 (data.flags & NFS_MOUNT_SOFT) != 0,
390 (data.flags & NFS_MOUNT_INTR) != 0, 386 (data.flags & NFS_MOUNT_INTR) != 0,
391 (data.flags & NFS_MOUNT_POSIX) != 0, 387 (data.flags & NFS_MOUNT_POSIX) != 0,
392 (data.flags & NFS_MOUNT_NOCTO) != 0, 388 (data.flags & NFS_MOUNT_NOCTO) != 0,
393 (data.flags & NFS_MOUNT_NOAC) != 0); 389 (data.flags & NFS_MOUNT_NOAC) != 0);
394#if NFS_MOUNT_VERSION >= 2 390#if NFS_MOUNT_VERSION >= 2
395 printf("tcp = %d\n", 391 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0);
396 (data.flags & NFS_MOUNT_TCP) != 0);
397#endif 392#endif
398#endif 393#endif
399 394
@@ -409,7 +404,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
409 * give up immediately, to avoid the initial timeout. 404 * give up immediately, to avoid the initial timeout.
410 */ 405 */
411 if (bg && !running_bg && 406 if (bg && !running_bg &&
412 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { 407 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
413 if (retry > 0) 408 if (retry > 0)
414 retval = EX_BG; 409 retval = EX_BG;
415 return retval; 410 return retval;
@@ -418,25 +413,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
418 /* create mount deamon client */ 413 /* create mount deamon client */
419 /* See if the nfs host = mount host. */ 414 /* See if the nfs host = mount host. */
420 if (mounthost) { 415 if (mounthost) {
421 if (mounthost[0] >= '0' && mounthost[0] <= '9') { 416 if (mounthost[0] >= '0' && mounthost[0] <= '9') {
422 mount_server_addr.sin_family = AF_INET; 417 mount_server_addr.sin_family = AF_INET;
423 mount_server_addr.sin_addr.s_addr = inet_addr(hostname); 418 mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
424 } else { 419 } else {
425 if ((hp = gethostbyname(mounthost)) == NULL) { 420 if ((hp = gethostbyname(mounthost)) == NULL) {
426 fprintf(stderr, _("mount: can't get address for %s\n"), 421 fprintf(stderr, _("mount: can't get address for %s\n"),
427 hostname); 422 hostname);
428 goto fail; 423 goto fail;
429 } else { 424 } else {
430 if (hp->h_length > sizeof(struct in_addr)) { 425 if (hp->h_length > sizeof(struct in_addr)) {
431 fprintf(stderr, 426 fprintf(stderr, _("mount: got bad hp->h_length?\n"));
432 _("mount: got bad hp->h_length?\n")); 427 hp->h_length = sizeof(struct in_addr);
433 hp->h_length = sizeof(struct in_addr); 428 }
434 } 429 mount_server_addr.sin_family = AF_INET;
435 mount_server_addr.sin_family = AF_INET; 430 memcpy(&mount_server_addr.sin_addr,
436 memcpy(&mount_server_addr.sin_addr, 431 hp->h_addr, hp->h_length);
437 hp->h_addr, hp->h_length); 432 }
438 } 433 }
439 }
440 } 434 }
441 435
442 /* 436 /*
@@ -466,7 +460,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
466 for (;;) { 460 for (;;) {
467 if (bg && stat(node, &statbuf) == -1) { 461 if (bg && stat(node, &statbuf) == -1) {
468 if (running_bg) { 462 if (running_bg) {
469 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ 463 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */
470 val *= 2; 464 val *= 2;
471 if (val > 30) 465 if (val > 30)
472 val = 30; 466 val = 30;
@@ -480,24 +474,24 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
480 mount_server_addr.sin_port = htons(mountport); 474 mount_server_addr.sin_port = htons(mountport);
481 msock = RPC_ANYSOCK; 475 msock = RPC_ANYSOCK;
482 mclient = clnttcp_create(&mount_server_addr, 476 mclient = clnttcp_create(&mount_server_addr,
483 mountprog, mountvers, 477 mountprog, mountvers, &msock, 0, 0);
484 &msock, 0, 0);
485 478
486 /* if this fails, contact the mount daemon via UDP */ 479 /* if this fails, contact the mount daemon via UDP */
487 if (!mclient) { 480 if (!mclient) {
488 mount_server_addr.sin_port = htons(mountport); 481 mount_server_addr.sin_port = htons(mountport);
489 msock = RPC_ANYSOCK; 482 msock = RPC_ANYSOCK;
490 mclient = clntudp_create(&mount_server_addr, 483 mclient = clntudp_create(&mount_server_addr,
491 mountprog, mountvers, 484 mountprog, mountvers,
492 retry_timeout, &msock); 485 retry_timeout, &msock);
493 } 486 }
494 if (mclient) { 487 if (mclient) {
495 /* try to mount hostname:dirname */ 488 /* try to mount hostname:dirname */
496 mclient->cl_auth = authunix_create_default(); 489 mclient->cl_auth = authunix_create_default();
497 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, 490 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
498 (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, 491 (xdrproc_t) xdr_dirpath,
499 (xdrproc_t) xdr_fhstatus, (caddr_t) &status, 492 (caddr_t) & dirname,
500 total_timeout); 493 (xdrproc_t) xdr_fhstatus,
494 (caddr_t) & status, total_timeout);
501 if (clnt_stat == RPC_SUCCESS) 495 if (clnt_stat == RPC_SUCCESS)
502 break; /* we're done */ 496 break; /* we're done */
503 if (errno != ECONNREFUSED) { 497 if (errno != ECONNREFUSED) {
@@ -517,7 +511,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
517 prevt = t; 511 prevt = t;
518 } 512 }
519 if (!bg) 513 if (!bg)
520 goto fail; 514 goto fail;
521 if (!running_bg) { 515 if (!running_bg) {
522 prev_bg_host = xstrdup(hostname); 516 prev_bg_host = xstrdup(hostname);
523 if (retry > 0) 517 if (retry > 0)
@@ -531,18 +525,18 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
531 525
532 if (status.fhs_status != 0) { 526 if (status.fhs_status != 0) {
533 fprintf(stderr, 527 fprintf(stderr,
534 _("mount: %s:%s failed, reason given by server: %s\n"), 528 _("mount: %s:%s failed, reason given by server: %s\n"),
535 hostname, dirname, nfs_strerror(status.fhs_status)); 529 hostname, dirname, nfs_strerror(status.fhs_status));
536 goto fail; 530 goto fail;
537 } 531 }
538 memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, 532 memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle,
539 sizeof (root_fhandle)); 533 sizeof(root_fhandle));
540 534
541 /* create nfs socket for kernel */ 535 /* create nfs socket for kernel */
542 536
543 if (tcp) { 537 if (tcp) {
544 if (nfs_mount_version < 3) { 538 if (nfs_mount_version < 3) {
545 printf(_("NFS over TCP is not supported.\n")); 539 printf(_("NFS over TCP is not supported.\n"));
546 goto fail; 540 goto fail;
547 } 541 }
548 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 542 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -559,7 +553,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
559 if (port == 0) { 553 if (port == 0) {
560 server_addr.sin_port = PMAPPORT; 554 server_addr.sin_port = PMAPPORT;
561 port = pmap_getport(&server_addr, nfsprog, nfsvers, 555 port = pmap_getport(&server_addr, nfsprog, nfsvers,
562 tcp ? IPPROTO_TCP : IPPROTO_UDP); 556 tcp ? IPPROTO_TCP : IPPROTO_UDP);
563 if (port == 0) 557 if (port == 0)
564 port = NFS_PORT; 558 port = NFS_PORT;
565#ifdef NFS_MOUNT_DEBUG 559#ifdef NFS_MOUNT_DEBUG
@@ -571,14 +565,14 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
571 printf(_("using port %d for nfs deamon\n"), port); 565 printf(_("using port %d for nfs deamon\n"), port);
572#endif 566#endif
573 server_addr.sin_port = htons(port); 567 server_addr.sin_port = htons(port);
574 /* 568 /*
575 * connect() the socket for kernels 1.3.10 and below only, 569 * connect() the socket for kernels 1.3.10 and below only,
576 * to avoid problems with multihomed hosts. 570 * to avoid problems with multihomed hosts.
577 * --Swen 571 * --Swen
578 */ 572 */
579 if (linux_version_code() <= 66314 573 if (linux_version_code() <= 66314
580 && connect(fsock, (struct sockaddr *) &server_addr, 574 && connect(fsock, (struct sockaddr *) &server_addr,
581 sizeof (server_addr)) < 0) { 575 sizeof(server_addr)) < 0) {
582 perror(_("nfs connect")); 576 perror(_("nfs connect"));
583 goto fail; 577 goto fail;
584 } 578 }
@@ -587,7 +581,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
587 581
588 data.fd = fsock; 582 data.fd = fsock;
589 memcpy((char *) &data.root, (char *) &root_fhandle, 583 memcpy((char *) &data.root, (char *) &root_fhandle,
590 sizeof (root_fhandle)); 584 sizeof(root_fhandle));
591 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); 585 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
592 strncpy(data.hostname, hostname, sizeof(data.hostname)); 586 strncpy(data.hostname, hostname, sizeof(data.hostname));
593 587
@@ -600,7 +594,7 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
600 594
601 /* abort */ 595 /* abort */
602 596
603fail: 597 fail:
604 if (msock != -1) { 598 if (msock != -1) {
605 if (mclient) { 599 if (mclient) {
606 auth_destroy(mclient->cl_auth); 600 auth_destroy(mclient->cl_auth);
@@ -611,7 +605,7 @@ fail:
611 if (fsock != -1) 605 if (fsock != -1)
612 close(fsock); 606 close(fsock);
613 return retval; 607 return retval;
614} 608}
615 609
616/* 610/*
617 * We need to translate between nfs status return values and 611 * We need to translate between nfs status return values and
@@ -630,33 +624,37 @@ static struct {
630 enum nfs_stat stat; 624 enum nfs_stat stat;
631 int errnum; 625 int errnum;
632} nfs_errtbl[] = { 626} nfs_errtbl[] = {
633 { NFS_OK, 0 }, 627 {
634 { NFSERR_PERM, EPERM }, 628 NFS_OK, 0}, {
635 { NFSERR_NOENT, ENOENT }, 629 NFSERR_PERM, EPERM}, {
636 { NFSERR_IO, EIO }, 630 NFSERR_NOENT, ENOENT}, {
637 { NFSERR_NXIO, ENXIO }, 631 NFSERR_IO, EIO}, {
638 { NFSERR_ACCES, EACCES }, 632 NFSERR_NXIO, ENXIO}, {
639 { NFSERR_EXIST, EEXIST }, 633 NFSERR_ACCES, EACCES}, {
640 { NFSERR_NODEV, ENODEV }, 634 NFSERR_EXIST, EEXIST}, {
641 { NFSERR_NOTDIR, ENOTDIR }, 635 NFSERR_NODEV, ENODEV}, {
642 { NFSERR_ISDIR, EISDIR }, 636 NFSERR_NOTDIR, ENOTDIR}, {
637 NFSERR_ISDIR, EISDIR},
643#ifdef NFSERR_INVAL 638#ifdef NFSERR_INVAL
644 { NFSERR_INVAL, EINVAL }, /* that Sun forgot */ 639 {
640 NFSERR_INVAL, EINVAL}, /* that Sun forgot */
645#endif 641#endif
646 { NFSERR_FBIG, EFBIG }, 642 {
647 { NFSERR_NOSPC, ENOSPC }, 643 NFSERR_FBIG, EFBIG}, {
648 { NFSERR_ROFS, EROFS }, 644 NFSERR_NOSPC, ENOSPC}, {
649 { NFSERR_NAMETOOLONG, ENAMETOOLONG }, 645 NFSERR_ROFS, EROFS}, {
650 { NFSERR_NOTEMPTY, ENOTEMPTY }, 646 NFSERR_NAMETOOLONG, ENAMETOOLONG}, {
651 { NFSERR_DQUOT, EDQUOT }, 647 NFSERR_NOTEMPTY, ENOTEMPTY}, {
652 { NFSERR_STALE, ESTALE }, 648 NFSERR_DQUOT, EDQUOT}, {
649 NFSERR_STALE, ESTALE},
653#ifdef EWFLUSH 650#ifdef EWFLUSH
654 { NFSERR_WFLUSH, EWFLUSH }, 651 {
652 NFSERR_WFLUSH, EWFLUSH},
655#endif 653#endif
656 /* Throw in some NFSv3 values for even more fun (HP returns these) */ 654 /* Throw in some NFSv3 values for even more fun (HP returns these) */
657 { 71, EREMOTE }, 655 {
658 656 71, EREMOTE}, {
659 { -1, EIO } 657 -1, EIO}
660}; 658};
661 659
662static char *nfs_strerror(int stat) 660static char *nfs_strerror(int stat)
@@ -673,33 +671,32 @@ static char *nfs_strerror(int stat)
673} 671}
674 672
675#if 0 673#if 0
676int 674int my_getport(struct in_addr server, struct timeval *timeo, ...)
677my_getport(struct in_addr server, struct timeval *timeo, ...)
678{ 675{
679 struct sockaddr_in sin; 676 struct sockaddr_in sin;
680 struct pmap pmap; 677 struct pmap pmap;
681 CLIENT *clnt; 678 CLIENT *clnt;
682 int sock = RPC_ANYSOCK, port; 679 int sock = RPC_ANYSOCK, port;
683 680
684 pmap.pm_prog = prog; 681 pmap.pm_prog = prog;
685 pmap.pm_vers = vers; 682 pmap.pm_vers = vers;
686 pmap.pm_prot = prot; 683 pmap.pm_prot = prot;
687 pmap.pm_port = 0; 684 pmap.pm_port = 0;
688 sin.sin_family = AF_INET; 685 sin.sin_family = AF_INET;
689 sin.sin_addr = server; 686 sin.sin_addr = server;
690 sin.sin_port = htons(111); 687 sin.sin_port = htons(111);
691 clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock); 688 clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock);
692 status = clnt_call(clnt, PMAP_GETPORT, 689 status = clnt_call(clnt, PMAP_GETPORT,
693 &pmap, (xdrproc_t) xdr_pmap, 690 &pmap, (xdrproc_t) xdr_pmap,
694 &port, (xdrproc_t) xdr_uint); 691 &port, (xdrproc_t) xdr_uint);
695 if (status != SUCCESS) { 692 if (status != SUCCESS) {
696 /* natter */ 693 /* natter */
697 port = 0; 694 port = 0;
698 } 695 }
699 696
700 clnt_destroy(clnt); 697 clnt_destroy(clnt);
701 close(sock); 698 close(sock);
702 return port; 699 return port;
703} 700}
704#endif 701#endif
705 702
@@ -756,28 +753,26 @@ my_getport(struct in_addr server, struct timeval *timeo, ...)
756 753
757/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ 754/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
758 755
759bool_t 756bool_t xdr_fhandle(XDR * xdrs, fhandle objp)
760xdr_fhandle(XDR *xdrs, fhandle objp)
761{ 757{
762 758
763 if (!xdr_opaque(xdrs, objp, FHSIZE)) { 759 if (!xdr_opaque(xdrs, objp, FHSIZE)) {
764 return (FALSE); 760 return (FALSE);
765 } 761 }
766 return (TRUE); 762 return (TRUE);
767} 763}
768 764
769bool_t 765bool_t xdr_fhstatus(XDR * xdrs, fhstatus * objp)
770xdr_fhstatus(XDR *xdrs, fhstatus *objp)
771{ 766{
772 767
773 if (!xdr_u_int(xdrs, &objp->fhs_status)) { 768 if (!xdr_u_int(xdrs, &objp->fhs_status)) {
774 return (FALSE); 769 return (FALSE);
775 } 770 }
776 switch (objp->fhs_status) { 771 switch (objp->fhs_status) {
777 case 0: 772 case 0:
778 if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) { 773 if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
779 return (FALSE); 774 return (FALSE);
780 } 775 }
781 break; 776 break;
782 default: 777 default:
783 break; 778 break;
@@ -785,245 +780,246 @@ xdr_fhstatus(XDR *xdrs, fhstatus *objp)
785 return (TRUE); 780 return (TRUE);
786} 781}
787 782
788bool_t 783bool_t xdr_dirpath(XDR * xdrs, dirpath * objp)
789xdr_dirpath(XDR *xdrs, dirpath *objp)
790{ 784{
791 785
792 if (!xdr_string(xdrs, objp, MNTPATHLEN)) { 786 if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
793 return (FALSE); 787 return (FALSE);
794 } 788 }
795 return (TRUE); 789 return (TRUE);
796} 790}
797 791
798bool_t 792bool_t xdr_name(XDR * xdrs, name * objp)
799xdr_name(XDR *xdrs, name *objp)
800{ 793{
801 794
802 if (!xdr_string(xdrs, objp, MNTNAMLEN)) { 795 if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
803 return (FALSE); 796 return (FALSE);
804 } 797 }
805 return (TRUE); 798 return (TRUE);
806} 799}
807 800
808bool_t 801bool_t xdr_mountlist(XDR * xdrs, mountlist * objp)
809xdr_mountlist(XDR *xdrs, mountlist *objp)
810{ 802{
811 803
812 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) { 804 if (!xdr_pointer
813 return (FALSE); 805 (xdrs, (char **) objp, sizeof(struct mountbody),
814 } 806 (xdrproc_t) xdr_mountbody)) {
807 return (FALSE);
808 }
815 return (TRUE); 809 return (TRUE);
816} 810}
817 811
818bool_t 812bool_t xdr_mountbody(XDR * xdrs, mountbody * objp)
819xdr_mountbody(XDR *xdrs, mountbody *objp)
820{ 813{
821 814
822 if (!xdr_name(xdrs, &objp->ml_hostname)) { 815 if (!xdr_name(xdrs, &objp->ml_hostname)) {
823 return (FALSE); 816 return (FALSE);
824 } 817 }
825 if (!xdr_dirpath(xdrs, &objp->ml_directory)) { 818 if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
826 return (FALSE); 819 return (FALSE);
827 } 820 }
828 if (!xdr_mountlist(xdrs, &objp->ml_next)) { 821 if (!xdr_mountlist(xdrs, &objp->ml_next)) {
829 return (FALSE); 822 return (FALSE);
830 } 823 }
831 return (TRUE); 824 return (TRUE);
832} 825}
833 826
834bool_t 827bool_t xdr_groups(XDR * xdrs, groups * objp)
835xdr_groups(XDR *xdrs, groups *objp)
836{ 828{
837 829
838 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) { 830 if (!xdr_pointer
839 return (FALSE); 831 (xdrs, (char **) objp, sizeof(struct groupnode),
840 } 832 (xdrproc_t) xdr_groupnode)) {
833 return (FALSE);
834 }
841 return (TRUE); 835 return (TRUE);
842} 836}
843 837
844bool_t 838bool_t xdr_groupnode(XDR * xdrs, groupnode * objp)
845xdr_groupnode(XDR *xdrs, groupnode *objp)
846{ 839{
847 840
848 if (!xdr_name(xdrs, &objp->gr_name)) { 841 if (!xdr_name(xdrs, &objp->gr_name)) {
849 return (FALSE); 842 return (FALSE);
850 } 843 }
851 if (!xdr_groups(xdrs, &objp->gr_next)) { 844 if (!xdr_groups(xdrs, &objp->gr_next)) {
852 return (FALSE); 845 return (FALSE);
853 } 846 }
854 return (TRUE); 847 return (TRUE);
855} 848}
856 849
857bool_t 850bool_t xdr_exports(XDR * xdrs, exports * objp)
858xdr_exports(XDR *xdrs, exports *objp)
859{ 851{
860 852
861 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) { 853 if (!xdr_pointer
862 return (FALSE); 854 (xdrs, (char **) objp, sizeof(struct exportnode),
863 } 855 (xdrproc_t) xdr_exportnode)) {
856 return (FALSE);
857 }
864 return (TRUE); 858 return (TRUE);
865} 859}
866 860
867bool_t 861bool_t xdr_exportnode(XDR * xdrs, exportnode * objp)
868xdr_exportnode(XDR *xdrs, exportnode *objp)
869{ 862{
870 863
871 if (!xdr_dirpath(xdrs, &objp->ex_dir)) { 864 if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
872 return (FALSE); 865 return (FALSE);
873 } 866 }
874 if (!xdr_groups(xdrs, &objp->ex_groups)) { 867 if (!xdr_groups(xdrs, &objp->ex_groups)) {
875 return (FALSE); 868 return (FALSE);
876 } 869 }
877 if (!xdr_exports(xdrs, &objp->ex_next)) { 870 if (!xdr_exports(xdrs, &objp->ex_next)) {
878 return (FALSE); 871 return (FALSE);
879 } 872 }
880 return (TRUE); 873 return (TRUE);
881} 874}
882 875
883bool_t 876bool_t xdr_ppathcnf(XDR * xdrs, ppathcnf * objp)
884xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
885{ 877{
886 878
887 register long *buf; 879 register long *buf;
888 880
889 int i; 881 int i;
890 882
891 if (xdrs->x_op == XDR_ENCODE) { 883 if (xdrs->x_op == XDR_ENCODE) {
892 buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); 884 buf = (long *) XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
893 if (buf == NULL) {
894 if (!xdr_int(xdrs, &objp->pc_link_max)) {
895 return (FALSE);
896 }
897 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
898 return (FALSE);
899 }
900 if (!xdr_short(xdrs, &objp->pc_max_input)) {
901 return (FALSE);
902 }
903 if (!xdr_short(xdrs, &objp->pc_name_max)) {
904 return (FALSE);
905 }
906 if (!xdr_short(xdrs, &objp->pc_path_max)) {
907 return (FALSE);
908 }
909 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
910 return (FALSE);
911 }
912
913 }
914 else {
915 IXDR_PUT_LONG(buf,objp->pc_link_max);
916 IXDR_PUT_SHORT(buf,objp->pc_max_canon);
917 IXDR_PUT_SHORT(buf,objp->pc_max_input);
918 IXDR_PUT_SHORT(buf,objp->pc_name_max);
919 IXDR_PUT_SHORT(buf,objp->pc_path_max);
920 IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
921 }
922 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
923 return (FALSE);
924 }
925 if (!xdr_char(xdrs, &objp->pc_xxx)) {
926 return (FALSE);
927 }
928 buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
929 if (buf == NULL) { 885 if (buf == NULL) {
930 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 886 if (!xdr_int(xdrs, &objp->pc_link_max)) {
931 return (FALSE); 887 return (FALSE);
932 } 888 }
933 889 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
934 } 890 return (FALSE);
935 else { 891 }
936 { register short *genp; 892 if (!xdr_short(xdrs, &objp->pc_max_input)) {
937 for ( i = 0,genp=objp->pc_mask; 893 return (FALSE);
938 i < 2; i++){ 894 }
939 IXDR_PUT_SHORT(buf,*genp++); 895 if (!xdr_short(xdrs, &objp->pc_name_max)) {
940 } 896 return (FALSE);
941 }; 897 }
942 } 898 if (!xdr_short(xdrs, &objp->pc_path_max)) {
943 899 return (FALSE);
944 return (TRUE); 900 }
901 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
902 return (FALSE);
903 }
904
905 } else {
906 IXDR_PUT_LONG(buf, objp->pc_link_max);
907 IXDR_PUT_SHORT(buf, objp->pc_max_canon);
908 IXDR_PUT_SHORT(buf, objp->pc_max_input);
909 IXDR_PUT_SHORT(buf, objp->pc_name_max);
910 IXDR_PUT_SHORT(buf, objp->pc_path_max);
911 IXDR_PUT_SHORT(buf, objp->pc_pipe_buf);
912 }
913 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
914 return (FALSE);
915 }
916 if (!xdr_char(xdrs, &objp->pc_xxx)) {
917 return (FALSE);
918 }
919 buf = (long *) XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
920 if (buf == NULL) {
921 if (!xdr_vector
922 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
923 (xdrproc_t) xdr_short)) {
924 return (FALSE);
925 }
926
927 } else {
928 {
929 register short *genp;
930
931 for (i = 0, genp = objp->pc_mask; i < 2; i++) {
932 IXDR_PUT_SHORT(buf, *genp++);
933 }
934 };
935 }
936
937 return (TRUE);
945 } else if (xdrs->x_op == XDR_DECODE) { 938 } else if (xdrs->x_op == XDR_DECODE) {
946 buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); 939 buf = (long *) XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
947 if (buf == NULL) { 940 if (buf == NULL) {
948 if (!xdr_int(xdrs, &objp->pc_link_max)) { 941 if (!xdr_int(xdrs, &objp->pc_link_max)) {
949 return (FALSE); 942 return (FALSE);
950 } 943 }
951 if (!xdr_short(xdrs, &objp->pc_max_canon)) { 944 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
952 return (FALSE); 945 return (FALSE);
953 } 946 }
954 if (!xdr_short(xdrs, &objp->pc_max_input)) { 947 if (!xdr_short(xdrs, &objp->pc_max_input)) {
955 return (FALSE); 948 return (FALSE);
956 } 949 }
957 if (!xdr_short(xdrs, &objp->pc_name_max)) { 950 if (!xdr_short(xdrs, &objp->pc_name_max)) {
958 return (FALSE); 951 return (FALSE);
959 } 952 }
960 if (!xdr_short(xdrs, &objp->pc_path_max)) { 953 if (!xdr_short(xdrs, &objp->pc_path_max)) {
961 return (FALSE); 954 return (FALSE);
962 } 955 }
963 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { 956 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
964 return (FALSE); 957 return (FALSE);
965 } 958 }
966 959
967 } 960 } else {
968 else { 961 objp->pc_link_max = IXDR_GET_LONG(buf);
969 objp->pc_link_max = IXDR_GET_LONG(buf); 962 objp->pc_max_canon = IXDR_GET_SHORT(buf);
970 objp->pc_max_canon = IXDR_GET_SHORT(buf); 963 objp->pc_max_input = IXDR_GET_SHORT(buf);
971 objp->pc_max_input = IXDR_GET_SHORT(buf); 964 objp->pc_name_max = IXDR_GET_SHORT(buf);
972 objp->pc_name_max = IXDR_GET_SHORT(buf); 965 objp->pc_path_max = IXDR_GET_SHORT(buf);
973 objp->pc_path_max = IXDR_GET_SHORT(buf); 966 objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
974 objp->pc_pipe_buf = IXDR_GET_SHORT(buf); 967 }
975 } 968 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
976 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { 969 return (FALSE);
977 return (FALSE); 970 }
978 } 971 if (!xdr_char(xdrs, &objp->pc_xxx)) {
979 if (!xdr_char(xdrs, &objp->pc_xxx)) { 972 return (FALSE);
980 return (FALSE); 973 }
981 } 974 buf = (long *) XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
982 buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
983 if (buf == NULL) { 975 if (buf == NULL) {
984 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 976 if (!xdr_vector
985 return (FALSE); 977 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
986 } 978 (xdrproc_t) xdr_short)) {
987 979 return (FALSE);
988 } 980 }
989 else { 981
990 { register short *genp; 982 } else {
991 for ( i = 0,genp=objp->pc_mask; 983 {
992 i < 2; i++){ 984 register short *genp;
993 *genp++ = IXDR_GET_SHORT(buf); 985
994 } 986 for (i = 0, genp = objp->pc_mask; i < 2; i++) {
995 }; 987 *genp++ = IXDR_GET_SHORT(buf);
996 } 988 }
997 return(TRUE); 989 };
990 }
991 return (TRUE);
998 } 992 }
999 993
1000 if (!xdr_int(xdrs, &objp->pc_link_max)) { 994 if (!xdr_int(xdrs, &objp->pc_link_max)) {
1001 return (FALSE); 995 return (FALSE);
1002 } 996 }
1003 if (!xdr_short(xdrs, &objp->pc_max_canon)) { 997 if (!xdr_short(xdrs, &objp->pc_max_canon)) {
1004 return (FALSE); 998 return (FALSE);
1005 } 999 }
1006 if (!xdr_short(xdrs, &objp->pc_max_input)) { 1000 if (!xdr_short(xdrs, &objp->pc_max_input)) {
1007 return (FALSE); 1001 return (FALSE);
1008 } 1002 }
1009 if (!xdr_short(xdrs, &objp->pc_name_max)) { 1003 if (!xdr_short(xdrs, &objp->pc_name_max)) {
1010 return (FALSE); 1004 return (FALSE);
1011 } 1005 }
1012 if (!xdr_short(xdrs, &objp->pc_path_max)) { 1006 if (!xdr_short(xdrs, &objp->pc_path_max)) {
1013 return (FALSE); 1007 return (FALSE);
1014 } 1008 }
1015 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { 1009 if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
1016 return (FALSE); 1010 return (FALSE);
1017 } 1011 }
1018 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { 1012 if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
1019 return (FALSE); 1013 return (FALSE);
1020 } 1014 }
1021 if (!xdr_char(xdrs, &objp->pc_xxx)) { 1015 if (!xdr_char(xdrs, &objp->pc_xxx)) {
1022 return (FALSE); 1016 return (FALSE);
1023 } 1017 }
1024 if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { 1018 if (!xdr_vector
1025 return (FALSE); 1019 (xdrs, (char *) objp->pc_mask, 2, sizeof(short),
1026 } 1020 (xdrproc_t) xdr_short)) {
1021 return (FALSE);
1022 }
1027 return (TRUE); 1023 return (TRUE);
1028} 1024}
1029 1025
@@ -1063,247 +1059,232 @@ xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
1063 1059
1064/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ 1060/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
1065 1061
1066#include <string.h> /* for memset() */ 1062#include <string.h> /* for memset() */
1067 1063
1068/* Default timeout can be changed using clnt_control() */ 1064/* Default timeout can be changed using clnt_control() */
1069static struct timeval TIMEOUT = { 25, 0 }; 1065static struct timeval TIMEOUT = { 25, 0 };
1070 1066
1071void * 1067void *mountproc_null_1(argp, clnt)
1072mountproc_null_1(argp, clnt) 1068void *argp;
1073 void *argp; 1069CLIENT *clnt;
1074 CLIENT *clnt;
1075{ 1070{
1076 static char clnt_res; 1071 static char clnt_res;
1077 1072
1078 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1073 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1079 if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1074 if (clnt_call
1075 (clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp,
1076 (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1080 return (NULL); 1077 return (NULL);
1081 } 1078 }
1082 return ((void *)&clnt_res); 1079 return ((void *) &clnt_res);
1083} 1080}
1084 1081
1085fhstatus * 1082fhstatus *mountproc_mnt_1(argp, clnt)
1086mountproc_mnt_1(argp, clnt) 1083dirpath *argp;
1087 dirpath *argp; 1084CLIENT *clnt;
1088 CLIENT *clnt;
1089{ 1085{
1090 static fhstatus clnt_res; 1086 static fhstatus clnt_res;
1091 1087
1092 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1088 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1093 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, 1089 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1094 (caddr_t) argp, (xdrproc_t) xdr_fhstatus, 1090 (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1095 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1091 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1096 return (NULL); 1092 return (NULL);
1097 } 1093 }
1098 return (&clnt_res); 1094 return (&clnt_res);
1099} 1095}
1100 1096
1101mountlist * 1097mountlist *mountproc_dump_1(argp, clnt)
1102mountproc_dump_1(argp, clnt) 1098void *argp;
1103 void *argp; 1099CLIENT *clnt;
1104 CLIENT *clnt;
1105{ 1100{
1106 static mountlist clnt_res; 1101 static mountlist clnt_res;
1107 1102
1108 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1103 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1109 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, 1104 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void,
1110 (caddr_t) argp, (xdrproc_t) xdr_mountlist, 1105 (caddr_t) argp, (xdrproc_t) xdr_mountlist,
1111 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1106 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1112 return (NULL); 1107 return (NULL);
1113 } 1108 }
1114 return (&clnt_res); 1109 return (&clnt_res);
1115} 1110}
1116 1111
1117void * 1112void *mountproc_umnt_1(argp, clnt)
1118mountproc_umnt_1(argp, clnt) 1113dirpath *argp;
1119 dirpath *argp; 1114CLIENT *clnt;
1120 CLIENT *clnt;
1121{ 1115{
1122 static char clnt_res; 1116 static char clnt_res;
1123 1117
1124 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1118 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1125 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, 1119 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1126 (caddr_t) argp, (xdrproc_t) xdr_void, 1120 (caddr_t) argp, (xdrproc_t) xdr_void,
1127 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1121 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1128 return (NULL); 1122 return (NULL);
1129 } 1123 }
1130 return ((void *)&clnt_res); 1124 return ((void *) &clnt_res);
1131} 1125}
1132 1126
1133void * 1127void *mountproc_umntall_1(argp, clnt)
1134mountproc_umntall_1(argp, clnt) 1128void *argp;
1135 void *argp; 1129CLIENT *clnt;
1136 CLIENT *clnt;
1137{ 1130{
1138 static char clnt_res; 1131 static char clnt_res;
1139 1132
1140 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1133 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1141 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, 1134 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1142 (caddr_t) argp, (xdrproc_t) xdr_void, 1135 (caddr_t) argp, (xdrproc_t) xdr_void,
1143 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1136 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1144 return (NULL); 1137 return (NULL);
1145 } 1138 }
1146 return ((void *)&clnt_res); 1139 return ((void *) &clnt_res);
1147} 1140}
1148 1141
1149exports * 1142exports *mountproc_export_1(argp, clnt)
1150mountproc_export_1(argp, clnt) 1143void *argp;
1151 void *argp; 1144CLIENT *clnt;
1152 CLIENT *clnt;
1153{ 1145{
1154 static exports clnt_res; 1146 static exports clnt_res;
1155 1147
1156 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1148 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1157 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, 1149 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1158 (caddr_t) argp, (xdrproc_t) xdr_exports, 1150 (caddr_t) argp, (xdrproc_t) xdr_exports,
1159 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1151 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1160 return (NULL); 1152 return (NULL);
1161 } 1153 }
1162 return (&clnt_res); 1154 return (&clnt_res);
1163} 1155}
1164 1156
1165exports * 1157exports *mountproc_exportall_1(argp, clnt)
1166mountproc_exportall_1(argp, clnt) 1158void *argp;
1167 void *argp; 1159CLIENT *clnt;
1168 CLIENT *clnt;
1169{ 1160{
1170 static exports clnt_res; 1161 static exports clnt_res;
1171 1162
1172 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1163 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1173 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, 1164 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void,
1174 (caddr_t) argp, (xdrproc_t) xdr_exports, 1165 (caddr_t) argp, (xdrproc_t) xdr_exports,
1175 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1166 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1176 return (NULL); 1167 return (NULL);
1177 } 1168 }
1178 return (&clnt_res); 1169 return (&clnt_res);
1179} 1170}
1180 1171
1181void * 1172void *mountproc_null_2(argp, clnt)
1182mountproc_null_2(argp, clnt) 1173void *argp;
1183 void *argp; 1174CLIENT *clnt;
1184 CLIENT *clnt;
1185{ 1175{
1186 static char clnt_res; 1176 static char clnt_res;
1187 1177
1188 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1178 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1189 if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1179 if (clnt_call
1180 (clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp,
1181 (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1190 return (NULL); 1182 return (NULL);
1191 } 1183 }
1192 return ((void *)&clnt_res); 1184 return ((void *) &clnt_res);
1193} 1185}
1194 1186
1195fhstatus * 1187fhstatus *mountproc_mnt_2(argp, clnt)
1196mountproc_mnt_2(argp, clnt) 1188dirpath *argp;
1197 dirpath *argp; 1189CLIENT *clnt;
1198 CLIENT *clnt;
1199{ 1190{
1200 static fhstatus clnt_res; 1191 static fhstatus clnt_res;
1201 1192
1202 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1193 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1203 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, 1194 if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1204 (caddr_t) argp, (xdrproc_t) xdr_fhstatus, 1195 (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1205 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1196 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1206 return (NULL); 1197 return (NULL);
1207 } 1198 }
1208 return (&clnt_res); 1199 return (&clnt_res);
1209} 1200}
1210 1201
1211mountlist * 1202mountlist *mountproc_dump_2(argp, clnt)
1212mountproc_dump_2(argp, clnt) 1203void *argp;
1213 void *argp; 1204CLIENT *clnt;
1214 CLIENT *clnt;
1215{ 1205{
1216 static mountlist clnt_res; 1206 static mountlist clnt_res;
1217 1207
1218 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1208 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1219 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, 1209 if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp,
1220 (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res, 1210 (xdrproc_t) xdr_mountlist, (caddr_t) & clnt_res,
1221 TIMEOUT) != RPC_SUCCESS) { 1211 TIMEOUT) != RPC_SUCCESS) {
1222 return (NULL); 1212 return (NULL);
1223 } 1213 }
1224 return (&clnt_res); 1214 return (&clnt_res);
1225} 1215}
1226 1216
1227void * 1217void *mountproc_umnt_2(argp, clnt)
1228mountproc_umnt_2(argp, clnt) 1218dirpath *argp;
1229 dirpath *argp; 1219CLIENT *clnt;
1230 CLIENT *clnt;
1231{ 1220{
1232 static char clnt_res; 1221 static char clnt_res;
1233 1222
1234 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1223 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1235 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, 1224 if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1236 (caddr_t) argp, (xdrproc_t) xdr_void, 1225 (caddr_t) argp, (xdrproc_t) xdr_void,
1237 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1226 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1238 return (NULL); 1227 return (NULL);
1239 } 1228 }
1240 return ((void *)&clnt_res); 1229 return ((void *) &clnt_res);
1241} 1230}
1242 1231
1243void * 1232void *mountproc_umntall_2(argp, clnt)
1244mountproc_umntall_2(argp, clnt) 1233void *argp;
1245 void *argp; 1234CLIENT *clnt;
1246 CLIENT *clnt;
1247{ 1235{
1248 static char clnt_res; 1236 static char clnt_res;
1249 1237
1250 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1238 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1251 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, 1239 if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1252 (caddr_t) argp, (xdrproc_t) xdr_void, 1240 (caddr_t) argp, (xdrproc_t) xdr_void,
1253 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1241 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1254 return (NULL); 1242 return (NULL);
1255 } 1243 }
1256 return ((void *)&clnt_res); 1244 return ((void *) &clnt_res);
1257} 1245}
1258 1246
1259exports * 1247exports *mountproc_export_2(argp, clnt)
1260mountproc_export_2(argp, clnt) 1248void *argp;
1261 void *argp; 1249CLIENT *clnt;
1262 CLIENT *clnt;
1263{ 1250{
1264 static exports clnt_res; 1251 static exports clnt_res;
1265 1252
1266 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1253 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1267 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, 1254 if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1268 argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, 1255 argp, (xdrproc_t) xdr_exports, (caddr_t) & clnt_res,
1269 TIMEOUT) != RPC_SUCCESS) { 1256 TIMEOUT) != RPC_SUCCESS) {
1270 return (NULL); 1257 return (NULL);
1271 } 1258 }
1272 return (&clnt_res); 1259 return (&clnt_res);
1273} 1260}
1274 1261
1275exports * 1262exports *mountproc_exportall_2(argp, clnt)
1276mountproc_exportall_2(argp, clnt) 1263void *argp;
1277 void *argp; 1264CLIENT *clnt;
1278 CLIENT *clnt;
1279{ 1265{
1280 static exports clnt_res; 1266 static exports clnt_res;
1281 1267
1282 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1268 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1283 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, 1269 if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp,
1284 (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, 1270 (xdrproc_t) xdr_exports, (caddr_t) & clnt_res,
1285 TIMEOUT) != RPC_SUCCESS) { 1271 TIMEOUT) != RPC_SUCCESS) {
1286 return (NULL); 1272 return (NULL);
1287 } 1273 }
1288 return (&clnt_res); 1274 return (&clnt_res);
1289} 1275}
1290 1276
1291ppathcnf * 1277ppathcnf *mountproc_pathconf_2(argp, clnt)
1292mountproc_pathconf_2(argp, clnt) 1278dirpath *argp;
1293 dirpath *argp; 1279CLIENT *clnt;
1294 CLIENT *clnt;
1295{ 1280{
1296 static ppathcnf clnt_res; 1281 static ppathcnf clnt_res;
1297 1282
1298 memset((char *)&clnt_res, 0, sizeof(clnt_res)); 1283 memset((char *) &clnt_res, 0, sizeof(clnt_res));
1299 if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, 1284 if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath,
1300 (caddr_t) argp, (xdrproc_t) xdr_ppathcnf, 1285 (caddr_t) argp, (xdrproc_t) xdr_ppathcnf,
1301 (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { 1286 (caddr_t) & clnt_res, TIMEOUT) != RPC_SUCCESS) {
1302 return (NULL); 1287 return (NULL);
1303 } 1288 }
1304 return (&clnt_res); 1289 return (&clnt_res);
1305} 1290}
1306
1307
1308
1309
diff --git a/util-linux/nfsmount.h b/util-linux/nfsmount.h
index 73c71fc68..64ac617c0 100644
--- a/util-linux/nfsmount.h
+++ b/util-linux/nfsmount.h
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Please do not edit this file. 3 * Please do not edit this file.
3 * It was generated using rpcgen. 4 * It was generated using rpcgen.
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 3c02bdd42..6bda22277 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini swapon/swapoff implementation for busybox 3 * Mini swapon/swapoff implementation for busybox
3 * 4 *
@@ -32,91 +33,93 @@
32 33
33 34
34static int whichApp; 35static int whichApp;
35static const char* appName; 36static const char *appName;
36 37
37static const char swapoff_usage[] = 38static const char swapoff_usage[] =
38"swapoff device\n" 39
39"\nStop swapping virtual memory pages on the given device.\n"; 40 "swapoff device\n"
40static const char swapon_usage[] = 41 "\nStop swapping virtual memory pages on the given device.\n";
41"swapon device\n" 42static const char swapon_usage[] =
42"\nStart swapping virtual memory pages on the given device.\n"; 43
44 "swapon device\n"
45 "\nStart swapping virtual memory pages on the given device.\n";
43 46
44 47
45#define SWAPON_APP 1 48#define SWAPON_APP 1
46#define SWAPOFF_APP 2 49#define SWAPOFF_APP 2
47 50
48 51
49static void 52static void swap_enable_disable(char *device)
50swap_enable_disable( char *device)
51{ 53{
52 int status; 54 int status;
53 if ( whichApp == SWAPON_APP ) 55
54 status = swapon(device, 0); 56 if (whichApp == SWAPON_APP)
55 else 57 status = swapon(device, 0);
56 status = swapoff(device); 58 else
57 59 status = swapoff(device);
58 if ( status != 0 ) { 60
59 perror(appName); 61 if (status != 0) {
60 exit( FALSE); 62 perror(appName);
61 } 63 exit(FALSE);
64 }
62} 65}
63 66
64static void 67static void do_em_all()
65do_em_all()
66{ 68{
67 struct mntent *m; 69 struct mntent *m;
68 FILE *f = setmntent ("/etc/fstab", "r"); 70 FILE *f = setmntent("/etc/fstab", "r");
69 71
70 if (f == NULL) { 72 if (f == NULL) {
71 perror("/etc/fstab"); 73 perror("/etc/fstab");
72 exit( FALSE); 74 exit(FALSE);
73 } 75 }
74 while ((m = getmntent (f)) != NULL) { 76 while ((m = getmntent(f)) != NULL) {
75 if (!strstr (m->mnt_type, MNTTYPE_SWAP)) { 77 if (!strstr(m->mnt_type, MNTTYPE_SWAP)) {
76 swap_enable_disable( m->mnt_fsname); 78 swap_enable_disable(m->mnt_fsname);
77 } 79 }
78 } 80 }
79 endmntent (f); 81 endmntent(f);
80 exit( TRUE); 82 exit(TRUE);
81} 83}
82 84
83 85
84extern int 86extern int swap_on_off_main(int argc, char **argv)
85swap_on_off_main(int argc, char * * argv)
86{ 87{
87 struct stat statBuf; 88 struct stat statBuf;
88 if (stat("/etc/fstab", &statBuf) < 0) 89
89 fprintf(stderr, "/etc/fstab file missing -- Please install one.\n\n"); 90 if (stat("/etc/fstab", &statBuf) < 0)
90 91 fprintf(stderr,
91 if (strcmp(*argv, "swapon")==0) { 92 "/etc/fstab file missing -- Please install one.\n\n");
92 appName = *argv; 93
93 whichApp = SWAPON_APP; 94 if (strcmp(*argv, "swapon") == 0) {
94 95 appName = *argv;
95 } else { 96 whichApp = SWAPON_APP;
96 appName = *argv; 97
97 whichApp = SWAPOFF_APP; 98 } else {
98 } 99 appName = *argv;
99 100 whichApp = SWAPOFF_APP;
100 if (argc < 2) 101 }
101 goto usage_and_exit; 102
102 argc--; 103 if (argc < 2)
103 argv++;
104
105 /* Parse any options */
106 while (**argv == '-') {
107 while (*++(*argv)) switch (**argv) {
108 case 'a':
109 do_em_all();
110 break;
111 default:
112 goto usage_and_exit; 104 goto usage_and_exit;
105 argc--;
106 argv++;
107
108 /* Parse any options */
109 while (**argv == '-') {
110 while (*++(*argv))
111 switch (**argv) {
112 case 'a':
113 do_em_all();
114 break;
115 default:
116 goto usage_and_exit;
117 }
113 } 118 }
114 } 119 swap_enable_disable(*argv);
115 swap_enable_disable(*argv); 120 exit(TRUE);
116 exit( TRUE);
117 121
118usage_and_exit: 122 usage_and_exit:
119 usage( (whichApp==SWAPON_APP)? swapon_usage : swapoff_usage); 123 usage((whichApp == SWAPON_APP) ? swapon_usage : swapoff_usage);
120 exit( FALSE); 124 exit(FALSE);
121} 125}
122
diff --git a/util-linux/umount.c b/util-linux/umount.c
index b65caf76e..a2ca8c74a 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini umount implementation for busybox 3 * Mini umount implementation for busybox
3 * 4 *
@@ -28,24 +29,23 @@
28#include <fstab.h> 29#include <fstab.h>
29#include <errno.h> 30#include <errno.h>
30 31
31static const char umount_usage[] = 32static const char umount_usage[] =
32"umount [flags] filesystem|directory\n\n" 33 "umount [flags] filesystem|directory\n\n"
33"Flags:\n" 34 "Flags:\n" "\t-a:\tUnmount all file systems"
34"\t-a:\tUnmount all file systems"
35#ifdef BB_MTAB 35#ifdef BB_MTAB
36" in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n" 36 " in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n"
37#else 37#else
38"\n" 38 "\n"
39#endif 39#endif
40#ifdef BB_FEATURE_REMOUNT 40#ifdef BB_FEATURE_REMOUNT
41"\t-r:\tTry to remount devices as read-only if mount is busy\n" 41 "\t-r:\tTry to remount devices as read-only if mount is busy\n"
42#endif 42#endif
43; 43;
44 44
45struct _mtab_entry_t { 45struct _mtab_entry_t {
46 char *device; 46 char *device;
47 char *mountpt; 47 char *mountpt;
48 struct _mtab_entry_t *next; 48 struct _mtab_entry_t *next;
49}; 49};
50 50
51static struct _mtab_entry_t *mtab_cache = NULL; 51static struct _mtab_entry_t *mtab_cache = NULL;
@@ -55,113 +55,112 @@ static struct _mtab_entry_t *mtab_cache = NULL;
55static int useMtab = TRUE; 55static int useMtab = TRUE;
56static int umountAll = FALSE; 56static int umountAll = FALSE;
57static int doRemount = FALSE; 57static int doRemount = FALSE;
58extern const char mtab_file[]; /* Defined in utility.c */ 58extern const char mtab_file[]; /* Defined in utility.c */
59 59
60#define MIN(x,y) (x > y ? x : y) 60#define MIN(x,y) (x > y ? x : y)
61 61
62static int 62static int do_umount(const char *name, int useMtab)
63do_umount(const char* name, int useMtab)
64{ 63{
65 int status; 64 int status;
66 char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE); 65 char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
67 66
68 if (blockDevice && strcmp(blockDevice, name) == 0) 67 if (blockDevice && strcmp(blockDevice, name) == 0)
69 name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT); 68 name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
70 69
71 status = umount(name); 70 status = umount(name);
72 71
73#if defined BB_FEATURE_MOUNT_LOOP 72#if defined BB_FEATURE_MOUNT_LOOP
74 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) 73 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
75 /* this was a loop device, delete it */ 74 /* this was a loop device, delete it */
76 del_loop(blockDevice); 75 del_loop(blockDevice);
77#endif 76#endif
78#if defined BB_FEATURE_REMOUNT 77#if defined BB_FEATURE_REMOUNT
79 if ( status != 0 && doRemount == TRUE && errno == EBUSY ) { 78 if (status != 0 && doRemount == TRUE && errno == EBUSY) {
80 status = mount(blockDevice, name, NULL, 79 status = mount(blockDevice, name, NULL,
81 MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); 80 MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
82 if (status == 0) { 81 if (status == 0) {
83 fprintf(stderr, "umount: %s busy - remounted read-only\n", 82 fprintf(stderr, "umount: %s busy - remounted read-only\n",
84 blockDevice); 83 blockDevice);
85 /* TODO: update mtab if BB_MTAB is defined */ 84 /* TODO: update mtab if BB_MTAB is defined */
86 } else { 85 } else {
87 fprintf(stderr, "umount: Cannot remount %s read-only\n", 86 fprintf(stderr, "umount: Cannot remount %s read-only\n",
88 blockDevice); 87 blockDevice);
88 }
89 } 89 }
90 }
91#endif 90#endif
92 if ( status == 0 ) { 91 if (status == 0) {
93#if defined BB_MTAB 92#if defined BB_MTAB
94 if ( useMtab==TRUE ) 93 if (useMtab == TRUE)
95 erase_mtab(name); 94 erase_mtab(name);
96#endif 95#endif
97 return( TRUE); 96 return (TRUE);
98 } 97 }
99 return(FALSE); 98 return (FALSE);
100} 99}
101 100
102static int 101static int umount_all(int useMtab)
103umount_all(int useMtab)
104{ 102{
105 int status = TRUE; 103 int status = TRUE;
106 char *mountpt; 104 char *mountpt;
107 void *iter; 105 void *iter;
108 106
109 for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) { 107 for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
110 status=do_umount (mountpt, useMtab); 108 status = do_umount(mountpt, useMtab);
111 if (status != 0) {
112 /* Don't bother retrying the umount on busy devices */
113 if (errno == EBUSY) {
114 perror(mountpt);
115 continue;
116 }
117 status = do_umount (mountpt, useMtab);
118 if (status != 0) { 109 if (status != 0) {
119 printf ("Couldn't umount %s on %s: %s\n", 110 /* Don't bother retrying the umount on busy devices */
120 mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), strerror(errno)); 111 if (errno == EBUSY) {
112 perror(mountpt);
113 continue;
114 }
115 status = do_umount(mountpt, useMtab);
116 if (status != 0) {
117 printf("Couldn't umount %s on %s: %s\n",
118 mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
119 strerror(errno));
120 }
121 } 121 }
122 } 122 }
123 } 123 return (status);
124 return (status);
125} 124}
126 125
127extern int 126extern int umount_main(int argc, char **argv)
128umount_main(int argc, char** argv)
129{ 127{
130 if (argc < 2) { 128 if (argc < 2) {
131 usage( umount_usage); 129 usage(umount_usage);
132 } 130 }
133 131
134 /* Parse any options */ 132 /* Parse any options */
135 while (--argc > 0 && **(++argv) == '-') { 133 while (--argc > 0 && **(++argv) == '-') {
136 while (*++(*argv)) switch (**argv) { 134 while (*++(*argv))
137 case 'a': 135 switch (**argv) {
138 umountAll = TRUE; 136 case 'a':
139 break; 137 umountAll = TRUE;
138 break;
140#ifdef BB_MTAB 139#ifdef BB_MTAB
141 case 'n': 140 case 'n':
142 useMtab = FALSE; 141 useMtab = FALSE;
143 break; 142 break;
144#endif 143#endif
145#ifdef BB_FEATURE_REMOUNT 144#ifdef BB_FEATURE_REMOUNT
146 case 'r': 145 case 'r':
147 doRemount = TRUE; 146 doRemount = TRUE;
148 break; 147 break;
149#endif 148#endif
150 default: 149 default:
151 usage( umount_usage); 150 usage(umount_usage);
151 }
152 }
153
154 mtab_read();
155 if (umountAll == TRUE) {
156 exit(umount_all(useMtab));
157 }
158 if (do_umount(*argv, useMtab) == 0)
159 exit(TRUE);
160 else {
161 perror("umount");
162 exit(FALSE);
152 } 163 }
153 }
154
155 mtab_read();
156 if (umountAll==TRUE) {
157 exit(umount_all(useMtab));
158 }
159 if ( do_umount(*argv,useMtab) == 0 )
160 exit (TRUE);
161 else {
162 perror("umount");
163 exit(FALSE);
164 }
165} 164}
166 165
167 166
@@ -172,79 +171,89 @@ umount_main(int argc, char** argv)
172 */ 171 */
173void mtab_read(void) 172void mtab_read(void)
174{ 173{
175 struct _mtab_entry_t *entry = NULL; 174 struct _mtab_entry_t *entry = NULL;
176 struct mntent *e; 175 struct mntent *e;
177 FILE *fp; 176 FILE *fp;
178 177
179 if (mtab_cache != NULL) return; 178 if (mtab_cache != NULL)
180 179 return;
181 if ((fp = setmntent(mtab_file, "r")) == NULL) { 180
182 fprintf(stderr, "Cannot open %s\n", mtab_file); 181 if ((fp = setmntent(mtab_file, "r")) == NULL) {
183 return; 182 fprintf(stderr, "Cannot open %s\n", mtab_file);
184 } 183 return;
185 while ((e = getmntent(fp))) { 184 }
186 entry = malloc(sizeof(struct _mtab_entry_t)); 185 while ((e = getmntent(fp))) {
187 entry->device = strdup(e->mnt_fsname); 186 entry = malloc(sizeof(struct _mtab_entry_t));
188 entry->mountpt = strdup(e->mnt_dir); 187
189 entry->next = mtab_cache; 188 entry->device = strdup(e->mnt_fsname);
190 mtab_cache = entry; 189 entry->mountpt = strdup(e->mnt_dir);
191 } 190 entry->next = mtab_cache;
192 endmntent(fp); 191 mtab_cache = entry;
192 }
193 endmntent(fp);
193} 194}
194 195
195char *mtab_getinfo(const char *match, const char which) 196char *mtab_getinfo(const char *match, const char which)
196{ 197{
197 struct _mtab_entry_t *cur = mtab_cache; 198 struct _mtab_entry_t *cur = mtab_cache;
198 while (cur) { 199
199 if (strcmp(cur->mountpt, match) == 0 || 200 while (cur) {
200 strcmp(cur->device, match) == 0) { 201 if (strcmp(cur->mountpt, match) == 0 ||
201 if (which == MTAB_GETMOUNTPT) { 202 strcmp(cur->device, match) == 0) {
202 return cur->mountpt; 203 if (which == MTAB_GETMOUNTPT) {
203 } else { 204 return cur->mountpt;
205 } else {
204#if !defined BB_MTAB 206#if !defined BB_MTAB
205 if (strcmp(cur->device, "/dev/root") == 0) { 207 if (strcmp(cur->device, "/dev/root") == 0) {
206 struct fstab* fstabItem; 208 struct fstab *fstabItem;
207 fstabItem = getfsfile ("/"); 209
208 if (fstabItem != NULL) return fstabItem->fs_spec; 210 fstabItem = getfsfile("/");
209 } 211 if (fstabItem != NULL)
212 return fstabItem->fs_spec;
213 }
210#endif 214#endif
211 return cur->device; 215 return cur->device;
212 } 216 }
217 }
218 cur = cur->next;
213 } 219 }
214 cur = cur->next; 220 return NULL;
215 }
216 return NULL;
217} 221}
218 222
219char *mtab_first(void **iter) 223char *mtab_first(void **iter)
220{ 224{
221 struct _mtab_entry_t *mtab_iter; 225 struct _mtab_entry_t *mtab_iter;
222 if (!iter) return NULL; 226
223 mtab_iter = mtab_cache; 227 if (!iter)
224 *iter = (void *)mtab_iter; 228 return NULL;
225 return mtab_next(iter); 229 mtab_iter = mtab_cache;
230 *iter = (void *) mtab_iter;
231 return mtab_next(iter);
226} 232}
227 233
228char *mtab_next(void **iter) 234char *mtab_next(void **iter)
229{ 235{
230 char *mp; 236 char *mp;
231 if (iter == NULL || *iter == NULL) return NULL; 237
232 mp = ((struct _mtab_entry_t *)(*iter))->mountpt; 238 if (iter == NULL || *iter == NULL)
233 *iter = (void *)((struct _mtab_entry_t *)(*iter))->next; 239 return NULL;
234 return mp; 240 mp = ((struct _mtab_entry_t *) (*iter))->mountpt;
241 *iter = (void *) ((struct _mtab_entry_t *) (*iter))->next;
242 return mp;
235} 243}
236 244
237void mtab_free(void) 245void mtab_free(void)
238{ 246{
239 struct _mtab_entry_t *this, *next; 247 struct _mtab_entry_t *this, *next;
240
241 this = mtab_cache;
242 while (this) {
243 next = this->next;
244 if (this->device) free(this->device);
245 if (this->mountpt) free(this->mountpt);
246 free(this);
247 this = next;
248 }
249}
250 248
249 this = mtab_cache;
250 while (this) {
251 next = this->next;
252 if (this->device)
253 free(this->device);
254 if (this->mountpt)
255 free(this->mountpt);
256 free(this);
257 this = next;
258 }
259}
diff --git a/utility.c b/utility.c
index 10e107fc5..7f46f9bf4 100644
--- a/utility.c
+++ b/utility.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Utility routines. 3 * Utility routines.
3 * 4 *
@@ -46,7 +47,7 @@
46#include <sys/stat.h> 47#include <sys/stat.h>
47#include <unistd.h> 48#include <unistd.h>
48#include <ctype.h> 49#include <ctype.h>
49#include <sys/param.h> /* for PATH_MAX */ 50#include <sys/param.h> /* for PATH_MAX */
50 51
51#if defined BB_FEATURE_MOUNT_LOOP 52#if defined BB_FEATURE_MOUNT_LOOP
52#include <fcntl.h> 53#include <fcntl.h>
@@ -70,10 +71,10 @@ const char mtab_file[] = "/etc/mtab";
70 71
71extern void usage(const char *usage) 72extern void usage(const char *usage)
72{ 73{
73 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", 74 fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n",
74 BB_VER, BB_BT); 75 BB_VER, BB_BT);
75 fprintf(stderr, "Usage: %s\n", usage); 76 fprintf(stderr, "Usage: %s\n", usage);
76 exit FALSE; 77 exit FALSE;
77} 78}
78 79
79 80
@@ -86,22 +87,21 @@ extern void usage(const char *usage)
86 * so, for example, to check if the kernel is greater than 2.2.11: 87 * so, for example, to check if the kernel is greater than 2.2.11:
87 * if (get_kernel_revision() <= 2*65536+2*256+11) { <stuff> } 88 * if (get_kernel_revision() <= 2*65536+2*256+11) { <stuff> }
88 */ 89 */
89int 90int get_kernel_revision()
90get_kernel_revision()
91{ 91{
92 FILE *file; 92 FILE *file;
93 int major=0, minor=0, patch=0; 93 int major = 0, minor = 0, patch = 0;
94 94
95 file = fopen("/proc/sys/kernel/osrelease", "r"); 95 file = fopen("/proc/sys/kernel/osrelease", "r");
96 if (file == NULL) { 96 if (file == NULL) {
97 /* bummer, /proc must not be mounted... */ 97 /* bummer, /proc must not be mounted... */
98 return( 0); 98 return (0);
99 } 99 }
100 fscanf(file,"%d.%d.%d",&major,&minor,&patch); 100 fscanf(file, "%d.%d.%d", &major, &minor, &patch);
101 fclose(file); 101 fclose(file);
102 return major*65536 + minor*256 + patch; 102 return major * 65536 + minor * 256 + patch;
103} 103}
104#endif /* BB_INIT || BB_PS */ 104#endif /* BB_INIT || BB_PS */
105 105
106 106
107 107
@@ -112,19 +112,19 @@ get_kernel_revision()
112 */ 112 */
113int isDirectory(const char *fileName, const int followLinks) 113int isDirectory(const char *fileName, const int followLinks)
114{ 114{
115 struct stat statBuf; 115 struct stat statBuf;
116 int status; 116 int status;
117 117
118 if (followLinks == TRUE) 118 if (followLinks == TRUE)
119 status = stat(fileName, &statBuf); 119 status = stat(fileName, &statBuf);
120 else 120 else
121 status = lstat(fileName, &statBuf); 121 status = lstat(fileName, &statBuf);
122 122
123 if (status < 0) 123 if (status < 0)
124 return FALSE; 124 return FALSE;
125 if (S_ISDIR(statBuf.st_mode)) 125 if (S_ISDIR(statBuf.st_mode))
126 return TRUE; 126 return TRUE;
127 return FALSE; 127 return FALSE;
128} 128}
129#endif 129#endif
130 130
@@ -137,148 +137,150 @@ int isDirectory(const char *fileName, const int followLinks)
137 * -Erik Andersen 137 * -Erik Andersen
138 */ 138 */
139int 139int
140copyFile( const char *srcName, const char *destName, 140copyFile(const char *srcName, const char *destName,
141 int setModes, int followLinks) 141 int setModes, int followLinks)
142{ 142{
143 int rfd; 143 int rfd;
144 int wfd; 144 int wfd;
145 int rcc; 145 int rcc;
146 int status; 146 int status;
147 char buf[BUF_SIZE]; 147 char buf[BUF_SIZE];
148 struct stat srcStatBuf; 148 struct stat srcStatBuf;
149 struct stat dstStatBuf; 149 struct stat dstStatBuf;
150 struct utimbuf times; 150 struct utimbuf times;
151 151
152 if (followLinks == TRUE) 152 if (followLinks == TRUE)
153 status = stat(srcName, &srcStatBuf); 153 status = stat(srcName, &srcStatBuf);
154 else 154 else
155 status = lstat(srcName, &srcStatBuf); 155 status = lstat(srcName, &srcStatBuf);
156
157 if (status < 0) {
158 perror(srcName);
159 return FALSE;
160 }
161 156
162 if (followLinks == TRUE) 157 if (status < 0) {
163 status = stat(destName, &dstStatBuf); 158 perror(srcName);
164 else 159 return FALSE;
165 status = lstat(destName, &dstStatBuf); 160 }
166 161
167 if (status < 0) { 162 if (followLinks == TRUE)
168 dstStatBuf.st_ino = -1; 163 status = stat(destName, &dstStatBuf);
169 dstStatBuf.st_dev = -1; 164 else
170 } 165 status = lstat(destName, &dstStatBuf);
171 166
172 if ((srcStatBuf.st_dev == dstStatBuf.st_dev) &&
173 (srcStatBuf.st_ino == dstStatBuf.st_ino)) {
174 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName);
175 return FALSE;
176 }
177
178 if (S_ISDIR(srcStatBuf.st_mode)) {
179 //fprintf(stderr, "copying directory %s to %s\n", srcName, destName);
180 /* Make sure the directory is writable */
181 status = mkdir(destName, 0777777 ^ umask(0));
182 if (status < 0 && errno != EEXIST) {
183 perror(destName);
184 return FALSE;
185 }
186 } else if (S_ISLNK(srcStatBuf.st_mode)) {
187 char link_val[PATH_MAX + 1];
188 int link_size;
189
190 //fprintf(stderr, "copying link %s to %s\n", srcName, destName);
191 /* Warning: This could possibly truncate silently, to PATH_MAX chars */
192 link_size = readlink(srcName, &link_val[0], PATH_MAX);
193 if (link_size < 0) {
194 perror(srcName);
195 return FALSE;
196 }
197 link_val[link_size] = '\0';
198 status = symlink(link_val, destName);
199 if (status < 0) { 167 if (status < 0) {
200 perror(destName); 168 dstStatBuf.st_ino = -1;
201 return FALSE; 169 dstStatBuf.st_dev = -1;
202 } 170 }
203#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 171
204 if (setModes == TRUE) { 172 if ((srcStatBuf.st_dev == dstStatBuf.st_dev) &&
205 if (lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid) < 0) { 173 (srcStatBuf.st_ino == dstStatBuf.st_ino)) {
206 perror(destName); 174 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName);
207 return FALSE; 175 return FALSE;
208 }
209 } 176 }
177
178 if (S_ISDIR(srcStatBuf.st_mode)) {
179 //fprintf(stderr, "copying directory %s to %s\n", srcName, destName);
180 /* Make sure the directory is writable */
181 status = mkdir(destName, 0777777 ^ umask(0));
182 if (status < 0 && errno != EEXIST) {
183 perror(destName);
184 return FALSE;
185 }
186 } else if (S_ISLNK(srcStatBuf.st_mode)) {
187 char link_val[PATH_MAX + 1];
188 int link_size;
189
190 //fprintf(stderr, "copying link %s to %s\n", srcName, destName);
191 /* Warning: This could possibly truncate silently, to PATH_MAX chars */
192 link_size = readlink(srcName, &link_val[0], PATH_MAX);
193 if (link_size < 0) {
194 perror(srcName);
195 return FALSE;
196 }
197 link_val[link_size] = '\0';
198 status = symlink(link_val, destName);
199 if (status < 0) {
200 perror(destName);
201 return FALSE;
202 }
203#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
204 if (setModes == TRUE) {
205 if (lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid) < 0) {
206 perror(destName);
207 return FALSE;
208 }
209 }
210#endif 210#endif
211 return TRUE; 211 return TRUE;
212 } else if (S_ISFIFO(srcStatBuf.st_mode)) { 212 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
213 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName); 213 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
214 if (mkfifo(destName, 0644) < 0) { 214 if (mkfifo(destName, 0644) < 0) {
215 perror(destName); 215 perror(destName);
216 return FALSE; 216 return FALSE;
217 } 217 }
218 } else if (S_ISBLK(srcStatBuf.st_mode) || S_ISCHR(srcStatBuf.st_mode) 218 } else if (S_ISBLK(srcStatBuf.st_mode) || S_ISCHR(srcStatBuf.st_mode)
219 || S_ISSOCK (srcStatBuf.st_mode)) { 219 || S_ISSOCK(srcStatBuf.st_mode)) {
220 //fprintf(stderr, "copying soc, blk, or chr %s to %s\n", srcName, destName); 220 //fprintf(stderr, "copying soc, blk, or chr %s to %s\n", srcName, destName);
221 if (mknod(destName, srcStatBuf.st_mode, srcStatBuf.st_rdev) < 0) { 221 if (mknod(destName, srcStatBuf.st_mode, srcStatBuf.st_rdev) < 0) {
222 perror(destName); 222 perror(destName);
223 return FALSE; 223 return FALSE;
224 } 224 }
225 } else if (S_ISREG(srcStatBuf.st_mode)) { 225 } else if (S_ISREG(srcStatBuf.st_mode)) {
226 //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName); 226 //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName);
227 rfd = open(srcName, O_RDONLY); 227 rfd = open(srcName, O_RDONLY);
228 if (rfd < 0) { 228 if (rfd < 0) {
229 perror(srcName); 229 perror(srcName);
230 return FALSE; 230 return FALSE;
231 } 231 }
232 232
233 wfd = open(destName, O_WRONLY | O_CREAT | O_TRUNC, srcStatBuf.st_mode); 233 wfd =
234 if (wfd < 0) { 234 open(destName, O_WRONLY | O_CREAT | O_TRUNC,
235 perror(destName); 235 srcStatBuf.st_mode);
236 close(rfd); 236 if (wfd < 0) {
237 return FALSE; 237 perror(destName);
238 } 238 close(rfd);
239 return FALSE;
240 }
239 241
240 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) { 242 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
241 if (fullWrite(wfd, buf, rcc) < 0) 243 if (fullWrite(wfd, buf, rcc) < 0)
242 goto error_exit; 244 goto error_exit;
243 } 245 }
244 if (rcc < 0) { 246 if (rcc < 0) {
245 goto error_exit; 247 goto error_exit;
246 } 248 }
247 249
248 close(rfd); 250 close(rfd);
249 if (close(wfd) < 0) { 251 if (close(wfd) < 0) {
250 return FALSE; 252 return FALSE;
253 }
251 } 254 }
252 }
253 255
254 if (setModes == TRUE) { 256 if (setModes == TRUE) {
255 /* This is fine, since symlinks never get here */ 257 /* This is fine, since symlinks never get here */
256 if (chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid) < 0) { 258 if (chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid) < 0) {
257 perror(destName); 259 perror(destName);
258 exit FALSE; 260 exit FALSE;
259 } 261 }
260 if (chmod(destName, srcStatBuf.st_mode) < 0) { 262 if (chmod(destName, srcStatBuf.st_mode) < 0) {
261 perror(destName); 263 perror(destName);
262 exit FALSE; 264 exit FALSE;
263 } 265 }
264 times.actime = srcStatBuf.st_atime; 266 times.actime = srcStatBuf.st_atime;
265 times.modtime = srcStatBuf.st_mtime; 267 times.modtime = srcStatBuf.st_mtime;
266 if (utime(destName, &times) < 0) { 268 if (utime(destName, &times) < 0) {
267 perror(destName); 269 perror(destName);
268 exit FALSE; 270 exit FALSE;
271 }
269 } 272 }
270 }
271 273
272 return TRUE; 274 return TRUE;
273 275
274 error_exit: 276 error_exit:
275 perror(destName); 277 perror(destName);
276 close(rfd); 278 close(rfd);
277 close(wfd); 279 close(wfd);
278 280
279 return FALSE; 281 return FALSE;
280} 282}
281#endif /* BB_CP_MV */ 283#endif /* BB_CP_MV */
282 284
283 285
284 286
@@ -289,16 +291,16 @@ copyFile( const char *srcName, const char *destName,
289 291
290/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ 292/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
291static const mode_t SBIT[] = { 293static const mode_t SBIT[] = {
292 0, 0, S_ISUID, 294 0, 0, S_ISUID,
293 0, 0, S_ISGID, 295 0, 0, S_ISGID,
294 0, 0, S_ISVTX 296 0, 0, S_ISVTX
295}; 297};
296 298
297/* The 9 mode bits to test */ 299/* The 9 mode bits to test */
298static const mode_t MBIT[] = { 300static const mode_t MBIT[] = {
299 S_IRUSR, S_IWUSR, S_IXUSR, 301 S_IRUSR, S_IWUSR, S_IXUSR,
300 S_IRGRP, S_IWGRP, S_IXGRP, 302 S_IRGRP, S_IWGRP, S_IXGRP,
301 S_IROTH, S_IWOTH, S_IXOTH 303 S_IROTH, S_IWOTH, S_IXOTH
302}; 304};
303 305
304#define MODE1 "rwxrwxrwx" 306#define MODE1 "rwxrwxrwx"
@@ -312,21 +314,20 @@ static const mode_t MBIT[] = {
312 */ 314 */
313const char *modeString(int mode) 315const char *modeString(int mode)
314{ 316{
315 static char buf[12]; 317 static char buf[12];
316 318
317 int i; 319 int i;
318 buf[0] = TYPECHAR(mode); 320
319 for (i=0; i<9; i++) { 321 buf[0] = TYPECHAR(mode);
320 if (mode & SBIT[i]) 322 for (i = 0; i < 9; i++) {
321 buf[i+1] = (mode & MBIT[i])? 323 if (mode & SBIT[i])
322 SMODE1[i] : SMODE0[i]; 324 buf[i + 1] = (mode & MBIT[i]) ? SMODE1[i] : SMODE0[i];
323 else 325 else
324 buf[i+1] = (mode & MBIT[i])? 326 buf[i + 1] = (mode & MBIT[i]) ? MODE1[i] : MODE0[i];
325 MODE1[i] : MODE0[i]; 327 }
326 } 328 return buf;
327 return buf;
328} 329}
329#endif /* BB_TAR || BB_LS */ 330#endif /* BB_TAR || BB_LS */
330 331
331 332
332#if defined BB_TAR 333#if defined BB_TAR
@@ -336,25 +337,25 @@ const char *modeString(int mode)
336 */ 337 */
337const char *timeString(time_t timeVal) 338const char *timeString(time_t timeVal)
338{ 339{
339 time_t now; 340 time_t now;
340 char *str; 341 char *str;
341 static char buf[26]; 342 static char buf[26];
342 343
343 time(&now); 344 time(&now);
344 345
345 str = ctime(&timeVal); 346 str = ctime(&timeVal);
346 347
347 strcpy(buf, &str[4]); 348 strcpy(buf, &str[4]);
348 buf[12] = '\0'; 349 buf[12] = '\0';
349 350
350 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) { 351 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) {
351 strcpy(&buf[7], &str[20]); 352 strcpy(&buf[7], &str[20]);
352 buf[11] = '\0'; 353 buf[11] = '\0';
353 } 354 }
354 355
355 return buf; 356 return buf;
356} 357}
357#endif /* BB_TAR */ 358#endif /* BB_TAR */
358 359
359#if defined BB_TAR || defined BB_CP_MV 360#if defined BB_TAR || defined BB_CP_MV
360/* 361/*
@@ -364,25 +365,25 @@ const char *timeString(time_t timeVal)
364 */ 365 */
365int fullWrite(int fd, const char *buf, int len) 366int fullWrite(int fd, const char *buf, int len)
366{ 367{
367 int cc; 368 int cc;
368 int total; 369 int total;
369 370
370 total = 0; 371 total = 0;
371 372
372 while (len > 0) { 373 while (len > 0) {
373 cc = write(fd, buf, len); 374 cc = write(fd, buf, len);
374 375
375 if (cc < 0) 376 if (cc < 0)
376 return -1; 377 return -1;
377 378
378 buf += cc; 379 buf += cc;
379 total += cc; 380 total += cc;
380 len -= cc; 381 len -= cc;
381 } 382 }
382 383
383 return total; 384 return total;
384} 385}
385#endif /* BB_TAR || BB_CP_MV */ 386#endif /* BB_TAR || BB_CP_MV */
386 387
387 388
388#if defined BB_TAR || defined BB_TAIL 389#if defined BB_TAR || defined BB_TAIL
@@ -394,28 +395,28 @@ int fullWrite(int fd, const char *buf, int len)
394 */ 395 */
395int fullRead(int fd, char *buf, int len) 396int fullRead(int fd, char *buf, int len)
396{ 397{
397 int cc; 398 int cc;
398 int total; 399 int total;
399 400
400 total = 0; 401 total = 0;
401 402
402 while (len > 0) { 403 while (len > 0) {
403 cc = read(fd, buf, len); 404 cc = read(fd, buf, len);
404 405
405 if (cc < 0) 406 if (cc < 0)
406 return -1; 407 return -1;
407 408
408 if (cc == 0) 409 if (cc == 0)
409 break; 410 break;
410 411
411 buf += cc; 412 buf += cc;
412 total += cc; 413 total += cc;
413 len -= cc; 414 len -= cc;
414 } 415 }
415 416
416 return total; 417 return total;
417} 418}
418#endif /* BB_TAR || BB_TAIL */ 419#endif /* BB_TAR || BB_TAIL */
419 420
420 421
421#if defined (BB_CHMOD_CHOWN_CHGRP) \ 422#if defined (BB_CHMOD_CHOWN_CHGRP) \
@@ -434,102 +435,104 @@ int fullRead(int fd, char *buf, int len)
434 * is so stinking huge. 435 * is so stinking huge.
435 */ 436 */
436int recursiveAction(const char *fileName, 437int recursiveAction(const char *fileName,
437 int recurse, int followLinks, int depthFirst, 438 int recurse, int followLinks, int depthFirst,
438 int (*fileAction) (const char *fileName, 439 int (*fileAction) (const char *fileName,
439 struct stat* statbuf), 440 struct stat * statbuf),
440 int (*dirAction) (const char *fileName, 441 int (*dirAction) (const char *fileName,
441 struct stat* statbuf)) 442 struct stat * statbuf))
442{ 443{
443 int status; 444 int status;
444 struct stat statbuf; 445 struct stat statbuf;
445 struct dirent *next; 446 struct dirent *next;
446 447
447 if (followLinks == TRUE) 448 if (followLinks == TRUE)
448 status = stat(fileName, &statbuf); 449 status = stat(fileName, &statbuf);
449 else 450 else
450 status = lstat(fileName, &statbuf); 451 status = lstat(fileName, &statbuf);
451 452
452 if (status < 0) { 453 if (status < 0) {
453#ifdef BB_DEBUG_PRINT_SCAFFOLD 454#ifdef BB_DEBUG_PRINT_SCAFFOLD
454 fprintf(stderr, 455 fprintf(stderr,
455 "status=%d followLinks=%d TRUE=%d\n", 456 "status=%d followLinks=%d TRUE=%d\n",
456 status, followLinks, TRUE); 457 status, followLinks, TRUE);
457#endif 458#endif
458 perror(fileName);
459 return FALSE;
460 }
461
462 if ((followLinks == FALSE) && (S_ISLNK(statbuf.st_mode)) ) {
463 if (fileAction == NULL)
464 return TRUE;
465 else
466 return fileAction(fileName, &statbuf);
467 }
468
469 if (recurse == FALSE) {
470 if (S_ISDIR(statbuf.st_mode)) {
471 if (dirAction != NULL)
472 return (dirAction(fileName, &statbuf));
473 else
474 return TRUE;
475 }
476 }
477
478 if (S_ISDIR(statbuf.st_mode)) {
479 DIR *dir;
480 dir = opendir(fileName);
481 if (!dir) {
482 perror(fileName);
483 return FALSE;
484 }
485 if (dirAction != NULL && depthFirst == FALSE) {
486 status = dirAction(fileName, &statbuf);
487 if (status == FALSE) {
488 perror(fileName); 459 perror(fileName);
489 return FALSE; 460 return FALSE;
490 }
491 } 461 }
492 while ((next = readdir(dir)) != NULL) { 462
493 char nextFile[PATH_MAX + 1]; 463 if ((followLinks == FALSE) && (S_ISLNK(statbuf.st_mode))) {
494 if ((strcmp(next->d_name, "..") == 0) 464 if (fileAction == NULL)
495 || (strcmp(next->d_name, ".") == 0)) { 465 return TRUE;
496 continue; 466 else
497 } 467 return fileAction(fileName, &statbuf);
498 if (strlen(fileName) + strlen(next->d_name) + 1 > PATH_MAX) {
499 fprintf(stderr, name_too_long, "ftw");
500 return FALSE;
501 }
502 sprintf(nextFile, "%s/%s", fileName, next->d_name);
503 status =
504 recursiveAction(nextFile, TRUE, followLinks, depthFirst,
505 fileAction, dirAction);
506 if (status < 0) {
507 closedir(dir);
508 return FALSE;
509 }
510 } 468 }
511 status = closedir(dir); 469
512 if (status < 0) { 470 if (recurse == FALSE) {
513 perror(fileName); 471 if (S_ISDIR(statbuf.st_mode)) {
514 return FALSE; 472 if (dirAction != NULL)
473 return (dirAction(fileName, &statbuf));
474 else
475 return TRUE;
476 }
515 } 477 }
516 if (dirAction != NULL && depthFirst == TRUE) { 478
517 status = dirAction(fileName, &statbuf); 479 if (S_ISDIR(statbuf.st_mode)) {
518 if (status == FALSE) { 480 DIR *dir;
519 perror(fileName); 481
520 return FALSE; 482 dir = opendir(fileName);
521 } 483 if (!dir) {
484 perror(fileName);
485 return FALSE;
486 }
487 if (dirAction != NULL && depthFirst == FALSE) {
488 status = dirAction(fileName, &statbuf);
489 if (status == FALSE) {
490 perror(fileName);
491 return FALSE;
492 }
493 }
494 while ((next = readdir(dir)) != NULL) {
495 char nextFile[PATH_MAX + 1];
496
497 if ((strcmp(next->d_name, "..") == 0)
498 || (strcmp(next->d_name, ".") == 0)) {
499 continue;
500 }
501 if (strlen(fileName) + strlen(next->d_name) + 1 > PATH_MAX) {
502 fprintf(stderr, name_too_long, "ftw");
503 return FALSE;
504 }
505 sprintf(nextFile, "%s/%s", fileName, next->d_name);
506 status =
507 recursiveAction(nextFile, TRUE, followLinks, depthFirst,
508 fileAction, dirAction);
509 if (status < 0) {
510 closedir(dir);
511 return FALSE;
512 }
513 }
514 status = closedir(dir);
515 if (status < 0) {
516 perror(fileName);
517 return FALSE;
518 }
519 if (dirAction != NULL && depthFirst == TRUE) {
520 status = dirAction(fileName, &statbuf);
521 if (status == FALSE) {
522 perror(fileName);
523 return FALSE;
524 }
525 }
526 } else {
527 if (fileAction == NULL)
528 return TRUE;
529 else
530 return fileAction(fileName, &statbuf);
522 } 531 }
523 } else { 532 return TRUE;
524 if (fileAction == NULL)
525 return TRUE;
526 else
527 return fileAction(fileName, &statbuf);
528 }
529 return TRUE;
530} 533}
531 534
532#endif /* BB_CHMOD_CHOWN_CHGRP || BB_CP_MV || BB_FIND || BB_LS || BB_INSMOD */ 535#endif /* BB_CHMOD_CHOWN_CHGRP || BB_CP_MV || BB_FIND || BB_LS || BB_INSMOD */
533 536
534 537
535 538
@@ -540,30 +543,30 @@ int recursiveAction(const char *fileName,
540 * while all previous ones get default protections. Errors are not reported 543 * while all previous ones get default protections. Errors are not reported
541 * here, as failures to restore files can be reported later. 544 * here, as failures to restore files can be reported later.
542 */ 545 */
543extern int createPath (const char *name, int mode) 546extern int createPath(const char *name, int mode)
544{ 547{
545 char *cp; 548 char *cp;
546 char *cpOld; 549 char *cpOld;
547 char buf[PATH_MAX + 1]; 550 char buf[PATH_MAX + 1];
548 int retVal=0; 551 int retVal = 0;
549 552
550 strcpy( buf, name); 553 strcpy(buf, name);
551 for (cp = buf; *cp == '/'; cp++); 554 for (cp = buf; *cp == '/'; cp++);
552 cp = strchr(cp, '/'); 555 cp = strchr(cp, '/');
553 while (cp) { 556 while (cp) {
554 cpOld = cp; 557 cpOld = cp;
555 cp = strchr(cp + 1, '/'); 558 cp = strchr(cp + 1, '/');
556 *cpOld = '\0'; 559 *cpOld = '\0';
557 retVal = mkdir(buf, cp ? 0777 : mode); 560 retVal = mkdir(buf, cp ? 0777 : mode);
558 if (retVal != 0 && errno != EEXIST) { 561 if (retVal != 0 && errno != EEXIST) {
559 perror(buf); 562 perror(buf);
560 return FALSE; 563 return FALSE;
564 }
565 *cpOld = '/';
561 } 566 }
562 *cpOld = '/'; 567 return TRUE;
563 }
564 return TRUE;
565} 568}
566#endif /* BB_TAR || BB_MKDIR */ 569#endif /* BB_TAR || BB_MKDIR */
567 570
568 571
569 572
@@ -572,67 +575,68 @@ extern int createPath (const char *name, int mode)
572 575
573 576
574 577
575extern int 578extern int parse_mode(const char *s, mode_t * theMode)
576parse_mode( const char* s, mode_t* theMode)
577{ 579{
578 mode_t andMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 580 mode_t andMode =
581
582 S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
579 mode_t orMode = 0; 583 mode_t orMode = 0;
580 mode_t mode = 0; 584 mode_t mode = 0;
581 mode_t groups = 0; 585 mode_t groups = 0;
582 char type; 586 char type;
583 char c; 587 char c;
584 588
585 do { 589 do {
586 for ( ; ; ) { 590 for (;;) {
587 switch ( c = *s++ ) { 591 switch (c = *s++) {
588 case '\0': 592 case '\0':
589 return -1; 593 return -1;
590 case 'u': 594 case 'u':
591 groups |= S_ISUID|S_IRWXU; 595 groups |= S_ISUID | S_IRWXU;
592 continue; 596 continue;
593 case 'g': 597 case 'g':
594 groups |= S_ISGID|S_IRWXG; 598 groups |= S_ISGID | S_IRWXG;
595 continue; 599 continue;
596 case 'o': 600 case 'o':
597 groups |= S_IRWXO; 601 groups |= S_IRWXO;
598 continue; 602 continue;
599 case 'a': 603 case 'a':
600 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 604 groups |= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
601 continue; 605 continue;
602 case '+': 606 case '+':
603 case '=': 607 case '=':
604 case '-': 608 case '-':
605 type = c; 609 type = c;
606 if ( groups == 0 ) /* The default is "all" */ 610 if (groups == 0) /* The default is "all" */
607 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 611 groups |=
612 S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
608 break; 613 break;
609 default: 614 default:
610 if ( isdigit(c) && c >= '0' && c <= '7' && 615 if (isdigit(c) && c >= '0' && c <= '7' &&
611 mode == 0 && groups == 0 ) { 616 mode == 0 && groups == 0) {
612 *theMode = strtol(--s, NULL, 8); 617 *theMode = strtol(--s, NULL, 8);
613 return (TRUE); 618 return (TRUE);
614 } 619 } else
615 else
616 return (FALSE); 620 return (FALSE);
617 } 621 }
618 break; 622 break;
619 } 623 }
620 624
621 while ( (c = *s++) != '\0' ) { 625 while ((c = *s++) != '\0') {
622 switch ( c ) { 626 switch (c) {
623 case ',': 627 case ',':
624 break; 628 break;
625 case 'r': 629 case 'r':
626 mode |= S_IRUSR|S_IRGRP|S_IROTH; 630 mode |= S_IRUSR | S_IRGRP | S_IROTH;
627 continue; 631 continue;
628 case 'w': 632 case 'w':
629 mode |= S_IWUSR|S_IWGRP|S_IWOTH; 633 mode |= S_IWUSR | S_IWGRP | S_IWOTH;
630 continue; 634 continue;
631 case 'x': 635 case 'x':
632 mode |= S_IXUSR|S_IXGRP|S_IXOTH; 636 mode |= S_IXUSR | S_IXGRP | S_IXOTH;
633 continue; 637 continue;
634 case 's': 638 case 's':
635 mode |= S_IXGRP|S_ISUID|S_ISGID; 639 mode |= S_IXGRP | S_ISUID | S_ISGID;
636 continue; 640 continue;
637 case 't': 641 case 't':
638 mode |= 0; 642 mode |= 0;
@@ -640,11 +644,11 @@ parse_mode( const char* s, mode_t* theMode)
640 default: 644 default:
641 *theMode &= andMode; 645 *theMode &= andMode;
642 *theMode |= orMode; 646 *theMode |= orMode;
643 return( TRUE); 647 return (TRUE);
644 } 648 }
645 break; 649 break;
646 } 650 }
647 switch ( type ) { 651 switch (type) {
648 case '=': 652 case '=':
649 andMode &= ~(groups); 653 andMode &= ~(groups);
650 /* fall through */ 654 /* fall through */
@@ -656,14 +660,14 @@ parse_mode( const char* s, mode_t* theMode)
656 orMode &= andMode; 660 orMode &= andMode;
657 break; 661 break;
658 } 662 }
659 } while ( c == ',' ); 663 } while (c == ',');
660 *theMode &= andMode; 664 *theMode &= andMode;
661 *theMode |= orMode; 665 *theMode |= orMode;
662 return (TRUE); 666 return (TRUE);
663} 667}
664 668
665 669
666#endif /* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR */ 670#endif /* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR */
667 671
668 672
669 673
@@ -676,82 +680,77 @@ parse_mode( const char* s, mode_t* theMode)
676/* Use this to avoid needing the glibc NSS stuff 680/* Use this to avoid needing the glibc NSS stuff
677 * This uses storage buf to hold things. 681 * This uses storage buf to hold things.
678 * */ 682 * */
679uid_t 683uid_t my_getid(const char *filename, char *name, uid_t id)
680my_getid(const char *filename, char *name, uid_t id)
681{ 684{
682 FILE *file; 685 FILE *file;
683 char *rname, *start, *end, buf[128]; 686 char *rname, *start, *end, buf[128];
684 uid_t rid; 687 uid_t rid;
685 688
686 file=fopen(filename,"r"); 689 file = fopen(filename, "r");
687 if (file == NULL) { 690 if (file == NULL) {
688 perror(filename); 691 perror(filename);
689 return (-1); 692 return (-1);
690 } 693 }
691 694
692 while (fgets (buf, 128, file) != NULL) { 695 while (fgets(buf, 128, file) != NULL) {
693 if (buf[0] == '#') 696 if (buf[0] == '#')
694 continue; 697 continue;
695 698
696 start = buf; 699 start = buf;
697 end = strchr (start, ':'); 700 end = strchr(start, ':');
698 if (end == NULL) 701 if (end == NULL)
699 continue; 702 continue;
700 *end = '\0'; 703 *end = '\0';
701 rname = start; 704 rname = start;
702 705
703 start = end + 1; 706 start = end + 1;
704 end = strchr (start, ':'); 707 end = strchr(start, ':');
705 if (end == NULL) 708 if (end == NULL)
706 continue; 709 continue;
707 710
708 start = end + 1; 711 start = end + 1;
709 rid = (uid_t) strtol (start, &end, 10); 712 rid = (uid_t) strtol(start, &end, 10);
710 if (end == start) 713 if (end == start)
711 continue; 714 continue;
712 715
713 if (name) { 716 if (name) {
714 if (0 == strcmp(rname, name)) { 717 if (0 == strcmp(rname, name)) {
715 fclose( file); 718 fclose(file);
716 return( rid); 719 return (rid);
717 } 720 }
718 } 721 }
719 if ( id != -1 && id == rid ) { 722 if (id != -1 && id == rid) {
720 strncpy(name, rname, 8); 723 strncpy(name, rname, 8);
721 fclose( file); 724 fclose(file);
722 return( TRUE); 725 return (TRUE);
723 } 726 }
724 } 727 }
725 fclose(file); 728 fclose(file);
726 return (-1); 729 return (-1);
727} 730}
728 731
729uid_t 732uid_t my_getpwnam(char *name)
730my_getpwnam(char *name)
731{ 733{
732 return my_getid("/etc/passwd", name, -1); 734 return my_getid("/etc/passwd", name, -1);
733} 735}
734 736
735gid_t 737gid_t my_getgrnam(char *name)
736my_getgrnam(char *name)
737{ 738{
738 return my_getid("/etc/group", name, -1); 739 return my_getid("/etc/group", name, -1);
739} 740}
740 741
741void 742void my_getpwuid(char *name, uid_t uid)
742my_getpwuid(char* name, uid_t uid)
743{ 743{
744 my_getid("/etc/passwd", name, uid); 744 my_getid("/etc/passwd", name, uid);
745} 745}
746 746
747void 747void my_getgrgid(char *group, gid_t gid)
748my_getgrgid(char* group, gid_t gid)
749{ 748{
750 my_getid("/etc/group", group, gid); 749 my_getid("/etc/group", group, gid);
751} 750}
752 751
753 752
754#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS */ 753#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS */
755 754
756 755
757 756
@@ -762,43 +761,42 @@ my_getgrgid(char* group, gid_t gid)
762#include <linux/kd.h> 761#include <linux/kd.h>
763#include <sys/ioctl.h> 762#include <sys/ioctl.h>
764 763
765int is_a_console(int fd) 764int is_a_console(int fd)
766{ 765{
767 char arg; 766 char arg;
768 767
769 arg = 0; 768 arg = 0;
770 return (ioctl(fd, KDGKBTYPE, &arg) == 0 769 return (ioctl(fd, KDGKBTYPE, &arg) == 0
771 && ((arg == KB_101) || (arg == KB_84))); 770 && ((arg == KB_101) || (arg == KB_84)));
772} 771}
773 772
774static int open_a_console(char *fnam) 773static int open_a_console(char *fnam)
775{ 774{
776 int fd; 775 int fd;
777 776
778 /* try read-only */ 777 /* try read-only */
779 fd = open(fnam, O_RDWR); 778 fd = open(fnam, O_RDWR);
780 779
781 /* if failed, try read-only */ 780 /* if failed, try read-only */
782 if (fd < 0 && errno == EACCES) 781 if (fd < 0 && errno == EACCES)
783 fd = open(fnam, O_RDONLY); 782 fd = open(fnam, O_RDONLY);
784 783
785 /* if failed, try write-only */ 784 /* if failed, try write-only */
786 if (fd < 0 && errno == EACCES) 785 if (fd < 0 && errno == EACCES)
787 fd = open(fnam, O_WRONLY); 786 fd = open(fnam, O_WRONLY);
788 787
789 /* if failed, fail */ 788 /* if failed, fail */
790 if (fd < 0) 789 if (fd < 0)
791 return -1; 790 return -1;
792 791
793 /* if not a console, fail */ 792 /* if not a console, fail */
794 if (! is_a_console(fd)) 793 if (!is_a_console(fd)) {
795 { 794 close(fd);
796 close(fd); 795 return -1;
797 return -1; 796 }
798 } 797
799 798 /* success */
800 /* success */ 799 return fd;
801 return fd;
802} 800}
803 801
804/* 802/*
@@ -809,59 +807,59 @@ static int open_a_console(char *fnam)
809 * if tty_name is non-NULL, try this one instead. 807 * if tty_name is non-NULL, try this one instead.
810 */ 808 */
811 809
812int get_console_fd(char* tty_name) 810int get_console_fd(char *tty_name)
813{ 811{
814 int fd; 812 int fd;
815 813
816 if (tty_name) 814 if (tty_name) {
817 { 815 if (-1 == (fd = open_a_console(tty_name)))
818 if (-1 == (fd = open_a_console(tty_name))) 816 return -1;
819 return -1; 817 else
820 else 818 return fd;
821 return fd; 819 }
822 } 820
823 821 fd = open_a_console("/dev/tty");
824 fd = open_a_console("/dev/tty"); 822 if (fd >= 0)
825 if (fd >= 0) 823 return fd;
826 return fd; 824
827 825 fd = open_a_console("/dev/tty0");
828 fd = open_a_console("/dev/tty0"); 826 if (fd >= 0)
829 if (fd >= 0) 827 return fd;
830 return fd; 828
831 829 fd = open_a_console("/dev/console");
832 fd = open_a_console("/dev/console"); 830 if (fd >= 0)
833 if (fd >= 0) 831 return fd;
834 return fd; 832
835 833 for (fd = 0; fd < 3; fd++)
836 for (fd = 0; fd < 3; fd++) 834 if (is_a_console(fd))
837 if (is_a_console(fd)) 835 return fd;
838 return fd; 836
839 837 fprintf(stderr,
840 fprintf(stderr, 838 "Couldnt get a file descriptor referring to the console\n");
841 "Couldnt get a file descriptor referring to the console\n"); 839 return -1; /* total failure */
842 return -1; /* total failure */
843} 840}
844 841
845 842
846#endif /* BB_CHVT || BB_DEALLOCVT */ 843#endif /* BB_CHVT || BB_DEALLOCVT */
847 844
848 845
849#if !defined BB_REGEXP && (defined BB_GREP || defined BB_SED) 846#if !defined BB_REGEXP && (defined BB_GREP || defined BB_SED)
850 847
851/* Do a case insensitive strstr() */ 848/* Do a case insensitive strstr() */
852char* stristr(char *haystack, const char *needle) 849char *stristr(char *haystack, const char *needle)
853{ 850{
854 int len = strlen( needle ); 851 int len = strlen(needle);
855 while( *haystack ) {
856 if( !strncasecmp( haystack, needle, len ) )
857 break;
858 haystack++;
859 }
860 852
861 if( !(*haystack) ) 853 while (*haystack) {
862 haystack = NULL; 854 if (!strncasecmp(haystack, needle, len))
855 break;
856 haystack++;
857 }
863 858
864 return haystack; 859 if (!(*haystack))
860 haystack = NULL;
861
862 return haystack;
865} 863}
866 864
867/* This tries to find a needle in a haystack, but does so by 865/* This tries to find a needle in a haystack, but does so by
@@ -873,56 +871,61 @@ char* stristr(char *haystack, const char *needle)
873extern int find_match(char *haystack, char *needle, int ignoreCase) 871extern int find_match(char *haystack, char *needle, int ignoreCase)
874{ 872{
875 873
876 if (ignoreCase == FALSE) 874 if (ignoreCase == FALSE)
877 haystack = strstr (haystack, needle); 875 haystack = strstr(haystack, needle);
878 else 876 else
879 haystack = stristr (haystack, needle); 877 haystack = stristr(haystack, needle);
880 if (haystack == NULL) 878 if (haystack == NULL)
881 return FALSE; 879 return FALSE;
882 return TRUE; 880 return TRUE;
883} 881}
884 882
885 883
886/* This performs substitutions after a string match has been found. */ 884/* This performs substitutions after a string match has been found. */
887extern int replace_match(char *haystack, char *needle, char *newNeedle, int ignoreCase) 885extern int replace_match(char *haystack, char *needle, char *newNeedle,
886 int ignoreCase)
888{ 887{
889 int foundOne=0; 888 int foundOne = 0;
890 char *where, *slider, *slider1, *oldhayStack; 889 char *where, *slider, *slider1, *oldhayStack;
891 890
892 if (ignoreCase == FALSE) 891 if (ignoreCase == FALSE)
893 where = strstr (haystack, needle); 892 where = strstr(haystack, needle);
894 else 893 else
895 where = stristr (haystack, needle); 894 where = stristr(haystack, needle);
896 895
897 if (strcmp(needle, newNeedle)==0) 896 if (strcmp(needle, newNeedle) == 0)
898 return FALSE; 897 return FALSE;
899 898
900 oldhayStack = (char*)malloc((unsigned)(strlen(haystack))); 899 oldhayStack = (char *) malloc((unsigned) (strlen(haystack)));
901 while(where!=NULL) { 900 while (where != NULL) {
902 foundOne++; 901 foundOne++;
903 strcpy(oldhayStack, haystack); 902 strcpy(oldhayStack, haystack);
904#if 0 903#if 0
905 if ( strlen(newNeedle) > strlen(needle)) { 904 if (strlen(newNeedle) > strlen(needle)) {
906 haystack = (char *)realloc(haystack, (unsigned)(strlen(haystack) - 905 haystack =
907 strlen(needle) + strlen(newNeedle))); 906 (char *) realloc(haystack,
908 } 907 (unsigned) (strlen(haystack) -
908 strlen(needle) +
909 strlen(newNeedle)));
910 }
909#endif 911#endif
910 for(slider=haystack,slider1=oldhayStack;slider!=where;slider++,slider1++); 912 for (slider = haystack, slider1 = oldhayStack; slider != where;
911 *slider=0; 913 slider++, slider1++);
912 haystack=strcat(haystack, newNeedle); 914 *slider = 0;
913 slider1+=strlen(needle); 915 haystack = strcat(haystack, newNeedle);
914 haystack = strcat(haystack, slider1); 916 slider1 += strlen(needle);
915 where = strstr (slider, needle); 917 haystack = strcat(haystack, slider1);
916 } 918 where = strstr(slider, needle);
917 free( oldhayStack); 919 }
918 920 free(oldhayStack);
919 if (foundOne > 0) 921
920 return TRUE; 922 if (foundOne > 0)
921 else 923 return TRUE;
922 return FALSE; 924 else
925 return FALSE;
923} 926}
924 927
925#endif /* ! BB_REGEXP && (BB_GREP || BB_SED) */ 928#endif /* ! BB_REGEXP && (BB_GREP || BB_SED) */
926 929
927 930
928#if defined BB_FIND 931#if defined BB_FIND
@@ -940,91 +943,84 @@ extern int replace_match(char *haystack, char *needle, char *newNeedle, int igno
940 * provided that this copyright notice remains intact. 943 * provided that this copyright notice remains intact.
941 * Permission to distribute this code under the GPL has been granted. 944 * Permission to distribute this code under the GPL has been granted.
942 */ 945 */
943extern int 946extern int check_wildcard_match(const char *text, const char *pattern)
944check_wildcard_match(const char* text, const char* pattern)
945{ 947{
946 const char* retryPat; 948 const char *retryPat;
947 const char* retryText; 949 const char *retryText;
948 int ch; 950 int ch;
949 int found; 951 int found;
950
951 retryPat = NULL;
952 retryText = NULL;
953
954 while (*text || *pattern)
955 {
956 ch = *pattern++;
957
958 switch (ch)
959 {
960 case '*':
961 retryPat = pattern;
962 retryText = text;
963 break;
964 952
965 case '[': 953 retryPat = NULL;
966 found = FALSE; 954 retryText = NULL;
967 955
968 while ((ch = *pattern++) != ']') 956 while (*text || *pattern) {
969 { 957 ch = *pattern++;
970 if (ch == '\\')
971 ch = *pattern++;
972 958
973 if (ch == '\0') 959 switch (ch) {
974 return FALSE; 960 case '*':
961 retryPat = pattern;
962 retryText = text;
963 break;
975 964
976 if (*text == ch) 965 case '[':
977 found = TRUE; 966 found = FALSE;
978 }
979 967
980 //if (!found) 968 while ((ch = *pattern++) != ']') {
981 if (found==TRUE) 969 if (ch == '\\')
982 { 970 ch = *pattern++;
983 pattern = retryPat; 971
984 text = ++retryText; 972 if (ch == '\0')
985 } 973 return FALSE;
986 974
987 /* fall into next case */ 975 if (*text == ch)
976 found = TRUE;
977 }
988 978
989 case '?': 979 //if (!found)
990 if (*text++ == '\0') 980 if (found == TRUE) {
991 return FALSE; 981 pattern = retryPat;
982 text = ++retryText;
983 }
992 984
993 break; 985 /* fall into next case */
994 986
995 case '\\': 987 case '?':
996 ch = *pattern++; 988 if (*text++ == '\0')
989 return FALSE;
997 990
998 if (ch == '\0') 991 break;
999 return FALSE; 992
993 case '\\':
994 ch = *pattern++;
1000 995
1001 /* fall into next case */ 996 if (ch == '\0')
997 return FALSE;
1002 998
1003 default: 999 /* fall into next case */
1004 if (*text == ch)
1005 {
1006 if (*text)
1007 text++;
1008 break;
1009 }
1010 1000
1011 if (*text) 1001 default:
1012 { 1002 if (*text == ch) {
1013 pattern = retryPat; 1003 if (*text)
1014 text = ++retryText; 1004 text++;
1015 break; 1005 break;
1006 }
1007
1008 if (*text) {
1009 pattern = retryPat;
1010 text = ++retryText;
1011 break;
1012 }
1013
1014 return FALSE;
1016 } 1015 }
1017 1016
1018 return FALSE; 1017 if (pattern == NULL)
1018 return FALSE;
1019 } 1019 }
1020 1020
1021 if (pattern == NULL) 1021 return TRUE;
1022 return FALSE;
1023 }
1024
1025 return TRUE;
1026} 1022}
1027#endif /* BB_FIND */ 1023#endif /* BB_FIND */
1028 1024
1029 1025
1030 1026
@@ -1039,36 +1035,36 @@ check_wildcard_match(const char* text, const char* pattern)
1039 */ 1035 */
1040extern struct mntent *findMountPoint(const char *name, const char *table) 1036extern struct mntent *findMountPoint(const char *name, const char *table)
1041{ 1037{
1042 struct stat s; 1038 struct stat s;
1043 dev_t mountDevice; 1039 dev_t mountDevice;
1044 FILE *mountTable; 1040 FILE *mountTable;
1045 struct mntent *mountEntry; 1041 struct mntent *mountEntry;
1046 1042
1047 if (stat(name, &s) != 0) 1043 if (stat(name, &s) != 0)
1048 return 0; 1044 return 0;
1049 1045
1050 if ((s.st_mode & S_IFMT) == S_IFBLK) 1046 if ((s.st_mode & S_IFMT) == S_IFBLK)
1051 mountDevice = s.st_rdev; 1047 mountDevice = s.st_rdev;
1052 else 1048 else
1053 mountDevice = s.st_dev; 1049 mountDevice = s.st_dev;
1054 1050
1055 1051
1056 if ((mountTable = setmntent(table, "r")) == 0) 1052 if ((mountTable = setmntent(table, "r")) == 0)
1057 return 0; 1053 return 0;
1058 1054
1059 while ((mountEntry = getmntent(mountTable)) != 0) { 1055 while ((mountEntry = getmntent(mountTable)) != 0) {
1060 if (strcmp(name, mountEntry->mnt_dir) == 0 1056 if (strcmp(name, mountEntry->mnt_dir) == 0
1061 || strcmp(name, mountEntry->mnt_fsname) == 0) /* String match. */ 1057 || strcmp(name, mountEntry->mnt_fsname) == 0) /* String match. */
1062 break; 1058 break;
1063 if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice) /* Match the device. */ 1059 if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice) /* Match the device. */
1064 break; 1060 break;
1065 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice) /* Match the directory's mount point. */ 1061 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice) /* Match the directory's mount point. */
1066 break; 1062 break;
1067 } 1063 }
1068 endmntent(mountTable); 1064 endmntent(mountTable);
1069 return mountEntry; 1065 return mountEntry;
1070} 1066}
1071#endif /* BB_DF || BB_MTAB */ 1067#endif /* BB_DF || BB_MTAB */
1072 1068
1073 1069
1074 1070
@@ -1077,74 +1073,74 @@ extern struct mntent *findMountPoint(const char *name, const char *table)
1077 * Read a number with a possible multiplier. 1073 * Read a number with a possible multiplier.
1078 * Returns -1 if the number format is illegal. 1074 * Returns -1 if the number format is illegal.
1079 */ 1075 */
1080extern long getNum (const char *cp) 1076extern long getNum(const char *cp)
1081{ 1077{
1082 long value; 1078 long value;
1083 1079
1084 if (!isDecimal (*cp)) 1080 if (!isDecimal(*cp))
1085 return -1; 1081 return -1;
1086 1082
1087 value = 0; 1083 value = 0;
1088 1084
1089 while (isDecimal (*cp)) 1085 while (isDecimal(*cp))
1090 value = value * 10 + *cp++ - '0'; 1086 value = value * 10 + *cp++ - '0';
1091 1087
1092 switch (*cp++) { 1088 switch (*cp++) {
1093 case 'M': 1089 case 'M':
1094 case 'm': /* `tail' uses it traditionally */ 1090 case 'm': /* `tail' uses it traditionally */
1095 value *= 1048576; 1091 value *= 1048576;
1096 break; 1092 break;
1097 1093
1098 case 'k': 1094 case 'k':
1099 value *= 1024; 1095 value *= 1024;
1100 break; 1096 break;
1101 1097
1102 case 'b': 1098 case 'b':
1103 value *= 512; 1099 value *= 512;
1104 break; 1100 break;
1105 1101
1106 case 'w': 1102 case 'w':
1107 value *= 2; 1103 value *= 2;
1108 break; 1104 break;
1109 1105
1110 case '\0': 1106 case '\0':
1111 return value; 1107 return value;
1112 1108
1113 default: 1109 default:
1114 return -1; 1110 return -1;
1115 } 1111 }
1116 1112
1117 if (*cp) 1113 if (*cp)
1118 return -1; 1114 return -1;
1119 1115
1120 return value; 1116 return value;
1121} 1117}
1122#endif /* BB_DD || BB_TAIL */ 1118#endif /* BB_DD || BB_TAIL */
1123 1119
1124 1120
1125#if defined BB_INIT || defined BB_SYSLOGD 1121#if defined BB_INIT || defined BB_SYSLOGD
1126/* try to open up the specified device */ 1122/* try to open up the specified device */
1127extern int device_open(char *device, int mode) 1123extern int device_open(char *device, int mode)
1128{ 1124{
1129 int m, f, fd = -1; 1125 int m, f, fd = -1;
1130 1126
1131 m = mode | O_NONBLOCK; 1127 m = mode | O_NONBLOCK;
1132 1128
1133 /* Retry up to 5 times */ 1129 /* Retry up to 5 times */
1134 for (f = 0; f < 5; f++) 1130 for (f = 0; f < 5; f++)
1135 if ((fd = open(device, m, 0600)) >= 0) 1131 if ((fd = open(device, m, 0600)) >= 0)
1136 break; 1132 break;
1137 if (fd < 0) 1133 if (fd < 0)
1134 return fd;
1135 /* Reset original flags. */
1136 if (m != mode)
1137 fcntl(fd, F_SETFL, mode);
1138 return fd; 1138 return fd;
1139 /* Reset original flags. */
1140 if (m != mode)
1141 fcntl(fd, F_SETFL, mode);
1142 return fd;
1143} 1139}
1144#endif /* BB_INIT BB_SYSLOGD */ 1140#endif /* BB_INIT BB_SYSLOGD */
1145 1141
1146 1142
1147#if defined BB_INIT || defined BB_HALT || defined BB_REBOOT 1143#if defined BB_INIT || defined BB_HALT || defined BB_REBOOT
1148 1144
1149#if ! defined BB_FEATURE_USE_PROCFS 1145#if ! defined BB_FEATURE_USE_PROCFS
1150#error Sorry, I depend on the /proc filesystem right now. 1146#error Sorry, I depend on the /proc filesystem right now.
@@ -1158,101 +1154,103 @@ extern int device_open(char *device, int mode)
1158 * 0 failure 1154 * 0 failure
1159 * pid when init's pid is found. 1155 * pid when init's pid is found.
1160 */ 1156 */
1161extern pid_t 1157extern pid_t findInitPid()
1162findInitPid()
1163{ 1158{
1164 pid_t init_pid; 1159 pid_t init_pid;
1165 char filename[256]; 1160 char filename[256];
1166 char buffer[256]; 1161 char buffer[256];
1167 1162
1168 /* no need to opendir ;) */ 1163 /* no need to opendir ;) */
1169 for (init_pid = 1; init_pid < 65536; init_pid++) { 1164 for (init_pid = 1; init_pid < 65536; init_pid++) {
1170 FILE *status; 1165 FILE *status;
1171 1166
1172 sprintf(filename, "/proc/%d/status", init_pid); 1167 sprintf(filename, "/proc/%d/status", init_pid);
1173 status = fopen(filename, "r"); 1168 status = fopen(filename, "r");
1174 if (!status) { continue; } 1169 if (!status) {
1175 fgets(buffer, 256, status); 1170 continue;
1176 fclose(status); 1171 }
1177 1172 fgets(buffer, 256, status);
1178 if ( (strstr(buffer, "init\n") != NULL )) { 1173 fclose(status);
1179 return init_pid; 1174
1175 if ((strstr(buffer, "init\n") != NULL)) {
1176 return init_pid;
1177 }
1180 } 1178 }
1181 } 1179 return 0;
1182 return 0;
1183} 1180}
1184#endif /* BB_INIT || BB_HALT || BB_REBOOT */ 1181#endif /* BB_INIT || BB_HALT || BB_REBOOT */
1185 1182
1186#if defined BB_GUNZIP \ 1183#if defined BB_GUNZIP \
1187 || defined BB_GZIP \ 1184 || defined BB_GZIP \
1188 || defined BB_PRINTF \ 1185 || defined BB_PRINTF \
1189 || defined BB_TAIL 1186 || defined BB_TAIL
1190extern void *xmalloc (size_t size) 1187extern void *xmalloc(size_t size)
1191{ 1188{
1192 void *cp = malloc (size); 1189 void *cp = malloc(size);
1193 1190
1194 if (cp == NULL) { 1191 if (cp == NULL) {
1195 error("out of memory"); 1192 error("out of memory");
1196 } 1193 }
1197 return cp; 1194 return cp;
1198} 1195}
1199 1196
1200extern void error(char *msg) 1197extern void error(char *msg)
1201{ 1198{
1202 fprintf(stderr, "\n%s\n", msg); 1199 fprintf(stderr, "\n%s\n", msg);
1203 exit(1); 1200 exit(1);
1204} 1201}
1205#endif /* BB_GUNZIP || BB_GZIP || BB_PRINTF || BB_TAIL */ 1202#endif /* BB_GUNZIP || BB_GZIP || BB_PRINTF || BB_TAIL */
1206 1203
1207#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT) 1204#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
1208extern int vdprintf(int d, const char *format, va_list ap) 1205extern int vdprintf(int d, const char *format, va_list ap)
1209{ 1206{
1210 char buf[BUF_SIZE]; 1207 char buf[BUF_SIZE];
1211 int len; 1208 int len;
1212 1209
1213 len = vsprintf(buf, format, ap); 1210 len = vsprintf(buf, format, ap);
1214 return write(d, buf, len); 1211 return write(d, buf, len);
1215} 1212}
1216#endif /* BB_SYSLOGD */ 1213#endif /* BB_SYSLOGD */
1217 1214
1218#if defined BB_FEATURE_MOUNT_LOOP 1215#if defined BB_FEATURE_MOUNT_LOOP
1219extern int del_loop(const char *device) 1216extern int del_loop(const char *device)
1220{ 1217{
1221 int fd; 1218 int fd;
1222 1219
1223 if ((fd = open(device, O_RDONLY)) < 0) { 1220 if ((fd = open(device, O_RDONLY)) < 0) {
1224 perror(device); 1221 perror(device);
1225 return( FALSE); 1222 return (FALSE);
1226 } 1223 }
1227 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { 1224 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
1228 perror("ioctl: LOOP_CLR_FD"); 1225 perror("ioctl: LOOP_CLR_FD");
1229 return( FALSE); 1226 return (FALSE);
1230 } 1227 }
1231 close(fd); 1228 close(fd);
1232 return( TRUE); 1229 return (TRUE);
1233} 1230}
1234 1231
1235extern int set_loop(const char *device, const char *file, int offset, int *loopro) 1232extern int set_loop(const char *device, const char *file, int offset,
1233 int *loopro)
1236{ 1234{
1237 struct loop_info loopinfo; 1235 struct loop_info loopinfo;
1238 int fd, ffd, mode; 1236 int fd, ffd, mode;
1239 1237
1240 mode = *loopro ? O_RDONLY : O_RDWR; 1238 mode = *loopro ? O_RDONLY : O_RDWR;
1241 if ((ffd = open (file, mode)) < 0 && !*loopro 1239 if ((ffd = open(file, mode)) < 0 && !*loopro
1242 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) { 1240 && (errno != EROFS || (ffd = open(file, mode = O_RDONLY)) < 0)) {
1243 perror (file); 1241 perror(file);
1244 return 1; 1242 return 1;
1245 } 1243 }
1246 if ((fd = open (device, mode)) < 0) { 1244 if ((fd = open(device, mode)) < 0) {
1247 close(ffd); 1245 close(ffd);
1248 perror (device); 1246 perror(device);
1249 return 1; 1247 return 1;
1250 } 1248 }
1251 *loopro = (mode == O_RDONLY); 1249 *loopro = (mode == O_RDONLY);
1252 1250
1253 memset(&loopinfo, 0, sizeof(loopinfo)); 1251 memset(&loopinfo, 0, sizeof(loopinfo));
1254 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); 1252 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
1255 loopinfo.lo_name[LO_NAME_SIZE-1] = 0; 1253 loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
1256 1254
1257 loopinfo.lo_offset = offset; 1255 loopinfo.lo_offset = offset;
1258 1256
@@ -1275,30 +1273,30 @@ extern int set_loop(const char *device, const char *file, int offset, int *loopr
1275 return 0; 1273 return 0;
1276} 1274}
1277 1275
1278extern char *find_unused_loop_device (void) 1276extern char *find_unused_loop_device(void)
1279{ 1277{
1280 char dev[20]; 1278 char dev[20];
1281 int i, fd; 1279 int i, fd;
1282 struct stat statbuf; 1280 struct stat statbuf;
1283 struct loop_info loopinfo; 1281 struct loop_info loopinfo;
1284 1282
1285 for(i = 0; i <= 7; i++) { 1283 for (i = 0; i <= 7; i++) {
1286 sprintf(dev, "/dev/loop%d", i); 1284 sprintf(dev, "/dev/loop%d", i);
1287 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { 1285 if (stat(dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
1288 if ((fd = open (dev, O_RDONLY)) >= 0) { 1286 if ((fd = open(dev, O_RDONLY)) >= 0) {
1289 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) { 1287 if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == -1) {
1290 if (errno == ENXIO) { /* probably free */ 1288 if (errno == ENXIO) { /* probably free */
1291 close (fd); 1289 close(fd);
1292 return strdup(dev); 1290 return strdup(dev);
1291 }
1292 }
1293 close(fd);
1293 } 1294 }
1294 }
1295 close (fd);
1296 } 1295 }
1297 }
1298 } 1296 }
1299 return NULL; 1297 return NULL;
1300} 1298}
1301#endif /* BB_FEATURE_MOUNT_LOOP */ 1299#endif /* BB_FEATURE_MOUNT_LOOP */
1302 1300
1303 1301
1304/* END CODE */ 1302/* END CODE */
diff --git a/wc.c b/wc.c
index e69f0d899..8004e6294 100644
--- a/wc.c
+++ b/wc.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini wc implementation for busybox 3 * Mini wc implementation for busybox
3 * 4 *
@@ -23,78 +24,82 @@
23#include <stdio.h> 24#include <stdio.h>
24 25
25static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n" 26static const char wc_usage[] = "wc [OPTION]... [FILE]...\n\n"
26"Print line, word, and byte counts for each FILE, and a total line if\n" 27 "Print line, word, and byte counts for each FILE, and a total line if\n"
27"more than one FILE is specified. With no FILE, read standard input.\n" 28 "more than one FILE is specified. With no FILE, read standard input.\n"
28"\t-c\tprint the byte counts\n" 29 "\t-c\tprint the byte counts\n"
29"\t-l\tprint the newline counts\n" 30 "\t-l\tprint the newline counts\n"
30"\t-L\tprint the length of the longest line\n" 31
31"\t-w\tprint the word counts\n"; 32 "\t-L\tprint the length of the longest line\n"
33 "\t-w\tprint the word counts\n";
32 34
33static int total_lines, total_words, total_chars, max_length; 35static int total_lines, total_words, total_chars, max_length;
34static int print_lines, print_words, print_chars, print_length; 36static int print_lines, print_words, print_chars, print_length;
35 37
36void print_counts (int lines, int words, int chars, int length, 38void print_counts(int lines, int words, int chars, int length,
37 const char *name) { 39 const char *name)
40{
38 char const *space = ""; 41 char const *space = "";
42
39 if (print_lines) { 43 if (print_lines) {
40 printf ("%7d", lines); 44 printf("%7d", lines);
41 space = " "; 45 space = " ";
42 } 46 }
43 if (print_words) { 47 if (print_words) {
44 printf ("%s%7d", space, words); 48 printf("%s%7d", space, words);
45 space = " "; 49 space = " ";
46 } 50 }
47 if (print_chars) { 51 if (print_chars) {
48 printf ("%s%7d", space, chars); 52 printf("%s%7d", space, chars);
49 space = " "; 53 space = " ";
50 } 54 }
51 if (print_length) 55 if (print_length)
52 printf ("%s%7d", space, length); 56 printf("%s%7d", space, length);
53 if (*name) 57 if (*name)
54 printf (" %s", name); 58 printf(" %s", name);
55 putchar ('\n'); 59 putchar('\n');
56} 60}
57 61
58static void wc_file(FILE *file, const char *name) 62static void wc_file(FILE * file, const char *name)
59{ 63{
60 int lines, words, chars, length; 64 int lines, words, chars, length;
61 int in_word = 0, linepos = 0; 65 int in_word = 0, linepos = 0;
62 int c; 66 int c;
67
63 lines = words = chars = length = 0; 68 lines = words = chars = length = 0;
64 while ((c = getc(file)) != EOF) { 69 while ((c = getc(file)) != EOF) {
65 chars++; 70 chars++;
66 switch (c) { 71 switch (c) {
67 case '\n': 72 case '\n':
68 lines++; 73 lines++;
69 case '\r': 74 case '\r':
70 case '\f': 75 case '\f':
71 if (linepos > length) 76 if (linepos > length)
72 length = linepos; 77 length = linepos;
73 linepos = 0; 78 linepos = 0;
74 goto word_separator; 79 goto word_separator;
75 case '\t': 80 case '\t':
76 linepos += 8 - (linepos % 8); 81 linepos += 8 - (linepos % 8);
77 goto word_separator; 82 goto word_separator;
78 case ' ': 83 case ' ':
79 linepos++; 84 linepos++;
80 case '\v': 85 case '\v':
81 word_separator: 86 word_separator:
82 if (in_word) { 87 if (in_word) {
83 in_word = 0; 88 in_word = 0;
84 words++; 89 words++;
85 } 90 }
86 break; 91 break;
87 default: 92 default:
88 linepos++; 93 linepos++;
89 in_word = 1; 94 in_word = 1;
90 break; 95 break;
91 } 96 }
92 } 97 }
93 if (linepos > length) 98 if (linepos > length)
94 length = linepos; 99 length = linepos;
95 if (in_word) 100 if (in_word)
96 words++; 101 words++;
97 print_counts (lines, words, chars, length, name); 102 print_counts(lines, words, chars, length, name);
98 total_lines += lines; 103 total_lines += lines;
99 total_words += words; 104 total_words += words;
100 total_chars += chars; 105 total_chars += chars;
@@ -104,28 +109,30 @@ static void wc_file(FILE *file, const char *name)
104 fflush(stdout); 109 fflush(stdout);
105} 110}
106 111
107int wc_main(int argc, char **argv) { 112int wc_main(int argc, char **argv)
113{
108 FILE *file; 114 FILE *file;
115
109 total_lines = total_words = total_chars = max_length = 0; 116 total_lines = total_words = total_chars = max_length = 0;
110 print_lines = print_words = print_chars = print_length = 0; 117 print_lines = print_words = print_chars = print_length = 0;
111 118
112 while (--argc && **(++argv) == '-') { 119 while (--argc && **(++argv) == '-') {
113 while (*++(*argv)) 120 while (*++(*argv))
114 switch (**argv) { 121 switch (**argv) {
115 case 'c': 122 case 'c':
116 print_chars = 1; 123 print_chars = 1;
117 break; 124 break;
118 case 'l': 125 case 'l':
119 print_lines = 1; 126 print_lines = 1;
120 break; 127 break;
121 case 'L': 128 case 'L':
122 print_length = 1; 129 print_length = 1;
123 break; 130 break;
124 case 'w': 131 case 'w':
125 print_words = 1; 132 print_words = 1;
126 break; 133 break;
127 default: 134 default:
128 usage (wc_usage); 135 usage(wc_usage);
129 } 136 }
130 } 137 }
131 138
@@ -135,16 +142,14 @@ int wc_main(int argc, char **argv) {
135 if (argc == 0) { 142 if (argc == 0) {
136 wc_file(stdin, ""); 143 wc_file(stdin, "");
137 exit(TRUE); 144 exit(TRUE);
138 } 145 } else if (argc == 1) {
139 else if (argc == 1) {
140 file = fopen(*argv, "r"); 146 file = fopen(*argv, "r");
141 if (file == NULL) { 147 if (file == NULL) {
142 perror(*argv); 148 perror(*argv);
143 exit(FALSE); 149 exit(FALSE);
144 } 150 }
145 wc_file(file, *argv); 151 wc_file(file, *argv);
146 } 152 } else {
147 else {
148 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) { 153 while (argc-- > 0 && *argv != '\0' && strlen(*argv)) {
149 file = fopen(*argv, "r"); 154 file = fopen(*argv, "r");
150 if (file == NULL) { 155 if (file == NULL) {
@@ -154,8 +159,8 @@ int wc_main(int argc, char **argv) {
154 wc_file(file, *argv); 159 wc_file(file, *argv);
155 argv++; 160 argv++;
156 } 161 }
157 print_counts (total_lines, total_words, total_chars, 162 print_counts(total_lines, total_words, total_chars,
158 max_length, "total"); 163 max_length, "total");
159 } 164 }
160 exit(TRUE); 165 exit(TRUE);
161} 166}
diff --git a/whoami.c b/whoami.c
index 7fd5d01b2..3677c2fbc 100644
--- a/whoami.c
+++ b/whoami.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini whoami implementation for busybox 3 * Mini whoami implementation for busybox
3 * 4 *
@@ -24,21 +25,25 @@
24#include <pwd.h> 25#include <pwd.h>
25 26
26static const char whoami_usage[] = "whoami\n\n" 27static const char whoami_usage[] = "whoami\n\n"
27"Print the user name associated with the current effective user id.\n" 28 "Print the user name associated with the current effective user id.\n"
28"Same as id -un.\n";
29 29
30extern int whoami_main(int argc, char **argv) { 30 "Same as id -un.\n";
31
32extern int whoami_main(int argc, char **argv)
33{
31 struct passwd *pw; 34 struct passwd *pw;
32 uid_t uid; 35 uid_t uid;
33 36
34 if (argc > 1) usage (whoami_usage); 37 if (argc > 1)
38 usage(whoami_usage);
35 39
36 uid = geteuid (); 40 uid = geteuid();
37 pw = getpwuid (uid); 41 pw = getpwuid(uid);
38 if (pw) { 42 if (pw) {
39 puts (pw->pw_name); 43 puts(pw->pw_name);
40 exit (TRUE); 44 exit(TRUE);
41 } 45 }
42 fprintf (stderr, "%s: cannot find username for UID %u\n", argv[0], (unsigned) uid); 46 fprintf(stderr, "%s: cannot find username for UID %u\n", argv[0],
43 exit (FALSE); 47 (unsigned) uid);
48 exit(FALSE);
44} 49}
diff --git a/yes.c b/yes.c
index 96d6257d0..ac67845ac 100644
--- a/yes.c
+++ b/yes.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini yes implementation for busybox 3 * Mini yes implementation for busybox
3 * 4 *
@@ -22,19 +23,22 @@
22#include "internal.h" 23#include "internal.h"
23#include <stdio.h> 24#include <stdio.h>
24 25
25extern int yes_main(int argc, char **argv) { 26extern int yes_main(int argc, char **argv)
27{
26 int i; 28 int i;
29
27 if (argc == 1) 30 if (argc == 1)
28 while (1) 31 while (1)
29 if (puts ("y") == EOF) { 32 if (puts("y") == EOF) {
30 perror ("yes"); 33 perror("yes");
31 exit(FALSE); 34 exit(FALSE);
32 } 35 }
33 36
34 while (1) 37 while (1)
35 for (i = 1; i < argc; i++) 38 for (i = 1; i < argc; i++)
36 if (fputs (argv[i], stdout) == EOF || putchar (i == argc - 1 ? '\n' : ' ') == EOF) { 39 if (fputs(argv[i], stdout) == EOF
37 perror ("yes"); 40 || putchar(i == argc - 1 ? '\n' : ' ') == EOF) {
41 perror("yes");
38 exit(FALSE); 42 exit(FALSE);
39 } 43 }
40 exit(TRUE); 44 exit(TRUE);