SUSv3 who for Busybox
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Mon Dec 8 17:16:16 UTC 2008
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.
> * 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>
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: ....
>
>// -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.
>#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?
> 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);
> }
>
>
>
> /* 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.
More information about the busybox
mailing list