@@ -79,14 +79,15 @@ static int show_user(UserRecord *ur, Table *table) {
7979
8080 r = table_add_many (
8181 table ,
82+ TABLE_STRING , "" ,
8283 TABLE_STRING , ur -> user_name ,
8384 TABLE_STRING , user_disposition_to_string (user_record_disposition (ur )),
8485 TABLE_UID , ur -> uid ,
8586 TABLE_GID , user_record_gid (ur ),
8687 TABLE_STRING , empty_to_null (ur -> real_name ),
8788 TABLE_STRING , user_record_home_directory (ur ),
8889 TABLE_STRING , user_record_shell (ur ),
89- TABLE_INT , ( int ) user_record_disposition ( ur ) );
90+ TABLE_INT , 0 );
9091 if (r < 0 )
9192 return table_log_add_error (r );
9293
@@ -99,6 +100,115 @@ static int show_user(UserRecord *ur, Table *table) {
99100 return 0 ;
100101}
101102
103+ static const struct {
104+ uid_t first , last ;
105+ const char * name ;
106+ UserDisposition disposition ;
107+ } uid_range_table [] = {
108+ {
109+ .first = 1 ,
110+ .last = SYSTEM_UID_MAX ,
111+ .name = "system" ,
112+ .disposition = USER_SYSTEM ,
113+ },
114+ {
115+ .first = DYNAMIC_UID_MIN ,
116+ .last = DYNAMIC_UID_MAX ,
117+ .name = "dynamic system" ,
118+ .disposition = USER_DYNAMIC ,
119+ },
120+ {
121+ .first = CONTAINER_UID_BASE_MIN ,
122+ .last = CONTAINER_UID_BASE_MAX ,
123+ .name = "container" ,
124+ .disposition = USER_CONTAINER ,
125+ },
126+ #if ENABLE_HOMED
127+ {
128+ .first = HOME_UID_MIN ,
129+ .last = HOME_UID_MAX ,
130+ .name = "systemd-homed" ,
131+ .disposition = USER_REGULAR ,
132+ },
133+ #endif
134+ {
135+ .first = MAP_UID_MIN ,
136+ .last = MAP_UID_MAX ,
137+ .name = "mapped" ,
138+ .disposition = USER_REGULAR ,
139+ },
140+ };
141+
142+ static int table_add_uid_boundaries (Table * table ) {
143+ int r ;
144+
145+ assert (table );
146+
147+ for (size_t i = 0 ; i < ELEMENTSOF (uid_range_table ); i ++ ) {
148+ _cleanup_free_ char * name = NULL , * comment = NULL ;
149+
150+ name = strjoin (special_glyph (SPECIAL_GLYPH_ARROW_DOWN ),
151+ " begin " , uid_range_table [i ].name , " users " ,
152+ special_glyph (SPECIAL_GLYPH_ARROW_DOWN ));
153+ if (!name )
154+ return log_oom ();
155+
156+ comment = strjoin ("First " , uid_range_table [i ].name , " user" );
157+ if (!comment )
158+ return log_oom ();
159+
160+ r = table_add_many (
161+ table ,
162+ TABLE_STRING , special_glyph (SPECIAL_GLYPH_TREE_TOP ),
163+ TABLE_STRING , name ,
164+ TABLE_SET_COLOR , ansi_grey (),
165+ TABLE_STRING , user_disposition_to_string (uid_range_table [i ].disposition ),
166+ TABLE_SET_COLOR , ansi_grey (),
167+ TABLE_UID , uid_range_table [i ].first ,
168+ TABLE_SET_COLOR , ansi_grey (),
169+ TABLE_EMPTY ,
170+ TABLE_STRING , comment ,
171+ TABLE_SET_COLOR , ansi_grey (),
172+ TABLE_EMPTY ,
173+ TABLE_EMPTY ,
174+ TABLE_INT , -1 ); /* sort before an other entry with the same UID */
175+ if (r < 0 )
176+ return table_log_add_error (r );
177+
178+ free (name );
179+ name = strjoin (special_glyph (SPECIAL_GLYPH_ARROW_UP ),
180+ " end " , uid_range_table [i ].name , " users " ,
181+ special_glyph (SPECIAL_GLYPH_ARROW_UP ));
182+ if (!name )
183+ return log_oom ();
184+
185+ free (comment );
186+ comment = strjoin ("Last " , uid_range_table [i ].name , " user" );
187+ if (!comment )
188+ return log_oom ();
189+
190+ r = table_add_many (
191+ table ,
192+ TABLE_STRING , special_glyph (SPECIAL_GLYPH_TREE_RIGHT ),
193+ TABLE_STRING , name ,
194+ TABLE_SET_COLOR , ansi_grey (),
195+ TABLE_STRING , user_disposition_to_string (uid_range_table [i ].disposition ),
196+ TABLE_SET_COLOR , ansi_grey (),
197+ TABLE_UID , uid_range_table [i ].last ,
198+ TABLE_SET_COLOR , ansi_grey (),
199+ TABLE_EMPTY ,
200+ TABLE_STRING , comment ,
201+ TABLE_SET_COLOR , ansi_grey (),
202+ TABLE_EMPTY ,
203+ TABLE_EMPTY ,
204+ TABLE_INT , 1 ); /* sort after an other entry with the same UID */
205+ if (r < 0 )
206+ return table_log_add_error (r );
207+ }
208+
209+ return ELEMENTSOF (uid_range_table ) * 2 ;
210+ }
211+
102212static int display_user (int argc , char * argv [], void * userdata ) {
103213 _cleanup_ (table_unrefp ) Table * table = NULL ;
104214 bool draw_separator = false;
@@ -108,15 +218,15 @@ static int display_user(int argc, char *argv[], void *userdata) {
108218 arg_output = argc > 1 ? OUTPUT_FRIENDLY : OUTPUT_TABLE ;
109219
110220 if (arg_output == OUTPUT_TABLE ) {
111- table = table_new ("name" , "disposition" , "uid" , "gid" , "realname" , "home" , "shell" , "disposition-numeric " );
221+ table = table_new (" " , " name" , "disposition" , "uid" , "gid" , "realname" , "home" , "shell" , "order " );
112222 if (!table )
113223 return log_oom ();
114224
115- (void ) table_set_align_percent (table , table_get_cell (table , 0 , 2 ), 100 );
116225 (void ) table_set_align_percent (table , table_get_cell (table , 0 , 3 ), 100 );
226+ (void ) table_set_align_percent (table , table_get_cell (table , 0 , 4 ), 100 );
117227 (void ) table_set_empty_string (table , "-" );
118- (void ) table_set_sort (table , (size_t ) 7 , (size_t ) 2 );
119- (void ) table_set_display (table , (size_t ) 0 , (size_t ) 1 , (size_t ) 2 , (size_t ) 3 , (size_t ) 4 , (size_t ) 5 , (size_t ) 6 );
228+ (void ) table_set_sort (table , (size_t ) 3 , (size_t ) 8 );
229+ (void ) table_set_display (table , (size_t ) 0 , (size_t ) 1 , (size_t ) 2 , (size_t ) 3 , (size_t ) 4 , (size_t ) 5 , (size_t ) 6 , ( size_t ) 7 );
120230 }
121231
122232 if (argc > 1 ) {
@@ -186,6 +296,12 @@ static int display_user(int argc, char *argv[], void *userdata) {
186296 }
187297
188298 if (table ) {
299+ int boundary_lines ;
300+
301+ boundary_lines = table_add_uid_boundaries (table );
302+ if (boundary_lines < 0 )
303+ return boundary_lines ;
304+
189305 if (table_get_rows (table ) > 1 ) {
190306 r = table_print_with_pager (table , arg_json_format_flags , arg_pager_flags , arg_legend );
191307 if (r < 0 )
@@ -194,7 +310,7 @@ static int display_user(int argc, char *argv[], void *userdata) {
194310
195311 if (arg_legend ) {
196312 if (table_get_rows (table ) > 1 )
197- printf ("\n%zu users listed.\n" , table_get_rows (table ) - 1 );
313+ printf ("\n%zu users listed.\n" , table_get_rows (table ) - 1 - boundary_lines );
198314 else
199315 printf ("No users.\n" );
200316 }
@@ -246,11 +362,12 @@ static int show_group(GroupRecord *gr, Table *table) {
246362
247363 r = table_add_many (
248364 table ,
365+ TABLE_STRING , "" ,
249366 TABLE_STRING , gr -> group_name ,
250367 TABLE_STRING , user_disposition_to_string (group_record_disposition (gr )),
251368 TABLE_GID , gr -> gid ,
252369 TABLE_STRING , gr -> description ,
253- TABLE_INT , ( int ) group_record_disposition ( gr ) );
370+ TABLE_INT , 0 );
254371 if (r < 0 )
255372 return table_log_add_error (r );
256373
@@ -263,6 +380,69 @@ static int show_group(GroupRecord *gr, Table *table) {
263380 return 0 ;
264381}
265382
383+ static int table_add_gid_boundaries (Table * table ) {
384+ int r ;
385+
386+ assert (table );
387+
388+ for (size_t i = 0 ; i < ELEMENTSOF (uid_range_table ); i ++ ) {
389+ _cleanup_free_ char * name = NULL , * comment = NULL ;
390+
391+ name = strjoin (special_glyph (SPECIAL_GLYPH_ARROW_DOWN ),
392+ " begin " , uid_range_table [i ].name , " groups " ,
393+ special_glyph (SPECIAL_GLYPH_ARROW_DOWN ));
394+ if (!name )
395+ return log_oom ();
396+
397+ comment = strjoin ("First " , uid_range_table [i ].name , " group" );
398+ if (!comment )
399+ return log_oom ();
400+
401+ r = table_add_many (
402+ table ,
403+ TABLE_STRING , special_glyph (SPECIAL_GLYPH_TREE_TOP ),
404+ TABLE_STRING , name ,
405+ TABLE_SET_COLOR , ansi_grey (),
406+ TABLE_STRING , user_disposition_to_string (uid_range_table [i ].disposition ),
407+ TABLE_SET_COLOR , ansi_grey (),
408+ TABLE_GID , uid_range_table [i ].first ,
409+ TABLE_SET_COLOR , ansi_grey (),
410+ TABLE_STRING , comment ,
411+ TABLE_SET_COLOR , ansi_grey (),
412+ TABLE_INT , -1 ); /* sort before an other entry with the same GID */
413+ if (r < 0 )
414+ return table_log_add_error (r );
415+
416+ free (name );
417+ name = strjoin (special_glyph (SPECIAL_GLYPH_ARROW_UP ),
418+ " end " , uid_range_table [i ].name , " groups " ,
419+ special_glyph (SPECIAL_GLYPH_ARROW_UP ));
420+ if (!name )
421+ return log_oom ();
422+
423+ free (comment );
424+ comment = strjoin ("Last " , uid_range_table [i ].name , " group" );
425+ if (!comment )
426+ return log_oom ();
427+
428+ r = table_add_many (
429+ table ,
430+ TABLE_STRING , special_glyph (SPECIAL_GLYPH_TREE_RIGHT ),
431+ TABLE_STRING , name ,
432+ TABLE_SET_COLOR , ansi_grey (),
433+ TABLE_STRING , user_disposition_to_string (uid_range_table [i ].disposition ),
434+ TABLE_SET_COLOR , ansi_grey (),
435+ TABLE_GID , uid_range_table [i ].last ,
436+ TABLE_SET_COLOR , ansi_grey (),
437+ TABLE_STRING , comment ,
438+ TABLE_SET_COLOR , ansi_grey (),
439+ TABLE_INT , 1 ); /* sort after an other entry with the same GID */
440+ if (r < 0 )
441+ return table_log_add_error (r );
442+ }
443+
444+ return ELEMENTSOF (uid_range_table ) * 2 ;
445+ }
266446
267447static int display_group (int argc , char * argv [], void * userdata ) {
268448 _cleanup_ (table_unrefp ) Table * table = NULL ;
@@ -273,14 +453,14 @@ static int display_group(int argc, char *argv[], void *userdata) {
273453 arg_output = argc > 1 ? OUTPUT_FRIENDLY : OUTPUT_TABLE ;
274454
275455 if (arg_output == OUTPUT_TABLE ) {
276- table = table_new ("name" , "disposition" , "gid" , "description" , "disposition-numeric " );
456+ table = table_new (" " , " name" , "disposition" , "gid" , "description" , "order " );
277457 if (!table )
278458 return log_oom ();
279459
280- (void ) table_set_align_percent (table , table_get_cell (table , 0 , 2 ), 100 );
460+ (void ) table_set_align_percent (table , table_get_cell (table , 0 , 3 ), 100 );
281461 (void ) table_set_empty_string (table , "-" );
282- (void ) table_set_sort (table , (size_t ) 3 , (size_t ) 2 );
283- (void ) table_set_display (table , (size_t ) 0 , (size_t ) 1 , (size_t ) 2 , (size_t ) 3 );
462+ (void ) table_set_sort (table , (size_t ) 3 , (size_t ) 5 );
463+ (void ) table_set_display (table , (size_t ) 0 , (size_t ) 1 , (size_t ) 2 , (size_t ) 3 , ( size_t ) 4 );
284464 }
285465
286466 if (argc > 1 ) {
@@ -351,6 +531,12 @@ static int display_group(int argc, char *argv[], void *userdata) {
351531 }
352532
353533 if (table ) {
534+ int boundary_lines ;
535+
536+ boundary_lines = table_add_gid_boundaries (table );
537+ if (boundary_lines < 0 )
538+ return boundary_lines ;
539+
354540 if (table_get_rows (table ) > 1 ) {
355541 r = table_print_with_pager (table , arg_json_format_flags , arg_pager_flags , arg_legend );
356542 if (r < 0 )
@@ -359,7 +545,7 @@ static int display_group(int argc, char *argv[], void *userdata) {
359545
360546 if (arg_legend ) {
361547 if (table_get_rows (table ) > 1 )
362- printf ("\n%zu groups listed.\n" , table_get_rows (table ) - 1 );
548+ printf ("\n%zu groups listed.\n" , table_get_rows (table ) - 1 - boundary_lines );
363549 else
364550 printf ("No groups.\n" );
365551 }
0 commit comments