嵌入式成长轨迹24【Linux应用编程强化】【Linux下的C编程 下】【实例:Linux命令实现】

 

 

  功能与参数介绍

id [-gGnru] [--help] [--version] [用户名称]

 

各参数的具体含义如下所示:

-g-group:显示有效用户组ID

-G-groups:显示辅助用户组ID

-n-name:显示名称,而不是ID

-r-real:显示实际用户ID

-u-user:显示有效用户ID

-help:显示帮助信息;

-version:显示版本信息。

 

  主函数代码精要

1

enum

{

  GETOPT_HELP_CHAR = (CHAR_MIN - 2),

  GETOPT_VERSION_CHAR = (CHAR_MIN - 3)

};

 

#define EXIT_FAILURE             1

#define EXIT_SUCCESS             0

 

2

#include <system.h>

#define HELP_OPTION_DESCRIPTION \

  _("      --help     display this help and exit\n")

#define VERSION_OPTION_DESCRIPTION \

  _("      --version  output version information and exit\n")

 

#include <system.h>

#define _(msgid) gettext (msgid)

#define N_(msgid) msgid

 

3

#include <gettext.h>

# define gettext(Msgid) ((const char *) (Msgid))

 

initialize_main (&argc, &argv);

 

#include <system.h>

#ifndef initialize_main

# define initialize_main(ac, av)

#endif

 

4

#include <locale.h>

char *setlocale (int category, const char *locale)

LC_COLLATE:表示设定排列顺序

LC_CTYPE:字符分类和转换,例如将所有的字符转换成小写或大写形式

LC_MESSAGES:系统信息的格式

LC_MONETARY:货币的格式

LC_NUMERIC:数值的格式

LC_TIME:日期和时间的格式

LC_ALL:设置上述所有的选项

setlocale (LC_ALL, NULL);

 

5

#include <system.h>

#if ! ENABLE_NLS            

# undef textdomain

# define textdomain(Domainname)

# undef bindtextdomain

# define bindtextdomain(Domainname, Dirname)

#endif

 

6

int atexit (void (*)(void));

 

int getopt_long(int argc, char * const argv[],

              const char *optstring,

              const struct option *longopts, int *longindex);

 

 

 

7

#include <system.h>

enum

{

  GETOPT_HELP_CHAR = (CHAR_MIN - 2),

  GETOPT_VERSION_CHAR = (CHAR_MIN - 3)

};

#define case_GETOPT_HELP_CHAR \

  case GETOPT_HELP_CHAR: \

    usage (EXIT_SUCCESS); \

    break;

#define case_GETOPT_VERSION_CHAR(Program_name, Authors) \

  case GETOPT_VERSION_CHAR: \

    version_etc (stdout, Program_name, GNU_PACKAGE, VERSION, Authors, \

               (char *) NULL); \

    exit (EXIT_SUCCESS); \

    break;

 

 

  其他函数代码

接下来主要为一些相关支持函数的定义,包括print_userprint_groupxgetgroupsprint_group_list、以及print_full_info等。

 

 

小结

