Imported from util-linux-2.12j tarball.

This commit is contained in:
Karel Zak 2006-12-07 00:26:24 +01:00
parent 0b0bb92085
commit d162fcb550
50 changed files with 13571 additions and 13106 deletions

14
HISTORY
View File

@ -1,3 +1,17 @@
util-linux 2.12j
* cal: highlight today (Pádraig Brady)
* lomount: stop reading passwd at NUL, fix lo_encrypt key_size (Wolfram Kleff)
* losetup: add -f option to find an unused loop device
(Alexander Wigen, Remco van Mook)
* more: code cleanup (Joachim Henke)
* mount: add "group" mount option (Martin Dickopp)
* sfdisk: fix 2.6.8 BLKRRPART ioctl damage (Eric Lammerts)
* swapon: let swapon -a skip the swapfiles marked "noauto" (Dale R. Worley)
* umount: fix problem with empty mtab (Bryan Kadzban)
* umount: use special umount program if it exists (Ram Pai)
* New Danish messages
util-linux 2.12i
* MCONFIG: fix build conditions

View File

@ -90,6 +90,11 @@ HAVE_KILL=no
# file descriptor after logging out to trick the next user.
ALLOW_VCS_USE=yes
# If DO_STAT_MAIL is set to "yes", then login will stat() the mailbox
# and tell the user that she has new mail. This can hang the login if
# the mailbox is on a NFS mounted filesystem.
DO_STAT_MAIL=no
# If HAVE_RESET is set to "yes", then reset won't be installed. The version
# of reset that comes with the ncurses package is less aggressive.
HAVE_RESET=yes
@ -118,7 +123,7 @@ ifeq "$(ARCH)" "intel"
CPUHEAD=-m
else
CPUHEAD=-mcpu=i
# recent versions want -march=i
# it is rumoured that recent gcc versions want -march=i
# must add the right test
endif
ifeq "$(CPU)" "i386"

View File

@ -1 +1 @@
2.12i
2.12j

3
configure vendored
View File

@ -145,7 +145,7 @@ if ./testincl "sys/user.h"; then
echo "#define HAVE_sys_user_h" >> defines.h
else if ./testincl "asm/page.h"; then
echo "#define HAVE_asm_page_h" >> defines.h
fi fi
fi; fi
#
# H7. For nfsmount.c: do we have <rpcsvc/nfs_prot.h>?
@ -418,6 +418,7 @@ if [ $have_ncurses = 0 ]; then
echo "You don't have ncurses - I will not make ul and setterm."
else
echo "LIBCURSES=-lncurses" >> make_include
echo "#define HAVE_ncurses" >> defines.h
fi
#

View File

@ -1444,8 +1444,10 @@ new_part(int i) {
print_warning(_("No room to create the extended partition"));
return;
}
(void) add_part(ext, DOS_EXTENDED, 0, first, last,
(first == 0 ? sectors : 0), 0, &errmsg);
errmsg = 0;
if (add_part(ext, DOS_EXTENDED, 0, first, last,
(first == 0 ? sectors : 0), 0, &errmsg) && errmsg)
print_warning(errmsg);
first = ext_info.first_sector + ext_info.offset;
}
@ -1456,7 +1458,9 @@ new_part(int i) {
if (first == 0 || IS_LOGICAL(num))
offset = sectors;
(void) add_part(num, id, flags, first, last, offset, 0, &errmsg);
errmsg = 0;
if (add_part(num, id, flags, first, last, offset, 0, &errmsg) && errmsg)
print_warning(errmsg);
}
static void

View File

@ -295,6 +295,20 @@ set_changed(int i) {
ptes[i].changed = 1;
}
static int
is_garbage_table(void) {
int i;
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
if (p->boot_ind != 0 && p->boot_ind != 0x80)
return 1;
}
return 0;
}
/*
* Avoid warning about DOS partitions when no DOS partition was changed.
* Here a heuristic "is probably dos partition".
@ -630,7 +644,7 @@ read_extended(int ext) {
struct pte *pre = &ptes[partitions-1];
fprintf(stderr,
_("Warning: deleting partitions after %d\n"),
_("Warning: omitting partitions after %d\n"),
partitions);
clear_partition(pre->ext_pointer);
pre->changed = 1;
@ -1684,6 +1698,12 @@ list_table(int xtra) {
return;
}
if (is_garbage_table()) {
printf(_("This doesn't look like a partition table\n"
"Probably you selected the wrong device.\n\n"));
}
/* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
but if the device name ends in a digit, say /dev/foo1,
then the partition is called /dev/foo1p3. */

View File

@ -74,6 +74,7 @@ struct systypes i386_sys_types[] = {
{0xb8, N_("BSDI swap")},
{0xbb, N_("Boot Wizard hidden")},
{0xbe, N_("Solaris boot")},
{0xbf, N_("Solaris")},
{0xc1, N_("DRDOS/sec (FAT-12)")},
{0xc4, N_("DRDOS/sec (FAT-16 < 32M)")},
{0xc6, N_("DRDOS/sec (FAT-16)")},

View File

@ -792,7 +792,10 @@ static int
reread_ioctl(int fd) {
if (ioctl(fd, BLKRRPART)) {
perror("BLKRRPART");
return -1;
/* 2.6.8 returns EIO for a zero table */
if (errno == EBUSY)
return -1;
}
return 0;
}

View File

@ -143,6 +143,9 @@ endif
ifeq "$(ALLOW_VCS_USE)" "yes"
LOGINFLAGS += -DCHOWNVCS
endif
ifeq "$(DO_STAT_MAIL)" "yes"
LOGINFLAGS += -DDO_STAT_MAIL
endif
login.o: login.c $(LIB)/pathnames.h $(LIB)/setproctitle.c $(LIB)/setproctitle.h
$(CC) -c $(CFLAGS) $(PAMFL) $(LOGINFLAGS) login.c

View File

@ -1081,17 +1081,28 @@ Michael Riepe <michael@stud.uni-hannover.de>
}
if (!quietlog) {
struct stat st;
char *mail;
motd();
mail = getenv("MAIL");
if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
#ifdef DO_STAT_MAIL
/*
* This turns out to be a bad idea: when the mail spool
* is NFS mounted, and the NFS connection hangs, the
* login hangs, even root cannot login.
* Checking for mail should be done from the shell.
*/
{
struct stat st;
char *mail;
mail = getenv("MAIL");
if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
if (st.st_mtime > st.st_atime)
printf(_("You have new mail.\n"));
else
printf(_("You have mail.\n"));
}
}
#endif
}
signal(SIGALRM, SIG_DFL);

View File

@ -51,7 +51,6 @@ LIBPTY:=$(LIBPTY) -lutil
endif
# Programs requiring special compilation
NEEDS_CURSES= setterm
NEEDS_OPENPTY= script
@ -64,6 +63,16 @@ else
@echo $@ not made since it requires ncurses
endif
ifeq "$(HAVE_NCURSES)" "yes"
cal:
$(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES)
else
ifeq "$(HAVE_TERMCAP)" "yes"
cal:
$(CC) $(LDFLAGS) $^ -o $@ $(LIBTERMCAP)
endif
endif
$(NEEDS_OPENPTY):
$(CC) $(LDFLAGS) $^ -o $@ $(LIBPTY)

View File

