Bernhard Reutner-Fischer schrieb:
> On Sun, Feb 01, 2009 at 08:02:48PM +0100, walter harms wrote:
>> Hi list,
>> this is latest version of a SUSv3 compliant busybox who
>> i have replaced option_mask32 with a local opt. The save is impressiv.
>>
>> re,
>> wh
>>
>>
>>
>> Final link with: <none>
>> function old new delta
>> .rodata 1434 1418 -16
>> who_main 1237 1168 -69
>> ------------------------------------------------------------------------------
>> (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-85) Total: -85
>> bytes
>>
>
> Looks nice, size-wise :)
>> /* vi: set sw=4 ts=4: */
>> /*
>> * SUSv3 who implementation for busybox
>
> The current standard is SUSv4, fwiw.
>
>> *
>> * Copyright (C) 2008 by <[email protected]>
>
> missing real name
>
>> * http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html
>
> wrong URL. The SUSv4 one for who would be
> http://www.opengroup.org/onlinepubs/9699919799/utilities/who.html
>
i work after that specs, did they change something ?
>> *
>> * BB_AUDIT SUSv3 defects - missing long options
>
> I do not see any long options mentioned in the standard?
>
> But i do see 'who am i' in the standard but not handled below?
>
>> * Licensed under GPLv2 or later, see file LICENSE in this tarball for
>> details.
>> * $Id: who.c,v 1.14 2009/01/30 20:31:25 walter Exp walter $
>
> please remove that $Id
>
please after this is moved to bb svn. it is my cvs and i need them to keep track
about the changes.
>> */
>>
>> #include "libbb.h"
>> #include <utmp.h>
>>
>> #define ENABLE_FEATURE_GLOBAL_BUFFER 0
>> #define ENABLE_FEATURE_POSIX_TIMEFMT 0
>>
>> #if ENABLE_FEATURE_POSIX_TIMEFMT
>> #define TIMEFMT "%b %e %H:%M"
>> #else
>> #define TIMEFMT "%Y-%m-%d %T"
>> #endif
>>
>> /*
>> who -q file
>> who [-mu]-s[-bHlprt][<file>]
>> -a enables: -b,-d, -l, -p, -r, -t, -T and -u
>> no support for 'who am i' or 'mon loves'
>
> ah, ok. The helptext in the config should mention that too.
i hope to add this for 1.0 but first the functions should work
i will fix also "mom loves".
>> */
>>
>> // "%b %e %H:%M"
>> //
>> // char bb_common_bufsiz1[COMMON_BUFSIZE]
>> // move this to libbb ??
>>
>>
>> #if ENABLE_FEATURE_GLOBAL_BUFFER
>>
>> static char *time2str(const char *fmt, time_t t)
>> {
>> strftime(bb_common_bufsiz1, COMMON_BUFSIZE, fmt, localtime(&t));
>> return bb_common_bufsiz1;
>> }
>> #else
>> static char *time2str(const char *fmt, time_t t)
>> {
>> static char buf[20];
>> strftime(buf, sizeof(buf), fmt, localtime(&t));
>> return buf;
>> }
>>
>> #endif
>>
>>
>> #define OPT_a 1 /* -b,-d, -l, -p, -r, -t, -T and -u */
>> #define OPT_b 2 /* last reboot */
>> #define OPT_d 4 /* dead process */
>> #define OPT_H 8 /* add Header */
>> #define OPT_l 16 /* login process */
>> #define OPT_m 32 /* current terminal only */
>> #define OPT_p 64 /* processes spawn by init */
>> #define OPT_q 128 /* quick */
>> #define OPT_r 256 /* current runlevel */
>> #define OPT_s 512 /* default */
>> #define OPT_t 1024 /* last time change */
>> #define OPT_T 2048 /* add time of login */
>> #define OPT_u 4096 /* idle */
>> #define OPT_D 8192 /* debug DUMPFILE */
>>
>>
>> /* option -w: like q with full info, GNU extension */
>>
>> static int _stat(char *line,struct stat *st)
>> {
>> int ret;
>> line = xasprintf("/dev/%s", line);
>> ret=stat(line, st);
>
> missing spaces before and after '='
>
>> free(line);
>> return ret;
>> }
>>
>> static char term_state(char *line)
>> {
>> struct stat st;
>>
>> if (_stat(line,&st) < 0) {
>> return '?';
>> } else {
>> if (st.st_mode & S_IWOTH)
>> return '-';
>> }
>> return '+';
>> }
>>
>>
>> static void idle_time(char *line)
>> {
>> struct stat st;
>> time_t t;
>>
>> if (_stat(line, &st) < 0)
>> {
>> putchar('?');
>> goto print;
>> }
>>
>>
>> /* one of the few occation we use atime */
>
> "occasions"
>
>> t = time(NULL) - st.st_atime;
>
> difftime()
>> if (t < 60) {
>> putchar('.');
>> goto print;
>> }
>>
>
> whitespace damage above.
>
>> /* always t >= 0 && */
>> if ( t < (24 * 60 * 60)) {
>> printf("%02d:%02d",
>> (int) (t / (60 * 60)), (int) ((t % (60 * 60)) /
>> 60));
>>
>> }
>> else
>> printf("old");
>>
>
> ditto
>
>> print:
>> putchar('\t');
>>
>> }
>>
>> enum {
>> NAME = 1 << 0,
>> STATE = 1 << 1,
>> LINE = 1 << 2,
>> TIME = 1 << 3,
>> ACTIVITY = 1 << 4,
>> PID = 1 << 5,
>> COMMENT = 1 << 6,
>> EXIT = 1 << 7
>> };
>>
>>
>> static void print_header(int pattern)
>> {
>>
>> #define str "NAME\0"\
>
> ditto
>> "STATE\0"\
>> "LINE\0"\
>> "TIME\0"\
>> "ACTIVITY\0"\
>> "PID\0"\
>> "COMMENT\0"\
>> "EXIT"
>>
>> int i=0;
>
> missing spaces
>
>> if (pattern < 0)
>> return;
>
> why is this called even for pattern < 0 ?
>
>> while(pattern)
>
> missing space and surplus trailing space
>> {
>> if (pattern&1)
>> printf("%s\t",nth_string(str,i));
>>
>
> whitespace damage above.
>
>> pattern>>=1;
>
> missing space.
>
>> i++;
>> }
>> putchar('\n');
>> #undef str
>> }
>>
>>
>> /*
>> print content of struct utmp, select what with mask
>> */
>>
>> static void print_ut(struct utmp *ut, int mask)
>> {
>> #define str "EMPTY\0"\
>> "RUN_LVL\0"\
>> "BOOT_TIME\0"\
>> "NEW_TIME\0"\
>> "OLD_TIME\0"\
>> "INIT_PROCESS\0"\
>> "LOGIN_PROCESS\0"\
>> "USER_PROCESS\0"\
>> "DEAD_PROCESS\0"\
>> "ACCOUNTING"
>>
>> /*
>> 10 = number of strings in str
>> */
>>
>>
>> if ( option_mask32 & OPT_D)
>> printf("%s\t", nth_string(str, ut->ut_type % 10 ) );
>> #undef str
>>
>> if (mask & NAME)
>> printf("%s\t", ut->ut_user); /* NAME */
>>
>> if (mask & STATE)
>> printf("%c\t", term_state(ut->ut_line)); /* STATE */
>>
>> if (mask & LINE)
>> printf("%s\t", ut->ut_line); /* LINE */
>>
>> if (mask & TIME)
>> printf("%s\t", time2str(TIMEFMT, ut->ut_tv.tv_sec)); /* TIME
>> */
>>
>> if (mask & ACTIVITY)
>> idle_time(ut->ut_line); /* ACTIVITY */
>>
>> if (mask & PID)
>> printf("%d\t", ut->ut_pid); /* PID */
>>
>> if (mask & COMMENT)
>> printf("ID=%s\t%s\t", ut->ut_id, ut->ut_host); /* COMMENT */
>>
>>
>> if (mask & EXIT)
>> printf("%d/%d", ut->ut_exit.e_termination, ut->ut_exit.e_exit);
>> /* EXIT */
>>
>
> whitespace damage above, several.
>
>> putchar('\n');
>> }
>>
>> int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
>>
>> int who_main(int argc UNUSED_PARAM, char **argv)
>> {
>> struct utmp *ut;
>> char *name;
>> unsigned int ucnt = 0;
>> int pattern = -1;
>> unsigned int opt;
>> /*
>> FIXME: make better use of opt_complementary
>> */
>> // opt_complementary = "q-abdHlmqprstuD";
>>
>> opt=getopt32(argv, "abdHlmpqrstTuD");
>> argv += optind;
>> /*
>> utmpname() will not fail if the file does not exists
>> */
>> if (*argv)
>> utmpname(*argv);
>
> perhaps utmpname returning <0 should set EXIT_FAILURE? The big one on my
> box doesn't seem to do that but i would have expected 'who /nope' to fail.
>
void utmpname(const char *file);
>> if (opt == 0)
>> opt = OPT_s;
>> if (opt == OPT_u)
>> opt |= OPT_s;
>>
>> if (opt & OPT_a)
>> opt |=(OPT_b | OPT_d | OPT_l | OPT_p | OPT_r | OPT_T | OPT_u);
>>
>> /*
>> figure out pattern to figure out pattern for heading
>> */
>>
>> if (opt & OPT_T)
>> pattern =
>> (opt & OPT_u) ? NAME | STATE | LINE | TIME | PID |
>> COMMENT | ACTIVITY : NAME | STATE | LINE | TIME | PID |
>> COMMENT;
>>
>> else if (opt & OPT_s)
>> pattern = (opt & OPT_u) ? NAME | LINE | TIME | ACTIVITY
>> : NAME | LINE | TIME;
>>
>>
>> else if (opt & OPT_l)
>> pattern =
>> (opt & OPT_u) ? NAME | LINE | TIME | PID | COMMENT |
>> ACTIVITY : NAME | LINE | TIME | PID | COMMENT;
>>
>> else if (opt & OPT_p)
>> pattern =
>> (opt & OPT_u) ? NAME | LINE | TIME | PID | COMMENT |
>> EXIT | ACTIVITY : NAME | LINE | TIME | PID | COMMENT |
>> EXIT;
>> else if (opt & OPT_D)
>> pattern = NAME | LINE | TIME | PID | COMMENT |EXIT;
>
> could be that it's cheaper to set the unconditional stuff (e.g. NAME) once,
> before that block.
i do not understand. do you suggest something like ..
pattern=NAME
if (foo)
pattern|=LINE;
>> if (opt & OPT_m) {
>> name = ttyname(STDIN_FILENO);
>> if (!name || strncmp(name, "/dev/", 5) )
>> bb_perror_msg_and_die("ttyname()");
>> name += 5;
>> /*
>> else
>> something strange is going on
>> can this ever happen ?
>> */
>>
>> }
>>
>> setutent();
>>
>> if (opt & OPT_H)
>> print_header(pattern);
>
> I'd just test pattern here and don't call it otherwise?
pattern is used by print_header so what what header infos are needed , is that
the question ?
>
>> while ((ut = getutent()) != NULL) {
>>
>> /* -m : only current terminal */
>> if (opt & OPT_m && strcmp(name, ut->ut_line))
>> continue;
>>
>> /* -b */
>> if ((opt & OPT_b) && BOOT_TIME == ut->ut_type) {
>> if (opt & OPT_H)
>> printf("last reboot\t");
>>
>> print_ut(ut, TIME);
>>
>> /*
>> if OPT_a is set we have to show this here only once
>> and continue to handle the other options
>> */
>>
>> if (opt & OPT_a)
>> opt &= ~OPT_b;
>> else
>> break;
>> }
>>
>> /* -d */
>> if ((opt & OPT_d) && DEAD_PROCESS == ut->ut_type) {
>> print_ut(ut, pattern);
>> }
>>
>> /* -l */
>> if ((opt & OPT_l) && LOGIN_PROCESS == ut->ut_type) {
>> print_ut(ut, pattern);
>> }
>>
>> /* -p */
>> if ((opt & OPT_p) && INIT_PROCESS == ut->ut_type) {
>> print_ut(ut, pattern);
>> }
>
> perhaps cheaper to merge these three above?
i would like to leave it for 1.0 when the functions here are checked.
>> /* -q */
>> if ((opt & OPT_q) && USER_PROCESS == ut->ut_type) {
>> printf("%s ", ut->ut_user);
>> ucnt++;
>> }
>>
>> /* -r */
>> if ((opt & OPT_r) && RUN_LVL == ut->ut_type) {
>> if (opt & OPT_H)
>> printf("Current\tTime\t\tLast\n");
>>
>
> whitespace damage. You've seen our .indentpro script, didn't you. Just run
> indent
> on that whole file.
>
actualy i did some time ago, it seems i added some spaces
i will rerun indent again and resend
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox