3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #define _WIN32_WINNT 0x0600
24 #include <sys/fcntl.h>
25 #include <sys/cygwin.h>
26 #include <cygwin/version.h>
36 #define print_win_error(x) _print_win_error(x, __LINE__)
38 #define MAX_SID_LEN 40
40 SID_IDENTIFIER_AUTHORITY sid_world_auth
= {SECURITY_WORLD_SID_AUTHORITY
};
41 SID_IDENTIFIER_AUTHORITY sid_nt_auth
= {SECURITY_NT_AUTHORITY
};
44 #define min(a,b) (((a)<(b))?(a):(b))
56 _print_win_error (DWORD code
, int line
)
60 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
61 | FORMAT_MESSAGE_IGNORE_INSERTS
,
64 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
65 (LPTSTR
) buf
, sizeof (buf
), NULL
))
66 fprintf (stderr
, "mkgroup (%d): [%" PRIu32
"] %s",
67 line
, (unsigned int) code
, buf
);
69 fprintf (stderr
, "mkgroup (%d): error %" PRIu32
,
70 line
, (unsigned int) code
);
74 get_dcname (char *domain
)
76 static WCHAR server
[INTERNET_MAX_HOST_NAME_LENGTH
+ 1];
78 WCHAR domain_name
[MAX_DOMAIN_NAME_LEN
+ 1];
79 PDOMAIN_CONTROLLER_INFOW pdci
= NULL
;
83 mbstowcs (domain_name
, domain
, strlen (domain
) + 1);
84 rc
= DsGetDcNameW (NULL
, domain_name
, NULL
, NULL
, 0, &pdci
);
87 rc
= DsGetDcNameW (NULL
, NULL
, NULL
, NULL
, 0, &pdci
);
88 if (rc
!= ERROR_SUCCESS
)
93 wcscpy (server
, pdci
->DomainControllerName
);
94 NetApiBufferFree (pdci
);
106 sprintf(t
, "%u", GetSidIdentifierAuthority (psid
)->Value
[5]);
108 for (i
= 0; i
< *GetSidSubAuthorityCount (psid
); ++i
)
110 sprintf(t
, "-%" PRIu32
, (unsigned int) *GetSidSubAuthority (psid
, i
));
118 BYTE SubAuthorityCount
;
119 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
120 DWORD SubAuthority
[8];
123 #define MAX_BUILTIN_SIDS 100 /* Should be enough for the forseable future. */
124 DBGSID builtin_sid_list
[MAX_BUILTIN_SIDS
];
125 DWORD builtin_sid_cnt
;
132 static sidbuf curr_pgrp
;
133 static BOOL got_curr_pgrp
= FALSE
;
136 fetch_current_pgrp_sid ()
141 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &ptok
)
142 || !GetTokenInformation (ptok
, TokenPrimaryGroup
, &curr_pgrp
,
143 sizeof curr_pgrp
, &len
)
144 || !CloseHandle (ptok
))
146 print_win_error (GetLastError ());
152 current_group (const char *sep
, DWORD id_offset
)
154 WCHAR grp
[GNLEN
+ 1];
155 WCHAR dom
[MAX_DOMAIN_NAME_LEN
+ 1];
156 DWORD glen
= GNLEN
+ 1;
157 DWORD dlen
= MAX_DOMAIN_NAME_LEN
+ 1;
159 SID_NAME_USE acc_type
;
162 || !LookupAccountSidW (NULL
, curr_pgrp
.psid
, grp
, &glen
, dom
, &dlen
,
165 print_win_error (GetLastError ());
168 gid
= *GetSidSubAuthority (curr_pgrp
.psid
,
169 *GetSidSubAuthorityCount(curr_pgrp
.psid
) - 1);
170 printf ("%ls%s%ls:%s:%" PRIu32
":\n",
174 put_sid (curr_pgrp
.psid
),
175 (unsigned int) (id_offset
+ gid
));
179 enum_unix_groups (domlist_t
*dom_or_machine
, const char *sep
, DWORD id_offset
,
182 WCHAR machine
[INTERNET_MAX_HOST_NAME_LENGTH
+ 1];
183 PWCHAR servername
= NULL
;
184 char *d_or_m
= dom_or_machine
? dom_or_machine
->str
: NULL
;
185 BOOL with_dom
= dom_or_machine
? dom_or_machine
->with_dom
: FALSE
;
186 SID_IDENTIFIER_AUTHORITY auth
= { { 0, 0, 0, 0, 0, 22 } };
187 char *gstr
, *grp_list
;
188 WCHAR grp
[GNLEN
+ sizeof ("Unix Group\\") + 1];
189 WCHAR dom
[MAX_DOMAIN_NAME_LEN
+ 1];
190 DWORD glen
, dlen
, sidlen
;
192 char psid_buffer
[MAX_SID_LEN
];
193 SID_NAME_USE acc_type
;
198 int ret
= mbstowcs (machine
, d_or_m
, INTERNET_MAX_HOST_NAME_LENGTH
+ 1);
199 if (ret
< 1 || ret
>= INTERNET_MAX_HOST_NAME_LENGTH
+ 1)
201 fprintf (stderr
, "%s: Invalid machine name '%s'. Skipping...\n",
202 program_invocation_short_name
, d_or_m
);
205 servername
= machine
;
207 if (!AllocateAndInitializeSid (&auth
, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid
))
210 if (!(grp_list
= strdup (unix_grp_list
)))
216 for (gstr
= strtok (grp_list
, ","); gstr
; gstr
= strtok (NULL
, ","))
218 if (!isdigit ((unsigned char) gstr
[0]) && gstr
[0] != '-')
220 PWCHAR p
= wcpcpy (grp
, L
"Unix Group\\");
221 ret
= mbstowcs (p
, gstr
, GNLEN
+ 1);
222 if (ret
< 1 || ret
>= GNLEN
+ 1)
223 fprintf (stderr
, "%s: Invalid group name '%s'. Skipping...\n",
224 program_invocation_short_name
, gstr
);
225 else if (LookupAccountNameW (servername
, grp
,
226 psid
= (PSID
) psid_buffer
,
227 (sidlen
= MAX_SID_LEN
, &sidlen
),
229 (dlen
= MAX_DOMAIN_NAME_LEN
+ 1, &dlen
),
231 printf ("%s%s%ls:%s:%" PRIu32
":\n",
232 with_dom
? "Unix Group" : "",
236 (unsigned int) (id_offset
+
237 *GetSidSubAuthority (psid
,
238 *GetSidSubAuthorityCount(psid
) - 1)));
247 start
= strtol (p
, &p
, 10);
250 else if (*p
++ != '-' || !isdigit ((unsigned char) *p
)
251 || (stop
= strtol (p
, &p
, 10)) < start
|| *p
)
253 fprintf (stderr
, "%s: Malformed unix group list entry '%s'. "
255 program_invocation_short_name
, gstr
);
258 for (; start
<= stop
; ++ start
)
260 *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1)
262 if (LookupAccountSidW (servername
, psid
,
263 grp
, (glen
= GNLEN
+ 1, &glen
),
265 (dlen
= MAX_DOMAIN_NAME_LEN
+ 1, &dlen
),
267 && !iswdigit (grp
[0]))
268 printf ("%s%s%ls:%s:%" PRIu32
":\n",
269 with_dom
? "Unix Group" : "",
273 (unsigned int) (id_offset
+ start
));
283 enum_local_groups (BOOL domain
, domlist_t
*dom_or_machine
, const char *sep
,
284 DWORD id_offset
, char *disp_groupname
, int print_builtin
,
287 WCHAR machine
[INTERNET_MAX_HOST_NAME_LENGTH
+ 1];
288 PWCHAR servername
= NULL
;
289 char *d_or_m
= dom_or_machine
? dom_or_machine
->str
: NULL
;
290 BOOL with_dom
= dom_or_machine
? dom_or_machine
->with_dom
: FALSE
;
291 LOCALGROUP_INFO_0
*buffer
;
292 DWORD entriesread
= 0;
293 DWORD totalentries
= 0;
294 DWORD_PTR resume_handle
= 0;
295 WCHAR gname
[GNLEN
+ 1];
300 servername
= get_dcname (d_or_m
);
301 if (servername
== (PWCHAR
) -1)
306 int ret
= mbstowcs (machine
, d_or_m
, INTERNET_MAX_HOST_NAME_LENGTH
+ 1);
307 if (ret
< 1 || ret
>= INTERNET_MAX_HOST_NAME_LENGTH
+ 1)
309 fprintf (stderr
, "%s: Invalid machine name '%s'. Skipping...\n",
310 program_invocation_short_name
, d_or_m
);
313 servername
= machine
;
322 mbstowcs (gname
, disp_groupname
, GNLEN
+ 1);
323 rc
= NetLocalGroupGetInfo (servername
, gname
, 0, (void *) &buffer
);
324 if (rc
== ERROR_SUCCESS
)
326 /* Allow further searching for the group and avoid annoying
327 error messages just because the group is not a local group or
328 the group hasn't been found. */
329 else if (rc
== ERROR_NO_SUCH_ALIAS
|| rc
== NERR_GroupNotFound
)
333 rc
= NetLocalGroupEnum (servername
, 0, (void *) &buffer
,
334 MAX_PREFERRED_LENGTH
, &entriesread
,
335 &totalentries
, &resume_handle
);
338 case ERROR_ACCESS_DENIED
:
339 print_win_error (rc
);
342 case ERROR_MORE_DATA
:
347 print_win_error (rc
);
351 for (i
= 0; i
< entriesread
; i
++)
353 WCHAR domain_name
[MAX_DOMAIN_NAME_LEN
+ 1];
354 DWORD domname_len
= MAX_DOMAIN_NAME_LEN
+ 1;
355 char psid_buffer
[MAX_SID_LEN
];
356 PSID psid
= (PSID
) psid_buffer
;
357 DWORD sid_length
= MAX_SID_LEN
;
359 SID_NAME_USE acc_type
;
361 BOOL is_builtin
= FALSE
;
363 if (!LookupAccountNameW (servername
, buffer
[i
].lgrpi0_name
, psid
,
364 &sid_length
, domain_name
, &domname_len
,
367 print_win_error (GetLastError ());
368 fprintf (stderr
, " (%ls)\n", buffer
[i
].lgrpi0_name
);
371 else if (acc_type
== SidTypeDomain
)
373 WCHAR domname
[MAX_DOMAIN_NAME_LEN
+ GNLEN
+ 2];
375 wcscpy (domname
, domain_name
);
376 wcscat (domname
, L
"\\");
377 wcscat (domname
, buffer
[i
].lgrpi0_name
);
378 sid_length
= MAX_SID_LEN
;
379 domname_len
= MAX_DOMAIN_NAME_LEN
+ 1;
380 if (!LookupAccountNameW (servername
, domname
,
382 domain_name
, &domname_len
,
385 print_win_error (GetLastError ());
386 fprintf(stderr
, " (%ls)\n", domname
);
391 /* Store all local SIDs with prefix "S-1-5-32-" and check if it
392 has been printed already. This allows to get all builtin
393 groups exactly once and not once per domain. */
394 pdsid
= (PDBGSID
) psid
;
395 if (pdsid
->IdentifierAuthority
.Value
[5] == sid_nt_auth
.Value
[5]
396 && pdsid
->SubAuthority
[0] == SECURITY_BUILTIN_DOMAIN_RID
)
404 for (b
= 0; b
< builtin_sid_cnt
; b
++)
405 if (EqualSid (&builtin_sid_list
[b
], psid
))
407 if (builtin_sid_cnt
< MAX_BUILTIN_SIDS
)
408 CopySid (sizeof (DBGSID
), &builtin_sid_list
[builtin_sid_cnt
++],
413 else if (EqualSid (curr_pgrp
.psid
, psid
))
414 got_curr_pgrp
= TRUE
;
416 gid
= *GetSidSubAuthority (psid
, *GetSidSubAuthorityCount(psid
) - 1);
417 printf ("%ls%s%ls:%s:%" PRIu32
":\n",
418 with_dom
&& !is_builtin
? domain_name
: L
"",
419 with_dom
&& !is_builtin
? sep
: "",
420 buffer
[i
].lgrpi0_name
,
422 (unsigned int) (gid
+ (is_builtin
? 0 : id_offset
)));
427 NetApiBufferFree (buffer
);
430 while (rc
== ERROR_MORE_DATA
);
432 /* Return 1 if the single group we're looking for has been found here to
433 avoid calling enum_groups for the same group, thus avoiding a spurious
434 error message "group name could not be found" in enum_groups. */
435 return disp_groupname
&& entriesread
? 1 : 0;
439 enum_groups (BOOL domain
, domlist_t
*dom_or_machine
, const char *sep
,
440 DWORD id_offset
, char *disp_groupname
, int print_current
)
442 WCHAR machine
[INTERNET_MAX_HOST_NAME_LENGTH
+ 1];
443 PWCHAR servername
= NULL
;
444 char *d_or_m
= dom_or_machine
? dom_or_machine
->str
: NULL
;
445 BOOL with_dom
= dom_or_machine
? dom_or_machine
->with_dom
: FALSE
;
446 GROUP_INFO_2
*buffer
;
447 DWORD entriesread
= 0;
448 DWORD totalentries
= 0;
449 DWORD_PTR resume_handle
= 0;
450 WCHAR gname
[GNLEN
+ 1];
455 servername
= get_dcname (d_or_m
);
456 if (servername
== (PWCHAR
) -1)
461 int ret
= mbstowcs (machine
, d_or_m
, INTERNET_MAX_HOST_NAME_LENGTH
+ 1);
462 if (ret
< 1 || ret
>= INTERNET_MAX_HOST_NAME_LENGTH
+ 1)
464 fprintf (stderr
, "%s: Invalid machine name '%s'. Skipping...\n",
465 program_invocation_short_name
, d_or_m
);
468 servername
= machine
;
475 if (disp_groupname
!= NULL
)
477 mbstowcs (gname
, disp_groupname
, GNLEN
+ 1);
478 rc
= NetGroupGetInfo (servername
, (LPWSTR
) & gname
, 2,
481 /* Avoid annoying error messages just because the group hasn't been
483 if (rc
== NERR_GroupNotFound
)
487 rc
= NetGroupEnum (servername
, 2, (void *) & buffer
,
488 MAX_PREFERRED_LENGTH
, &entriesread
, &totalentries
,
492 case ERROR_ACCESS_DENIED
:
493 print_win_error (rc
);
496 case ERROR_MORE_DATA
:
501 print_win_error (rc
);
505 for (i
= 0; i
< entriesread
; i
++)
507 WCHAR domain_name
[MAX_DOMAIN_NAME_LEN
+ 1];
508 DWORD domname_len
= MAX_DOMAIN_NAME_LEN
+ 1;
509 char psid_buffer
[MAX_SID_LEN
];
510 PSID psid
= (PSID
) psid_buffer
;
511 DWORD sid_length
= MAX_SID_LEN
;
512 SID_NAME_USE acc_type
;
514 int gid
= buffer
[i
].grpi2_group_id
;
515 if (!LookupAccountNameW (servername
, buffer
[i
].grpi2_name
,
517 domain_name
, &domname_len
,
520 print_win_error (GetLastError ());
521 fprintf(stderr
, " (%ls)\n", buffer
[i
].grpi2_name
);
524 else if (acc_type
== SidTypeDomain
)
526 WCHAR domname
[MAX_DOMAIN_NAME_LEN
+ GNLEN
+ 2];
528 wcscpy (domname
, domain
|| !servername
529 ? domain_name
: servername
);
530 wcscat (domname
, L
"\\");
531 wcscat (domname
, buffer
[i
].grpi2_name
);
532 sid_length
= MAX_SID_LEN
;
533 domname_len
= MAX_DOMAIN_NAME_LEN
+ 1;
534 if (!LookupAccountNameW (servername
, domname
,
536 domain_name
, &domname_len
,
539 print_win_error (GetLastError ());
540 fprintf(stderr
, " (%ls)\n", domname
);
546 else if (EqualSid (curr_pgrp
.psid
, psid
))
547 got_curr_pgrp
= TRUE
;
549 printf ("%ls%s%ls:%s:%" PRIu32
":\n",
550 with_dom
? domain_name
: L
"",
552 buffer
[i
].grpi2_name
,
554 (unsigned int) (id_offset
+ gid
));
557 NetApiBufferFree (buffer
);
560 while (rc
== ERROR_MORE_DATA
);
564 print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth
, BYTE cnt
,
565 DWORD sub1
, DWORD sub2
, DWORD sub3
, DWORD sub4
,
566 DWORD sub5
, DWORD sub6
, DWORD sub7
, DWORD sub8
)
568 WCHAR grp
[GNLEN
+ 1], dom
[MAX_DOMAIN_NAME_LEN
+ 1];
569 DWORD glen
, dlen
, rid
;
571 SID_NAME_USE acc_type
;
573 if (AllocateAndInitializeSid (auth
, cnt
, sub1
, sub2
, sub3
, sub4
,
574 sub5
, sub6
, sub7
, sub8
, &psid
))
576 if (LookupAccountSidW (NULL
, psid
,
577 grp
, (glen
= GNLEN
+ 1, &glen
),
578 dom
, (dlen
= MAX_DOMAIN_NAME_LEN
+ 1, &dlen
),
597 printf ("%ls:%s:%" PRIu32
":\n", grp
, put_sid (psid
),
605 print_special_by_name (PCWSTR name
, gid_t gid
)
607 DWORD size
= 256, dom_size
= 256;
608 PSID sid
= (PSID
) alloca (size
);
612 PWCHAR name_only
= wcschr (name
, L
'\\');
616 if (LookupAccountNameW (NULL
, name
, sid
, &size
, dom
, &dom_size
, &use
))
617 printf ("%ls:%s:%lu:\n",
618 name_only
?: name
, put_sid (sid
), (unsigned long) gid
);
622 usage (FILE * stream
)
625 "Usage: %s [OPTION]...\n"
627 "Print /etc/group file to stdout\n"
631 " -l,--local [machine[,offset]]\n"
632 " print local groups with gid offset offset\n"
633 " (from local machine if no machine specified)\n"
634 " -L,--Local [machine[,offset]]\n"
635 " ditto, but generate groupname with machine prefix\n"
636 " -d,--domain [domain[,offset]]\n"
637 " print domain groups with gid offset offset\n"
638 " (from current domain if no domain specified)\n"
639 " -D,--Domain [domain[,offset]]\n"
640 " ditto, but generate groupname with machine prefix\n"
641 " -c,--current print current group\n"
642 " -C,--Current ditto, but generate groupname with machine or\n"
644 " -S,--separator char for -L, -D, -C use character char as domain\\group\n"
645 " separator in groupname instead of the default '\\'\n"
646 " -o,--id-offset offset change the default offset (10000) added to gids\n"
647 " in domain or foreign server accounts.\n"
648 " -g,--group groupname only return information for the specified group\n"
649 " one of -l, -L, -d, -D must be specified, too\n"
650 " -b,--no-builtin don't print BUILTIN groups\n"
651 " -U,--unix grouplist additionally print UNIX groups when using -l or -L\n"
652 " on a UNIX Samba server\n"
653 " grouplist is a comma-separated list of groupnames\n"
654 " or gid ranges (root,-25,50-100).\n"
655 " (enumerating large ranges can take a long time!)\n"
656 " -s,--no-sids (ignored)\n"
657 " -u,--users (ignored)\n"
658 " -h,--help print this message\n"
659 " -v,--version print version information and exit\n"
661 "Default is to print local groups on stand-alone machines, plus domain\n"
662 "groups on domain controllers and domain member machines.\n"
663 "\n", program_invocation_short_name
);
667 struct option longopts
[] = {
668 {"no-builtin", no_argument
, NULL
, 'b'},
669 {"current", no_argument
, NULL
, 'c'},
670 {"Current", no_argument
, NULL
, 'C'},
671 {"domain", optional_argument
, NULL
, 'd'},
672 {"Domain", optional_argument
, NULL
, 'D'},
673 {"group", required_argument
, NULL
, 'g'},
674 {"help", no_argument
, NULL
, 'h'},
675 {"local", optional_argument
, NULL
, 'l'},
676 {"Local", optional_argument
, NULL
, 'L'},
677 {"id-offset", required_argument
, NULL
, 'o'},
678 {"no-sids", no_argument
, NULL
, 's'},
679 {"separator", required_argument
, NULL
, 'S'},
680 {"users", no_argument
, NULL
, 'u'},
681 {"unix", required_argument
, NULL
, 'U'},
682 {"version", no_argument
, NULL
, 'V'},
683 {0, no_argument
, NULL
, 0}
686 static char opts
[] = "bcCd::D::g:hl::L::o:sS:uU:V";
691 printf ("mkgroup (cygwin) %d.%d.%d\n"
692 "Group File Generator\n"
693 "Copyright (C) 1997 - %s Red Hat, Inc.\n"
694 "This is free software; see the source for copying conditions. There is NO\n"
695 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
696 CYGWIN_VERSION_DLL_MAJOR
/ 1000,
697 CYGWIN_VERSION_DLL_MAJOR
% 1000,
698 CYGWIN_VERSION_DLL_MINOR
,
699 strrchr (__DATE__
, ' ') + 1);
702 static PPOLICY_PRIMARY_DOMAIN_INFO p_dom
;
705 fetch_primary_domain ()
708 LSA_OBJECT_ATTRIBUTES oa
= { 0, 0, 0, 0, 0, 0 };
713 status
= LsaOpenPolicy (NULL
, &oa
, POLICY_EXECUTE
, &lsa
);
714 if (!NT_SUCCESS (status
))
716 status
= LsaQueryInformationPolicy (lsa
, PolicyPrimaryDomainInformation
,
717 (PVOID
*) ((void *) &p_dom
));
719 if (!NT_SUCCESS (status
))
726 main (int argc
, char **argv
)
728 int print_domlist
= 0;
729 domlist_t domlist
[32];
731 int print_current
= 0;
732 int print_system
= 0;
733 int print_builtin
= 1;
734 char *print_unix
= NULL
;
735 const char *sep_char
= "\\";
736 DWORD id_offset
= 10000, off
;
738 char *disp_groupname
= NULL
;
740 int optional_args
= 0;
743 setmode (1, O_BINARY
);
745 /* Use locale from environment. If not set or set to "C", use UTF-8. */
746 setlocale (LC_CTYPE
, "");
747 if (!strcmp (setlocale (LC_CTYPE
, NULL
), "C"))
748 setlocale (LC_CTYPE
, "en_US.UTF-8");
749 in_domain
= fetch_primary_domain ();
750 fetch_current_pgrp_sid ();
754 print_special_by_sid (&sid_nt_auth
, 1, SECURITY_LOCAL_SYSTEM_RID
,
755 0, 0, 0, 0, 0, 0, 0);
758 if (!enum_local_groups (TRUE
, NULL
, sep_char
, id_offset
,
759 disp_groupname
, print_builtin
, 0))
760 enum_groups (TRUE
, NULL
, sep_char
, id_offset
, disp_groupname
, 0);
762 else if (!enum_local_groups (FALSE
, NULL
, sep_char
, 0, disp_groupname
,
764 enum_groups (FALSE
, NULL
, sep_char
, 0, disp_groupname
, 0);
768 unsetenv ("POSIXLY_CORRECT"); /* To get optional arg processing right. */
769 while ((c
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
776 if (print_domlist
>= 32)
778 fprintf (stderr
, "%s: Can not enumerate from more than 32 "
779 "domains and machines.\n",
780 program_invocation_short_name
);
783 domlist
[print_domlist
].domain
= (c
== 'd' || c
== 'D');
785 argv
[optind
] && argv
[optind
][0] != '-' ? argv
[optind
] : NULL
;
786 if (argv
[optind
] && opt
== argv
[optind
])
788 for (i
= 0; i
< print_domlist
; ++i
)
789 if (domlist
[i
].domain
== domlist
[print_domlist
].domain
790 && ((!domlist
[i
].str
&& !opt
)
791 || (domlist
[i
].str
&& opt
792 && (off
= strlen (domlist
[i
].str
))
793 && !strncmp (domlist
[i
].str
, opt
, off
)
794 && (!opt
[off
] || opt
[off
] == ','))))
796 fprintf (stderr
, "%s: Duplicate %s '%s'. Skipping...\n",
797 program_invocation_short_name
,
798 domlist
[i
].domain
? "domain" : "machine",
802 if (!(domlist
[print_domlist
].str
= opt
))
804 domlist
[print_domlist
].id_offset
= UINT32_MAX
;
805 if (opt
&& (p
= strchr (opt
, ',')))
808 || !isdigit ((unsigned char) p
[1])
809 || (domlist
[print_domlist
].id_offset
= strtol (p
+ 1, &ep
, 10)
812 fprintf (stderr
, "%s: Malformed machine,offset string '%s'. "
813 "Skipping...\n", program_invocation_short_name
, opt
);
818 domlist
[print_domlist
++].with_dom
= (c
== 'D' || c
== 'L');
823 if (strlen (sep_char
) > 1)
825 fprintf (stderr
, "%s: Only one character allowed as domain\\user "
826 "separator character.\n",
827 program_invocation_short_name
);
830 if (*sep_char
== ':')
832 fprintf (stderr
, "%s: Colon not allowed as domain\\user separator "
833 "character.\n", program_invocation_short_name
);
847 id_offset
= strtol (optarg
, NULL
, 10);
857 disp_groupname
= optarg
;
866 fprintf (stderr
, "Try `%s --help' for more information.\n", argv
[0]);
870 optind
+= optional_args
;
874 "mkgroup: non-option command line argument `%s' is not allowed.\n"
875 "Try `mkgroup --help' for more information.\n", argv
[optind
]);
879 /* Get 'system' group */
880 if (!disp_groupname
&& print_system
&& print_builtin
&& print_domlist
)
882 print_special_by_sid (&sid_nt_auth
, 1, SECURITY_LOCAL_SYSTEM_RID
,
883 0, 0, 0, 0, 0, 0, 0);
884 print_special_by_name (L
"NT SERVICE\\TrustedInstaller", -2);
888 for (i
= 0; i
< print_domlist
; ++i
)
890 DWORD my_off
= (domlist
[i
].domain
|| domlist
[i
].str
)
891 ? domlist
[i
].id_offset
!= UINT_MAX
892 ? domlist
[i
].id_offset
: off
: 0;
893 if (!enum_local_groups (domlist
[i
].domain
, domlist
+ i
, sep_char
,
894 my_off
, disp_groupname
, print_builtin
, print_current
))
896 if (!domlist
[i
].domain
&& domlist
[i
].str
&& print_unix
)
897 enum_unix_groups (domlist
+ i
, sep_char
, my_off
, print_unix
);
898 enum_groups (domlist
[i
].domain
, domlist
+ i
, sep_char
, my_off
,
899 disp_groupname
, print_current
);
905 if (print_current
&& !got_curr_pgrp
)
906 current_group (sep_char
, off
);