阅读Coreutilsid命令的源代码,它是Linux系统中实际应用的程序,代码是稳定、高效、经过严格测试过的。程序中的很多地方,尤其是宏的使用、出错处理等部分,是非常值得用户学习和借鉴的。

 

  1 /* id -- print real and effective UIDs and GIDs
  2 
  3    Copyright (C) 1989-2005 Free Software Foundation, Inc.
  4 
  5  
  6 
  7    This program is free software; you can redistribute it and/or modify
  8 
  9    it under the terms of the GNU General Public License as published by
 10 
 11    the Free Software Foundation; either version 2, or (at your option)
 12 
 13    any later version.
 14 
 15  
 16 
 17    This program is distributed in the hope that it will be useful,
 18 
 19    but WITHOUT ANY WARRANTY; without even the implied warranty of
 20 
 21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 22 
 23    GNU General Public License for more details.
 24 
 25  
 26 
 27    You should have received a copy of the GNU General Public License
 28 
 29    along with this program; if not, write to the Free Software Foundation,
 30 
 31    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 32 
 33  
 34 
 35 /* Written by Arnold Robbins.
 36 
 37    Major rewrite by David MacKenzie, djm@gnu.ai.mit.edu. */
 38 
 39  
 40 
 41 #include <config.h>
 42 
 43 #include <stdio.h>
 44 
 45 #include <getopt.h>
 46 
 47 #include <sys/types.h>
 48 
 49 #include <pwd.h>
 50 
 51 #include <grp.h>
 52 
 53 #include <getopt.h>
 54 
 55  
 56 
 57 #include "system.h"
 58 
 59 #include "error.h"
 60 
 61 #include "quote.h"
 62 
 63 #define PROGRAM_NAME "id"
 64 
 65 #define AUTHORS "Arnold Robbins", "David MacKenzie"
 66 
 67 int getugroups (); 
 68 
 69  
 70 
 71 static void print_user (uid_t uid);
 72 
 73 static void print_group (gid_t gid);
 74 
 75 static void print_group_list (const char *username);
 76 
 77 static void print_full_info (const char *username);
 78 
 79 char *program_name;                  /* 程序名 */
 80 
 81 static bool use_name = false; /* 如果设为true,输出用户或组的名称,而不是ID,对应于-n选项 */
 82 
 83 static uid_t ruid, euid;          /* 用户的实际ID和有效ID */
 84 
 85 static gid_t rgid, egid;          /* 用户组的实际ID和有效ID */
 86 
 87 static bool ok = true;                   /* 如果发生错误,将该变量设为ture */
 88 
 89 static struct option const longopts[] =
 90 
 91 {
 92 
 93   {"group", no_argument, NULL, 'g'},
 94 
 95   {"groups", no_argument, NULL, 'G'},
 96 
 97   {"name", no_argument, NULL, 'n'},
 98 
 99   {"real", no_argument, NULL, 'r'},
100 
101   {"user", no_argument, NULL, 'u'},
102 
103   {GETOPT_HELP_OPTION_DECL},
104 
105   {GETOPT_VERSION_OPTION_DECL},
106 
107   {NULL, 0, NULL, 0}
108 
109 };
110 
111 void 
112 
113 usage (int status)
114 
115 {
116 
117   if (status != EXIT_SUCCESS)
118 
119     fprintf (stderr, _("Try `%s --help' for more information.\n"),
120 
121              program_name);
122 
123   else
124 
125     {
126 
127       printf (_("Usage: %s [OPTION]... [USERNAME]\n"), program_name);
128 
129       fputs (_("\
130 
131 Print information for USERNAME, or the current user.\n\
132 
133 \n\
134 
135   -a               ignore, for compatibility with other versions\n\
136 
137   -g, --group  print only the effective group ID\n\
138 
139   -G, --groups       print all group IDs\n\
140 
141   -n, --name   print a name instead of a number, for -ugG\n\
142 
143   -r, --real             print the real ID instead of the effective ID, with -ugG\n\
144 
145   -u, --user    print only the effective user ID\n\
146 
147 "), stdout);
148 
149       fputs (HELP_OPTION_DESCRIPTION, stdout);
150 
151       fputs (VERSION_OPTION_DESCRIPTION, stdout);
152 
153       fputs (_("\
154 
155 \n\
156 
157 Without any OPTION, print some useful set of identified information.\n\
158 
159 "), stdout);
160 
161       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
162 
163     }
164 
165   exit (status);
166 
167 }
168 
169 int 
170 
171 main (int argc, char **argv)
172 
173 {
174 
175   int optc;
176 
177  
178 
179   bool just_group_list = false;      /* 如果设为true,输出所有用户组ID列表,对应于-G选项 */
180 
181   bool just_group = false;            /* 如果设为true,输出用户组ID,对应于-g选项 */
182 
183   bool use_real = false;               /* 如果设为true,输出实际用户ID和组ID,默认情况下输出 */
184 
185                                          /* 有效用户ID和组ID,对应于-r选项 */
186 
187   bool just_user = false;              /* 如果设为true,输出实际用户ID,对应于-u选项*/
188 
189   program_name = argv[0];        /* 程序名 */
190 
191   setlocale (LC_ALL, "");
192 
193   bindtextdomain (PACKAGE, LOCALEDIR);
194 
195   textdomain (PACKAGE);
196 
197   atexit (close_stdout);
198 
199   while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)  /* 分析命令行参数 */
200 
201     {
202 
203       switch (optc)
204 
205         {
206 
207         case 'a':    /*忽略-a选项,主要是出于SVR4(UNIX System V Release4)兼容性的考虑 */
208 
209  
210 
211           break;
212 
213         case 'g':                         /* -g选项,将变量just_group设为true */
214 
215           just_group = true;
216 
217           break;
218 
219         case 'n':                        /* -n选项,将变量use_name设为true */
220 
221           use_name = true;
222 
223           break;
224 
225         case 'r':                        /* -r选项,将变量use_real设为true */
226 
227           use_real = true;
228 
229           break;
230 
231         case 'u':                        /* -u选项,将变量just_user设为true */
232 
233           just_user = true;
234 
235           break;
236 
237         case 'G':                       /* -G选项,将变量just_group_list设为true */
238 
239           just_group_list = true;
240 
241           break;
242 
243         case_GETOPT_HELP_CHAR;
244 
245         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
246 
247         default:
248 
249           usage (EXIT_FAILURE);
250 
251         }
252 
253     }
254 
255   if (just_user + just_group + just_group_list > 1)
256 
257     error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
258 
259  
260 
261   if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
262 
263     error (EXIT_FAILURE, 0,
264 
265            _("cannot print only names or real IDs in default format"));
266 
267  
268 
269   if (argc - optind > 1)
270 
271     {
272 
273       error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
274 
275       usage (EXIT_FAILURE);
276 
277     }
278 
279   if (argc - optind == 1)
280 
281     {
282 
283       struct passwd *pwd = getpwnam (argv[optind]);            /* 获取指定用户的账号信息 */
284 
285       if (pwd == NULL)
286 
287         error (EXIT_FAILURE, 0, _("%s: No such user"), argv[optind]);
288 
289       ruid = euid = pwd->pw_uid;
290 
291       rgid = egid = pwd->pw_gid;
292 
293     }
294 
295   else
296 
297     {
298 
299       euid = geteuid ();                     /* 获取有效用户ID */
300 
301       ruid = getuid ();                /* 获取实际用户ID */
302 
303       egid = getegid ();                     /* 获取有效组ID */
304 
305       rgid = getgid ();                /* 获取实际组ID */
306 
307     }
308 
309   if (just_user)
310 
311     print_user (use_real ? ruid : euid);
312 
313   else if (just_group)
314 
315     print_group (use_real ? rgid : egid);
316 
317   else if (just_group_list)
318 
319     print_group_list (argv[optind]);
320 
321   else
322 
323     print_full_info (argv[optind]);
324 
325   putchar ('\n');
326 
327   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
328 
329 }
330 
331 static void
332 
333 print_user (uid_t uid)
334 
335 {
336 
337   struct passwd *pwd = NULL;           /* 定义指向passwd结构的指针 */
338 
339  
340 
341   if (use_name)
342 
343     {
344 
345       pwd = getpwuid (uid);              /* 从密码文件中获取指定uid的数据 */
346 
347       if (pwd == NULL)                   /* 如果数据获取失败,输出错误信息,并将变量ok设为false */
348 
349         {
350 
351           error (0, 0, _("cannot find name for user ID %lu"),
352 
353                  (unsigned long int) uid);
354 
355           ok = false;
356 
357         }
358 
359     }
360 
361  
362 
363   if (pwd == NULL)
364 
365     printf ("%lu", (unsigned long int) uid);              /* 输出用户ID */
366 
367   else
368 
369     printf ("%s", pwd->pw_name);                  /* 输出用户名称 */
370 
371 }
372 
373 static void
374 
375 print_group (gid_t gid)
376 
377 {
378 
379   struct group *grp = NULL;             /* 定义指向group结构的指针 */
380 
381  
382 
383   if (use_name)
384 
385     {
386 
387       grp = getgrgid (gid);                /* 从组文件中获取指定gid的数据 */
388 
389       if (grp == NULL)                   /* 如果数据获取失败,输出错误信息,并将变量ok设为false */
390 
391         {
392 
393           error (0, 0, _("cannot find name for group ID %lu"),
394 
395                  (unsigned long int) gid);
396 
397           ok = false;
398 
399         }
400 
401     }
402 
403  
404 
405   if (grp == NULL)
406 
407     printf ("%lu", (unsigned long int) gid);              /* 输出用户组ID */
408 
409   else
410 
411     printf ("%s", grp->gr_name);                    /* 输出用户组名称 */
412 
413 }
414 
415 static bool
416 
417 xgetgroups (const char *username, gid_t gid, int *n_groups,
418 
419            GETGROUPS_T **groups)
420 
421 {
422 
423   int max_n_groups;
424 
425   int ng;
426 
427   GETGROUPS_T *g = NULL;
428 
429   /* 调用getgroups或getugroups函数获取用户所属的组数,并保存到变量max_n_groups之中 */
430 
431   if (!username) 
432 
433     max_n_groups = getgroups (0, NULL);
434 
435   else
436 
437     max_n_groups = getugroups (0, NULL, username, gid);
438 
439  
440 
441   if (max_n_groups < 0)
442 
443     ng = -1;
444 
445   else
446 
447     {
448 
449       g = xnmalloc (max_n_groups, sizeof *g);               /* 根据组数分配内存空间 */
450 
451       if (!username)
452 
453         ng = getgroups (max_n_groups, g);                    /* 获取用户所属的组ID,报讯到 */
454 
455       else
456 
457         ng = getugroups (max_n_groups, g, username, gid);
458 
459     }
460 
461   /* 根据ng的取值,完成函数返回前的相关处理工作,例如释放内存空间,返回组数、组ID等 */
462 
463   if (ng < 0)
464 
465     {
466 
467       error (0, errno, _("cannot get supplemental group list"));
468 
469       free (g);
470 
471       return false;
472 
473     }
474 
475   else
476 
477     {
478 
479       *n_groups = ng;
480 
481       *groups = g;
482 
483       return true;
484 
485     }
486 
487 }
488 
489 static void
490 
491 print_group_list (const char *username)       /* 输入参数为用户名 */
492 
493 {
494 
495   struct passwd *pwd;                       /* 定义指向passwd结构的指针 */
496 
497  
498 
499   pwd = getpwuid (ruid);                          /* 从密码文件中获取指定uid的数据 */
500 
501   if (pwd == NULL)                                /* 如果数据获取失败,并将变量ok设为false */
502 
503     ok = false;
504 
505  
506 
507   print_group (rgid);                                 /* 输出实际组ID或组名 */
508 
509   if (egid != rgid)                              /* 判断有效组ID与实际组ID是否相同 */
510 
511     {
512 
513       putchar (' ');
514 
515       print_group (egid);                         /* 输出有效组ID或组名 */
516 
517     }
518 
519   int n_groups;
520 
521   GETGROUPS_T *groups;
522 
523   int i;
524 
525   /* 调用xgetgroups函数获取用户所属组的数目和组ID,并处理函数的返回结果 */
526 
527   if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
528 
529                 &n_groups, &groups))
530 
531     {
532 
533       ok = false;
534 
535       return;
536 
537     }
538 
539   /* 输出用户所有的附加组ID或名称 */
540 
541   for (i = 0; i < n_groups; i++)
542 
543     if (groups[i] != rgid && groups[i] != egid)    /* 判断是否为实际用户组ID和有效用户组ID */
544 
545       {
546 
547         putchar (' ');
548 
549         print_group (groups[i]);
550 
551       }
552 
553   free (groups);
554 
555 }
556 
557 t_group_list函数的功能是输出用户所属附加组的标识符或名称。
558 
559 static void
560 
561 print_full_info (const char *username)
562 
563 {
564 
565   struct passwd *pwd;                       /* 定义指向passwd结构的指针 */
566 
567   struct group *grp;                                 /* 定义指向group结构的指针 */
568 
569  
570 
571   printf ("uid=%lu", (unsigned long int) ruid);         /* 输出实际用户ID */
572 
573   pwd = getpwuid (ruid);                          /* 获取实际用户的信息 */
574 
575   if (pwd)
576 
577     printf ("(%s)", pwd->pw_name);               /* 输出实际用户的名称 */
578 
579  
580 
581   printf (" gid=%lu", (unsigned long int) rgid);               /* 输出实际用户组ID */
582 
583   grp = getgrgid (rgid);                            /* 获取实际用户组的信息 */
584 
585   if (grp)
586 
587     printf ("(%s)", grp->gr_name);           /* 输出实际用户组的名称 */
588 
589   /* 如果有效用户ID与实际用户ID不同,输出有效用户ID与名称 */
590 
591   if (euid != ruid)         
592 
593     {
594 
595       printf (" euid=%lu", (unsigned long int) euid);
596 
597       pwd = getpwuid (euid);
598 
599       if (pwd)
600 
601         printf ("(%s)", pwd->pw_name);
602 
603     }
604 
605   /* 如果有效用户组ID与实际用户组ID不同,输出有效用户组ID与名称 */
606 
607   if (egid != rgid)
608 
609     {
610 
611       printf (" egid=%lu", (unsigned long int) egid);
612 
613       grp = getgrgid (egid);
614 
615       if (grp)
616 
617         printf ("(%s)", grp->gr_name);
618 
619     }
620 
621  
622 
623   int n_groups;
624 
625   GETGROUPS_T *groups;
626 
627   int i;
628 
629   /* 输出用户所有的附加组ID */
630 
631   if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
632 
633                 &n_groups, &groups))
634 
635     {
636 
637       ok = false;
638 
639       return;
640 
641     }
642 
643   /* 输出用户所有的附加组名称 */
644 
645   if (n_groups > 0)
646 
647     fputs (_(" groups="), stdout);
648 
649   for (i = 0; i < n_groups; i++)
650 
651     {
652 
653       if (i > 0)
654 
655         putchar (',');
656 
657       printf ("%lu", (unsigned long int) groups[i]);
658 
659       grp = getgrgid (groups[i]);
660 
661       if (grp)
662 
663         printf ("(%s)", grp->gr_name);
664 
665     }
666 
667   free (groups);
668 
669 }

 

 

 

posted @ 2012-04-19 19:27  MooreZHENG  阅读(554)  评论(0编辑  收藏  举报