@ -35,11 +35,11 @@
*/
/* 1999-02-01 Jean-Francois Bignolles: added option '-m' to display
* monday as the first day of the week.
* monday as the first day of the week.
* 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*
* 2000-09-01 Michael Charles Pruznick <dummy@netwiz.net>
* 2000-09-01 Michael Charles Pruznick <dummy@netwiz.net>
* Added "-3" option to print prev/next month with current.
* Added over-ridable default NUM_MONTHS and "-1" option to
* get traditional output when -3 is the default. I hope that
@ -68,6 +68,57 @@
#include "nls.h"
#include "../defines.h"
#if defined(HAVE_ncurses)
#if NCH
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include <term.h> /* include after <curses.h> */
static void
my_setupterm(const char *term, int fildes, int *errret) {
setupterm((char*)term, fildes, errret);
}
static void
my_putstring(char *s) {
putp(s);
}
static char *
my_tgetstr(char *s, char *ss) {
return tigetstr(ss);
}
#elif defined(HAVE_termcap)
#include <termcap.h>
char termbuffer[4096];
char tcbuffer[4096];
char *strbuf = termbuffer;
static void
my_setupterm(const char *term, int fildes, int *errret) {
*errret = tgetent(tcbuffer, term);
}
static void
my_putstring(char *s) {
tputs (s, 1, putchar);
}
static char *
my_tgetstr(char *s, char *ss) {
return tgetstr(s, &strbuf);
}
#endif
const char *term="";
const char *Senter="", *Sexit="";/* enter and exit standout mode */
#ifdef HAVE_langinfo_h
# include <langinfo.h>
#else
@ -77,7 +128,7 @@
#include "widechar.h"
#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
/* allow compile-time define to over-ride default */
#ifndef NUM_MONTHS
#define NUM_MONTHS 1
@ -88,10 +139,10 @@
#endif
#define THURSDAY 4 /* for reformation */
#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
#define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */
#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
#define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */
#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
#define MAXDAYS 43 /* max slots in a month array */
#define SPACE -1 /* used in day array */
@ -162,6 +213,8 @@ const char *full_month[12];
int week1stday=0;
int julian;
#define TODAY_FLAG 0x400 /* flag day for highlighting */
#define FMT_ST_LINES 8
#define FMT_ST_CHARS 300 /* 90 suffices in most locales */
struct fmt_st
@ -169,26 +222,27 @@ struct fmt_st
char s[FMT_ST_LINES][FMT_ST_CHARS];
};
void ascii_day __P((char *, int));
void center __P((const char *, int, int));
void day_array __P((int, int, int *));
int day_in_week __P((int, int, int));
int day_in_year __P((int, int, int));
void j_yearly __P((int));
void do_monthly __P((int, int, struct fmt_st*));
void monthly __P((int, int));
void monthly3 __P((int, int));
void trim_trailing_spaces __P((char *));
void usage __P((void));
void yearly __P((int));
void headers_init(void);
char * ascii_day(char *, int);
void center_str(const char* src, char* dest, size_t dest_size, int width);
void center(const char *, int, int);
void day_array(int, int, int, int *);
int day_in_week(int, int, int);
int day_in_year(int, int, int);
void yearly(int, int);
void j_yearly(int, int);
void do_monthly(int, int, int, struct fmt_st*);
void monthly(int, int, int);
void monthly3(int, int, int);
void trim_trailing_spaces(char *);
void usage(void);
void headers_init(void);
extern char *__progname;
int
main(int argc, char **argv) {
struct tm *local_time;
time_t now;
int ch, month, year, yflag;
int ch, day, month, year, yflag;
char *progname, *p;
int num_months = NUM_MONTHS;
@ -201,6 +255,17 @@ main(int argc, char **argv) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#if defined(HAVE_ncurses) || defined(HAVE_termcap)
if ((term = getenv("TERM"))) {
int ret;
my_setupterm(term, 1, &ret);
if (ret > 0) {
Senter = my_tgetstr("so","smso");
Sexit = my_tgetstr("se","rmso");
}
}
#endif
#if 0 /* setting week1stday is against man page */
/*
* What *is* the first day of the week? Note that glibc does not
@ -214,7 +279,7 @@ main(int argc, char **argv) {
*
* The traditional Unix cal utility starts at Sunday.
* We start at Sunday and have an option -m for starting at Monday.
*
*
* At some future time this may become -s for Sunday, -m for Monday,
* no option for glibc-determined locale-dependent version.
*/
@ -222,16 +287,16 @@ main(int argc, char **argv) {
week1stday = (int)(nl_langinfo(_NL_TIME_FIRST_WEEKDAY))[0];
#endif
#endif
yflag = 0;
while ((ch = getopt(argc, argv, "13mjsyV")) != -1)
switch(ch) {
case '1':
num_months = 1; /* default */
break;
case '3':
num_months = 3;
break;
case '1':
num_months = 1; /* default */
break;
case '3':
num_months = 3;
break;
case 's':
week1stday = 0; /* default */
break;
@ -255,7 +320,7 @@ main(int argc, char **argv) {
argc -= optind;
argv += optind;
month = year = 0;
day = month = year = 0;
switch(argc) {
case 2:
if ((month = atoi(*argv++)) < 1 || month > 12)
@ -266,8 +331,10 @@ main(int argc, char **argv) {
errx(1, _("illegal year value: use 1-9999"));
break;
case 0:
(void)time(&now);
time(&now);
local_time = localtime(&now);
if (isatty(1))
day = local_time->tm_yday + 1;
year = local_time->tm_year + 1900;
if (!yflag)
month = local_time->tm_mon + 1;
@ -278,13 +345,13 @@ main(int argc, char **argv) {
headers_init();
if (month && num_months == 1)
monthly(month, year);
monthly(day, month, year);
else if (month && num_months == 3)
monthly3(month, year);
monthly3(day, month, year);
else if (julian)
j_yearly(year);
j_yearly(day, year);
else
yearly(year);
yearly(day, year);
exit(0);
}
@ -316,7 +383,7 @@ void headers_init(void)
#else
# define weekday(wd) _time_info->abbrev_wkday[wd]
#endif
for(i = 0 ; i < 7 ; i++ ) {
wd = (i + week1stday) % 7;
#ifdef ENABLE_WIDECHAR
@ -342,8 +409,10 @@ void headers_init(void)
wcstombs(j_day_headings,j_day_headings_wc,sizeof(j_day_headings));
#endif
trim_trailing_spaces(day_headings);
trim_trailing_spaces(j_day_headings);
#undef weekday
for (i = 0; i < 12; i++) {
#ifdef HAVE_langinfo_h
full_month[i] = nl_langinfo(MON_1+i);
@ -354,62 +423,51 @@ void headers_init(void)
}
void
do_monthly(month, year, out)
int month, year;
struct fmt_st* out;
{
do_monthly(int day, int month, int year, struct fmt_st *out) {
int col, row, len, days[MAXDAYS];
char *p, lineout[300];
#ifdef ENABLE_WIDECHAR
wchar_t lineout_wc[300];
#endif
day_array(month, year, days);
/* %s is the month name, %d the year number.
char *p, lineout[FMT_ST_CHARS];
int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1;
day_array(day, month, year, days);
/*
* %s is the month name, %d the year number.
* you can change the order and/or add something here; eg for
* Basque the translation should be: "%2$dko %1$s", and
* the Vietnamese should be "%s na(m %d", etc.
*/
len = sprintf(lineout, _("%s %d"), full_month[month - 1], year);
#ifdef ENABLE_WIDECHAR
if (mbstowcs(lineout_wc,lineout,len) > 0) {
len = wcswidth(lineout_wc,len);
} else {
len = strlen(lineout);
}
#endif
(void)sprintf(out->s[0],"%*s%s",
((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", lineout );
(void)sprintf(out->s[1],"%s",
julian ? j_day_headings : day_headings);
center_str(lineout, out->s[0], SIZE(out->s[0]), width);
sprintf(out->s[1],"%s",
julian ? j_day_headings : day_headings);
for (row = 0; row < 6; row++) {
for (col = 0, p = lineout; col < 7; col++,
p += julian ? J_DAY_LEN : DAY_LEN)
ascii_day(p, days[row * 7 + col]);
for (col = 0, p = lineout; col < 7; col++)
p = ascii_day(p, days[row * 7 + col]);
*p = '\0';
trim_trailing_spaces(lineout);
(void)sprintf(out->s[row+2],"%s", lineout);
sprintf(out->s[row+2], "%s", lineout);
}
}
void
monthly(month, year)
int month, year;
{
monthly(int day, int month, int year) {
int i;
struct fmt_st out;
do_monthly(month, year, &out);
for ( i = 0; i < FMT_ST_LINES; i++ )
{
printf("%s\n", out.s[i]);
do_monthly(day, month, year, &out);
for (i = 0; i < FMT_ST_LINES; i++) {
#if defined(HAVE_ncurses) || defined(HAVE_termcap)
my_putstring(out.s[i]);putchar('\n');
#else
puts(out.s[i]);
#endif
}
}
void
monthly3(month, year)
int month, year;
{
monthly3(int day, int month, int year) {
char lineout[FMT_ST_CHARS];
int i;
int width;
struct fmt_st out_prev;
@ -418,109 +476,117 @@ monthly3(month, year)
int prev_month, prev_year;
int next_month, next_year;
if ( month == 1 )
{
prev_month = 12;
prev_year = year - 1;
if (month == 1) {
prev_month = 12;
prev_year = year - 1;
} else {
prev_month = month - 1;
prev_year = year;
}
else
{
prev_month = month - 1;
prev_year = year;
}
if ( month == 12 )
{
next_month = 1;
next_year = year + 1;
}
else
{
next_month = month + 1;
next_year = year;
if (month == 12) {
next_month = 1;
next_year = year + 1;
} else {
next_month = month + 1;
next_year = year;
}
do_monthly(prev_month, prev_year, &out_prev);
do_monthly(month, year, &out_curm);
do_monthly(next_month, next_year, &out_next);
width = (julian ? J_WEEK_LEN : WEEK_LEN);
for ( i = 0; i < FMT_ST_LINES; i++ )
{
printf("%-*.*s %-*.*s %-*.*s\n",
width, width, out_prev.s[i],
width, width, out_curm.s[i],
width, width, out_next.s[i] );
do_monthly(day, prev_month, prev_year, &out_prev);
do_monthly(day, month, year, &out_curm);
do_monthly(day, next_month, next_year, &out_next);
width = (julian ? J_WEEK_LEN : WEEK_LEN) -1;
for (i = 0; i < 2; i++)
printf("%s %s %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]);
for (i = 2; i < FMT_ST_LINES; i++) {
snprintf(lineout, SIZE(lineout), "%-*s %-*s %-*s\n",
width, out_prev.s[i],
width, out_curm.s[i],
width, out_next.s[i]);
#if defined(HAVE_ncurses) || defined(HAVE_termcap)
my_putstring(lineout);
#else
fputs(lineout,stdout);
#endif
}
}
void
j_yearly(year)
int year;
{
j_yearly(int day, int year) {
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
(void)sprintf(lineout, "%d", year);
sprintf(lineout, "%d", year);
center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
(void)printf("\n\n");
printf("\n\n");
for (i = 0; i < 12; i++)
day_array(i + 1, year, days[i]);
(void)memset(lineout, ' ', sizeof(lineout) - 1);
day_array(day, i + 1, year, days[i]);
memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 2) {
center(full_month[month], J_WEEK_LEN, J_HEAD_SEP);
center(full_month[month + 1], J_WEEK_LEN, 0);
(void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
printf("\n%s%*s %s\n", j_day_headings, J_HEAD_SEP, "",
j_day_headings);
for (row = 0; row < 6; row++) {
p = lineout;
for (which_cal = 0; which_cal < 2; which_cal++) {
p = lineout + which_cal * (J_WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
for (col = 0; col < 7; col++, p += J_DAY_LEN)
ascii_day(p, *dp++);
for (col = 0; col < 7; col++)
p = ascii_day(p, *dp++);
p += sprintf(p, " ");
}
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
#if defined(HAVE_ncurses) || defined(HAVE_termcap)
my_putstring(lineout);putchar('\n');
#else
puts(lineout);
#endif
}
}
(void)printf("\n");
printf("\n");
}
void
yearly(year)
int year;
{
yearly(int day, int year) {
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
char *p, lineout[100];
(void)sprintf(lineout, "%d", year);
sprintf(lineout, "%d", year);
center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
(void)printf("\n\n");
printf("\n\n");
for (i = 0; i < 12; i++)
day_array(i + 1, year, days[i]);
(void)memset(lineout, ' ', sizeof(lineout) - 1);
day_array(day, i + 1, year, days[i]);
memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 3) {
center(full_month[month], WEEK_LEN, HEAD_SEP);
center(full_month[month + 1], WEEK_LEN, HEAD_SEP);
center(full_month[month + 2], WEEK_LEN, 0);
(void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
printf("\n%s%*s %s%*s %s\n", day_headings, HEAD_SEP,
"", day_headings, HEAD_SEP, "", day_headings);
for (row = 0; row < 6; row++) {
p = lineout;
for (which_cal = 0; which_cal < 3; which_cal++) {
p = lineout + which_cal * (WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
for (col = 0; col < 7; col++, p += DAY_LEN)
ascii_day(p, *dp++);
for (col = 0; col < 7; col++)
p = ascii_day(p, *dp++);
p += sprintf(p, " ");
}
*p = '\0';
trim_trailing_spaces(lineout);
(void)printf("%s\n", lineout);
#if defined(HAVE_ncurses) || defined(HAVE_termcap)
my_putstring(lineout);putchar('\n');
#else
puts(lineout);
#endif
}
}
(void)printf("\n");
printf("\n");
}
/*
@ -531,11 +597,8 @@ yearly(year)
* builds that array for any month from Jan. 1 through Dec. 9999.
*/
void
day_array(month, year, days)
int month, year;
int *days;
{
int day, dw, dm;
day_array(int day, int month, int year, int *days) {
int julday, daynum, dw, dm;
int *d_sep1752;
if (month == 9 && year == 1752) {
@ -546,9 +609,14 @@ day_array(month, year, days)
memcpy(days, empty, MAXDAYS * sizeof(int));
dm = days_in_month[leap_year(year)][month];
dw = (day_in_week(1, month, year) - week1stday + 7) % 7;
day = julian ? day_in_year(1, month, year) : 1;
while (dm--)
days[dw++] = day++;
julday = day_in_year(1, month, year);
daynum = julian ? julday : 1;
while (dm--) {
days[dw] = daynum++;
if (julday++ == day)
days[dw] |= TODAY_FLAG;
dw++;
}
}
/*
@ -556,15 +624,13 @@ day_array(month, year, days)
* return the 1 based day number within the year
*/
int
day_in_year(day, month, year)
int day, month, year;
{
day_in_year(int day, int month, int year) {
int i, leap;
leap = leap_year(year);
for (i = 1; i < month; i++)
day += days_in_month[leap][i];
return (day);
return day;
}
/*
@ -575,9 +641,7 @@ day_in_year(day, month, year)
* missing days.
*/
int
day_in_week(day, month, year)
int day, month, year;
{
day_in_week(int day, int month, int year) {
long temp;
temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
@ -589,12 +653,10 @@ day_in_week(day, month, year)
return (THURSDAY);
}
void
ascii_day(p, day)
char *p;
int day;
{
char *
ascii_day(char *p, int day) {
int display, val;
int highlight = 0;
static char *aday[] = {
"",
" 1", " 2", " 3", " 4", " 5", " 6", " 7",
@ -605,8 +667,14 @@ ascii_day(p, day)
};
if (day == SPACE) {
memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
return;
int len = julian ? J_DAY_LEN : DAY_LEN;
memset(p, ' ', len);
return p+len;
}
if (day & TODAY_FLAG) {
day &= ~TODAY_FLAG;
p += sprintf(p, Senter);
highlight = 1;
}
if (julian) {
if ((val = day / 100)) {
@ -627,7 +695,10 @@ ascii_day(p, day)
*p++ = aday[day][0];
*p++ = aday[day][1];
}
*p = ' ';
if (highlight)
p += sprintf(p, Sexit);
*p++ = ' ';
return p;
}
void
@ -645,26 +716,59 @@ trim_trailing_spaces(s)
*p = '\0';
}
/*
* Center string, handling multibyte characters appropriately.
* In addition if the string is too large for the width it's truncated.
*/
void
center_str(const char* src, char* dest, size_t dest_size, int width)
{
#ifdef ENABLE_WIDECHAR
wchar_t str_wc[FMT_ST_CHARS];
#endif
char str[FMT_ST_CHARS];
const char* str_to_print=src;
int len, spaces, wide_char_enabled=0;
len = strlen(src);
#ifdef ENABLE_WIDECHAR
if (mbstowcs(str_wc, src, FMT_ST_CHARS) > 0) {
wide_char_enabled = 1;
len = wcswidth(str_wc, SIZE(str_wc));
}
#endif
if (len > width) {
str_to_print=str;
if (wide_char_enabled) {
#ifdef ENABLE_WIDECHAR
str_wc[width]=L'\0';
wcstombs(str, str_wc, SIZE(str));
#endif
} else {
strncpy(str, src, SIZE(str));
str[width]='\0';
}
}
spaces = width - len;
spaces = ( spaces < 0 ? 0 : spaces );
snprintf(dest, dest_size, "%*s%s%*s",
spaces / 2, "",
str_to_print,
spaces / 2 + spaces % 2, "" );
}
void
center(str, len, separate)
const char *str;
int len;
int separate;
{
#ifdef ENABLE_WIDECHAR
wchar_t str_wc[300];
int str_len;
if (mbstowcs(str_wc,str,300) > 0) {
str_len = wcswidth(str_wc,300);
} else {
str_len = strlen(str);
}
len -= str_len;
#else
len -= strlen(str);
#endif
(void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
char lineout[FMT_ST_CHARS];
center_str(str, lineout, SIZE(lineout), len);
fputs(lineout, stdout);
if (separate)
(void)printf("%*s", separate, "");
}

9
misc-utils/cal_test.sh Normal file
View File

@ -0,0 +1,9 @@
#!/bin/sh
LANG=ga_IE.utf8 ./cal -3 11 2004 #truncation
LANG=zh_HK.utf8 ./cal -3 #centering
./cal | cat #no highlight
TERM= ./cal #no highlight
TERM=vt100 ./cal #highlight with characters to be stripped by putp
./cal -y | head -10 | tr ' ' . #3 spaces
./cal -3 | tr ' ' . #2 spaces ?

View File

@ -46,7 +46,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <ctype.h> /* for isdigit() */
#include <unistd.h>
#include <signal.h>
#include "kill.h"

View File

@ -1,319 +0,0 @@
diff -uNr util-linux-2.12/mount/get_label_uuid.c ../patch/util-linux-2.12/mount/get_label_uuid.c
--- util-linux-2.12/mount/get_label_uuid.c 2002-11-26 12:18:01.000000000 +0100
+++ ../patch/util-linux-2.12/mount/get_label_uuid.c 2003-10-20 18:27:56.000000000 +0200
@@ -43,7 +43,139 @@
#endif
}
-/* for now, only ext2, ext3, xfs, ocfs are supported */
+/* Remove trailing spaces */
+static void remtrailspc(char *label) {
+ char *c;
+
+ c = strchr(label, 0)-1;
+ while (c >= label && *c == ' ')
+ *(c--) = 0;
+}
+
+static int handle_fat_dirent(struct fat_dirent *dirent, char **label) {
+ size_t namesize;
+
+ /* end-of-directory marker */
+ if (!dirent->s_filename[0])
+ return -1;
+
+ /* valid volume label */
+ if ((dirent->s_attr == 0x08 || dirent->s_attr == 0x28) && dirent->s_filename[0] != 0xe5) {
+
+ /* sanity check */
+ if (dirent->s_size[0] || dirent->s_size[1] || dirent->s_size[2] || dirent->s_size[3] ||
+ dirent->s_cluster[0] || dirent->s_cluster[1])
+ return -1;
+
+ namesize = sizeof(dirent->s_filename);
+ if (!(*label = calloc(namesize + 1, 1)))
+ return -1;
+ memcpy(*label, dirent->s_filename, namesize);
+ (*label)[namesize] = 0;
+ remtrailspc(*label);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static int read_volume_label_fat(int fd, struct fat_super_block *fatsb, char **label) {
+ unsigned i, m;
+ off_t o;
+
+ m = assemble2le(fatsb->s_dirents); /* root directory entries */
+
+ o = (off_t) assemble2le(fatsb->s_ssec) * /* bytes per sector */
+ ((off_t) assemble2le(fatsb->s_rsecs) + /* reserved sectors */
+ (off_t) assemble2le(fatsb->s_spfat) * /* sectors per fat */
+ (off_t) fatsb->s_nfats); /* number of fats */
+
+ for (i = 0; i < m; i++) {
+ struct fat_dirent dirent;
+ int rv;
+
+ if (lseek(fd, o, SEEK_SET) != o ||
+ read(fd, &dirent, sizeof(dirent)) != sizeof(dirent))
+ return -1;
+
+ if ((rv = handle_fat_dirent(&dirent, label)) != 1)
+ return rv;
+
+ o += sizeof(dirent);
+ }
+
+ return -1;
+}
+
+static int read_volume_label_fat32(int fd, struct fat32_super_block *fat32sb, char **label) {
+ unsigned c;
+ off_t fo, b, o;
+ int i, ifat;
+ size_t m, cs;
+
+ ifat = fat32sb->s_mirror[0] & 128 ? (fat32sb->s_mirror[0] & 0xF) : 0;
+
+ if (ifat >= fat32sb->s_nfats)
+ return -1;
+
+ fo = (off_t) assemble2le(fat32sb->s_ssec) * /* bytes per sector */
+ ((off_t) assemble2le(fat32sb->s_rsecs) + /* reserved sectors */
+ (off_t) assemble4le(fat32sb->s_spfat) * /* sectors per fat */
+ (off_t) ifat); /* number of FAT used */
+
+ b = (off_t) assemble2le(fat32sb->s_ssec) * /* bytes per sector */
+ ((off_t) assemble2le(fat32sb->s_rsecs) + /* reserved sectors */
+ (off_t) assemble4le(fat32sb->s_spfat) * /* sectors per fat */
+ (off_t) fat32sb->s_nfats); /* number of FATs */
+
+ c = assemble4le(fat32sb->s_rcluster) & 0x0fffffffL;
+ if (c < 2 || c >= 0x0ffffff0)
+ return -1;
+
+ m = cs = assemble2le(fat32sb->s_ssec) * (size_t) fat32sb->s_scluster;
+ o = b + (off_t) cs*(c-2);
+
+ for (i = 0; i < 0xFFFF; i++) { /* safety against DoS attack */
+ struct fat_dirent dirent;
+ int rv;
+
+ if (lseek(fd, o, SEEK_SET) != o ||
+ read(fd, &dirent, sizeof(dirent)) != sizeof(dirent))
+ return -1;
+
+ if ((rv = handle_fat_dirent(&dirent, label)) != 1)
+ return rv;
+
+ if (m > sizeof(dirent)) {
+ m -= sizeof(dirent);
+ o += sizeof(dirent);
+ } else {
+ off_t d;
+
+ /* next cluster */
+
+ d = fo+4*c;
+ if (lseek(fd, d, SEEK_SET) != d ||
+ read(fd, &c, 4) != 4)
+ return -1;
+
+ c = assemble4le((char*) &c) & 0x0fffffffL;
+ if (c < 2 || c >= 0x0ffffff0) {
+ return -1;
+ }
+
+ m = cs;
+ o = b + cs*(c-2);
+ }
+ }
+
+
+ return -1;
+}
+
+
+/* for now, only ext2, ext3, xfs, ocfs, fat, fat32 are supported */
int
get_label_uuid(const char *device, char **label, char *uuid) {
int fd;
@@ -54,8 +186,10 @@
struct jfs_super_block jfssb;
struct ocfs_volume_header ovh; /* Oracle */
struct ocfs_volume_label olbl;
+ struct fat_super_block fatsb;
+ struct fat32_super_block fat32sb;
- fd = open(device, O_RDONLY);
+ fd = open(device, O_RDONLY);
if (fd < 0)
return rv;
@@ -111,7 +245,87 @@
memcpy(*label, jfssb.s_label, namesize);
}
rv = 0;
- }
+ } else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char*) &fat32sb, sizeof(fat32sb)) == sizeof(fat32sb)
+ && fat32sb.s_sig[0] == 0x55
+ && fat32sb.s_sig[1] == 0xAA
+ && (fat32sb.s_media & 0xF0) == 0xF0
+ && (fat32sb.s_spfat_old[0] == 0)
+ && (fat32sb.s_spfat_old[1] == 0)
+ && fat32sb.s_extsig == 0x29
+ && (memcmp(fat32sb.s_fs, "FAT32 ", 8) == 0)) {
+
+ *label = NULL;
+
+ /* If no root directory entry volume name was found use the one from the boot sector */
+ if (read_volume_label_fat32(fd, &fat32sb, label) != 0) {
+ if (memcmp(fat32sb.s_label, "NO NAME ", 11) != 0 &&
+ memcmp(fat32sb.s_label, " ", 11) != 0 &&
+ memcmp(fat32sb.s_label, "\0\0\0\0\0\0\0\0", 8) != 0) {
+
+ namesize = sizeof(fat32sb.s_label);
+ if ((*label = calloc(namesize + 1, 1)) != NULL) {
+ memcpy(*label, fat32sb.s_label, namesize);
+ (*label)[namesize] = 0;
+ remtrailspc(*label);
+ }
+ }
+ }
+
+ if (*label) {
+
+ /* Set UUID from serial */
+ uuid[0] = fat32sb.s_serial[3];
+ uuid[1] = fat32sb.s_serial[2];
+ uuid[2] = fat32sb.s_serial[1];
+ uuid[3] = fat32sb.s_serial[0];
+ memset(uuid+4, 0, 12);
+
+ rv = 0;
+ }
+ } else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char*) &fatsb, sizeof(fatsb)) == sizeof(fatsb)
+ && fatsb.s_sig[0] == 0x55
+ && fatsb.s_sig[1] == 0xAA
+ && (fatsb.s_media & 0xF0) == 0xF0
+ && fatsb.s_extsig == 0x29
+ && (memcmp(fatsb.s_fs, "FAT12 ", 8) == 0
+ || memcmp(fatsb.s_fs, "FAT16 ", 8) == 0
+ || memcmp(fatsb.s_fs, "FAT ", 8) == 0
+ || memcmp(fatsb.s_fs, "\0\0\0\0\0\0\0\0", 8) == 0)
+ && memcmp(fatsb.s_fs2, "FAT32 ", 8) != 0) {
+
+ *label = NULL;
+
+ if (read_volume_label_fat(fd, &fatsb, label) != 0) {
+
+ /* If no root directory entry volume name was found use the one from the boot sector */
+ if (memcmp(fatsb.s_label, "NO NAME ", 11) != 0 &&
+ memcmp(fatsb.s_label, " ", 11) != 0 &&
+ memcmp(fatsb.s_label, "\0\0\0\0\0\0\0\0", 8) != 0) {
+
+ namesize = sizeof(fatsb.s_label);
+ if ((*label = calloc(namesize + 1, 1)) != NULL) {
+ memcpy(*label, fatsb.s_label, namesize);
+ (*label)[namesize] = 0;
+ remtrailspc(*label);
+ }
+
+ }
+ }
+
+ if (*label) {
+
+ /* Set UUID from serial */
+ uuid[0] = fatsb.s_serial[3];
+ uuid[1] = fatsb.s_serial[2];
+ uuid[2] = fatsb.s_serial[1];
+ uuid[3] = fatsb.s_serial[0];
+ memset(uuid+4, 0, 12);
+
+ rv = 0;
+ }
+ }
close(fd);
return rv;
diff -uNr util-linux-2.12/mount/linux_fs.h ../patch/util-linux-2.12/mount/linux_fs.h
--- util-linux-2.12/mount/linux_fs.h 2003-07-05 22:16:32.000000000 +0200
+++ ../patch/util-linux-2.12/mount/linux_fs.h 2003-10-20 18:07:06.000000000 +0200
@@ -122,13 +122,65 @@
u_char s_dummy[3];
u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
/* mtools-3.9.4 writes "MTOOL394" */
- u_char s_dummy2[32];
+ u_char s_ssec[2]; /* bytes per sector */
+ u_char s_scluster; /* sectors per cluster */
+ u_char s_rsecs[2]; /* reserved sectors */
+ u_char s_nfats; /* number of FATs */
+ u_char s_dirents[2]; /* maximum root directory entries */
+ u_char s_nsecs[2]; /* total number of sectors */
+ u_char s_media; /* media type, upper nibble is 0xF */
+ u_char s_spfat[2]; /* sectors per fat */
+
+ u_char s_dummy2[14];
+ u_char s_extsig; /* extended signature */
+ u_char s_serial[4]; /* serial number */
u_char s_label[11]; /* for DOS? */
- u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
+ u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
/* OS/2 BM has "FAT " here. */
- u_char s_dummy3[9];
- u_char s_label2[11]; /* for Windows? */
- u_char s_fs2[8]; /* garbage or "FAT32 " */
+
+ u_char s_dummy3[20];
+ u_char s_fs2[8]; /* "FAT32 " */
+
+ u_char s_dummy4[420];
+ u_char s_sig[2]; /* 55 AA */
+};
+
+struct fat32_super_block {
+ u_char s_dummy[3];
+ u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
+ /* mtools-3.9.4 writes "MTOOL394" */
+
+ u_char s_ssec[2]; /* bytes per sector */
+ u_char s_scluster; /* sectors per cluster */
+ u_char s_rsecs[2]; /* reserved sectors */
+ u_char s_nfats; /* number of FATs */
+ u_char s_dirents[2]; /* maximum root directory entries */
+ u_char s_nsecs[2]; /* total number of sectors */
+ u_char s_media; /* media type, upper nibble is 0xF */
+ u_char s_spfat_old[2]; /* sectors per fat */
+
+ u_char s_dummy2[12];
+ u_char s_spfat[4]; /* sectors per FAT */
+ u_char s_mirror[2]; /* mirror flag */
+ u_char s_version[2]; /* fs version */
+ u_char s_rcluster[4]; /* root directory cluster */
+
+ u_char s_dummy3[18];
+ u_char s_extsig; /* extended signature 0x29 */
+ u_char s_serial[4]; /* serial number */
+ u_char s_label[11]; /* label */
+ u_char s_fs[8]; /* filesystem type "FAT32 " */
+
+ u_char s_dummy4[420];
+ u_char s_sig[2]; /* 55 AA */
+};
+
+struct fat_dirent {
+ u_char s_filename[11]; /* Filename with extension */
+ u_char s_attr; /* File attribute flags */
+ u_char s_dummy[14];
+ u_char s_cluster[2]; /* Starting cluster */
+ u_char s_size[4]; /* File size */
};
#define XFS_SUPER_MAGIC "XFSB"

View File

@ -105,7 +105,7 @@ static void
discard_mntentchn(struct mntentchn *mc0) {
struct mntentchn *mc, *mc1;
for (mc = mc0->nxt; mc != mc0; mc = mc1) {
for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) {
mc1 = mc->nxt;
my_free(mc->m.mnt_fsname);
my_free(mc->m.mnt_dir);

View File

@ -1,17 +1,4 @@
/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
/* Added vfs mount options - aeb - 960223 */
/* Removed lomount - aeb - 960224 */
/*
* 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
* 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - fixed strerr(errno) in gettext calls
* 2000-09-24 Marc Mutz <Marc@Mutz.com>
* - added -p option to pass passphrases via fd's to losetup/mount.
* Used for encryption in non-interactive environments.
* The idea behind xgetpass() is stolen from GnuPG, v.1.0.3.
*/
/* Originally from Ted's losetup.c */
#define LOOPMAJOR 7
@ -37,6 +24,7 @@
#include "nls.h"
extern int verbose;
extern char *progname;
extern char *xstrdup (const char *s); /* not: #include "sundries.h" */
extern void error (const char *fmt, ...); /* idem */
@ -186,15 +174,15 @@ find_unused_loop_device (void) {
}
if (!somedev)
error(_("mount: could not find any device /dev/loop#"));
else if (!someloop) {
error(_("%s: could not find any device /dev/loop#"), progname);
else if (!someloop)
error(_(
"mount: Could not find any loop device. Maybe this kernel "
"%s: Could not find any loop device. Maybe this kernel "
"does not know\n"
" about the loop device? (If so, recompile or "
"`modprobe loop'.)"));
} else
error(_("mount: could not find any free loop device"));
"`modprobe loop'.)"), progname);
else
error(_("%s: could not find any free loop device"), progname);
return 0;
}
@ -226,15 +214,16 @@ xgetpass(int pfd, const char *prompt) {
break;
}
}
if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n')
if (read(pfd, pass+i, 1) != 1 ||
pass[i] == '\n' || pass[i] == 0)
break;
}
if (pass == NULL)
return "";
else {
pass[i] = 0;
return pass;
}
pass[i] = 0;
return pass;
}
static int
@ -249,7 +238,7 @@ int
set_loop(const char *device, const char *file, unsigned long long offset,
const char *encryption, int pfd, int *loopro) {
struct loop_info64 loopinfo64;
int fd, ffd, mode, i;
int fd, ffd, mode, i, n;
char *pass;
mode = (*loopro ? O_RDONLY : O_RDWR);
@ -302,16 +291,15 @@ set_loop(const char *device, const char *file, unsigned long long offset,
break;
case LO_CRYPT_XOR:
pass = getpass(_("Password: "));
xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
memset(pass, 0, strlen(pass));
loopinfo64.lo_encrypt_key_size =
strlen(loopinfo64.lo_encrypt_key);
break;
goto gotpass;
default:
pass = xgetpass(pfd, _("Password: "));
gotpass:
xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
memset(pass, 0, strlen(pass));
loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
n = strlen(pass);
memset(pass, 0, n);
loopinfo64.lo_encrypt_key_size =
(n < LO_KEY_SIZE) ? n : LO_KEY_SIZE;
}
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
@ -413,10 +401,11 @@ static char *progname;
static void
usage(void) {
fprintf(stderr, _("usage:\n\
%s loop_device # give info\n\
%s -d loop_device # delete\n\
%s [ -e encryption ] [ -o offset ] loop_device file # setup\n"),
progname, progname, progname);
%s loop_device # give info\n\
%s -d loop_device # delete\n\
%s -f # find unused\n\
%s [-e encryption] [-o offset] {-f|loop_device} file # setup\n"),
progname, progname, progname, progname);
exit(1);
}
@ -449,8 +438,8 @@ error (const char *fmt, ...) {
int
main(int argc, char **argv) {
char *offset, *encryption, *passfd;
int delete, c;
char *p, *offset, *encryption, *passfd, *device, *file;
int delete, find, c;
int res = 0;
int ro = 0;
int pfd = -1;
@ -460,10 +449,15 @@ main(int argc, char **argv) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
delete = off = 0;
delete = find = 0;
off = 0;
offset = encryption = passfd = NULL;
progname = argv[0];
while ((c = getopt(argc,argv,"de:E:o:p:v")) != -1) {
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
while ((c = getopt(argc, argv, "de:E:fo:p:v")) != -1) {
switch (c) {
case 'd':
delete = 1;
@ -472,6 +466,9 @@ main(int argc, char **argv) {
case 'e':
encryption = optarg;
break;
case 'f':
find = 1;
break;
case 'o':
offset = optarg;
break;
@ -485,22 +482,49 @@ main(int argc, char **argv) {
usage();
}
}
if (argc == 1) usage();
if ((delete && (argc != optind+1 || encryption || offset)) ||
(!delete && (argc < optind+1 || argc > optind+2)))
if (argc == 1) {
usage();
if (argc == optind+1) {
if (delete)
res = del_loop(argv[optind]);
else
res = show_loop(argv[optind]);
} else if (delete) {
if (argc != optind+1 || encryption || offset || find)
usage();
} else if (find) {
if (argc < optind || argc > optind+1)
usage();
} else {
if (argc < optind+1 || argc > optind+2)
usage();
}
if (find) {
device = find_unused_loop_device();
if (device == NULL)
return -1;
if (verbose)
printf("Loop device is %s\n", device);
if (argc == optind) {
printf("%s\n", device);
return 0;
}
file = argv[optind];
} else {
device = argv[optind];
if (argc == optind+1)
file = NULL;
else
file = argv[optind+1];
}
if (delete)
res = del_loop(device);
else if (file == NULL)
res = show_loop(device);
else {
if (offset && sscanf(offset, "%llu", &off) != 1)
usage();
if (passfd && sscanf(passfd, "%d", &pfd) != 1)
usage();
res = set_loop(argv[optind], argv[optind+1], off,
encryption, pfd, &ro);
res = set_loop(device, file, off, encryption, pfd, &ro);
}
return res;
}

View File

@ -3,24 +3,40 @@
losetup \- set up and control loop devices
.SH SYNOPSIS
.ad l
Get info:
.sp
.in +5
.B losetup
[
.RB [ \-e | \-E ]
.I encryption
] [
.B \-o
.I offset
] [
.B \-p
.I pfd
]
.I loop_device file
.br
.B losetup
[
.B \-d
]
.I loop_device
.sp
.in -5
Delete loop:
.sp
.in +5
.B "losetup \-d"
.I loop_device
.sp
.in -5
Print name of first unused loop device:
.sp
.in +5
.B "losetup \-f"
.sp
.in -5
Setup loop device:
.sp
.in +5
.B losetup
.RB [{\-e | \-E}
.IR encryption ]
.RB [ \-o
.IR offset ]
.RB [ \-p
.IR pfd ]
.in +8
.RB { \-f | \fIloop_device\fP }
.I file
.in -13
.ad b
.SH DESCRIPTION
.B losetup
@ -56,6 +72,10 @@ Detach the file or device associated with the specified loop device.
Enable data encryption with specified number.
.IP "\fB\-e \fIencryption_name\fP"
Enable data encryption with specified name.
.IP "\fB\-f\fP"
Find the first unused loop device. If a
.I file
argument is present, use this device. Otherwise, print its name.
.IP "\fB\-o \fIoffset\fP"
The data start is moved \fIoffset\fP bytes into the specified file or
device.

View File

@ -216,6 +216,10 @@ option, with the restriction that the user must be the owner
of the special file. This may be useful e.g. for
.I /dev/fd
if a login script makes the console user owner of this device.
The
.B group
option is similar, with the restriction that the user must be
member of the group of the special file.
The programs
.B mount
@ -551,6 +555,14 @@ Interpret character or block special devices on the file system.
.B exec
Permit execution of binaries.
.TP
.B group
Allow an ordinary (i.e., non-root) user to mount the file system if one
of his groups matches the group of the device.
This option implies the options
.BR nosuid " and " nodev
(unless overridden by subsequent options, as in the option line
.BR group,dev,suid ).
.TP
.B _netdev
The filesystem resides on a device that requires network access
(used to prevent the system from attempting to mount these filesystems
@ -583,6 +595,14 @@ suidperl(1) installed.)
Forbid an ordinary (i.e., non-root) user to mount the file system.
This is the default.
.TP
.B owner
Allow an ordinary (i.e., non-root) user to mount the file system if he
is the owner of the device.
This option implies the options
.BR nosuid " and " nodev
(unless overridden by subsequent options, as in the option line
.BR owner,dev,suid ).
.TP
.B remount
Attempt to remount an already-mounted file system. This is commonly
used to change the mount flags for a file system, especially to make a

View File

@ -96,6 +96,7 @@ struct opt_map {
#define MS_USERS 0x40000000
#define MS_USER 0x20000000
#define MS_OWNER 0x10000000
#define MS_GROUP 0x08000000
#define MS_COMMENT 0x00020000
#define MS_LOOP 0x00010000
@ -135,6 +136,8 @@ static const struct opt_map opt_map[] = {
{ "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
{ "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
{ "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */
{ "group", 0, 0, MS_GROUP }, /* Let the group of the device mount */
{ "nogroup", 0, 1, MS_GROUP }, /* Device group has no special privs */
{ "_netdev", 0, 0, MS_COMMENT}, /* Device requires network */
{ "comment", 0, 0, MS_COMMENT}, /* fstab comment only (kudzu,_netdev)*/
@ -263,7 +266,8 @@ parse_opt (const char *opt, int *mask, char *extra_opts) {
if ((om->mask == MS_USER || om->mask == MS_USERS)
&& !om->inv)
*mask |= MS_SECURE;
if ((om->mask == MS_OWNER) && !om->inv)
if ((om->mask == MS_OWNER || om->mask == MS_GROUP)
&& !om->inv)
*mask |= MS_OWNERSECURE;
#ifdef MS_SILENT
if (om->mask == MS_SILENT && om->inv) {
@ -507,20 +511,47 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types,
static void
suid_check(const char *spec, const char *node, int *flags, char **user) {
if (suid) {
/* RedHat patch: allow owners to mount when fstab contains
the owner option. Note that this should never be used
in a high security environment, but may be useful to give
people at the console the possibility of mounting a floppy. */
if (*flags & MS_OWNER) {
if (!strncmp(spec, "/dev/", 5)) {
struct stat sb;
/*
* MS_OWNER: Allow owners to mount when fstab contains
* the owner option. Note that this should never be used
* in a high security environment, but may be useful to give
* people at the console the possibility of mounting a floppy.
* MS_GROUP: Allow members of device group to mount. (Martin Dickopp)
*/
if (*flags & (MS_OWNER | MS_GROUP)) {
struct stat sb;
if (!stat(spec, &sb)) {
if (!strncmp(spec, "/dev/", 5) && stat(spec, &sb) == 0) {
if (*flags & MS_OWNER) {
if (getuid() == sb.st_uid)
*flags |= MS_USER;
}
if (*flags & MS_GROUP) {
if (getgid() == sb.st_gid)
*flags |= MS_USER;
else {
int n = getgroups(0, NULL);
if (n > 0) {
gid_t *groups = xmalloc(n * sizeof(*groups));
if (getgroups(n, groups) == n) {
int i;
for (i = 0; i < n; i++) {
if (groups[i] == sb.st_gid) {
*flags |= MS_USER;
break;
}
}
}
free(groups);
}
}
}
}
}
/* James Kehl <mkehl@gil.com.au> came with a similar patch:
allow an arbitrary user to mount when he is the owner of
the mount-point and has write-access to the device.
@ -537,8 +568,7 @@ suid_check(const char *spec, const char *node, int *flags, char **user) {
*user = getusername();
}
if (*flags & MS_OWNER)
*flags &= ~MS_OWNER;
*flags &= ~(MS_OWNER | MS_GROUP);
}
static int
@ -927,13 +957,13 @@ retry_nfs:
error (_("mount: %s not mounted already, or bad option"), node);
} else {
error (_("mount: wrong fs type, bad option, bad superblock on %s,\n"
" or too many mounted file systems"),
" missing codepage, or too many mounted file systems"),
spec);
if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)
&& (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) {
if (ioctl(fd, BLKGETSIZE, &size) == 0) {
if (size == 0) {
if (size == 0 && !loop) {
warned++;
error (" (could this be the IDE device where you in fact use\n"
" ide-scsi so that sr0 or sda or so is needed?)");
@ -1111,61 +1141,63 @@ is_existing_file (const char *s) {
static int
mount_one (const char *spec, const char *node, const char *types,
const char *opts, char *cmdlineopts, int freq, int pass) {
int status, status2;
const char *nspec;
int status, status2;
const char *nspec;
/* Substitute values in opts, if required */
opts = usersubst(opts);
/* Substitute values in opts, if required */
opts = usersubst(opts);
/* Merge the fstab and command line options. */
if (opts == NULL)
opts = cmdlineopts;
else if (cmdlineopts != NULL)
opts = xstrconcat3(opts, ",", cmdlineopts);
/* Merge the fstab and command line options. */
if (opts == NULL)
opts = cmdlineopts;
else if (cmdlineopts != NULL)
opts = xstrconcat3(opts, ",", cmdlineopts);
/* Handle possible LABEL= and UUID= forms of spec */
nspec = mount_get_devname_for_mounting(spec);
if (nspec)
spec = nspec;
/* Handle possible LABEL= and UUID= forms of spec */
nspec = mount_get_devname_for_mounting(spec);
if (nspec)
spec = nspec;
if (types == NULL && !mounttype && !is_existing_file(spec)) {
if (strchr (spec, ':') != NULL) {
types = "nfs";
if (verbose)
printf(_("mount: no type was given - "
"I'll assume nfs because of the colon\n"));
} else if(!strncmp(spec, "//", 2)) {
types = "smbfs";
if (verbose)
printf(_("mount: no type was given - "
"I'll assume smbfs because of the // prefix\n"));
}
}
if (types == NULL && !mounttype && !is_existing_file(spec)) {
if (strchr (spec, ':') != NULL) {
types = "nfs";
if (verbose)
printf(_("mount: no type was given - "
"I'll assume nfs because of "
"the colon\n"));
} else if(!strncmp(spec, "//", 2)) {
types = "smbfs";
if (verbose)
printf(_("mount: no type was given - "
"I'll assume smbfs because of "
"the // prefix\n"));
}
}
/*
* Try to mount the file system. When the exit status is EX_BG,
* we will retry in the background. Otherwise, we're done.
*/
status = try_mount_one (spec, node, types, opts, freq, pass, 0, 0);
if (status != EX_BG)
return status;
/*
* Try to mount the file system. When the exit status is EX_BG,
* we will retry in the background. Otherwise, we're done.
*/
status = try_mount_one (spec, node, types, opts, freq, pass, 0, 0);
if (status != EX_BG)
return status;
/*
* Retry in the background.
*/
printf (_("mount: backgrounding \"%s\"\n"), spec);
fflush( stdout ); /* prevent duplicate output */
if (fork() > 0)
return 0; /* parent returns "success" */
spec = xstrdup(spec); /* arguments will be destroyed */
node = xstrdup(node); /* by set_proc_name() */
types = xstrdup(types);
opts = xstrdup(opts);
set_proc_name (spec); /* make a nice "ps" listing */
status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0);
if (verbose && status2)
printf (_("mount: giving up \"%s\"\n"), spec);
exit (0); /* child stops here */
/*
* Retry in the background.
*/
printf (_("mount: backgrounding \"%s\"\n"), spec);
fflush( stdout ); /* prevent duplicate output */
if (fork() > 0)
return 0; /* parent returns "success" */
spec = xstrdup(spec); /* arguments will be destroyed */
node = xstrdup(node); /* by set_proc_name() */
types = xstrdup(types);
opts = xstrdup(opts);
set_proc_name (spec); /* make a nice "ps" listing */
status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0);
if (verbose && status2)
printf (_("mount: giving up \"%s\"\n"), spec);
exit (0); /* child stops here */
}
/* Check if an fsname/dir pair was already in the old mtab. */
@ -1177,6 +1209,8 @@ mounted (const char *spec0, const char *node0) {
/* Handle possible UUID= and LABEL= in spec */
spec0 = mount_get_devname(spec0);
if (!spec0)
return ret;
spec = canonicalize(spec0);
node = canonicalize(node0);
@ -1189,8 +1223,8 @@ mounted (const char *spec0, const char *node0) {
break;
}
free(spec);
free(node);
my_free(spec);
my_free(node);
return ret;
}
@ -1407,14 +1441,17 @@ usage (FILE *fp, int n) {
exit (n);
}
char *progname;
int
main (int argc, char *argv[]) {
main(int argc, char *argv[]) {
int c, result = 0, specseen;
char *options = NULL, *test_opts = NULL, *node;
const char *spec;
char *volumelabel = NULL;
char *uuid = NULL;
char *types = NULL;
char *p;
struct mntentchn *mc;
int fd;
@ -1423,6 +1460,10 @@ main (int argc, char *argv[]) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
umask(033);
/* People report that a mount called from init without console

View File

@ -57,7 +57,7 @@ mount_blkid_put_cache(void) {
const char *
mount_get_volume_label_by_spec(const char *spec) {
return strdup(get_volume_label_by_spec(spec));
return xstrdup(get_volume_label_by_spec(spec));
}
const char *

View File

@ -94,7 +94,7 @@ uuidcache_init_lvm(void) {
sprintf(lvm_device, "%s/%s/%s", DEVLABELDIR,
vg_iter->d_name, lv_iter->d_name);
if (!get_label_uuid(lvm_device, &label, uuid))
uuidcache_addentry(strdup(lvm_device),
uuidcache_addentry(xstrdup(lvm_device),
label, uuid);
}
closedir(lv_list);
@ -117,7 +117,7 @@ uuidcache_init_evms(void) {
while (fgets(line, sizeof(line), procvol)) {
if (sscanf(line, "%*d %*d %*d %*s %*s %[^\n]", volname) == 1) {
if (!get_label_uuid(volname, &label, uuid))
uuidcache_addentry(strdup(volname), label, uuid);
uuidcache_addentry(xstrdup(volname), label, uuid);
}
}
@ -243,7 +243,7 @@ uuidcache_init(void) {
*/
sprintf(device, "%s/%s", DEVLABELDIR, ptname);
if (!get_label_uuid(device, &label, uuid))
uuidcache_addentry(strdup(device), label, uuid);
uuidcache_addentry(xstrdup(device), label, uuid);
}
}
}

View File

@ -559,7 +559,7 @@ procfsnext(FILE *procfs) {
while (fgets(line, sizeof(line), procfs)) {
if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
return strdup(fsname);
return xstrdup(fsname);
}
return 0;
}

View File

@ -60,7 +60,7 @@ rootdev(char *p) {
sprintf(devname, "/dev/%s%c", type, let);
else
sprintf(devname, "/dev/%s%c%d", type, let, mi);
return strdup(devname);
return xstrdup(devname);
}
return NULL;
}

View File

@ -80,8 +80,8 @@ Not available before Linux 2.1.25.
.B \-a
All devices marked as ``swap'' swap devices in
.I /etc/fstab
are made available. Devices that are already running as swap are silently
skipped.
are made available, except for those with the ``noauto'' option.
Devices that are already running as swap are silently skipped.
.TP
.B \-e
When

View File

@ -315,6 +315,7 @@ main_swapon(int argc, char *argv[]) {
}
while ((fstab = getmntent(fp)) != NULL) {
char *special = fstab->mnt_fsname;
int skip = 0;
if (streq(fstab->mnt_type, MNTTYPE_SWAP) &&
!is_in_proc_swaps(special)
@ -323,10 +324,14 @@ main_swapon(int argc, char *argv[]) {
char *opt, *opts = strdup(fstab->mnt_opts);
for (opt = strtok(opts, ","); opt != NULL;
opt = strtok(NULL, ","))
opt = strtok(NULL, ",")) {
if (strncmp(opt, "pri=", 4) == 0)
priority = atoi(opt+4);
status |= do_swapon(special, priority);
if (strcmp(opt, "noauto") == 0)
skip = 1;
}
if (!skip)
status |= do_swapon(special, priority);
}
}
fclose(fp);

View File

@ -74,6 +74,9 @@ In case unmounting fails, try to remount read-only.
In case the unmounted device was a loop device, also
free this loop device.
.TP
.B \-i
Don't call the /sbin/umount.<filesystem> helper even if it exists. By default /sbin/umount.<filesystem> helper is called if one exists.
.TP
.B \-a
All of the file systems described in
.I /etc/mtab

View File

@ -1,32 +1,5 @@
/*
* A umount(8) for Linux 0.99.
* umount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*
* Wed Sep 14 22:43:54 1994: Sebastian Lederer
* (lederer@next-pc.informatik.uni-bonn.de) added support for sending an
* unmount RPC call to the server when an NFS-filesystem is unmounted.
*
* Tue Sep 26 16:33:09 1995: Added patches from Greg Page (greg@caldera.com)
* so that NetWare filesystems can be unmounted.
*
* 951213: Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>:
* Ignore any RPC errors, so that you can umount an nfs mounted filesystem
* if the server is down.
*
* 960223: aeb - several minor changes
* 960324: aeb - added some changes from Rob Leslie <rob@mars.org>
* 960823: aeb - also try umount(spec) when umount(node) fails
* 970307: aeb - canonicalise names from fstab
* 970726: aeb - remount read-only in cases where umount fails
* 980810: aeb - umount2 support
* 981222: aeb - If mount point or special file occurs several times
* in mtab, try them all, with last one tried first
* - Differentiate "user" and "users" key words in fstab
* 001202: aeb - remove at most one line from /etc/mtab
* 010716: Michael K. Johnson <johnsonm@redhat.com: -a -O
* 010914: Jamie Strandboge - use tcp if that was used for mount
* 011005: hch - add lazy umount support
* 020105: aeb - permission test owner umount
* umount(8) for Linux 0.99 - jrs, 1993
*/
#include <stdio.h>
@ -36,6 +9,7 @@
#include <errno.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include "mount_constants.h"
#include "sundries.h"
@ -91,6 +65,10 @@ umount2(const char *path, int flags) {
#define MNT_DETACH 2
#endif
/* True if we are allowed to call /sbin/umount.${FSTYPE} */
int external_allowed = 1;
/* Nonzero for force umount (-f). There is kernel support since 2.1.116. */
int force = 0;
@ -112,15 +90,61 @@ int verbose = 0;
/* True if ruid != euid. */
int suid = 0;
#ifdef USE_SPECIAL_UMOUNTPROG
/* unimplemented so far */
/*
* check_special_umountprog()
* If there is a special umount program for this type, exec it.
* returns: 0: no exec was done, 1: exec was done, status has result
*/
static int
check_special_umountprog() {
/* find type from command line or /etc/mtab;
stat /sbin/umount.%s
if it exists, use it */
check_special_umountprog(const char *spec, const char *node,
const char *type, int *status) {
char umountprog[120];
struct stat statbuf;
int res;
if (!external_allowed)
return 0;
if (type && strlen(type) < 100) {
sprintf(umountprog, "/sbin/umount.%s", type);
if (stat(umountprog, &statbuf) == 0) {
res = fork();
if (res == 0) {
char *umountargs[8];
int i = 0;
setuid(getuid());
setgid(getgid());
umountargs[i++] = umountprog;
umountargs[i++] = xstrdup(node);
if (nomtab)
umountargs[i++] = "-n";
if (lazy)
umountargs[i++] = "-l";
if (force)
umountargs[i++] = "-f";
if (verbose)
umountargs[i++] = "-v";
if (remount)
umountargs[i++] = "-r";
umountargs[i] = NULL;
execv(umountprog, umountargs);
exit(1); /* exec failed */
} else if (res != -1) {
int st;
wait(&st);
*status = (WIFEXITED(st) ? WEXITSTATUS(st)
: EX_SYSERR);
return 1;
} else {
int errsv = errno;
error(_("umount: cannot fork: %s"),
strerror(errsv));
}
}
}
return 0;
}
#endif
#ifdef HAVE_NFS
static int xdr_dir(XDR *xdrsp, char *dirp)
@ -248,6 +272,7 @@ umount_one (const char *spec, const char *node, const char *type,
int umnt_err, umnt_err2;
int isroot;
int res;
int status;
const char *loopdev;
/* Special case for root. As of 0.99pl10 we can (almost) unmount root;
@ -260,6 +285,13 @@ umount_one (const char *spec, const char *node, const char *type,
|| streq (node, "rootfs"));
if (isroot)
nomtab++;
/*
* Call umount.TYPE for types that require a separate umount program.
* All such special things must occur isolated in the types string.
*/
if (check_special_umountprog(spec, node, type, &status))
return status;
#ifdef HAVE_NFS
/* Ignore any RPC errors, so that you can umount the filesystem
@ -322,7 +354,7 @@ umount_one (const char *spec, const char *node, const char *type,
spec);
remnt.mnt_type = remnt.mnt_fsname = NULL;
remnt.mnt_dir = xstrdup(node);
remnt.mnt_opts = "ro";
remnt.mnt_opts = xstrdup("ro");
update_mtab(node, &remnt);
return 0;
} else if (errno != EBUSY) { /* hmm ... */
@ -514,7 +546,8 @@ static int
umount_file (char *arg) {
struct mntentchn *mc, *fs;
const char *file, *options;
int fstab_has_user, fstab_has_users, fstab_has_owner, ok;
int fstab_has_user, fstab_has_users, fstab_has_owner, fstab_has_group;
int ok;
file = canonicalize(arg); /* mtab paths are canonicalized */
if (verbose > 1)
@ -556,16 +589,17 @@ umount_file (char *arg) {
"the fstab"), file);
}
/* User mounting and unmounting is allowed only
if fstab contains one of the options `user',
`users' or `owner'. */
/* The option `users' allows arbitrary users to mount
and unmount - this may be a security risk. */
/* The option `user' only allows unmounting by the user
that mounted. */
/* The option `owner' only allows (un)mounting by the owner. */
/* A convenient side effect is that the user who mounted
is visible in mtab. */
/*
* User mounting and unmounting is allowed only
* if fstab contains one of the options `user',
* `users' or `owner' or `group'.
*
* The option `users' allows arbitrary users to mount
* and unmount - this may be a security risk.
*
* The options `user', `owner' and `group' only allow
* unmounting by the user that mounted (visible in mtab).
*/
options = fs->m.mnt_opts;
if (!options)
@ -573,12 +607,14 @@ umount_file (char *arg) {
fstab_has_user = contains(options, "user");
fstab_has_users = contains(options, "users");
fstab_has_owner = contains(options, "owner");
fstab_has_group = contains(options, "group");
ok = 0;
if (fstab_has_users)
ok = 1;
if (!ok && (fstab_has_user || fstab_has_owner)) {
if (!ok && (fstab_has_user || fstab_has_owner ||
fstab_has_group)) {
char *user = getusername();
options = mc->m.mnt_opts;
@ -601,11 +637,13 @@ umount_file (char *arg) {
return umount_one (arg, arg, arg, arg, NULL);
}
char *progname;
int
main (int argc, char *argv[]) {
int c;
int all = 0;
char *types = NULL, *test_opts = NULL;
char *types = NULL, *test_opts = NULL, *p;
int result = 0;
sanitize_env();
@ -613,9 +651,13 @@ main (int argc, char *argv[]) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
umask(033);
while ((c = getopt_long (argc, argv, "adfhlnrt:O:vV",
while ((c = getopt_long (argc, argv, "adfhlnrit:O:vV",
longopts, NULL)) != -1)
switch (c) {
case 'a': /* umount everything */
@ -652,6 +694,9 @@ main (int argc, char *argv[]) {
case 't': /* specify file system type */
types = optarg;
break;
case 'i':
external_allowed = 0;
break;
case 0:
break;
case '?':

1351
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1351
po/cs.po

File diff suppressed because it is too large Load Diff

1779
po/da.po

File diff suppressed because it is too large Load Diff

1351
po/de.po

File diff suppressed because it is too large Load Diff

1351
po/es.po

File diff suppressed because it is too large Load Diff

1349
po/et.po

File diff suppressed because it is too large Load Diff

1351
po/fi.po

File diff suppressed because it is too large Load Diff

1365
po/fr.po

File diff suppressed because it is too large Load Diff

1351
po/it.po

File diff suppressed because it is too large Load Diff

1351
po/ja.po

File diff suppressed because it is too large Load Diff

1351
po/nl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1356
po/sl.po

File diff suppressed because it is too large Load Diff

1351
po/sv.po

File diff suppressed because it is too large Load Diff

1351
po/tr.po

File diff suppressed because it is too large Load Diff

1351
po/uk.po

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ include ../MCONFIG
# Where to put man pages?
MAN1= arch.1 readprofile.1
MAN1= arch.1 flock.1 readprofile.1
MAN8= ctrlaltdel.8 cytune.8 dmesg.8 \
ipcrm.8 ipcs.8 renice.8 \
@ -19,7 +19,7 @@ MAN8= ctrlaltdel.8 cytune.8 dmesg.8 \
BIN= arch dmesg
USRBIN= cytune ipcrm ipcs renice setsid
USRBIN= cytune flock ipcrm ipcs renice setsid
USRSBIN= readprofile tunelp

45
sys-utils/flock.1 Normal file
View File

@ -0,0 +1,45 @@
.TH FLOCK "1" "November 2004" "flock (util-linux)" "User Commands"
.SH NAME
flock \- acquire a file lock and then execute a command with the lock held
.SH SYNOPSIS
.BR flock
[ \fB\-\-shared\fR | \fB\-\-timeout=\fR\fIseconds\fR ] lockfile command ..
.SH DESCRIPTION
.\" Add any additional description here
.PP
Acquire a file lock using the flock(2) system call and then execute
the given command with the lock held. Depending on the options given,
the lock can be either exclusive or shared, and the behavior in the
event of lock contention can be specified as either waiting
indefinitely for the lock to become available (the default), or
failing if the lock does not become available after a specific time,
which can be specified as zero to make the command not wait at all.
.PP
.TP
\fB\-\-shared\fR
Acquire a shared lock. Acquiring a shared lock does
not stop others from acquiring a shared lock, but it will stop others
from acquiring an exclusive lock. Conversely, acquiring an exclusive
lock (the default) stops both exclusive and shared attempts to acquire
the lock. Typically, a shared lock is used if a command is just going
to read the locked data, and an exclusive lock is used if the command
might write to it.
.TP
\fB\-\-timeout=n\fR
Abort if the lock cannot be acquired before \fIn\fR seconds.
For a completely non-blocking attempt to acquire a lock, specify
\fB\-\-timeout=0\fR.
The timer applies only to the attempt to acquire the lock. As soon
as the lock is acquired, the timeout is cancelled. The command to
be run is not subject to the timeout.
.PP
.SH "EXAMPLES (invoking some imaginary programs)"
.hl
.PP
flock /etc/passwd read-and-write-to-passwd
.PP
flock \-\-shared /etc/passwd just-read-something-from-passwd
.PP
flock \-\-timeout=0 /sys /usr/local/bin/update-hotplug /sys
.SH AUTHOR
Written by Adam J. Richter

116
sys-utils/flock.c Normal file
View File

@ -0,0 +1,116 @@
/*
flock - acquires a file lock and executes a command with the lock held.
Usage: flock [--shared | --timeout=seconds] lockfile program [args...]
Written by Adam J. Richter
Copyright (C) 2004 Yggdrasil Computing, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/file.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <signal.h> /* kill */
#include <stdio.h>
#include "nls.h"
static int non_blocking = 0;
static int shared = LOCK_EX;
static const struct option options[] = {
{"shared", no_argument, &shared, LOCK_SH },
{"timeout", required_argument, NULL, 't' },
{NULL, 0, NULL, 0 },
};
int main(int argc, char **argv)
{
int fd;
int opt;
int pid;
int child_status;
int option_index;
int timeout = 0;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
do {
opt = getopt_long(argc, argv, "+", options, &option_index);
switch(opt) {
case '?':
fprintf (stderr,
_("flock: unknown option, aborting.\n"));
exit(1);
break;
case 't':
timeout = atoi(optarg);
if (timeout == 0)
non_blocking |= LOCK_NB;
break;
default:
break;
}
} while (opt != -1);
argc -= optind;
argv += optind;
if (argc < 2) {
fprintf(stderr,
_("Usage flock [--shared | --timeout=seconds] "
"filename command {arg arg...}\n"));
exit(2);
}
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
perror(argv[0]);
exit(3);
}
alarm(timeout);
if (flock(fd, shared | non_blocking) != 0) {
perror("flock");
exit(4);
}
alarm(0);
pid = fork();
if (pid < 0) {
perror("fork");
exit(5);
}
if (pid == 0) {
execvp(argv[1], argv+1);
perror(argv[1]);
exit(6);
}
waitpid(pid, &child_status, 0);
/* flock(fd, LOCK_UN); */
/* No need to explicitly release the flock, since we are just
going to exit now anyhow. */
/* Lame attempt to simulate child's mode of death. */
if (WIFSIGNALED(child_status))
kill(0, WTERMSIG(child_status));
return WEXITSTATUS(child_status);
}

View File

@ -388,6 +388,10 @@ main(int argc, char **argv) {
maplineno++;
}
/* clock ticks, out of kernel text - probably modules */
printf("%6i %s\n", buf[len/sizeof(*buf)-1], "*unknown*");
/* trailer */
if (optVerbose)
printf("%016x %-40s %6i %8.4f\n",

View File

@ -70,6 +70,9 @@
#define Fseek(f,off) (file_pos=off,fseek(f,off,0))
#define Getc(f) (++file_pos, getc(f))
#define Ungetc(c,f) (--file_pos, ungetc(c,f))
#define putcerr(c) fputc(c, stderr)
#define putserr(s) fputs(s, stderr)
#define putsout(s) fputs(s, stdout)
#define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
@ -94,8 +97,6 @@ void screen (register FILE *f, register int num_lines);
int command (char *filename, register FILE *f);
void erasep (register int col);
void show (register char ch);
int pr(char *s1);
int printd (int n);
void set_tty(void);
void reset_tty(void);
void ttyin (unsigned char buf[], register int nmax, char pchar);
@ -103,10 +104,7 @@ int number(char *cmd);
int readch (void);
int get_line(register FILE *f, int *length);
void prbuf (register char *s, register int n);
int xprintf (char *fmt, ...);
void execute (char *filename, char *cmd, ...);
void errwrite (char *txt);
void errwrite1 (char *sym);
FILE *checkf (char *, int *);
#define TBUFSIZ 1024
@ -182,7 +180,7 @@ extern char PC; /* pad character */
static void
my_putstring(char *s) {
putp(s);
tputs (s, 1, putchar); /* putp(s); */
}
static void
@ -412,14 +410,14 @@ int main(int argc, char **argv) {
erasep (0);
if (clreol)
cleareol ();
pr("::::::::::::::");
putsout("::::::::::::::");
if (promptlen > 14)
erasep (14);
xprintf ("\n");
putchar('\n');
if(clreol) cleareol();
xprintf("%s\n", fnames[fnum]);
puts(fnames[fnum]);
if(clreol) cleareol();
xprintf("::::::::::::::\n");
puts("::::::::::::::");
if (left > Lpp - 4)
left = Lpp - 4;
}
@ -483,10 +481,8 @@ void argscan(char *s, char *argv0) {
case '-': case ' ': case '\t':
break;
default:
fputs(argv0,stderr);
fputs(": unknown option \"-",stderr);
putc(*s,stderr);
fputs("\"\n",stderr);
fprintf(stderr,
_("%s: unknown option \"-%c\"\n"), argv0, *s);
usage(argv0);
exit(1);
break;
@ -518,7 +514,7 @@ checkf (fs, clearfirst)
return((FILE *)NULL);
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
xprintf(_("\n*** %s: directory ***\n\n"), fs);
printf(_("\n*** %s: directory ***\n\n"), fs);
return((FILE *)NULL);
}
if ((f = Fopen(fs, "r")) == NULL) {
@ -561,7 +557,7 @@ magic(f, fs)
case 0411:
case 0177545:
case 0x457f: /* simple ELF detection */
xprintf(_("\n******** %s: Not a text file ********\n\n"), fs);
printf(_("\n******** %s: Not a text file ********\n\n"), fs);
(void)fclose(f);
return(1);
}
@ -664,9 +660,7 @@ void onquit(int dummy) {
Pause++;
}
else if (!dum_opt && notell) {
char *s = _("[Use q or Q to quit]");
errwrite(s);
promptlen += strlen(s);
promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
notell = 0;
}
signal(SIGQUIT, onquit);
@ -712,7 +706,7 @@ void end_it (int dummy) {
fflush (stdout);
}
else
errwrite("\n");
putcerr('\n');
_exit(0);
}
@ -723,93 +717,7 @@ void copy_file(register FILE *f) {
putchar(c);
}
/* Simplified printf function */
int xprintf (char *fmt, ...) {
va_list ap;
char ch;
int ccount;
ccount = 0;
va_start(ap, fmt);
while (*fmt) {
while ((ch = *fmt++) != '%') {
if (ch == '\0')
return (ccount);
ccount++;
putchar (ch);
}
switch (*fmt++) {
case 'd':
ccount += printd (va_arg(ap, int));
break;
case 's':
ccount += pr (va_arg(ap, char *));
break;
case '%':
ccount++;
putchar ('%');
break;
case '0':
return (ccount);
default:
break;
}
}
va_end(ap);
return (ccount);
}
/*
** Print an integer as a string of decimal digits,
** returning the length of the print representation.
*/
int printd (int n)
{
int a, nchars;
if ((a = n/10) != 0)
nchars = 1 + printd(a);
else
nchars = 1;
putchar (n % 10 + '0');
return (nchars);
}
/* Put the print representation of an integer into a string */
static char *sptr;
static void Sprintf (int n) {
int a;
if ((a = n/10) != 0)
Sprintf (a);
*sptr++ = n % 10 + '0';
}
static void scanstr (int n, char *str)
{
sptr = str;
Sprintf (n);
*sptr = '\0';
}
#define ringbell() errwrite("\007");
#ifdef undef
strlen (s)
char *s;
{
register char *p;
p = s;
while (*p++)
;
return (p - s - 1);
}
#endif
#define ringbell() putcerr('\007')
/* See whether the last component of the path name "path" is equal to the
** string "string"
@ -844,15 +752,14 @@ static void prompt (char *filename)
}
if (clreol)
cleareol ();
promptlen += pr(_("--More--"));
promptlen += printf(_("--More--"));
if (filename != NULL) {
promptlen += xprintf (_("(Next file: %s)"), filename);
promptlen += printf(_("(Next file: %s)"), filename);
} else if (!no_intty) {
promptlen += xprintf ("(%d%%)",
(int)((file_pos * 100) / file_size));
promptlen += printf("(%d%%)", (int) ((file_pos * 100) / file_size));
}
if (dum_opt) {
promptlen += pr(_("[Press space to continue, 'q' to quit.]"));
promptlen += printf(_("[Press space to continue, 'q' to quit.]"));
}
if (Senter && Sexit)
my_putstring (Sexit);
@ -1119,21 +1026,6 @@ void clreos()
my_putstring(EodClr);
}
/*
** Print string and return number of characters
*/
int pr(char *s1)
{
register char *s;
register char c;
for (s = s1; (c = *s++) != 0; )
putchar(c);
return (int) (s - s1 - 1);
}
/* Print a buffer of n characters */
void prbuf (register char *s, register int n)
@ -1165,7 +1057,7 @@ void prbuf (register char *s, register int n)
if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0)
putchar(c);
if (state && *chUL) {
pr(chBS);
putsout(chBS);
my_putstring(chUL);
}
pstate = state;
@ -1262,16 +1154,16 @@ int command (char *filename, register FILE *f)
putchar ('\r');
erasep (0);
xprintf ("\n");
putchar('\n');
if (clreol)
cleareol ();
if (nlines != 1)
xprintf (_("...back %d pages"), nlines);
printf(_("...back %d pages"), nlines);
else
xprintf (_("...back 1 page"));
putsout(_("...back 1 page"));
if (clreol)
cleareol ();
pr ("\n");
putchar('\n');
initline = Currline - dlines * (nlines + 1);
if (! noscroll)
@ -1307,17 +1199,17 @@ int command (char *filename, register FILE *f)
nlines *= dlines;
putchar ('\r');
erasep (0);
xprintf ("\n");
putchar('\n');
if (clreol)
cleareol ();
if (nlines == 1)
xprintf (_("...skipping one line"));
putsout(_("...skipping one line"));
else
xprintf (_("...skipping %d lines"), nlines);
printf(_("...skipping %d lines"), nlines);
if (clreol)
cleareol ();
pr ("\n");
putchar('\n');
while (nlines > 0) {
while ((c = Getc (f)) != '\n')
@ -1350,7 +1242,7 @@ int command (char *filename, register FILE *f)
case '\'':
if (!no_intty) {
kill_line ();
pr (_("\n***Back***\n\n"));
putsout(_("\n***Back***\n\n"));
Fseek (f, context.chrctr);
Currline = context.line;
ret (dlines);
@ -1361,7 +1253,7 @@ int command (char *filename, register FILE *f)
}
case '=':
kill_line ();
promptlen = printd (Currline);
promptlen = printf("%d", Currline);
fflush (stdout);
break;
case 'n':
@ -1369,16 +1261,16 @@ int command (char *filename, register FILE *f)
case '/':
if (nlines == 0) nlines++;
kill_line ();
pr ("/");
putchar('/');
promptlen = 1;
fflush (stdout);
if (lastp) {
errwrite ("\r");
putcerr('\r');
search (NULL, f, nlines); /* Use previous r.e. */
}
else {
ttyin (cmdbuf, sizeof(cmdbuf)-2, '/');
errwrite("\r");
putcerr('\r');
search (cmdbuf, f, nlines);
}
ret (dlines-1);
@ -1388,13 +1280,13 @@ int command (char *filename, register FILE *f)
case '?':
case 'h':
if (noscroll) doclear();
xprintf(_("\n"
putsout(_("\n"
"Most commands optionally preceded by integer argument k. "
"Defaults in brackets.\n"
"Star (*) indicates argument becomes new default.\n"));
xprintf("---------------------------------------"
"----------------------------------------\n");
xprintf(_(
puts("---------------------------------------"
"----------------------------------------");
putsout(_(
"<space> Display next k lines of text [current screen size]\n"
"z Display next k lines of text [current screen size]*\n"
"<return> Display next k lines of text [1]*\n"
@ -1414,8 +1306,8 @@ int command (char *filename, register FILE *f)
":p Go to kth previous file [1]\n"
":f Display current file name and line number\n"
". Repeat previous command\n"));
xprintf("---------------------------------------"
"----------------------------------------\n");
puts("---------------------------------------"
"----------------------------------------");
prompt(filename);
break;
case 'v': /* This case should go right before default */
@ -1441,17 +1333,14 @@ int command (char *filename, register FILE *f)
else
p = editor;
if (!strcmp(p, "vi") || !strcmp(p, "ex")) {
strcpy(cmdbuf, "-c ");
scanstr(n, &cmdbuf[3]);
sprintf(cmdbuf, "-c %d", n);
split = 1;
} else {
cmdbuf[0] = '+';
scanstr(n, &cmdbuf[1]);
sprintf(cmdbuf, "+%d", n);
}
kill_line();
pr(editor); putchar(' ');
pr(cmdbuf); putchar(' '); pr(fnames[fnum]);
printf("%s %s %s", editor, cmdbuf, fnames[fnum]);
if (split) {
cmdbuf[2] = 0;
execute(filename, editor, editor, cmdbuf,
@ -1467,12 +1356,12 @@ int command (char *filename, register FILE *f)
kill_line ();
if (Senter && Sexit) {
my_putstring (Senter);
promptlen = pr (_("[Press 'h' for instructions.]"))
promptlen = printf(_("[Press 'h' for instructions.]"))
+ 2 * soglitch;
my_putstring (Sexit);
}
else
promptlen = pr (_("[Press 'h' for instructions.]"));
promptlen = printf(_("[Press 'h' for instructions.]"));
fflush (stdout);
}
else
@ -1506,9 +1395,9 @@ int colon (char *filename, int cmd, int nlines) {
case 'f':
kill_line ();
if (!no_intty)
promptlen = xprintf (_("\"%s\" line %d"), fnames[fnum], Currline);
promptlen = printf(_("\"%s\" line %d"), fnames[fnum], Currline);
else
promptlen = xprintf (_("[Not a file] line %d"), Currline);
promptlen = printf(_("[Not a file] line %d"), Currline);
fflush (stdout);
return (-1);
case 'n':
@ -1575,11 +1464,11 @@ void do_shell (char *filename)
char *expanded;
kill_line ();
pr ("!");
putchar('!');
fflush (stdout);
promptlen = 1;
if (lastp)
pr (shell_line);
putsout(shell_line);
else {
ttyin (cmdbuf, sizeof(cmdbuf)-2, '!');
expanded = 0;
@ -1592,16 +1481,16 @@ void do_shell (char *filename)
free(expanded);
}
if (rc < 0) {
errwrite(_(" Overflow\n"));
putserr(_(" Overflow\n"));
prompt (filename);
return;
} else if (rc > 0) {
kill_line ();
promptlen = xprintf ("!%s", shell_line);
promptlen = printf("!%s", shell_line);
}
}
fflush (stdout);
errwrite("\n");
putcerr('\n');
promptlen = 0;
shellp = 1;
execute (filename, shell, shell, "-c", shell_line, 0);
@ -1636,10 +1525,10 @@ void search(char buf[], FILE *file, register int n)
if (--n == 0) {
if (lncount > 3 || (lncount > 1 && no_intty))
{
pr ("\n");
putchar('\n');
if (clreol)
cleareol ();
pr(_("...skipping\n"));
putsout(_("...skipping\n"));
}
if (!no_intty) {
Currline -= (lncount >= 3 ? 3 : lncount);
@ -1663,8 +1552,7 @@ void search(char buf[], FILE *file, register int n)
else
doclear ();
}
pr (Line);
putchar ('\n');
puts(Line);
}
break;
}
@ -1681,7 +1569,7 @@ void search(char buf[], FILE *file, register int n)
Fseek (file, startline);
}
else {
pr (_("\nPattern not found\n"));
putsout(_("\nPattern not found\n"));
end_it (0);
}
error (_("Pattern not found"));
@ -1731,7 +1619,7 @@ void execute (char *filename, char *cmd, ...)
va_end(argp);
execvp (cmd, args);
errwrite(_("exec failed\n"));
putserr(_("exec failed\n"));
exit (1);
}
if (id > 0) {
@ -1745,9 +1633,9 @@ void execute (char *filename, char *cmd, ...)
if (catch_susp)
signal(SIGTSTP, onsusp);
} else
errwrite(_("can't fork\n"));
putserr(_("can't fork\n"));
set_tty ();
pr ("------------------------\n");
puts("------------------------");
prompt (filename);
}
/*
@ -1784,19 +1672,17 @@ void skipf (register int nskip)
fnum += nskip;
if (fnum < 0)
fnum = 0;
pr (_("\n...Skipping "));
pr ("\n");
puts(_("\n...Skipping "));
if (clreol)
cleareol ();
if (nskip > 0)
pr (_("...Skipping to file "));
putsout(_("...Skipping to file "));
else
pr (_("...Skipping back to file "));
pr (fnames[fnum]);
pr ("\n");
putsout(_("...Skipping back to file "));
puts(fnames[fnum]);
if (clreol)
cleareol ();
pr ("\n");
putchar('\n');
--fnum;
}
@ -1946,9 +1832,9 @@ static char *BSB = "\b \b";
static char *CARAT = "^";
#define ERASEONECOLUMN \
if (docrterase) \
errwrite(BSB); \
putserr(BSB); \
else \
errwrite(BS);
putserr(BS);
void ttyin (unsigned char buf[], register int nmax, char pchar) {
unsigned char *sp;
@ -2040,7 +1926,7 @@ void ttyin (unsigned char buf[], register int nmax, char pchar) {
erasep (1);
else if (docrtkill)
while (promptlen-- > 1)
errwrite(BSB);
putserr(BSB);
promptlen = 1;
}
sp = buf;
@ -2057,12 +1943,11 @@ void ttyin (unsigned char buf[], register int nmax, char pchar) {
*sp++ = c;
if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
c += (c == RUBOUT) ? -0100 : 0100;
errwrite(CARAT);
putserr(CARAT);
promptlen++;
}
if (c != '\n' && c != ESC) {
char cbuf = c;
errwrite1(&cbuf);
putcerr(c);
promptlen++;
}
else
@ -2134,28 +2019,15 @@ int expand (char **outbuf, char *inbuf) {
}
void show (char c) {
char cbuf;
if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
c += (c == RUBOUT) ? -0100 : 0100;
errwrite(CARAT);
putserr(CARAT);
promptlen++;
}
cbuf = c;
errwrite1(&cbuf);
putcerr(c);
promptlen++;
}
void errwrite (char *txt)
{
write (fileno(stderr), txt, strlen(txt));
}
void errwrite1 (char *sym)
{
write (fileno(stderr), sym, 1);
}
void error (char *mess)
{
if (clreol)
@ -2165,11 +2037,11 @@ void error (char *mess)
promptlen += strlen (mess);
if (Senter && Sexit) {
my_putstring (Senter);
pr(mess);
putsout(mess);
my_putstring (Sexit);
}
else
pr (mess);
putsout(mess);
fflush(stdout);
errors++;
siglongjmp (restore, 1);
@ -2185,7 +2057,7 @@ void set_tty () {
static int
ourputch(int c) {
return putc(c, stdout);
return putc(c, stdout);
}
void
@ -2193,7 +2065,7 @@ reset_tty () {
if (no_tty)
return;
if (pstate) {
tputs(ULexit, 1, ourputch);
tputs(ULexit, 1, ourputch); /* putchar - if that isnt a macro */
fflush(stdout);
pstate = 0;
}