Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5e3c30f

Browse files
nathan-bossartpull[bot]
authored andcommitted
Teach in-tree getopt_long() to move non-options to the end of argv.
Unlike the other implementations of getopt_long() I could find, thein-tree implementation does not reorder non-options to the end ofargv. Instead, it returns -1 as soon as the first non-option isfound, even if there are other options listed afterwards. Bymoving non-options to the end of argv, getopt_long() can parse allspecified options and return -1 when only non-options remain.This quirk is periodically missed by hackers (e.g.,869aa40,ffd3980, andd9ddc50). This commit introduces theaforementioned non-option reordering behavior to the in-treegetopt_long() implementation.Special thanks to Noah Misch for his help verifying behavior onAIX.Reviewed-by: Kyotaro Horiguchi, Michael PaquierDiscussion:https://postgr.es/m/20230609232257.GA121461%40nathanxps13
1 parent8dc2a54 commit5e3c30f

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

‎src/bin/scripts/t/040_createuser.pl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@
4242
'add a role as a member with admin option of the newly created role');
4343
$node->issues_sql_like(
4444
[
45-
'createuser','-m',
46-
'regress_user3','-m',
47-
'regress user #4','REGRESS_USER5'
45+
'createuser','REGRESS_USER5','-m','regress_user3',
46+
'-m','regress user #4'
4847
],
4948
qr/statement: CREATE ROLE "REGRESS_USER5" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS ROLE regress_user3,"regress user #4";/,
5049
'add a role as a member of the newly created role');
@@ -73,11 +72,14 @@
7372
qr/statement: CREATE ROLE regress_user11 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS IN ROLE regress_user1;/,
7473
'--role');
7574
$node->issues_sql_like(
76-
['createuser','--member-of','regress_user1','regress_user12' ],
75+
['createuser','regress_user12','--member-of','regress_user1' ],
7776
qr/statement: CREATE ROLE regress_user12 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS IN ROLE regress_user1;/,
7877
'--member-of');
7978

8079
$node->command_fails(['createuser','regress_user1' ],
8180
'fails if role already exists');
81+
$node->command_fails(
82+
['createuser','regress_user1','-m','regress_user2','regress_user3' ],
83+
'fails for too many non-options');
8284

8385
done_testing();

‎src/port/getopt_long.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@
5050
* This implementation does not use optreset. Instead, we guarantee that
5151
* it can be restarted on a new argv array after a previous call returned -1,
5252
* if the caller resets optind to 1 before the first call of the new series.
53-
* (Internally, this means we must be sure to reset "place" to EMSG before
54-
* returning -1.)
53+
* (Internally, this means we must be sure to reset "place" to EMSG,
54+
* "nonopt_start" to -1, and "force_nonopt" to false before returning -1.)
55+
*
56+
* Note that this routine reorders the pointers in argv (despite the const
57+
* qualifier) so that all non-options will be at the end when -1 is returned.
5558
*/
5659
int
5760
getopt_long(intargc,char*constargv[],
@@ -60,38 +63,58 @@ getopt_long(int argc, char *const argv[],
6063
{
6164
staticchar*place=EMSG;/* option letter processing */
6265
char*oli;/* option letter list index */
66+
staticintnonopt_start=-1;
67+
staticboolforce_nonopt= false;
6368

6469
if (!*place)
6570
{/* update scanning pointer */
66-
if (optind >=argc)
71+
char**args= (char**)argv;
72+
73+
retry:
74+
75+
/*
76+
* If we are out of arguments or only non-options remain, return -1.
77+
*/
78+
if (optind >=argc||optind==nonopt_start)
6779
{
6880
place=EMSG;
81+
nonopt_start=-1;
82+
force_nonopt= false;
6983
return-1;
7084
}
7185

7286
place=argv[optind];
7387

74-
if (place[0]!='-')
88+
/*
89+
* An argument is a non-option if it meets any of the following
90+
* criteria: it follows an argument that is equivalent to the string
91+
* "--", it does not start with '-', or it is equivalent to the string
92+
* "-". When we encounter a non-option, we move it to the end of argv
93+
* (after shifting all remaining arguments over to make room), and
94+
* then we try again with the next argument.
95+
*/
96+
if (force_nonopt||place[0]!='-'||place[1]=='\0')
7597
{
76-
place=EMSG;
77-
return-1;
78-
}
98+
for (inti=optind;i<argc-1;i++)
99+
args[i]=args[i+1];
100+
args[argc-1]=place;
79101

80-
place++;
102+
if (nonopt_start==-1)
103+
nonopt_start=argc-1;
104+
else
105+
nonopt_start--;
81106

82-
if (!*place)
83-
{
84-
/* treat "-" as not being an option */
85-
place=EMSG;
86-
return-1;
107+
gotoretry;
87108
}
88109

110+
place++;
111+
89112
if (place[0]=='-'&&place[1]=='\0')
90113
{
91114
/* found "--", treat it as end of options */
92115
++optind;
93-
place=EMSG;
94-
return-1;
116+
force_nonopt=true;
117+
gotoretry;
95118
}
96119

97120
if (place[0]=='-'&&place[1])

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp