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