zoukankan      html  css  js  c++  java
  • 嵌入式成长轨迹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 }

     

     

  • 相关阅读:
    华为OSPF与ACL综合应用
    综合练习2 设置访问权限,Easy-IP访问外网,内外网访问
    综合练习1,划分vlan,单臂路由,DHCP服务及其限制网段、租期,设置根桥,OSPF路由通告综合练习
    在eNSP下使用Hybird接口
    在eNSP上配置VLAN的Trunk端口
    在ensp上模拟企业网络场景并Access接口加入相应VLAN
    网络安全设备
    WooYun虚拟机的搭建以及配置
    IIS web服务器访问日志
    apache访问日志目录以及术语返回码
  • 原文地址:https://www.cnblogs.com/zeedmood/p/2457752.html
Copyright © 2011-2022 走看看