Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
e645c6e4
Commit
e645c6e4
authored
Oct 09, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor resetprop
parent
78a3d36c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
306 additions
and
201 deletions
+306
-201
resetprop.h
jni/include/resetprop.h
+4
-2
hide_utils.c
jni/magiskhide/hide_utils.c
+2
-2
magiskhide.c
jni/magiskhide/magiskhide.c
+2
-2
resetprop.cpp
jni/resetprop/resetprop.cpp
+298
-195
No files found.
jni/include/resetprop.h
View file @
e645c6e4
...
...
@@ -12,9 +12,11 @@ int prop_exist(const char *name);
int
setprop
(
const
char
*
name
,
const
char
*
value
);
int
setprop2
(
const
char
*
name
,
const
char
*
value
,
const
int
trigger
);
char
*
getprop
(
const
char
*
name
);
int
deleteprop
(
const
char
*
name
,
const
int
trigger
);
char
*
getprop2
(
const
char
*
name
,
int
persist
);
int
deleteprop
(
const
char
*
name
);
int
deleteprop2
(
const
char
*
name
,
const
int
persist
);
int
read_prop_file
(
const
char
*
filename
,
const
int
trigger
);
void
getprop_all
(
void
(
*
c
bk
)(
const
char
*
name
));
void
getprop_all
(
void
(
*
c
allback
)(
const
char
*
,
const
char
*
));
#ifdef __cplusplus
}
...
...
jni/magiskhide/hide_utils.c
View file @
e645c6e4
...
...
@@ -58,9 +58,9 @@ void hide_sensitive_props() {
}
}
static
void
rm_magisk_prop
(
const
char
*
name
)
{
static
void
rm_magisk_prop
(
const
char
*
name
,
const
char
*
value
)
{
if
(
strstr
(
name
,
"magisk"
))
{
deleteprop
(
name
,
0
);
deleteprop
2
(
name
,
0
);
}
}
...
...
jni/magiskhide/magiskhide.c
View file @
e645c6e4
...
...
@@ -55,7 +55,7 @@ void launch_magiskhide(int client) {
hideEnabled
=
1
;
LOGI
(
"* Starting MagiskHide
\n
"
);
deleteprop
(
MAGISKHIDE_PROP
,
1
);
deleteprop
2
(
MAGISKHIDE_PROP
,
1
);
hide_sensitive_props
();
...
...
@@ -102,7 +102,7 @@ void stop_magiskhide(int client) {
hideEnabled
=
0
;
setprop
(
MAGISKHIDE_PROP
,
"0"
);
// Remove without actually removing persist props
deleteprop
(
MAGISKHIDE_PROP
,
0
);
deleteprop
2
(
MAGISKHIDE_PROP
,
0
);
pthread_kill
(
proc_monitor_thread
,
SIGUSR1
);
write_int
(
client
,
DAEMON_SUCCESS
);
...
...
jni/resetprop/resetprop.cpp
View file @
e645c6e4
...
...
@@ -56,249 +56,352 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "_system_properties.h"
#include "system_properties.h"
#include "magisk.h"
#include "resetprop.h"
extern
"C"
{
#include "vector.h"
}
#define PRINT_D(...) { LOGD(__VA_ARGS__); if (verbose)
printf(
__VA_ARGS__); }
#define PRINT_D(...) { LOGD(__VA_ARGS__); if (verbose)
fprintf(stderr,
__VA_ARGS__); }
#define PRINT_E(...) { LOGE(__VA_ARGS__); fprintf(stderr, __VA_ARGS__); }
#define PERSISTENT_PROPERTY_DIR "/data/property"
static
int
verbose
=
0
;
static
bool
is_legal_property_name
(
const
char
*
name
,
size_t
namelen
)
{
if
(
namelen
<
1
)
return
false
;
if
(
name
[
0
]
==
'.'
)
return
false
;
if
(
name
[
namelen
-
1
]
==
'.'
)
return
false
;
/* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
/* Don't allow ".." to appear in a property name */
for
(
size_t
i
=
0
;
i
<
namelen
;
i
++
)
{
if
(
name
[
i
]
==
'.'
)
{
// i=0 is guaranteed to never have a dot. See above.
if
(
name
[
i
-
1
]
==
'.'
)
return
false
;
continue
;
}
if
(
name
[
i
]
==
'_'
||
name
[
i
]
==
'-'
||
name
[
i
]
==
'@'
||
name
[
i
]
==
':'
)
continue
;
if
(
name
[
i
]
>=
'a'
&&
name
[
i
]
<=
'z'
)
continue
;
if
(
name
[
i
]
>=
'A'
&&
name
[
i
]
<=
'Z'
)
continue
;
if
(
name
[
i
]
>=
'0'
&&
name
[
i
]
<=
'9'
)
continue
;
return
false
;
}
return
true
;
static
int
check_legal_property_name
(
const
char
*
name
)
{
int
namelen
=
strlen
(
name
);
if
(
namelen
<
1
)
goto
illegal
;
if
(
name
[
0
]
==
'.'
)
goto
illegal
;
if
(
name
[
namelen
-
1
]
==
'.'
)
goto
illegal
;
/* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
/* Don't allow ".." to appear in a property name */
for
(
size_t
i
=
0
;
i
<
namelen
;
i
++
)
{
if
(
name
[
i
]
==
'.'
)
{
// i=0 is guaranteed to never have a dot. See above.
if
(
name
[
i
-
1
]
==
'.'
)
goto
illegal
;
continue
;
}
if
(
name
[
i
]
==
'_'
||
name
[
i
]
==
'-'
||
name
[
i
]
==
'@'
||
name
[
i
]
==
':'
)
continue
;
if
(
name
[
i
]
>=
'a'
&&
name
[
i
]
<=
'z'
)
continue
;
if
(
name
[
i
]
>=
'A'
&&
name
[
i
]
<=
'Z'
)
continue
;
if
(
name
[
i
]
>=
'0'
&&
name
[
i
]
<=
'9'
)
continue
;
goto
illegal
;
}
return
0
;
illegal:
PRINT_E
(
"Illegal property name: [%s]
\n
"
,
name
);
return
1
;
}
static
int
usage
(
char
*
arg0
)
{
fprintf
(
stderr
,
"resetprop v"
xstr
(
MAGISK_VERSION
)
"("
xstr
(
MAGISK_VER_CODE
)
") (by topjohnwu & nkk71) - System Props Modification Tool
\n\n
"
"Usage: %s [options] [args...]
\n
"
"
\n
"
"Options:
\n
"
" -v show verbose output
\n
"
" -n only modify property in memory
\n
"
"
\n
"
"%s NAME VALUE set property entry NAME with VALUE
\n
"
"%s --file FILE load props from FILE
\n
"
"%s --delete NAME remove prop entry NAME
\n
"
"
\n
"
,
arg0
,
arg0
,
arg0
,
arg0
);
return
1
;
fprintf
(
stderr
,
"resetprop v"
xstr
(
MAGISK_VERSION
)
"("
xstr
(
MAGISK_VER_CODE
)
") (by topjohnwu & nkk71) - System Props Modification Tool
\n\n
"
"Usage: %s [flags] [options...]
\n
"
"
\n
"
"Options:
\n
"
" -h, --help show this message
\n
"
" (no arguments) print all properties
\n
"
" NAME get property
\n
"
" NAME VALUE set property entry NAME with VALUE
\n
"
" --file FILE load props from FILE
\n
"
" --delete NAME delete property
\n
"
"
\n
"
"Flags:
\n
"
" -v print verbose output to stderr
\n
"
" -n set properties without init triggers
\n
"
" only affects setprop
\n
"
" -p access actual persist storage
\n
"
" only affects getprop and deleteprop
\n
"
"
\n
"
,
arg0
);
return
1
;
}
static
int
init_resetprop
()
{
if
(
__system_properties_init2
())
{
PRINT_E
(
"resetprop: Initialize error
\n
"
);
return
-
1
;
}
return
0
;
if
(
__system_properties_init2
())
{
PRINT_E
(
"resetprop: Initialize error
\n
"
);
return
-
1
;
}
return
0
;
}
int
prop_exist
(
const
char
*
name
)
{
if
(
init_resetprop
())
return
0
;
return
__system_property_find2
(
name
)
!=
NULL
;
if
(
init_resetprop
())
return
0
;
return
__system_property_find2
(
name
)
!=
NULL
;
}
static
void
read_prop_info
(
void
*
cookie
,
const
char
*
name
,
const
char
*
value
,
uint32_t
serial
)
{
strcpy
((
char
*
)
cookie
,
value
);
strcpy
((
char
*
)
cookie
,
value
);
}
// Get prop by name, return string (should free manually!)
char
*
getprop
(
const
char
*
name
)
{
if
(
init_resetprop
())
return
NULL
;
const
prop_info
*
pi
=
__system_property_find2
(
name
);
if
(
pi
==
NULL
)
{
PRINT_D
(
"resetprop: prop [%s] does not exist
\n
"
,
name
);
return
NULL
;
}
char
value
[
PROP_VALUE_MAX
];
__system_property_read_callback2
(
pi
,
read_prop_info
,
value
);
PRINT_D
(
"resetprop: getprop [%s]: [%s]
\n
"
,
name
,
value
);
return
strdup
(
value
);
return
getprop2
(
name
,
0
);
}
static
void
(
*
cb
)(
const
char
*
);
// Get prop by name, return string (should free manually!)
char
*
getprop2
(
const
char
*
name
,
int
persist
)
{
if
(
check_legal_property_name
(
name
))
return
NULL
;
char
value
[
PROP_VALUE_MAX
];
if
(
init_resetprop
())
return
NULL
;
const
prop_info
*
pi
=
__system_property_find2
(
name
);
if
(
pi
==
NULL
)
{
if
(
persist
&&
strncmp
(
name
,
"persist."
,
8
)
==
0
)
{
// Try to read from file
char
path
[
PATH_MAX
];
snprintf
(
path
,
sizeof
(
path
),
PERSISTENT_PROPERTY_DIR
"/%s"
,
name
);
int
fd
=
open
(
path
,
O_RDONLY
|
O_CLOEXEC
);
if
(
fd
<
0
)
goto
no_prop
;
PRINT_D
(
"resetprop: read prop from [%s]
\n
"
,
path
);
size_t
len
=
read
(
fd
,
value
,
sizeof
(
value
));
value
[
len
]
=
'\0'
;
// Null terminate the read value
}
else
{
no_prop:
PRINT_D
(
"resetprop: prop [%s] does not exist
\n
"
,
name
);
return
NULL
;
}
}
else
{
__system_property_read_callback2
(
pi
,
read_prop_info
,
value
);
}
PRINT_D
(
"resetprop: getprop [%s]: [%s]
\n
"
,
name
,
value
);
return
strdup
(
value
);
}
static
void
run_actual_cb
(
void
*
cookie
,
const
char
*
name
,
const
char
*
value
,
uint32_t
serial
)
{
cb
(
name
);
struct
wrapper
{
void
(
*
func
)(
const
char
*
,
const
char
*
);
};
static
void
cb_wrapper
(
void
*
cookie
,
const
char
*
name
,
const
char
*
value
,
uint32_t
serial
)
{
((
wrapper
*
)
cookie
)
->
func
(
name
,
value
);
}
static
void
prop_foreach_cb
(
const
prop_info
*
pi
,
void
*
cookie
)
{
__system_property_read_callback2
(
pi
,
run_actual_cb
,
NULL
);
__system_property_read_callback2
(
pi
,
cb_wrapper
,
cookie
);
}
class
property
{
public
:
property
(
const
char
*
n
,
const
char
*
v
)
{
name
=
strdup
(
n
);
value
=
strdup
(
v
);
}
~
property
()
{
free
((
void
*
)
name
);
free
((
void
*
)
value
);
}
const
char
*
name
;
const
char
*
value
;
};
vector
prop_list
;
static
int
prop_cmp
(
const
void
*
p1
,
const
void
*
p2
)
{
return
strcmp
((
*
((
property
**
)
p1
))
->
name
,
(
*
((
property
**
)
p2
))
->
name
);
}
static
void
print_all_props_cb
(
const
char
*
name
,
const
char
*
value
)
{
vec_push_back
(
&
prop_list
,
new
property
(
name
,
value
));
}
static
void
print_all_props
(
int
persist
)
{
void
*
p
;
vec_init
(
&
prop_list
);
getprop_all
(
print_all_props_cb
);
if
(
persist
)
{
// Check all persist props in data
DIR
*
dir
=
opendir
(
PERSISTENT_PROPERTY_DIR
);
struct
dirent
*
entry
;
while
((
entry
=
readdir
(
dir
)))
{
if
(
strcmp
(
entry
->
d_name
,
"."
)
==
0
||
strcmp
(
entry
->
d_name
,
".."
)
==
0
)
continue
;
int
found
=
0
;
vec_for_each
(
&
prop_list
,
p
)
{
if
(
strcmp
(((
property
*
)
p
)
->
name
,
entry
->
d_name
)
==
0
)
{
found
=
1
;
break
;
}
}
if
(
!
found
)
vec_push_back
(
&
prop_list
,
new
property
(
entry
->
d_name
,
getprop2
(
entry
->
d_name
,
1
)));
}
}
vec_sort
(
&
prop_list
,
prop_cmp
);
vec_for_each
(
&
prop_list
,
p
)
{
printf
(
"[%s]: [%s]
\n
"
,
((
property
*
)
p
)
->
name
,
((
property
*
)
p
)
->
value
);
delete
((
property
*
)
p
);
}
vec_destroy
(
&
prop_list
);
}
void
getprop_all
(
void
(
*
cbk
)(
const
char
*
name
))
{
if
(
init_resetprop
())
return
;
cb
=
cbk
;
__system_property_foreach2
(
prop_foreach_cb
,
NULL
);
void
getprop_all
(
void
(
*
callback
)(
const
char
*
,
const
char
*
))
{
if
(
init_resetprop
())
return
;
struct
wrapper
wrap
=
{
.
func
=
callback
};
__system_property_foreach2
(
prop_foreach_cb
,
&
wrap
);
}
int
setprop
(
const
char
*
name
,
const
char
*
value
)
{
return
setprop2
(
name
,
value
,
1
);
return
setprop2
(
name
,
value
,
1
);
}
int
setprop2
(
const
char
*
name
,
const
char
*
value
,
const
int
trigger
)
{
if
(
init_resetprop
())
return
-
1
;
int
ret
;
prop_info
*
pi
=
(
prop_info
*
)
__system_property_find2
(
name
);
if
(
pi
!=
NULL
)
{
if
(
trigger
)
{
if
(
!
strncmp
(
name
,
"ro."
,
3
))
deleteprop
(
name
,
trigger
);
ret
=
__system_property_set2
(
name
,
value
);
}
else
{
ret
=
__system_property_update2
(
pi
,
value
,
strlen
(
value
));
}
}
else
{
PRINT_D
(
"resetprop: New prop [%s]
\n
"
,
name
);
if
(
trigger
)
{
ret
=
__system_property_set2
(
name
,
value
);
}
else
{
ret
=
__system_property_add2
(
name
,
strlen
(
name
),
value
,
strlen
(
value
));
}
}
PRINT_D
(
"resetprop: setprop [%s]: [%s] by %s
\n
"
,
name
,
value
,
trigger
?
"property_service"
:
"modifing prop data structure"
);
if
(
ret
)
PRINT_E
(
"resetprop: setprop error
\n
"
);
return
ret
;
if
(
check_legal_property_name
(
name
))
return
1
;
if
(
init_resetprop
())
return
-
1
;
int
ret
;
prop_info
*
pi
=
(
prop_info
*
)
__system_property_find2
(
name
);
if
(
pi
!=
NULL
)
{
if
(
trigger
)
{
if
(
strncmp
(
name
,
"ro."
,
3
)
==
0
)
deleteprop
(
name
);
ret
=
__system_property_set2
(
name
,
value
);
}
else
{
ret
=
__system_property_update2
(
pi
,
value
,
strlen
(
value
));
}
}
else
{
PRINT_D
(
"resetprop: New prop [%s]
\n
"
,
name
);
if
(
trigger
)
{
ret
=
__system_property_set2
(
name
,
value
);
}
else
{
ret
=
__system_property_add2
(
name
,
strlen
(
name
),
value
,
strlen
(
value
));
}
}
PRINT_D
(
"resetprop: setprop [%s]: [%s] by %s
\n
"
,
name
,
value
,
trigger
?
"property_service"
:
"modifing prop data structure"
);
if
(
ret
)
PRINT_E
(
"resetprop: setprop error
\n
"
);
return
ret
;
}
int
deleteprop
(
const
char
*
name
)
{
return
deleteprop2
(
name
,
1
);
}
int
deleteprop
(
const
char
*
name
,
const
int
trigger
)
{
if
(
init_resetprop
())
return
-
1
;
PRINT_D
(
"resetprop: deleteprop [%s]
\n
"
,
name
);
if
(
trigger
&&
strstr
(
name
,
"persist."
))
{
char
buffer
[
PATH_MAX
];
snprintf
(
buffer
,
sizeof
(
buffer
),
"%s/%s"
,
PERSISTENT_PROPERTY_DIR
,
name
);
unlink
(
buffer
);
}
return
__system_property_del
(
name
);
int
deleteprop2
(
const
char
*
name
,
const
int
persist
)
{
if
(
check_legal_property_name
(
name
))
return
1
;
if
(
init_resetprop
())
return
-
1
;
char
path
[
PATH_MAX
];
path
[
0
]
=
'\0'
;
PRINT_D
(
"resetprop: deleteprop [%s]
\n
"
,
name
);
if
(
persist
&&
strncmp
(
name
,
"persist."
,
8
)
==
0
)
snprintf
(
path
,
sizeof
(
path
),
PERSISTENT_PROPERTY_DIR
"/%s"
,
name
);
return
__system_property_del
(
name
)
&&
unlink
(
path
);
}
int
read_prop_file
(
const
char
*
filename
,
const
int
trigger
)
{
if
(
init_resetprop
())
return
-
1
;
PRINT_D
(
"resetprop: Load prop file [%s]
\n
"
,
filename
);
FILE
*
fp
=
fopen
(
filename
,
"r"
);
if
(
fp
==
NULL
)
{
PRINT_E
(
"Cannot open [%s]
\n
"
,
filename
);
return
1
;
}
char
*
line
=
NULL
,
*
pch
;
size_t
len
;
ssize_t
read
;
int
comment
=
0
,
i
;
while
((
read
=
getline
(
&
line
,
&
len
,
fp
))
!=
-
1
)
{
// Remove the trailing newline
if
(
line
[
read
-
1
]
==
'\n'
)
{
line
[
read
-
1
]
=
'\0'
;
--
read
;
}
comment
=
0
;
for
(
i
=
0
;
i
<
read
;
++
i
)
{
// Ignore starting spaces
if
(
line
[
i
]
==
' '
)
continue
;
else
{
// A line starting with # is ignored
if
(
line
[
i
]
==
'#'
)
comment
=
1
;
break
;
}
}
if
(
comment
)
continue
;
pch
=
strchr
(
line
,
'='
);
// Ignore ivalid formats
if
(
((
pch
==
NULL
)
||
(
i
>=
(
pch
-
line
)))
||
(
pch
>=
line
+
read
-
1
)
)
continue
;
// Separate the string
*
pch
=
'\0'
;
setprop2
(
line
+
i
,
pch
+
1
,
trigger
);
}
free
(
line
);
fclose
(
fp
);
return
0
;
if
(
init_resetprop
())
return
-
1
;
PRINT_D
(
"resetprop: Load prop file [%s]
\n
"
,
filename
);
FILE
*
fp
=
fopen
(
filename
,
"r"
);
if
(
fp
==
NULL
)
{
PRINT_E
(
"Cannot open [%s]
\n
"
,
filename
);
return
1
;
}
char
*
line
=
NULL
,
*
pch
;
size_t
len
;
ssize_t
read
;
int
comment
=
0
,
i
;
while
((
read
=
getline
(
&
line
,
&
len
,
fp
))
!=
-
1
)
{
// Remove the trailing newline
if
(
line
[
read
-
1
]
==
'\n'
)
{
line
[
read
-
1
]
=
'\0'
;
--
read
;
}
comment
=
0
;
for
(
i
=
0
;
i
<
read
;
++
i
)
{
// Ignore starting spaces
if
(
line
[
i
]
==
' '
)
continue
;
else
{
// A line starting with # is ignored
if
(
line
[
i
]
==
'#'
)
comment
=
1
;
break
;
}
}
if
(
comment
)
continue
;
pch
=
strchr
(
line
,
'='
);
// Ignore ivalid formats
if
(
((
pch
==
NULL
)
||
(
i
>=
(
pch
-
line
)))
||
(
pch
>=
line
+
read
-
1
)
)
continue
;
// Separate the string
*
pch
=
'\0'
;
setprop2
(
line
+
i
,
pch
+
1
,
trigger
);
}
free
(
line
);
fclose
(
fp
);
return
0
;
}
int
resetprop_main
(
int
argc
,
char
*
argv
[])
{
int
del
=
0
,
file
=
0
,
trigger
=
1
;
int
exp_arg
=
2
;
char
*
name
,
*
value
,
*
filename
;
if
(
argc
<
3
)
{
return
usage
(
argv
[
0
]);
}
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
if
(
!
strcmp
(
"-v"
,
argv
[
i
]))
{
verbose
=
1
;
}
else
if
(
!
strcmp
(
"-n"
,
argv
[
i
]))
{
trigger
=
0
;
}
else
if
(
!
strcmp
(
"--file"
,
argv
[
i
]))
{
file
=
1
;
exp_arg
=
1
;
}
else
if
(
!
strcmp
(
"--delete"
,
argv
[
i
]))
{
del
=
1
;
exp_arg
=
1
;
}
else
{
if
(
i
+
exp_arg
>
argc
)
{
return
usage
(
argv
[
0
]);
}
if
(
file
)
{
filename
=
argv
[
i
];
break
;
}
else
{
if
(
!
is_legal_property_name
(
argv
[
i
],
strlen
(
argv
[
i
])))
{
PRINT_E
(
"Illegal property name: [%s]
\n
"
,
argv
[
i
]);
return
1
;
}
name
=
argv
[
i
];
if
(
exp_arg
>
1
)
{
if
(
strlen
(
argv
[
i
+
1
])
>=
PROP_VALUE_MAX
)
{
PRINT_E
(
"Value too long: [%s]
\n
"
,
argv
[
i
+
1
]);
return
1
;
}
value
=
argv
[
i
+
1
];
}
break
;
}
}
}
if
(
file
)
{
return
read_prop_file
(
filename
,
trigger
);
}
else
if
(
del
)
{
return
deleteprop
(
name
,
trigger
);
}
else
{
return
setprop2
(
name
,
value
,
trigger
);
}
return
0
;
int
trigger
=
1
,
persist
=
0
;
char
*
argv0
=
argv
[
0
],
*
prop
;
--
argc
;
++
argv
;
// Parse flags and -- options
while
(
argc
&&
argv
[
0
][
0
]
==
'-'
)
{
for
(
int
idx
=
1
;
1
;
++
idx
)
{
switch
(
argv
[
0
][
idx
])
{
case
'-'
:
if
(
strcmp
(
argv
[
0
],
"--file"
)
==
0
&&
argc
==
2
)
{
return
read_prop_file
(
argv
[
1
],
trigger
);
}
else
if
(
strcmp
(
argv
[
0
],
"--delete"
)
==
0
&&
argc
==
2
)
{
return
deleteprop2
(
argv
[
1
],
persist
);
}
else
if
(
strcmp
(
argv
[
0
],
"--help"
)
==
0
)
{
goto
usage
;
}
case
'v'
:
verbose
=
1
;
continue
;
case
'p'
:
persist
=
1
;
continue
;
case
'n'
:
trigger
=
0
;
continue
;
case
'\0'
:
break
;
case
'h'
:
default:
usage:
return
usage
(
argv0
);
}
break
;
}
--
argc
;
++
argv
;
}
switch
(
argc
)
{
case
0
:
print_all_props
(
persist
);
return
0
;
case
1
:
prop
=
getprop2
(
argv
[
0
],
persist
);
if
(
prop
==
NULL
)
return
1
;
printf
(
"%s
\n
"
,
prop
);
free
(
prop
);
return
0
;
case
2
:
return
setprop2
(
argv
[
0
],
argv
[
1
],
trigger
);
default:
usage
(
argv0
);
return
1
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment