Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
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
Chen Yisong
lxc
Commits
0e4be3cf
Unverified
Commit
0e4be3cf
authored
Feb 27, 2018
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
console: s/tty_info/ttys/g
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
2520facd
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
48 additions
and
49 deletions
+48
-49
conf.c
src/lxc/conf.c
+20
-20
conf.h
src/lxc/conf.h
+4
-5
console.c
src/lxc/console.c
+11
-11
criu.c
src/lxc/criu.c
+6
-6
start.c
src/lxc/start.c
+7
-7
No files found.
src/lxc/conf.c
View file @
0e4be3cf
...
@@ -840,15 +840,15 @@ static bool append_ptyname(char **pp, char *name)
...
@@ -840,15 +840,15 @@ static bool append_ptyname(char **pp, char *name)
static
int
lxc_setup_ttys
(
struct
lxc_conf
*
conf
)
static
int
lxc_setup_ttys
(
struct
lxc_conf
*
conf
)
{
{
int
i
,
ret
;
int
i
,
ret
;
const
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
const
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
char
*
ttydir
=
conf
->
ttydir
;
char
*
ttydir
=
conf
->
ttydir
;
char
path
[
MAXPATHLEN
],
lxcpath
[
MAXPATHLEN
];
char
path
[
MAXPATHLEN
],
lxcpath
[
MAXPATHLEN
];
if
(
!
conf
->
rootfs
.
path
)
if
(
!
conf
->
rootfs
.
path
)
return
0
;
return
0
;
for
(
i
=
0
;
i
<
tty
_info
->
nbtty
;
i
++
)
{
for
(
i
=
0
;
i
<
tty
s
->
nbtty
;
i
++
)
{
struct
lxc_terminal_info
*
tty
=
&
tty
_info
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
tty
s
->
tty
[
i
];
ret
=
snprintf
(
path
,
sizeof
(
path
),
"/dev/tty%d"
,
i
+
1
);
ret
=
snprintf
(
path
,
sizeof
(
path
),
"/dev/tty%d"
,
i
+
1
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
))
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
))
...
@@ -926,32 +926,32 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
...
@@ -926,32 +926,32 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
}
}
}
}
INFO
(
"Finished setting up %d /dev/tty<N> device(s)"
,
tty
_info
->
nbtty
);
INFO
(
"Finished setting up %d /dev/tty<N> device(s)"
,
tty
s
->
nbtty
);
return
0
;
return
0
;
}
}
int
lxc_allocate_ttys
(
const
char
*
name
,
struct
lxc_conf
*
conf
)
int
lxc_allocate_ttys
(
const
char
*
name
,
struct
lxc_conf
*
conf
)
{
{
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
int
i
,
ret
;
int
i
,
ret
;
/* no tty in the configuration */
/* no tty in the configuration */
if
(
!
conf
->
tty
)
if
(
!
conf
->
tty
)
return
0
;
return
0
;
tty
_info
->
tty
=
malloc
(
sizeof
(
*
tty_info
->
tty
)
*
conf
->
tty
);
tty
s
->
tty
=
malloc
(
sizeof
(
*
ttys
->
tty
)
*
conf
->
tty
);
if
(
!
tty
_info
->
tty
)
if
(
!
tty
s
->
tty
)
return
-
ENOMEM
;
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
struct
lxc_terminal_info
*
tty
=
&
tty
_info
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
tty
s
->
tty
[
i
];
ret
=
openpty
(
&
tty
->
master
,
&
tty
->
slave
,
ret
=
openpty
(
&
tty
->
master
,
&
tty
->
slave
,
tty
->
name
,
NULL
,
NULL
);
tty
->
name
,
NULL
,
NULL
);
if
(
ret
)
{
if
(
ret
)
{
SYSERROR
(
"failed to create pty device number %d"
,
i
);
SYSERROR
(
"failed to create pty device number %d"
,
i
);
tty
_info
->
nbtty
=
i
;
tty
s
->
nbtty
=
i
;
lxc_delete_tty
(
tty
_info
);
lxc_delete_tty
(
tty
s
);
return
-
ENOTTY
;
return
-
ENOTTY
;
}
}
...
@@ -974,33 +974,33 @@ int lxc_allocate_ttys(const char *name, struct lxc_conf *conf)
...
@@ -974,33 +974,33 @@ int lxc_allocate_ttys(const char *name, struct lxc_conf *conf)
tty
->
busy
=
0
;
tty
->
busy
=
0
;
}
}
tty
_info
->
nbtty
=
conf
->
tty
;
tty
s
->
nbtty
=
conf
->
tty
;
INFO
(
"finished allocating %d pts devices"
,
conf
->
tty
);
INFO
(
"finished allocating %d pts devices"
,
conf
->
tty
);
return
0
;
return
0
;
}
}
void
lxc_delete_tty
(
struct
lxc_tty_info
*
tty
_info
)
void
lxc_delete_tty
(
struct
lxc_tty_info
*
tty
s
)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
tty
_info
->
nbtty
;
i
++
)
{
for
(
i
=
0
;
i
<
tty
s
->
nbtty
;
i
++
)
{
struct
lxc_terminal_info
*
tty
=
&
tty
_info
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
tty
s
->
tty
[
i
];
close
(
tty
->
master
);
close
(
tty
->
master
);
close
(
tty
->
slave
);
close
(
tty
->
slave
);
}
}
free
(
tty
_info
->
tty
);
free
(
tty
s
->
tty
);
tty
_info
->
tty
=
NULL
;
tty
s
->
tty
=
NULL
;
tty
_info
->
nbtty
=
0
;
tty
s
->
nbtty
=
0
;
}
}
static
int
lxc_send_ttys_to_parent
(
struct
lxc_handler
*
handler
)
static
int
lxc_send_ttys_to_parent
(
struct
lxc_handler
*
handler
)
{
{
int
i
;
int
i
;
struct
lxc_conf
*
conf
=
handler
->
conf
;
struct
lxc_conf
*
conf
=
handler
->
conf
;
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
int
sock
=
handler
->
data_sock
[
0
];
int
sock
=
handler
->
data_sock
[
0
];
int
ret
=
-
1
;
int
ret
=
-
1
;
...
@@ -1009,7 +1009,7 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
...
@@ -1009,7 +1009,7 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
int
ttyfds
[
2
];
int
ttyfds
[
2
];
struct
lxc_terminal_info
*
tty
=
&
tty
_info
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
tty
s
->
tty
[
i
];
ttyfds
[
0
]
=
tty
->
master
;
ttyfds
[
0
]
=
tty
->
master
;
ttyfds
[
1
]
=
tty
->
slave
;
ttyfds
[
1
]
=
tty
->
slave
;
...
@@ -1065,7 +1065,7 @@ static int lxc_create_ttys(struct lxc_handler *handler)
...
@@ -1065,7 +1065,7 @@ static int lxc_create_ttys(struct lxc_handler *handler)
ret
=
0
;
ret
=
0
;
on_error:
on_error:
lxc_delete_tty
(
&
conf
->
tty
_info
);
lxc_delete_tty
(
&
conf
->
tty
s
);
return
ret
;
return
ret
;
}
}
...
...
src/lxc/conf.h
View file @
0e4be3cf
...
@@ -134,8 +134,7 @@ struct id_map {
...
@@ -134,8 +134,7 @@ struct id_map {
unsigned
long
hostid
,
nsid
,
range
;
unsigned
long
hostid
,
nsid
,
range
;
};
};
/*
/* Defines the number of tty configured and contains the
* Defines the number of tty configured and contains the
* instantiated ptys
* instantiated ptys
* @nbtty = number of configured ttys
* @nbtty = number of configured ttys
*/
*/
...
@@ -203,7 +202,7 @@ enum {
...
@@ -203,7 +202,7 @@ enum {
* @fstab : path to a fstab file format
* @fstab : path to a fstab file format
* @caps : list of the capabilities to drop
* @caps : list of the capabilities to drop
* @keepcaps : list of the capabilities to keep
* @keepcaps : list of the capabilities to keep
* @tty
_info
: tty data
* @tty
s
: tty data
* @console : console data
* @console : console data
* @ttydir : directory (under /dev) in which to create console and ttys
* @ttydir : directory (under /dev) in which to create console and ttys
* @lsm_aa_profile : apparmor profile to switch to or NULL
* @lsm_aa_profile : apparmor profile to switch to or NULL
...
@@ -258,7 +257,7 @@ struct lxc_conf {
...
@@ -258,7 +257,7 @@ struct lxc_conf {
struct
lxc_list
mount_list
;
struct
lxc_list
mount_list
;
struct
lxc_list
caps
;
struct
lxc_list
caps
;
struct
lxc_list
keepcaps
;
struct
lxc_list
keepcaps
;
struct
lxc_tty_info
tty
_info
;
struct
lxc_tty_info
tty
s
;
/* Comma-separated list of lxc.tty.max pty names. */
/* Comma-separated list of lxc.tty.max pty names. */
char
*
pty_names
;
char
*
pty_names
;
struct
lxc_terminal
console
;
struct
lxc_terminal
console
;
...
@@ -387,7 +386,7 @@ extern void lxc_conf_free(struct lxc_conf *conf);
...
@@ -387,7 +386,7 @@ extern void lxc_conf_free(struct lxc_conf *conf);
extern
int
pin_rootfs
(
const
char
*
rootfs
);
extern
int
pin_rootfs
(
const
char
*
rootfs
);
extern
int
lxc_map_ids
(
struct
lxc_list
*
idmap
,
pid_t
pid
);
extern
int
lxc_map_ids
(
struct
lxc_list
*
idmap
,
pid_t
pid
);
extern
int
lxc_create_tty
(
const
char
*
name
,
struct
lxc_conf
*
conf
);
extern
int
lxc_create_tty
(
const
char
*
name
,
struct
lxc_conf
*
conf
);
extern
void
lxc_delete_tty
(
struct
lxc_tty_info
*
tty
_info
);
extern
void
lxc_delete_tty
(
struct
lxc_tty_info
*
tty
s
);
extern
int
lxc_clear_config_caps
(
struct
lxc_conf
*
c
);
extern
int
lxc_clear_config_caps
(
struct
lxc_conf
*
c
);
extern
int
lxc_clear_config_keepcaps
(
struct
lxc_conf
*
c
);
extern
int
lxc_clear_config_keepcaps
(
struct
lxc_conf
*
c
);
extern
int
lxc_clear_cgroups
(
struct
lxc_conf
*
c
,
const
char
*
key
,
int
version
);
extern
int
lxc_clear_cgroups
(
struct
lxc_conf
*
c
,
const
char
*
key
,
int
version
);
...
...
src/lxc/console.c
View file @
0e4be3cf
...
@@ -578,7 +578,7 @@ err1:
...
@@ -578,7 +578,7 @@ err1:
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttyreq
)
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttyreq
)
{
{
int
masterfd
=
-
1
,
ttynum
;
int
masterfd
=
-
1
,
ttynum
;
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
if
(
*
ttyreq
==
0
)
{
if
(
*
ttyreq
==
0
)
{
...
@@ -589,10 +589,10 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
...
@@ -589,10 +589,10 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
}
}
if
(
*
ttyreq
>
0
)
{
if
(
*
ttyreq
>
0
)
{
if
(
*
ttyreq
>
tty
_info
->
nbtty
)
if
(
*
ttyreq
>
tty
s
->
nbtty
)
goto
out
;
goto
out
;
if
(
tty
_info
->
tty
[
*
ttyreq
-
1
].
busy
)
if
(
tty
s
->
tty
[
*
ttyreq
-
1
].
busy
)
goto
out
;
goto
out
;
/* the requested tty is available */
/* the requested tty is available */
...
@@ -601,18 +601,18 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
...
@@ -601,18 +601,18 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
}
}
/* search for next available tty, fixup index tty1 => [0] */
/* search for next available tty, fixup index tty1 => [0] */
for
(
ttynum
=
1
;
ttynum
<=
tty
_info
->
nbtty
&&
tty_info
->
tty
[
ttynum
-
1
].
busy
;
ttynum
++
)
for
(
ttynum
=
1
;
ttynum
<=
tty
s
->
nbtty
&&
ttys
->
tty
[
ttynum
-
1
].
busy
;
ttynum
++
)
;
;
/* we didn't find any available slot for tty */
/* we didn't find any available slot for tty */
if
(
ttynum
>
tty
_info
->
nbtty
)
if
(
ttynum
>
tty
s
->
nbtty
)
goto
out
;
goto
out
;
*
ttyreq
=
ttynum
;
*
ttyreq
=
ttynum
;
out_tty
:
out_tty
:
tty
_info
->
tty
[
ttynum
-
1
].
busy
=
sockfd
;
tty
s
->
tty
[
ttynum
-
1
].
busy
=
sockfd
;
masterfd
=
tty
_info
->
tty
[
ttynum
-
1
].
master
;
masterfd
=
tty
s
->
tty
[
ttynum
-
1
].
master
;
out
:
out
:
return
masterfd
;
return
masterfd
;
}
}
...
@@ -620,12 +620,12 @@ out:
...
@@ -620,12 +620,12 @@ out:
void
lxc_terminal_free
(
struct
lxc_conf
*
conf
,
int
fd
)
void
lxc_terminal_free
(
struct
lxc_conf
*
conf
,
int
fd
)
{
{
int
i
;
int
i
;
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
for
(
i
=
0
;
i
<
tty
_info
->
nbtty
;
i
++
)
{
for
(
i
=
0
;
i
<
tty
s
->
nbtty
;
i
++
)
{
if
(
tty
_info
->
tty
[
i
].
busy
==
fd
)
if
(
tty
s
->
tty
[
i
].
busy
==
fd
)
tty
_info
->
tty
[
i
].
busy
=
0
;
tty
s
->
tty
[
i
].
busy
=
0
;
}
}
if
(
terminal
->
peerpty
.
busy
==
fd
)
{
if
(
terminal
->
peerpty
.
busy
==
fd
)
{
...
...
src/lxc/criu.c
View file @
0e4be3cf
...
@@ -176,7 +176,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -176,7 +176,7 @@ static void exec_criu(struct criu_opts *opts)
FILE
*
mnts
;
FILE
*
mnts
;
struct
mntent
mntent
;
struct
mntent
mntent
;
char
buf
[
4096
],
tty
_info
[
32
];
char
buf
[
4096
],
tty
s
[
32
];
size_t
pos
;
size_t
pos
;
/* If we are currently in a cgroup /foo/bar, and the container is in a
/* If we are currently in a cgroup /foo/bar, and the container is in a
...
@@ -233,12 +233,12 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -233,12 +233,12 @@ static void exec_criu(struct criu_opts *opts)
*/
*/
static_args
+=
6
;
static_args
+=
6
;
tty
_info
[
0
]
=
0
;
tty
s
[
0
]
=
0
;
if
(
load_tty_major_minor
(
opts
->
user
->
directory
,
tty
_info
,
sizeof
(
tty_info
)))
if
(
load_tty_major_minor
(
opts
->
user
->
directory
,
tty
s
,
sizeof
(
ttys
)))
return
;
return
;
/* --inherit-fd fd[%d]:tty[%s] */
/* --inherit-fd fd[%d]:tty[%s] */
if
(
tty
_info
[
0
])
if
(
tty
s
[
0
])
static_args
+=
2
;
static_args
+=
2
;
}
else
{
}
else
{
return
;
return
;
...
@@ -493,13 +493,13 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -493,13 +493,13 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG
(
"--restore-detached"
);
DECLARE_ARG
(
"--restore-detached"
);
DECLARE_ARG
(
"--restore-sibling"
);
DECLARE_ARG
(
"--restore-sibling"
);
if
(
tty
_info
[
0
])
{
if
(
tty
s
[
0
])
{
if
(
opts
->
console_fd
<
0
)
{
if
(
opts
->
console_fd
<
0
)
{
ERROR
(
"lxc.console.path configured on source host but not target"
);
ERROR
(
"lxc.console.path configured on source host but not target"
);
goto
err
;
goto
err
;
}
}
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
"fd[%d]:%s"
,
opts
->
console_fd
,
tty
_info
);
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
"fd[%d]:%s"
,
opts
->
console_fd
,
tty
s
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
goto
err
;
goto
err
;
...
...
src/lxc/start.c
View file @
0e4be3cf
...
@@ -824,7 +824,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
...
@@ -824,7 +824,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
out_restore_sigmask:
out_restore_sigmask:
sigprocmask
(
SIG_SETMASK
,
&
handler
->
oldmask
,
NULL
);
sigprocmask
(
SIG_SETMASK
,
&
handler
->
oldmask
,
NULL
);
out_delete_tty:
out_delete_tty:
lxc_delete_tty
(
&
conf
->
tty
_info
);
lxc_delete_tty
(
&
conf
->
tty
s
);
out_aborting:
out_aborting:
lxc_set_state
(
name
,
handler
,
ABORTING
);
lxc_set_state
(
name
,
handler
,
ABORTING
);
out_close_maincmd_fd:
out_close_maincmd_fd:
...
@@ -951,7 +951,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
...
@@ -951,7 +951,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
WARN
(
"%s - Failed to restore signal mask"
,
strerror
(
errno
));
WARN
(
"%s - Failed to restore signal mask"
,
strerror
(
errno
));
lxc_terminal_delete
(
&
handler
->
conf
->
console
);
lxc_terminal_delete
(
&
handler
->
conf
->
console
);
lxc_delete_tty
(
&
handler
->
conf
->
tty
_info
);
lxc_delete_tty
(
&
handler
->
conf
->
tty
s
);
/* The command socket is now closed, no more state clients can register
/* The command socket is now closed, no more state clients can register
* themselves from now on. So free the list of state clients.
* themselves from now on. So free the list of state clients.
...
@@ -1344,13 +1344,13 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
...
@@ -1344,13 +1344,13 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
int
ret
=
-
1
;
int
ret
=
-
1
;
int
sock
=
handler
->
data_sock
[
1
];
int
sock
=
handler
->
data_sock
[
1
];
struct
lxc_conf
*
conf
=
handler
->
conf
;
struct
lxc_conf
*
conf
=
handler
->
conf
;
struct
lxc_tty_info
*
tty
_info
=
&
conf
->
tty_info
;
struct
lxc_tty_info
*
tty
s
=
&
conf
->
ttys
;
if
(
!
conf
->
tty
)
if
(
!
conf
->
tty
)
return
0
;
return
0
;
tty
_info
->
tty
=
malloc
(
sizeof
(
*
tty_info
->
tty
)
*
conf
->
tty
);
tty
s
->
tty
=
malloc
(
sizeof
(
*
ttys
->
tty
)
*
conf
->
tty
);
if
(
!
tty
_info
->
tty
)
if
(
!
tty
s
->
tty
)
return
-
1
;
return
-
1
;
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
for
(
i
=
0
;
i
<
conf
->
tty
;
i
++
)
{
...
@@ -1360,7 +1360,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
...
@@ -1360,7 +1360,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
if
(
ret
<
0
)
if
(
ret
<
0
)
break
;
break
;
tty
=
&
tty
_info
->
tty
[
i
];
tty
=
&
tty
s
->
tty
[
i
];
tty
->
busy
=
0
;
tty
->
busy
=
0
;
tty
->
master
=
ttyfds
[
0
];
tty
->
master
=
ttyfds
[
0
];
tty
->
slave
=
ttyfds
[
1
];
tty
->
slave
=
ttyfds
[
1
];
...
@@ -1373,7 +1373,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
...
@@ -1373,7 +1373,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
else
else
TRACE
(
"Received %d ttys from child"
,
conf
->
tty
);
TRACE
(
"Received %d ttys from child"
,
conf
->
tty
);
tty
_info
->
nbtty
=
conf
->
tty
;
tty
s
->
nbtty
=
conf
->
tty
;
return
ret
;
return
ret
;
}
}
...
...
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