SUSv3 who for Busybox
walter harms
wharms at bfs.de
Mon Dec 8 18:17:38 UTC 2008
Bernhard Reutner-Fischer schrieb:
> On Mon, Dec 08, 2008 at 05:55:19PM +0100, walter harms wrote:
>> Hi list,
>> while replacing "touch" with a SUSv3 "touch" i noticed that the "who"-command
>> does support only one of several option that a propper "who" should support.
>>
>> The who.c is a drop-in-replacement for the current who.c. it will support
>> all SUSv3 options but the file support.
>
>> /* vi: set sw=4 ts=4: */
>> /*
>> * SUSv3 who implementation for busybox
>> *
>> * Copyright (C) 2008 by <u173034 at informatik.uni-oldenburg.de>
>> * http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html
>> *
> -> * no long option support yet
>
> + /* BB_AUDIT SUSv3 defects - missing long options, missing file support */
>
> Makes it easier to grep for them.
will fix that, i hope to add file support before it will go to svn
>> * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
>> * $Id: who.c,v 1.4 2008/12/07 19:13:17 walter Exp walter $
>
> Please remove the $Id: line
>
>> */
>>
>> #include "libbb.h"
>> #include <utmp.h>
>
>> #include <time.h>
will fix that
> redundant include
>> // who -q file
>>
>> // who [-mu]-s[-bHlprt][<file>]
>> // -a schaltet: -b,-d, -l, -p, -r, -t, -T and -u
>
> Niemand schaltet hier irgendetwas ;)
> -a forces on / turns on: ....
lost in translation ...
>> // -b time date of last reboot
>
> And it would be awesome if you could use C89 comments, i.e. /* */
> otherwise there are warnings from C89 compilers.
i will fix that
>
>> #if 0
>>
>> </name/>*[*</state/>*]*</line/></time/>*[*</activity/>*][*</pid/>*][*</comment/>*][*</exit/>*]*
>>
>> struct utmp
>> {
>> short int ut_type; /* Type of login. */
>> pid_t ut_pid; /* Process ID of login process. */ </pid />
>> char ut_line[UT_LINESIZE]; /* Devicename. */ </line/>
>> char ut_id[4]; /* Inittab ID. */
>> char ut_user[UT_NAMESIZE]; /* Username. */ </name/>
>> char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
>> struct exit_status ut_exit; /* Exit status of a process marked
>> as DEAD_PROCESS. */
>> /* The ut_session and ut_tv fields must be the same size when compiled
>> 32- and 64-bit. This allows data files and shared memory to be
>> shared between 32- and 64-bit applications. */
>> #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
>> int32_t ut_session; /* Session ID, used for windowing. */
>> struct
>> {
>> int32_t tv_sec; /* Seconds. */
>> int32_t tv_usec; /* Microseconds. */
>> } ut_tv; /* Time entry was made. */
>> #else
>> long int ut_session; /* Session ID, used for windowing. */
>> struct timeval ut_tv; /* Time entry was made. */
>> #endif
>>
>> int32_t ut_addr_v6[4]; /* Internet address of remote host. */
>> char __unused[20]; /* Reserved for future use. */
>> };
>>
>> #endif
>>
>>
>> // "%b %e %H:%M"
>>
>> static char *time2str(const char *fmt,time_t t)
>> {
>> static char buf[20];
>> strftime(buf,sizeof(buf),fmt,localtime(&t));
>> return buf;
>> }
>>
>> static char term_state(char *line)
>> {
>> struct stat st;
>> char c='+';
>>
>> line=xasprintf("/dev/%s",line);
>>
>>
>> if (stat(line,&st)<0) {
>> c= '?' ;
>> }
>> else {
>> if ( st.st_mode & S_IWOTH )
>> c='-' ;
>> }
>>
>> free(line);
>> return c;
>> }
>>
>>
>> static char *idle_time(char *line)
>> {
>> struct stat st;
>> time_t t;
>> static char buf[6]="old";
>
> whitespace damage above.
>
>> line=xasprintf("/dev/%s",line);
>> if ( stat(line,&st) < 0 )
>
> ditto, twice.
>
>> return (char *)"?";
>>
>> /* one of the few occation we use atime */
>> t = time(NULL) - st.st_atime;
>>
>> if (t < 60) {
>> return (char *)".";
>> }
>>
>> if (t >= 0 && t < (24 * 60 * 60)) {
>> sprintf(buf, "%02d:%02d",
>> (int) (t / (60 * 60)),
>> (int) ((t % (60 * 60)) / 60));
>>
>
> ditto
>> }
>> return buf;
>>
>
> ditto
>> }
>>
>> static const char *str[]= { " EMPTY"," RUN_LVL"," BOOT_TIME"," NEW_TIME"," OLD_TIME",
>> " INIT_PROCESS"," LOGIN_PROCESS"," USER_PROCESS"," DEAD_PROCESS",
>> " ACCOUNTING" };
>>
>>
>>
>> static void print_all(struct utmp *ut)
>> {
>> printf("type:%s\n",str[ut->ut_type % ARRAY_SIZE(str)] );
>> printf("pid :%d\n",ut->ut_pid);
>> printf("line:%s\n",ut->ut_line);
>> printf("id :%s\n",ut->ut_id);
>> printf("user:%s\n",ut->ut_user);
>> printf("host:%s\n",ut->ut_host);
>> printf("term: %d\n",ut->ut_exit. e_termination);
>> printf("exit: %d\n",ut->ut_exit. e_exit);
>> }
>>
>>
>> #define OPT_a 1
>> #define OPT_b 2 /* done */
>> #define OPT_d 4 /* done */
>> #define OPT_H 8 /* done */
>> #define OPT_l 16 /* done */
>> #define OPT_m 32 /* done */
>> #define OPT_p 64 /* done */
>> #define OPT_q 128 /* done */
>> #define OPT_r 256 /* done */
>> #define OPT_s 512 /* default done */
>> #define OPT_t 1024 /* done */
>> #define OPT_T 2048 /* done */
>> #define OPT_u 4096 /* done */
>> #define OPT_D 8192 /* debug DUMPFILE */
>>
>> //
>> //#define OPT_w 8192 /* like q with full info, GNU extension */
>> //
>>
>> 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
>> };
>>
>> #define HEAD(NAME) if (pattern&NAME) printf("%s\t",#NAME)
>>
>> static void print_header( int pattern)
>> {
>> if (pattern<0) return;
>
> better make sure that pattern has to be valid in the caller?
no, -1 means: -H is enabled but no header is needed (e.g. -r)
>> HEAD(NAME);
>> HEAD(STATE);
>> HEAD(LINE);
>> HEAD(TIME);
>> HEAD(ACTIVITY);
>> HEAD(PID);
>> HEAD(COMMENT);
>> HEAD(EXIT);
>> }
>>
>>
>> static void print_ut(struct utmp *ut, int mask)
>> {
>> 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("%b %e %H:%M",ut->ut_tv.tv_sec) ); /* TIME */
>>
>> if (mask&ACTIVITY)
>> printf("%s\t",idle_time(ut->ut_line) ); /* ACTIVITY */
>>
>> if (mask&PID)
>> printf("%d\t",ut->ut_pid); /* PID */
>>
>> if (mask&COMMENT) {
>> printf("ID=%s\t",ut->ut_id); /* COMMENT */
>> printf("%s\t",ut->ut_host); /* COMMENT */
>> }
>>
>> if (mask&EXIT) {
>> printf("%d/",ut->ut_exit. e_termination); /* EXIT */
>> printf("%d\t",ut->ut_exit. e_exit); /* EXIT */
>
> whitespace damage
>> }
>> 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;
>>
> whitespace damage
>> /*
>> filename hier setzen
>> int utmpname();
>> */
>>
>> opt_complementary="q-abdHlmqprstuD";
>
> you're using non-standard spacing about everywhere. Please run that file through indent perusing the
> toplevel .indent.pro. This is used per default if you do:
> $ indent */who.c
>
>> getopt32(argv, "abdHlmpqrstTuD");
>>
>> if (option_mask32 == 0) option_mask32=OPT_s;
>> if (option_mask32 == OPT_u) option_mask32|=OPT_s;
>>
>> if (option_mask32 & OPT_a ) option_mask32|=(OPT_b|OPT_d|OPT_l|OPT_p|OPT_r|OPT_T|OPT_u);
>>
>> #if 0
>> if (option_mask32 & OPT_H)
>> if (option_mask32 & (OPT_s|OPT_d|OPT_l) ) {
>> printf("name\t");
>> if (option_mask32 & OPT_H) printf("state\t");
>> printf("line\t");
>> printf("time\t");
>> if (option_mask32 & (OPT_u|OPT_H) ) printf("activity\t");
>
> please put those on their own line.
>
>> if (option_mask32 & (OPT_d|OPT_H) ) printf("pid\t");
>> if (option_mask32 & OPT_H) printf("comment\t");
>> if (option_mask32 & (OPT_d|OPT_H) ) printf("exit");
>> putchar('\n');
>> }
>> #endif
>> /*
>> figure out pattern to figure out pattern for heading
>> */
>>
>> if (option_mask32&OPT_T)
>> pattern=(option_mask32&OPT_u) ? NAME|STATE|LINE|TIME|PID|COMMENT|ACTIVITY
>> : NAME|STATE|LINE|TIME|PID|COMMENT ;
>>
>> else
>> if (option_mask32&OPT_s)
>> pattern=(option_mask32&OPT_u) ? NAME|LINE|TIME|ACTIVITY
>> : NAME|LINE|TIME;
>>
>>
> whitespace damage
>
> and please use "else if"
>
>> else
>> if (option_mask32&OPT_l)
>> pattern=(option_mask32&OPT_u) ? NAME|LINE|TIME|PID|COMMENT|ACTIVITY
>> : NAME|LINE|TIME|PID|COMMENT;
>>
>> else
>> if (option_mask32&OPT_p)
>> pattern=(option_mask32&OPT_u) ? NAME|LINE|TIME|PID|COMMENT|EXIT|ACTIVITY
>> : NAME|LINE|TIME|PID|COMMENT|EXIT;
>> else
>> if (option_mask32&OPT_p)
>> pattern=NAME|LINE|TIME|PID|COMMENT;
>>
>>
>>
>>
>>
> excess whitespace
>> if (option_mask32&OPT_m) {
>> name=ttyname(0);
>> if (!name)
>> fprintf(stderr,"not a tty\n");
>
> There must already be a function that does the above, perhaps.
>> /* skip leading dev */
>> if ( !strncmp(name,"/dev/",5) ) name+=5;
>
> open_device() (spelling?) does that already, doesn't it.
>> // printf("dev=%s\n",name);
>> }
i did a grep and found nothing useful in libbb.
>>
>>
>> /* use alternative file */
> whitespace damage
>> #if 0
>> if (optind==1) {
>> argv += optind;
> whitespace damage
>> printf("file=%s\n",*argv);
>> if ( utmpname(*argv) <0 )
>> {
>> bb_error_msg_and_die("can not get %s",*argv);
>> }
>>
>> }
>> #endif
>>
>> if (option_mask32&OPT_H)
>> print_header(pattern);
>>
>> while ((ut = getutent()) != NULL) {
>>
>> /* -m : only current terminal */
>> if (option_mask32&OPT_m && strcmp(name,ut->ut_line)) continue;
>>
>>
>> /* -b */
>> if ( (option_mask32&OPT_b) && BOOT_TIME == ut->ut_type) {
>> if (option_mask32&OPT_H) printf("last reboot\t");
>> //printf("%s\n",time2str("%b %e %H:%M",ut->ut_tv.tv_sec) );
>> print_ut(ut,TIME);
>> if (option_mask32&OPT_a)
> whitespace damage
>> option_mask32 &= ~OPT_b;
>> else
>> break;
>> }
>>
>>
>> /* -d */
>> if ( (option_mask32&OPT_d) && DEAD_PROCESS== ut->ut_type) {
>> print_ut(ut,pattern);
>> // print_ut(ut, (option_mask32&OPT_u) ? NAME|LINE|TIME|PID|COMMENT|EXIT|ACTIVITY
>> // : NAME|LINE|TIME|PID|COMMENT|EXIT );
>>
>> }
>>
>>
>> /* -l */
>> if ( (option_mask32&OPT_l) && LOGIN_PROCESS == ut->ut_type) {
>> // print_ut(ut, (option_mask32&OPT_u) ? NAME|LINE|TIME|PID|COMMENT|ACTIVITY
>> // : NAME|LINE|TIME|PID|COMMENT);
>> print_ut(ut,pattern);
>>
> whitespace damage
>> }
>>
>> /* -p */
>> if ( (option_mask32&OPT_p) && INIT_PROCESS == ut->ut_type) {
>> // print_ut(ut,NAME|LINE|TIME|PID|COMMENT);
>> print_ut(ut,pattern);
>>
> whitespace damage
>> }
>>
>>
>> /* -q */
>> if ( (option_mask32&OPT_q) && USER_PROCESS == ut->ut_type) {
>> printf("%s ",ut->ut_user);
>> ucnt++;
>> }
>>
>>
>> /* -r */
>> if ( (option_mask32&OPT_r) && RUN_LVL == ut->ut_type) {
>> if (option_mask32&OPT_H) { printf ("\t Current\tTime\tLast\n"); }
>> printf("%s %c\t",ut->ut_user,ut->ut_pid &255 );
> whitespace damage
>> printf("%s\t",time2str("%Y-%m-%d %H:%M",ut->ut_tv.tv_sec) );
>> printf("%c\n", (ut->ut_pid >> 8)?'N':(ut->ut_pid >> 8));
>>
>> /*
>> if OPT_a is set we have to show this here only once
>> and continue to handle the other options
>> */
>> if (option_mask32&OPT_a)
> whitespace damage
>> option_mask32 &= ~OPT_r;
>> else
>> break;
>> }
>>
>> /* -s | default */
>> if ( (option_mask32&OPT_s) && USER_PROCESS == ut->ut_type) {
>> print_ut(ut,pattern);
>> }
>>
>>
>>
>> /* -t */
>> if ( (option_mask32&OPT_t) && NEW_TIME == ut->ut_type) {
>> if (option_mask32&OPT_H) printf("last time change\t");
>> print_ut(ut,TIME);
>> break;
>> }
>>
>> /* -T */
>> if ( (option_mask32&OPT_T) && USER_PROCESS == ut->ut_type) {
>>
>> print_ut(ut,pattern);
>> // print_ut(ut, (option_mask32&OPT_u) ? NAME|STATE|LINE|TIME|PID|COMMENT|ACTIVITY
>> // : NAME|STATE|LINE|TIME|PID|COMMENT);
>>
>> }
>>
>>
>>
>> /* -D debug option */
>> if (option_mask32&OPT_D)
>> print_all(ut);
>>
>>
>>
>> } /* while */
>>
>> /*
>> write user count
>> */
>>
>> if (option_mask32&OPT_q)
>> printf("\n#User %d\n",ucnt);
>>
>> endutent();
>> return EXIT_SUCCESS;
>> }
>
> Most of the layout should be fixed by one indent invocation. Please resend
> a cleaned up version.
>
should be harmless
NTL thx for fast reply
can you please compile it with ulibc ?
re,
wh
More information about the busybox
mailing list