Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
b0f41a71
...
b0f41a7171dc889b5cf45b6d0ce60c5df462663e
authored
2001-05-09 04:23:52 +0000
by
Alain Magloire
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Finally!!!! I can use the GNU imap4d with Netscape .... It kinda work 8-)
sigh ... still more to do.
1 parent
5c2bb927
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
728 additions
and
231 deletions
ChangeLog
imap4d/Makefile.am
imap4d/fetch.c
imap4d/imap4d.c
imap4d/imap4d.h
imap4d/list.c
imap4d/login.c
imap4d/logout.c
imap4d/lsub.c
imap4d/select.c
imap4d/store.c
imap4d/subscribe.c
imap4d/sync.c
imap4d/unsubscribe.c
imap4d/util.c
mailbox/filter_rfc822.c
mailbox/folder_imap.c
mailbox/url_imap.c
pop3d/extra.c
pop3d/pop3d.c
pop3d/pop3d.h
pop3d/signal.c
ChangeLog
View file @
b0f41a7
2001-05-09 Alain Magloire
Take the missing pieces from the pop3d and make the
imap4d a standalone daemon.
* imap4d/fetch.c: Remove fetch_body_peek().
and use fetch_body() instead.
(fetch_operation): Malloc the entire message... not good.
* imap4d/bye.c: New file.
* imap4d/imap4d.c: Put the networking code taken from
pop3d.c.
* imap4d/lsub.c: Implemented.
* imap4d/subscribe.c: Implemented.
* imap4d/unsubscribe.c: Implemented.
* pop3d/pop3d.c: pop3d_usage() move from extra.c
* pop3d/signal.c: pop3d_signal () move from extra.c
* mailbox/url_imap.c: It was not checking for the port number.
* mailbox/filter_rfc822.c: Check for the lines if available.
2001-05-07 Alain Magloire
Now we can have multiple access to the mailbox and the server
...
...
imap4d/Makefile.am
View file @
b0f41a7
...
...
@@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
sbin_PROGRAMS
=
imap4d
imap4d_LDADD
=
../mailbox/libmailbox.la ../lib/libmailutils.a @AUTHLIBS@
imap4d_SOURCES
=
imap4d.c imap4d.h capability.c noop.c logout.c authenticat
e.c
\
login.c
select
.c examine.c create.c delete.c rename.c subscribe
.c
\
unsubscribe.c list.c lsub.c status.c append.c check.c close
.c
\
expunge.c search.c fetch.c store.c sync.c copy.c uid.c util.c commands
.c
imap4d_SOURCES
=
append.c authenticate.c bye.c capability.c check.c clos
e.c
\
commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d
.c
\
imap4d.h list.c logout.c login.c lsub.c noop.c rename.c search.c
select
.c
\
signal.c status.c store.c subscribe.c sync.c uid.c unsubscribe.c util
.c
...
...
imap4d/fetch.c
View file @
b0f41a7
...
...
@@ -48,7 +48,6 @@ static int fetch_rfc822 __P ((struct fetch_command *, char*));
static
int
fetch_bodystructure
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_bodystructure0
__P
((
message_t
,
int
));
static
int
bodystructure
__P
((
message_t
,
int
));
static
int
fetch_body_peek
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_body
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_uid
__P
((
struct
fetch_command
*
,
char
*
));
...
...
@@ -92,11 +91,9 @@ struct fetch_command
{
"RFC822"
,
fetch_rfc822
,
0
},
#define F_BODYSTRUCTURE 10
{
"BODYSTRUCTURE"
,
fetch_bodystructure
,
0
},
#define F_BODY_PEEK 11
{
"BODY.PEEK"
,
fetch_body_peek
,
0
},
#define F_BODY 12
#define F_BODY 11
{
"BODY"
,
fetch_body
,
0
},
#define F_UID 1
3
#define F_UID 1
2
{
"UID"
,
fetch_uid
,
0
},
{
NULL
,
0
,
0
}
};
...
...
@@ -160,40 +157,51 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen)
char
item
[
32
];
char
*
items
=
strdup
(
sp
);
char
*
p
=
items
;
size_t
msgno
;
int
space
=
0
;
int
uid_sent
=
!
isuid
;
/* Pretend we sent the uid if via fetch. */
util_send
(
"* %d FETCH ("
,
set
[
i
]);
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
if
(
msgno
)
{
fcmd
=
NULL
;
util_send
(
"* %d FETCH ("
,
msgno
);
item
[
0
]
=
'\0'
;
/* Server implementations MUST implicitly
include the UID message data item as part of any FETCH response
caused by a UID command, regardless of whether a UID was specified
as a message data item to the FETCH. */
if
(
!
uid_sent
)
{
fcmd
=
&
fetch_command_table
[
F_UID
];
fcmd
->
msgno
=
msgno
;
rc
=
fetch_uid
(
fcmd
,
p
);
uid_sent
=
1
;
}
/* Get the fetch command names. */
while
(
*
items
&&
*
items
!=
')'
)
{
util_token
(
item
,
sizeof
(
item
),
&
items
);
if
(
uid_sent
&&
strcasecmp
(
item
,
"UID"
)
==
0
)
continue
;
if
(
fcmd
)
util_send
(
" "
)
;
space
=
1
;
/* Search in the table. */
fcmd
=
fetch_getcommand
(
item
,
fetch_command_table
);
if
(
fcmd
)
{
fcmd
->
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
if
(
fcmd
->
msgno
!=
0
)
if
(
space
)
{
rc
=
fcmd
->
func
(
fcmd
,
items
);
util_send
(
" "
);
space
=
0
;
}
fcmd
->
msgno
=
msgno
;
rc
=
fcmd
->
func
(
fcmd
,
items
);
}
if
(
!
uid_sent
)
uid_sent
=
((
strstr
(
item
,
"UID"
)
!=
NULL
)
||
(
strstr
(
item
,
"uid"
)
!=
NULL
));
}
/* Always send the UID when fetch was done via the uid command. */
if
(
!
uid_sent
)
{
struct
fetch_command
c_uid
=
fetch_command_table
[
F_UID
];
c_uid
.
msgno
=
set
[
i
];
if
(
fcmd
)
util_send
(
" "
);
rc
=
fetch_uid
(
&
c_uid
,
items
);
util_send
(
")
\r\n
"
);
}
free
(
p
);
util_send
(
")
\r\n
"
);
}
free
(
set
);
snprintf
(
resp
,
resplen
,
"Completed"
);
...
...
@@ -733,8 +741,6 @@ bodystructure (message_t msg, int extension)
static
int
fetch_body
(
struct
fetch_command
*
command
,
char
*
arg
)
{
struct
fetch_command
c_body_p
=
fetch_command_table
[
F_BODY_PEEK
];
c_body_p
.
msgno
=
command
->
msgno
;
/* It's BODY set the message as seen */
if
(
*
arg
==
'['
)
{
...
...
@@ -766,15 +772,8 @@ fetch_body (struct fetch_command *command, char *arg)
util_send
(
")"
);
return
RESP_OK
;
}
return
fetch_body_peek
(
&
c_body_p
,
arg
);
}
static
int
fetch_body_peek
(
struct
fetch_command
*
command
,
char
*
arg
)
{
util_send
(
"%s "
,
command
->
name
);
fetch_operation
(
command
->
msgno
,
arg
,
0
);
return
RESP_OK
;
util_send
(
"%s"
,
command
->
name
);
return
fetch_operation
(
command
->
msgno
,
arg
,
0
);
}
static
int
...
...
@@ -903,32 +902,37 @@ static int
fetch_io
(
stream_t
stream
,
unsigned
long
start
,
unsigned
long
end
)
{
stream_t
rfc
=
NULL
;
char
buffer
[
1024
]
;
char
*
buffer
,
*
p
;
size_t
n
=
0
;
size_t
total
=
0
;
off_t
offset
;
offset
=
(
start
==
ULONG_MAX
)
?
0
:
start
;
filter_create
(
&
rfc
,
stream
,
"rfc822"
,
MU_FILTER_ENCODE
,
MU_STREAM_READ
);
if
(
start
==
ULONG_MAX
)
{
start
=
0
;
util_send
(
" {%u}
\r\n
"
,
end
);
}
else
util_send
(
"<%lu> {%u}
\r\n
"
,
start
,
end
);
while
(
start
<
end
&&
stream_read
(
rfc
,
buffer
,
sizeof
(
buffer
),
start
,
&
n
)
==
0
&&
n
>
0
)
p
=
buffer
=
calloc
(
end
+
2
,
1
);
while
(
end
>
0
&&
stream_read
(
rfc
,
buffer
,
end
+
1
,
offset
,
&
n
)
==
0
&&
n
>
0
)
{
star
t
+=
n
;
offse
t
+=
n
;
total
+=
n
;
if
(
total
>
end
)
{
size_t
diff
=
n
-
(
total
-
end
);
buffer
[
diff
]
=
'\0'
;
end
-=
n
;
buffer
+=
n
;
}
util_send
(
"%s"
,
buffer
);
/* Make sure we null terminate. */
*
buffer
=
'\0'
;
if
(
start
!=
ULONG_MAX
)
util_send
(
"<%lu>"
,
start
);
if
(
total
)
{
util_send
(
" {%u}
\r\n
"
,
total
);
util_send
(
"%s"
,
p
);
}
else
util_send
(
"
\"\"
"
);
free
(
p
);
return
RESP_OK
;
}
...
...
@@ -946,7 +950,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
status
=
memory_stream_create
(
&
stream
);
if
(
status
!=
0
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
/* Save the fields in an array. */
{
...
...
@@ -957,7 +961,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
{
array
=
realloc
(
array
,
(
array_len
+
1
)
*
sizeof
(
*
array
));
if
(
!
array
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
array
[
array_len
]
=
field
;
}
}
...
...
@@ -984,7 +988,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
if
(
status
!=
0
)
{
free
(
array
);
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
}
}
}
...
...
@@ -1027,7 +1031,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
status
=
memory_stream_create
(
&
stream
);
if
(
status
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
/* Save the field we want to ignore. */
{
...
...
@@ -1038,7 +1042,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
{
array
=
realloc
(
array
,
(
array_len
+
1
)
*
sizeof
(
*
array
));
if
(
!
array
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
array
[
array_len
]
=
field
;
}
}
...
...
@@ -1093,7 +1097,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
if
(
status
!=
0
)
{
free
(
array
);
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
}
}
}
...
...
imap4d/imap4d.c
View file @
b0f41a7
...
...
@@ -23,37 +23,177 @@ mailbox_t mbox;
char
*
homedir
;
int
state
=
STATE_NONAUTH
;
/* Number of child processes. */
volatile
size_t
children
;
static
struct
option
long_options
[]
=
{
{
"daemon"
,
optional_argument
,
0
,
'd'
},
{
"help"
,
no_argument
,
0
,
'h'
},
{
"inetd"
,
no_argument
,
0
,
'i'
},
{
"port"
,
required_argument
,
0
,
'p'
},
{
"timeout"
,
required_argument
,
0
,
't'
},
{
"version"
,
no_argument
,
0
,
'v'
},
{
0
,
0
,
0
,
0
}
};
const
char
*
short_options
=
"d::hip:t:v"
;
static
int
syslog_error_printer
__P
((
const
char
*
fmt
,
va_list
ap
));
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
void
imap4d_daemon_init
__P
((
void
));
static
void
imap4d_daemon
__P
((
unsigned
int
,
unsigned
int
));
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
void
imap4d_usage
__P
((
char
*
));
#ifndef DEFMAXCHILDREN
# define DEFMAXCHILDREN 20
/* Default maximum number of children */
#endif
int
main
(
int
argc
,
char
**
argv
)
{
chdir
(
"/"
);
openlog
(
"imap4d"
,
LOG_PID
,
LOG_MAIL
);
struct
group
*
gr
;
static
int
mode
=
INTERACTIVE
;
size_t
maxchildren
=
DEFMAXCHILDREN
;
int
c
=
0
;
int
status
=
EXIT_SUCCESS
;
unsigned
int
port
;
port
=
143
;
/* Default IMAP4 port. */
timeout
=
1800
;
/* RFC2060: 30 minutes, if enable. */
state
=
STATE_NONAUTH
;
/* Starting state in non-auth. */
while
((
c
=
getopt_long
(
argc
,
argv
,
short_options
,
long_options
,
NULL
))
!=
-
1
)
{
switch
(
c
)
{
case
'd'
:
mode
=
DAEMON
;
if
(
optarg
)
maxchildren
=
strtoul
(
optarg
,
NULL
,
10
);
if
(
maxchildren
==
0
)
maxchildren
=
DEFMAXCHILDREN
;
break
;
case
'h'
:
imap4d_usage
(
argv
[
0
]);
break
;
case
'i'
:
mode
=
INTERACTIVE
;
break
;
case
'p'
:
mode
=
DAEMON
;
port
=
strtoul
(
optarg
,
NULL
,
10
);
break
;
case
't'
:
timeout
=
strtoul
(
optarg
,
NULL
,
10
);
break
;
case
'v'
:
printf
(
"GNU imap4 daemon"
"("
PACKAGE
" "
VERSION
")
\n
"
);
exit
(
0
);
break
;
default:
break
;
}
}
/* First we want our group to be mail so we can access the spool. */
gr
=
getgrnam
(
"mail"
);
if
(
gr
==
NULL
)
{
perror
(
"Error getting mail group"
);
exit
(
1
);
}
if
(
setgid
(
gr
->
gr_gid
)
==
-
1
)
{
perror
(
"Error setting mail group"
);
exit
(
1
);
}
/* Register the desire formats. We only need Mbox mail format. */
{
list_t
bookie
;
registrar_get_list
(
&
bookie
);
/* list_append (bookie, mbox_record); */
list_append
(
bookie
,
path_record
);
}
/* FIXME: Incomplete, make it work for standalone, see pop3d. */
imap4d_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
return
0
;
/* Set the signal handlers. */
signal
(
SIGINT
,
imap4d_signal
);
signal
(
SIGQUIT
,
imap4d_signal
);
signal
(
SIGILL
,
imap4d_signal
);
signal
(
SIGBUS
,
imap4d_signal
);
signal
(
SIGFPE
,
imap4d_signal
);
signal
(
SIGSEGV
,
imap4d_signal
);
signal
(
SIGTERM
,
imap4d_signal
);
signal
(
SIGSTOP
,
imap4d_signal
);
signal
(
SIGPIPE
,
imap4d_signal
);
/*signal (SIGPIPE, SIG_IGN); */
signal
(
SIGABRT
,
imap4d_signal
);
if
(
mode
==
DAEMON
)
imap4d_daemon_init
();
/* Make sure we are in the root. */
chdir
(
"/"
);
/* Set up for syslog. */
openlog
(
"gnu-imap4d"
,
LOG_PID
,
LOG_FACILITY
);
/* Redirect any stdout error from the library to syslog, they
should not go to the client. */
mu_error_set_print
(
syslog_error_printer
);
umask
(
S_IROTH
|
S_IWOTH
|
S_IXOTH
);
/* 007 */
/* Actually run the daemon. */
if
(
mode
==
DAEMON
)
imap4d_daemon
(
maxchildren
,
port
);
/* exit (0) -- no way out of daemon except a signal. */
else
status
=
imap4d_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
/* Close the syslog connection and exit. */
closelog
();
return
status
;
}
static
int
imap4d_mainloop
(
int
infile
,
int
outfile
)
{
const
char
*
remote_host
=
""
;
FILE
*
ifile
;
/* Reset hup to exit. */
signal
(
SIGHUP
,
imap4d_signal
);
/* Timeout alarm. */
signal
(
SIGALRM
,
imap4d_signal
);
ifile
=
fdopen
(
infile
,
"r"
);
ofile
=
fdopen
(
outfile
,
"w"
);
if
(
!
ofile
||
!
ifile
)
util_quit
(
ERR_NO_OFILE
);
imap4d_bye
(
ERR_NO_OFILE
);
/* FIXME: Retreive hostname with getpeername() and log. */
syslog
(
LOG_INFO
,
"Incoming connection from %s"
,
remote_host
);
syslog
(
LOG_INFO
,
"Incoming connection opened"
);
/* log information on the connecting client */
{
struct
sockaddr_in
cs
;
int
len
=
sizeof
cs
;
if
(
getpeername
(
infile
,
(
struct
sockaddr
*
)
&
cs
,
&
len
)
<
0
)
syslog
(
LOG_ERR
,
"can't obtain IP address of client: %s"
,
strerror
(
errno
));
else
syslog
(
LOG_INFO
,
"connect from %s"
,
inet_ntoa
(
cs
.
sin_addr
));
}
/* Greetings. */
util_out
(
RESP_OK
,
"IMAP4rev1 GNU "
PACKAGE
" "
VERSION
);
...
...
@@ -71,5 +211,164 @@ imap4d_mainloop (int infile, int outfile)
}
closelog
();
return
EXIT_SUCCESS
;
}
/* Sets things up for daemon mode. */
static
void
imap4d_daemon_init
(
void
)
{
pid_t
pid
;
pid
=
fork
();
if
(
pid
==
-
1
)
{
perror
(
"fork failed:"
);
exit
(
1
);
}
else
if
(
pid
>
0
)
exit
(
0
);
/* Parent exits. */
setsid
();
/* Become session leader. */
signal
(
SIGHUP
,
SIG_IGN
);
/* Ignore SIGHUP. */
/* The second fork is to guarantee that the daemon cannot acquire a
controlling terminal. */
pid
=
fork
();
if
(
pid
==
-
1
)
{
perror
(
"fork failed:"
);
exit
(
1
);
}
else
if
(
pid
>
0
)
exit
(
0
);
/* Parent exits. */
/* Close inherited file descriptors. */
{
size_t
i
;
#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
size_t
fdlimit
=
sysconf
(
_SC_OPEN_MAX
);
#else
size_t
fdlimit
=
64
;
#endif
for
(
i
=
0
;
i
<
fdlimit
;
++
i
)
close
(
i
);
}
/* SIGCHLD is not ignore but rather use to do some simple load balancing. */
#ifdef HAVE_SIGACTION
{
struct
sigaction
act
;
act
.
sa_handler
=
imap4d_sigchld
;
sigemptyset
(
&
act
.
sa_mask
);
act
.
sa_flags
=
0
;
sigaction
(
SIGCHLD
,
&
act
,
NULL
);
}
#else
signal
(
SIGCHLD
,
imap4d_sigchld
);
#endif
}
/* Runs GNU imap4d in standalone daemon mode. This opens and binds to a port
(default 143) then executes a imap4d_mainloop() upon accepting a connection.
It starts maxchildren child processes to listen to and accept socket
connections. */
static
void
imap4d_daemon
(
unsigned
int
maxchildren
,
unsigned
int
port
)
{
struct
sockaddr_in
server
,
client
;
pid_t
pid
;
int
listenfd
,
connfd
;
size_t
size
;
listenfd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
listenfd
==
-
1
)
{
syslog
(
LOG_ERR
,
"socket: %s"
,
strerror
(
errno
));
exit
(
1
);
}
size
=
1
;
/* Use size here to avoid making a new variable. */
setsockopt
(
listenfd
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
size
,
sizeof
(
size
));
size
=
sizeof
(
server
);
memset
(
&
server
,
0
,
size
);
server
.
sin_family
=
AF_INET
;
server
.
sin_addr
.
s_addr
=
htonl
(
INADDR_ANY
);
server
.
sin_port
=
htons
(
port
);
if
(
bind
(
listenfd
,
(
struct
sockaddr
*
)
&
server
,
size
)
==
-
1
)
{
syslog
(
LOG_ERR
,
"bind: %s"
,
strerror
(
errno
));
exit
(
1
);
}
if
(
listen
(
listenfd
,
128
)
==
-
1
)
{
syslog
(
LOG_ERR
,
"listen: %s"
,
strerror
(
errno
));
exit
(
1
);
}
for
(;;)
{
if
(
children
>
maxchildren
)
{
syslog
(
LOG_ERR
,
"too many children (%d)"
,
children
);
pause
();
continue
;
}
connfd
=
accept
(
listenfd
,
(
struct
sockaddr
*
)
&
client
,
&
size
);
if
(
connfd
==
-
1
)
{
if
(
errno
==
EINTR
)
continue
;
syslog
(
LOG_ERR
,
"accept: %s"
,
strerror
(
errno
));
exit
(
1
);
}
pid
=
fork
();
if
(
pid
==
-
1
)
syslog
(
LOG_ERR
,
"fork: %s"
,
strerror
(
errno
));
else
if
(
pid
==
0
)
/* Child. */
{
int
status
;
close
(
listenfd
);
status
=
imap4d_mainloop
(
connfd
,
connfd
);
closelog
();
exit
(
status
);
}
else
{
++
children
;
}
close
(
connfd
);
}
}
/* Prints out usage information and exits the program */
static
void
imap4d_usage
(
char
*
argv0
)
{
printf
(
"Usage: %s [OPTIONS]
\n
"
,
argv0
);
printf
(
"Runs the GNU IMAP4 daemon.
\n\n
"
);
printf
(
" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum
\n
"
);
printf
(
" of MAXCHILDREN child processes
\n
"
);
printf
(
" -h, --help display this help and exit
\n
"
);
printf
(
" -i, --inetd runs in inetd mode (default)
\n
"
);
printf
(
" -p, --port=PORT specifies port to listen on, implies -d
\n
"
);
printf
(
" defaults to 143, which need not be specifi
ed
\n
"
);
printf
(
" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds
\n
"
);
printf
(
" TIMEOUT default is 1800 (30 minutes)
\n
"
);
printf
(
" -v, --version display version information and exit
\n
"
);
printf
(
"
\n
Report bugs to bug-mailutils@gnu.org
\n
"
);
exit
(
0
);
}
static
int
syslog_error_printer
(
const
char
*
fmt
,
va_list
ap
)
{
vsyslog
(
LOG_CRIT
,
fmt
,
ap
);
return
0
;
}
...
...
imap4d/imap4d.h
View file @
b0f41a7
...
...
@@ -49,6 +49,12 @@
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "getopt.h"
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
...
...
@@ -66,6 +72,7 @@
#include <mailutils/registrar.h>
#include <mailutils/filter.h>
#include <mailutils/stream.h>
#include <mailutils/error.h>
#ifdef __cplusplus
extern
"C"
{
...
...
@@ -89,6 +96,10 @@ struct imap4d_command
char
*
tag
;
};
/* Daemon modes. */
#define INTERACTIVE 0
#define DAEMON 1
/* Global variables and constants*/
#define STATE_NONE (0)
#define STATE_NONAUTH (1 << 0)
...
...
@@ -107,8 +118,11 @@ struct imap4d_command
#define RESP_NONE 4
/* Error values. */
#define OK 0
#define ERR_NO_MEM 1
#define ERR_NO_OFILE 2
#define ERR_TIMEOUT 3
#define ERR_SIGNAL 4
extern
struct
imap4d_command
imap4d_command_table
[];
extern
FILE
*
ofile
;
...
...
@@ -116,42 +130,48 @@ extern unsigned int timeout;
extern
mailbox_t
mbox
;
extern
char
*
homedir
;
extern
int
state
;
extern
volatile
size_t
children
;
/* Imap4 commands */
extern
int
imap4d_capability
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_noop
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_logout
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_authenticate
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_login
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_select
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_select0
__P
((
struct
imap4d_command
*
,
char
*
,
int
));
extern
int
imap4d_examine
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_create
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_delete
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_rename
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_subscribe
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_unsubscribe
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_list
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_lsub
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_status
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_append
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_authenticate
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_capability
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_check
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_close
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_copy
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_copy0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_create
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_delete
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_examine
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_expunge
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_search
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_fetch
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_fetch0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_list
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_lsub
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_login
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_logout
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_noop
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_rename
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_search
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_select
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_select0
__P
((
struct
imap4d_command
*
,
char
*
,
int
));
extern
int
imap4d_status
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_store
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_store0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_copy
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_copy0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_subscribe
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_uid
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_unsubscribe
__P
((
struct
imap4d_command
*
,
char
*
));
/* Synchronisation on simultenous access. */
extern
int
imap4d_sync
__P
((
void
));
extern
int
imap4d_sync_flags
__P
((
size_t
));
extern
size_t
uid_to_msgno
__P
((
size_t
));
/* Signal handling. */
extern
RETSIGTYPE
imap4d_sigchld
__P
((
int
));
extern
RETSIGTYPE
imap4d_signal
__P
((
int
));
extern
int
imap4d_bye
__P
((
int
));
/* Helper functions. */
extern
int
util_out
__P
((
int
,
const
char
*
,
...));
extern
int
util_send
__P
((
const
char
*
,
...));
...
...
@@ -160,7 +180,6 @@ extern int util_finish __P ((struct imap4d_command *, int, const char *, ...));
extern
int
util_getstate
__P
((
void
));
extern
int
util_do_command
__P
((
char
*
));
extern
char
*
imap4d_readline
__P
((
FILE
*
));
extern
void
util_quit
__P
((
int
));
extern
char
*
util_getword
__P
((
char
*
,
char
**
));
extern
int
util_token
__P
((
char
*
,
size_t
,
char
**
));
extern
void
util_unquote
__P
((
char
**
));
...
...
imap4d/list.c
View file @
b0f41a7
...
...
@@ -47,7 +47,7 @@
static
int
match
__P
((
const
char
*
,
const
char
*
,
const
char
*
));
static
int
imap_match
__P
((
const
char
*
,
const
char
*
,
const
char
*
));
static
void
list_file
__P
((
const
char
*
,
const
char
*
,
char
*
,
const
char
*
));
static
void
list_file
__P
((
const
char
*
,
const
char
*
,
c
onst
c
har
*
,
const
char
*
));
static
void
print_file
__P
((
const
char
*
,
const
char
*
,
const
char
*
));
static
void
print_dir
__P
((
const
char
*
,
const
char
*
,
const
char
*
));
...
...
@@ -150,7 +150,7 @@ imap4d_list (struct imap4d_command *command, char *arg)
if
(
chdir
(
cwd
)
==
0
)
{
list_file
(
cwd
,
ref
,
dir
,
delim
);
list_file
(
cwd
,
ref
,
(
dir
)
?
dir
:
""
,
delim
);
chdir
(
homedir
);
}
free
(
cwd
);
...
...
@@ -161,17 +161,22 @@ imap4d_list (struct imap4d_command *command, char *arg)
/* Recusively calling the files. */
static
void
list_file
(
const
char
*
cwd
,
const
char
*
ref
,
char
*
pattern
,
const
char
*
delim
)
list_file
(
const
char
*
cwd
,
const
char
*
ref
,
const
char
*
pattern
,
const
char
*
delim
)
{
DIR
*
dirp
;
struct
dirent
*
dp
;
char
*
next
;
/* Shortcut no wildcards. */
if
(
!
strpbrk
(
pattern
,
"%*"
))
if
(
*
pattern
==
'\0'
||
!
strpbrk
(
pattern
,
"%*"
))
{
/* Equivalent to stat(). */
int
status
=
match
(
pattern
,
pattern
,
delim
);
int
status
;
if
(
*
pattern
==
'\0'
)
status
=
match
(
cwd
,
cwd
,
delim
);
else
status
=
match
(
pattern
,
pattern
,
delim
);
if
(
status
&
NOSELECT
)
print_dir
(
ref
,
pattern
,
delim
);
else
if
(
status
&
NOINFERIORS
)
...
...
imap4d/login.c
View file @
b0f41a7
...
...
@@ -32,7 +32,7 @@ static int _perr = 0;
return util_finish (command, RESP_NO, "User name or passwd rejected"); }
static
int
PAM_gnu
pop3
d_conv
(
int
num_msg
,
const
struct
pam_message
**
msg
,
PAM_gnu
imap4
d_conv
(
int
num_msg
,
const
struct
pam_message
**
msg
,
struct
pam_response
**
resp
,
void
*
appdata_ptr
)
{
int
replies
=
0
;
...
...
@@ -73,7 +73,7 @@ PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg,
return
PAM_SUCCESS
;
}
static
struct
pam_conv
PAM_conversation
=
{
&
PAM_gnu
pop3
d_conv
,
NULL
};
static
struct
pam_conv
PAM_conversation
=
{
&
PAM_gnu
imap4
d_conv
,
NULL
};
#endif
/* USE_LIBPAM */
int
...
...
@@ -91,12 +91,16 @@ imap4d_login (struct imap4d_command *command, char *arg)
username
=
util_getword
(
arg
,
&
sp
);
pass
=
util_getword
(
NULL
,
&
sp
);
if
(
username
==
NULL
||
pass
==
NULL
)
/* Remove the double quotes. */
util_unquote
(
&
username
);
util_unquote
(
&
pass
);
if
(
username
==
NULL
||
*
username
==
'\0'
||
pass
==
NULL
)
return
util_finish
(
command
,
RESP_NO
,
"Too few args"
);
else
if
(
util_getword
(
NULL
,
&
sp
))
return
util_finish
(
command
,
RESP_NO
,
"Too many args"
);
pw
=
getpwnam
(
arg
);
pw
=
getpwnam
(
username
);
#ifndef USE_LIBPAM
if
(
pw
==
NULL
||
pw
->
pw_uid
<
1
)
...
...
@@ -105,17 +109,17 @@ imap4d_login (struct imap4d_command *command, char *arg)
{
#ifdef HAVE_SHADOW_H
struct
spwd
*
spw
;
spw
=
getspnam
(
arg
);
spw
=
getspnam
(
username
);
if
(
spw
==
NULL
||
strcmp
(
spw
->
sp_pwdp
,
(
char
*
)
crypt
(
pass
,
spw
->
sp_pwdp
)))
#endif
/* HAVE_SHADOW_H */
return
util_finish
(
command
,
RESP_NO
,
"User name or passwd rejected"
);
}
#else
/* !USE_LIBPAM */
_user
=
(
char
*
)
arg
;
_user
=
(
char
*
)
username
;
_pwd
=
pass
;
/* libpam doesn't log to LOG_MAIL */
closelog
();
pamerror
=
pam_start
(
"gnu-imap4d"
,
arg
,
&
PAM_conversation
,
&
pamh
);
pamerror
=
pam_start
(
"gnu-imap4d"
,
username
,
&
PAM_conversation
,
&
pamh
);
PAM_ERROR
;
pamerror
=
pam_authenticate
(
pamh
,
0
);
PAM_ERROR
;
...
...
imap4d/logout.c
View file @
b0f41a7
...
...
@@ -29,7 +29,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
if
(
util_getword
(
arg
,
&
sp
))
return
util_finish
(
command
,
RESP_BAD
,
"Too many args"
);
util_out
(
RESP_BYE
,
"Logging out"
);
util_finish
(
command
,
RESP_OK
,
"Completed"
);
/* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
command MAY be issued without previously issuing a CLOSE command.
...
...
@@ -40,6 +39,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
mailbox_close
(
mbox
);
mailbox_destroy
(
&
mbox
);
}
util_quit
(
0
);
imap4d_bye
(
OK
);
return
0
;
}
...
...
imap4d/lsub.c
View file @
b0f41a7
...
...
@@ -24,7 +24,41 @@
int
imap4d_lsub
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
char
*
sp
;
char
*
ref
;
char
*
wcard
;
char
*
file
;
const
char
*
delim
=
"/"
;
FILE
*
fp
;
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
return
util_finish
(
command
,
RESP_NO
,
"Not supported"
);
ref
=
util_getword
(
arg
,
&
sp
);
wcard
=
util_getword
(
NULL
,
&
sp
);
if
(
!
ref
||
!
wcard
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few arguments"
);
/* Remove the double quotes. */
util_unquote
(
&
ref
);
util_unquote
(
&
wcard
);
/* FIXME: Get the matching in list. */
asprintf
(
&
file
,
"%s/.mailboxlist"
,
homedir
);
fp
=
fopen
(
file
,
"r"
);
free
(
file
);
if
(
fp
)
{
char
buffer
[
124
];
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
))
{
size_t
n
=
strlen
(
buffer
);
if
(
n
&&
buffer
[
n
-
1
]
==
'\n'
)
buffer
[
n
-
1
]
=
'\0'
;
util_out
(
RESP_NONE
,
"LIST ()
\"
%s
\"
%s"
,
delim
,
buffer
);
}
fclose
(
fp
);
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
}
return
util_finish
(
command
,
RESP_NO
,
"Can not list subscriber"
);
}
...
...
imap4d/select.c
View file @
b0f41a7
...
...
@@ -37,10 +37,9 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
/* FIXME: Check state. */
mailbox_name
=
util_getword
(
arg
,
&
sp
);
if
(
mailbox_name
==
NULL
)
util_unquote
(
&
mailbox_name
);
if
(
mailbox_name
==
NULL
||
*
mailbox_name
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few arguments"
);
if
(
util_getword
(
NULL
,
&
sp
))
return
util_finish
(
command
,
RESP_BAD
,
"Too many arguments"
);
/* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
command MAY be issued without previously issuing a CLOSE command.
...
...
@@ -56,7 +55,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
if
(
strcasecmp
(
mailbox_name
,
"INBOX"
)
==
0
)
{
pw
=
getpwuid
(
getuid
());
pw
=
getpwuid
(
getuid
());
if
(
pw
)
mailbox_name
=
pw
->
pw_name
;
}
...
...
imap4d/store.c
View file @
b0f41a7
...
...
@@ -109,8 +109,11 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen)
char
*
flags
=
strdup
(
""
);
int
first
=
1
;
size_t
msgno
;
char
*
p
=
items
;
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
if
(
msgno
)
{
mailbox_get_message
(
mbox
,
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
...
...
@@ -141,9 +144,10 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen)
strcat
(
flags
,
item
);
}
}
}
if
(
ack
&&
*
flags
)
util_out
(
RESP_NONE
,
"%d FETCH FLAGS (%s)"
,
set
[
i
]
,
flags
);
free
(
items
);
util_out
(
RESP_NONE
,
"%d FETCH FLAGS (%s)"
,
msgno
,
flags
);
free
(
p
);
free
(
flags
);
/* Update the flags of uid table. */
imap4d_sync_flags
(
set
[
i
]);
...
...
imap4d/subscribe.c
View file @
b0f41a7
...
...
@@ -18,13 +18,34 @@
#include "imap4d.h"
/*
*
FIXME: We need to lock the file to prevent simultaneous access.
*/
int
imap4d_subscribe
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
char
*
sp
=
NULL
;
char
*
name
;
char
*
file
;
FILE
*
fp
;
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
return
util_finish
(
command
,
RESP_NO
,
"Not supported"
);
name
=
util_getword
(
arg
,
&
sp
);
util_unquote
(
&
name
);
if
(
!
name
||
*
name
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few arguments"
);
asprintf
(
&
file
,
"%s/.mailboxlist"
,
homedir
);
fp
=
fopen
(
file
,
"a"
);
free
(
file
);
if
(
fp
)
{
fputs
(
name
,
fp
);
fputs
(
"
\n
"
,
fp
);
fclose
(
fp
);
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
}
return
util_finish
(
command
,
RESP_NO
,
"Can not subscribe"
);
}
...
...
imap4d/sync.c
View file @
b0f41a7
...
...
@@ -37,7 +37,7 @@ add_flag (char **pbuf, const char *f)
char
*
abuf
=
*
pbuf
;
abuf
=
realloc
(
abuf
,
strlen
(
abuf
)
+
strlen
(
f
)
+
2
);
if
(
abuf
==
NULL
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
if
(
*
abuf
)
strcat
(
abuf
,
" "
);
strcat
(
abuf
,
"
\\
Seen"
);
...
...
@@ -58,7 +58,7 @@ notify_flag (size_t msgno, attribute_t oattr)
{
char
*
abuf
=
malloc
(
1
);;
if
(
!
abuf
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
*
abuf
=
'\0'
;
if
(
attribute_is_seen
(
nattr
)
&&
attribute_is_read
(
nattr
))
if
(
!
attribute_is_seen
(
oattr
)
&&
!
attribute_is_read
(
oattr
))
...
...
@@ -197,7 +197,7 @@ reset_uids (void)
uid_table
=
realloc
(
uid_table
,
sizeof
(
*
uid_table
)
*
(
uid_table_count
+
1
));
if
(
!
uid_table
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
mailbox_get_message
(
mbox
,
i
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
message_get_uid
(
msg
,
&
uid
);
...
...
imap4d/unsubscribe.c
View file @
b0f41a7
...
...
@@ -24,7 +24,68 @@
int
imap4d_unsubscribe
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
char
*
sp
=
NULL
;
char
*
name
;
char
*
file
;
FILE
*
fp
;
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
return
util_finish
(
command
,
RESP_NO
,
"Not supported"
);
name
=
util_getword
(
arg
,
&
sp
);
util_unquote
(
&
name
);
if
(
!
name
||
*
name
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few arguments"
);
asprintf
(
&
file
,
"%s/.mailboxlist"
,
homedir
);
fp
=
fopen
(
file
,
"r"
);
free
(
file
);
if
(
fp
)
{
char
buffer
[
124
];
int
found
=
0
;
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
))
{
size_t
n
=
strlen
(
buffer
);
if
(
n
&&
buffer
[
n
-
1
]
==
'\n'
)
buffer
[
n
-
1
]
=
'\0'
;
if
(
strcmp
(
buffer
,
name
)
==
0
)
{
found
=
1
;
break
;
}
}
if
(
found
)
{
FILE
*
fp2
;
asprintf
(
&
file
,
"%s/.mailboxlist.%d"
,
homedir
,
getpid
());
fp2
=
fopen
(
file
,
"a"
);
if
(
fp2
)
{
rewind
(
fp
);
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
))
{
size_t
n
=
strlen
(
buffer
);
if
(
n
&&
buffer
[
n
-
1
]
==
'\n'
)
buffer
[
n
-
1
]
=
'\0'
;
if
(
strcmp
(
buffer
,
name
)
==
0
)
continue
;
fputs
(
buffer
,
fp2
);
fputs
(
"
\n
"
,
fp2
);
}
fclose
(
fp2
);
remove
(
file
);
}
free
(
file
);
}
else
{
fclose
(
fp
);
return
util_finish
(
command
,
RESP_NO
,
"Can not unsubscribe"
);
}
fclose
(
fp
);
}
else
return
util_finish
(
command
,
RESP_NO
,
"Can not unsubscribe"
);
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
}
...
...
imap4d/util.c
View file @
b0f41a7
...
...
@@ -184,6 +184,9 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
status
=
mailbox_messages_count
(
mbox
,
&
max
);
if
(
status
!=
0
)
return
status
;
/* The number after the "*" in an untagged FETCH response is always a
message sequence number, not a unique identifier, even for a UID
command response. But do what they meant not what they say. */
/* If it is a uid sequence, override max with the UID. */
if
(
isuid
)
{
...
...
@@ -357,24 +360,26 @@ imap4d_readline (FILE *fp)
char
*
line
=
malloc
(
1
);
if
(
!
line
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
line
[
0
]
=
'\0'
;
/* start with a empty string. */
do
{
alarm
(
timeout
);
if
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
)
==
NULL
)
util_quit
(
0
);
/* Logout. */
{
imap4d_bye
(
ERR_NO_OFILE
);
/* Logout. */
}
alarm
(
0
);
len
=
strlen
(
buffer
);
/* If we were in a litteral substract. We have to do
it
since the CR
/* If we were in a litteral substract. We have to do
here
since the CR
is part of the count in a literal. */
if
(
number
)
number
-=
len
;
/* Remove CR. */
if
(
len
>
2
&&
buffer
[
len
-
1
]
==
'\n'
)
if
(
len
>
1
&&
buffer
[
len
-
1
]
==
'\n'
)
{
if
(
buffer
[
len
-
2
]
==
'\r'
)
{
...
...
@@ -382,10 +387,9 @@ imap4d_readline (FILE *fp)
buffer
[
len
-
1
]
=
'\0'
;
}
}
line
=
realloc
(
line
,
total
+
len
+
1
);
if
(
!
line
)
util_quit
(
ERR_NO_MEM
);
imap4d_bye
(
ERR_NO_MEM
);
strcat
(
line
,
buffer
);
total
=
strlen
(
line
);
...
...
@@ -413,6 +417,7 @@ imap4d_readline (FILE *fp)
}
}
while
(
number
>
0
);
/* syslog (LOG_INFO, "readline: %s", line); */
return
line
;
}
...
...
@@ -474,24 +479,6 @@ util_start (char *tag)
return
0
;
}
/* FIXME: Incomplete send errmsg to syslog, see pop3d:pop3_abquit(). */
void
util_quit
(
int
err
)
{
switch
(
err
)
{
case
ERR_NO_OFILE
:
/*util_out (RESP_BYE, "Server terminating dead socket."); */
break
;
case
ERR_NO_MEM
:
util_out
(
RESP_BYE
,
"Server terminating no more ressources."
);
break
;
default:
util_out
(
RESP_BYE
,
"Server terminating"
);
}
exit
(
err
);
}
/* FIXME: What is this for? */
int
util_getstate
(
void
)
...
...
mailbox/filter_rfc822.c
View file @
b0f41a7
...
...
@@ -126,11 +126,18 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
/* Catch up i.e bring us to the current offset. */
if
(
rfc822
->
r_offset
!=
off
)
{
rfc822
->
r_offset
=
off
-
rfc822
->
lines
;
rfc822
->
residue
=
0
;
/* Try to find a starting point. */
if
(
rfc822
->
lines
)
{
rfc822
->
r_offset
=
off
-
rfc822
->
lines
;
if
(
rfc822
->
r_offset
<
0
)
rfc822
->
r_offset
=
0
;
}
else
rfc822
->
r_offset
=
0
;
rfc822
->
s_offset
=
rfc822
->
r_offset
;
while
(
rfc822
->
r_offset
<
off
)
...
...
@@ -141,7 +148,11 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
if
(
status
!=
0
)
return
status
;
if
(
n
==
0
)
break
;
{
if
(
pnread
)
*
pnread
=
0
;
return
0
;
}
if
(
c
==
'\n'
)
{
rfc822
->
r_offset
++
;
...
...
@@ -191,7 +202,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
buffer
+=
nread
;
}
while
(
buflen
>
0
&&
!
isreadline
);
if
(
isreadline
)
if
(
isreadline
&&
buffer
)
*
buffer
=
'\0'
;
if
(
pnread
)
...
...
mailbox/folder_imap.c
View file @
b0f41a7
...
...
@@ -812,6 +812,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr)
for
(
len0
=
len
=
total
=
0
;
total
<
f_imap
->
callback
.
nleft
;
total
+=
(
len
+
1
))
{
status
=
imap_readline
(
f_imap
);
/*fprintf (stderr, "%d: %s", strlen (f_imap->buffer), f_imap->buffer);*/
if
(
status
!=
0
)
{
/* Return what we got so far. */
...
...
mailbox/url_imap.c
View file @
b0f41a7
...
...
@@ -45,7 +45,8 @@ url_imap_destroy (url_t url)
int
_url_imap_init
(
url_t
url
)
{
const
char
*
host
,
*
indexe
;
const
char
*
host_port
;
const
char
*
indexe
;
char
*
name
=
url
->
name
;
/* reject the obvious */
...
...
@@ -67,12 +68,12 @@ _url_imap_init (url_t url)
name
+=
MU_IMAP_SCHEME_LEN
;
/* pass the scheme */
host
=
strchr
(
name
,
'@'
);
if
(
host
==
NULL
)
host
=
name
;
host
_port
=
strchr
(
name
,
'@'
);
if
(
host
_port
==
NULL
)
host
_port
=
name
;
/* looking for ";auth=auth-enc" */
for
(
indexe
=
name
;
indexe
!=
host
;
indexe
++
)
for
(
indexe
=
name
;
indexe
!=
host
_port
;
indexe
++
)
{
/* Auth ? */
if
(
*
indexe
==
';'
)
...
...
@@ -93,7 +94,7 @@ _url_imap_init (url_t url)
((
char
*
)
memcpy
(
url
->
user
,
name
,
indexe
-
name
))[
indexe
-
name
]
=
'\0'
;
/* AUTH */
if
(
indexe
==
host
)
if
(
indexe
==
host
_port
)
{
/* Use default AUTH '*' */
url
->
auth
=
malloc
(
1
+
1
);
...
...
@@ -107,11 +108,11 @@ _url_imap_init (url_t url)
{
/* move pass AUTH= */
indexe
+=
6
;
url
->
auth
=
malloc
(
host
-
indexe
+
1
);
url
->
auth
=
malloc
(
host
_port
-
indexe
+
1
);
if
(
url
->
auth
)
{
((
char
*
)
memcpy
(
url
->
auth
,
indexe
,
host
-
indexe
))
[
host
-
indexe
]
=
'\0'
;
((
char
*
)
memcpy
(
url
->
auth
,
indexe
,
host
_port
-
indexe
))
[
host
_port
-
indexe
]
=
'\0'
;
}
}
...
...
@@ -121,19 +122,45 @@ _url_imap_init (url_t url)
return
-
1
;
}
/* HOST*/
if
(
*
host
==
'@'
)
host
++
;
/* HOST:PORT*/
if
(
*
host_port
==
'@'
)
host_port
++
;
indexe
=
strchr
(
host_port
,
':'
);
if
(
indexe
)
{
char
*
s
=
NULL
;
long
int
p
=
strtol
(
indexe
+
1
,
&
s
,
10
);
url
->
host
=
malloc
(
indexe
-
host_port
+
1
);
if
(
url
->
host
)
{
((
char
*
)
memcpy
(
url
->
host
,
host_port
,
indexe
-
host_port
))
[
indexe
-
host_port
]
=
'\0'
;
}
url
->
port
=
(
p
==
0
)
?
MU_IMAP_PORT
:
p
;
host_port
=
s
;
}
else
url
->
port
=
MU_IMAP_PORT
;
indexe
=
strchr
(
host_port
,
'/'
);
indexe
=
strchr
(
host
,
'/'
);
if
(
indexe
==
NULL
)
url
->
host
=
strdup
(
host
);
{
if
(
url
->
host
==
NULL
)
url
->
host
=
strdup
(
host_port
);
}
else
{
char
*
question
;
url
->
host
=
malloc
(
indexe
-
host
+
1
);
if
(
url
->
host
==
NULL
)
{
url
->
host
=
malloc
(
indexe
-
host_port
+
1
);
if
(
url
->
host
)
((
char
*
)
memcpy
(
url
->
host
,
host
,
indexe
-
host
))[
indexe
-
host
]
=
'\0'
;
((
char
*
)
memcpy
(
url
->
host
,
host_port
,
indexe
-
host_port
))
[
indexe
-
host_port
]
=
'\0'
;
}
indexe
++
;
/* The query starts after a '?'. */
question
=
strchr
(
indexe
,
'?'
);
...
...
@@ -155,6 +182,5 @@ _url_imap_init (url_t url)
return
ENOMEM
;
}
url
->
port
=
MU_IMAP_PORT
;
return
0
;
}
...
...
pop3d/extra.c
View file @
b0f41a7
...
...
@@ -126,45 +126,7 @@ pop3d_abquit (int reason)
}
closelog
();
exit
(
1
);
}
/* Prints out usage information and exits the program */
void
pop3d_usage
(
char
*
argv0
)
{
printf
(
"Usage: %s [OPTIONS]
\n
"
,
argv0
);
printf
(
"Runs the GNU POP3 daemon.
\n\n
"
);
printf
(
" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum
\n
"
);
printf
(
" of MAXCHILDREN child processes
\n
"
);
printf
(
" -h, --help display this help and exit
\n
"
);
printf
(
" -i, --inetd runs in inetd mode (default)
\n
"
);
printf
(
" -p, --port=PORT specifies port to listen on, implies -d
\n
"
);
printf
(
" defaults to 110, which need not be specified
\n
"
);
printf
(
" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds
\n
"
);
printf
(
" TIMEOUT default is 600 (10 minutes)
\n
"
);
printf
(
" -v, --version display version information and exit
\n
"
);
printf
(
"
\n
Report bugs to bug-mailutils@gnu.org
\n
"
);
exit
(
0
);
}
/* Default signal handler to call the pop3d_abquit() function */
RETSIGTYPE
pop3d_signal
(
int
signo
)
{
syslog
(
LOG_CRIT
,
"got signal %d"
,
signo
);
/* Master process. */
if
(
!
ofile
)
{
syslog
(
LOG_CRIT
,
"MASTER: exiting on signal"
);
exit
(
1
);
/* abort(); */
}
if
(
signo
==
SIGALRM
)
pop3d_abquit
(
ERR_TIMEOUT
);
pop3d_abquit
(
ERR_SIGNAL
);
exit
(
EXIT_FAILURE
);
}
/* Gets a line of input from the client, caller should free() */
...
...
pop3d/pop3d.c
View file @
b0f41a7
...
...
@@ -41,6 +41,10 @@ static struct option long_options[] =
const
char
*
short_options
=
"d::hip:t:v"
;
static
int
syslog_error_printer
__P
((
const
char
*
fmt
,
va_list
ap
));
static
int
pop3d_mainloop
__P
((
int
,
int
));
static
void
pop3d_daemon_init
__P
((
void
));
static
void
pop3d_daemon
__P
((
unsigned
int
,
unsigned
int
));
static
void
pop3d_usage
__P
((
char
*
));
#ifndef DEFMAXCHILDREN
# define DEFMAXCHILDREN 10
/* Default maximum number of children */
...
...
@@ -91,7 +95,7 @@ main (int argc, char **argv)
case
'v'
:
printf
(
IMPL
" ("
PACKAGE
" "
VERSION
")
\n
"
);
exit
(
0
);
exit
(
EXIT_SUCCESS
);
break
;
default:
...
...
@@ -104,13 +108,13 @@ main (int argc, char **argv)
if
(
gr
==
NULL
)
{
perror
(
"Error getting mail group"
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
if
(
setgid
(
gr
->
gr_gid
)
==
-
1
)
{
perror
(
"Error setting mail group"
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
/* Register the desire formats. We only need Mbox mail format. */
...
...
@@ -136,7 +140,7 @@ main (int argc, char **argv)
if
(
mode
==
DAEMON
)
pop3d_daemon_init
();
/* Make sure
that to b
e in the root directory. */
/* Make sure
we ar
e in the root directory. */
chdir
(
"/"
);
/* Set up for syslog. */
...
...
@@ -150,7 +154,7 @@ main (int argc, char **argv)
/* Actually run the daemon. */
if
(
mode
==
DAEMON
)
pop3d_daemon
(
maxchildren
,
port
);
/* exit (
0
) -- no way out of daemon except a signal. */
/* exit (
EXIT_SUCCESS
) -- no way out of daemon except a signal. */
else
status
=
pop3d_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
...
...
@@ -160,7 +164,7 @@ main (int argc, char **argv)
}
/* Sets things up for daemon mode. */
void
static
void
pop3d_daemon_init
(
void
)
{
pid_t
pid
;
...
...
@@ -169,10 +173,10 @@ pop3d_daemon_init (void)
if
(
pid
==
-
1
)
{
perror
(
"fork failed:"
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
else
if
(
pid
>
0
)
exit
(
0
);
/* Parent exits. */
exit
(
EXIT_SUCCESS
);
/* Parent exits. */
setsid
();
/* Become session leader. */
...
...
@@ -184,10 +188,10 @@ pop3d_daemon_init (void)
if
(
pid
==
-
1
)
{
perror
(
"fork failed:"
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
else
if
(
pid
>
0
)
exit
(
0
);
/* Parent exits. */
exit
(
EXIT_SUCCESS
);
/* Parent exits. */
/* Close inherited file descriptors. */
{
...
...
@@ -217,7 +221,7 @@ pop3d_daemon_init (void)
/* The main part of the daemon. This function reads input from the client and
executes the proper functions. Also handles the bulk of error reporting. */
int
static
int
pop3d_mainloop
(
int
infile
,
int
outfile
)
{
int
status
=
OK
;
...
...
@@ -377,7 +381,7 @@ pop3d_mainloop (int infile, int outfile)
(default 110) then executes a pop3d_mainloop() upon accepting a connection.
It starts maxchildren child processes to listen to and accept socket
connections. */
void
static
void
pop3d_daemon
(
unsigned
int
maxchildren
,
unsigned
int
port
)
{
struct
sockaddr_in
server
,
client
;
...
...
@@ -389,7 +393,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if
(
listenfd
==
-
1
)
{
syslog
(
LOG_ERR
,
"socket: %s"
,
strerror
(
errno
));
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
size
=
1
;
/* Use size here to avoid making a new variable. */
setsockopt
(
listenfd
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
size
,
sizeof
(
size
));
...
...
@@ -402,13 +406,13 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if
(
bind
(
listenfd
,
(
struct
sockaddr
*
)
&
server
,
size
)
==
-
1
)
{
syslog
(
LOG_ERR
,
"bind: %s"
,
strerror
(
errno
));
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
if
(
listen
(
listenfd
,
128
)
==
-
1
)
{
syslog
(
LOG_ERR
,
"listen: %s"
,
strerror
(
errno
));
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
for
(;;)
...
...
@@ -425,7 +429,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if
(
errno
==
EINTR
)
continue
;
syslog
(
LOG_ERR
,
"accept: %s"
,
strerror
(
errno
));
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
pid
=
fork
();
...
...
@@ -447,6 +451,28 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
}
}
/* Prints out usage information and exits the program */
static
void
pop3d_usage
(
char
*
argv0
)
{
printf
(
"Usage: %s [OPTIONS]
\n
"
,
argv0
);
printf
(
"Runs the GNU POP3 daemon.
\n\n
"
);
printf
(
" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum
\n
"
);
printf
(
" of MAXCHILDREN child processes
\n
"
);
printf
(
" -h, --help display this help and exit
\n
"
);
printf
(
" -i, --inetd runs in inetd mode (default)
\n
"
);
printf
(
" -p, --port=PORT specifies port to listen on, implies -d
\n
"
);
printf
(
" defaults to 110, which need not be specifi
ed
\n
"
);
printf
(
" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds
\n
"
);
printf
(
" TIMEOUT default is 600 (10 minutes)
\n
"
);
printf
(
" -v, --version display version information and exit
\n
"
);
printf
(
"
\n
Report bugs to bug-mailutils@gnu.org
\n
"
);
exit
(
EXIT_SUCCESS
);
}
static
int
syslog_error_printer
(
const
char
*
fmt
,
va_list
ap
)
{
...
...
pop3d/pop3d.h
View file @
b0f41a7
...
...
@@ -175,31 +175,27 @@ extern FILE *ofile;
extern
char
*
md5shared
;
extern
volatile
size_t
children
;
extern
int
pop3d_abquit
__P
((
int
));
extern
int
pop3d_apop
__P
((
const
char
*
));
extern
char
*
pop3d_apopuser
__P
((
const
char
*
));
extern
char
*
pop3d_args
__P
((
const
char
*
));
extern
int
pop3d_auth
__P
((
const
char
*
));
extern
int
pop3d_capa
__P
((
const
char
*
));
extern
char
*
pop3d_cmd
__P
((
const
char
*
));
extern
int
pop3d_dele
__P
((
const
char
*
));
extern
int
pop3d_list
__P
((
const
char
*
));
extern
int
pop3d_lock
__P
((
void
));
extern
int
pop3d_noop
__P
((
const
char
*
));
extern
int
pop3d_quit
__P
((
const
char
*
));
extern
char
*
pop3d_readline
__P
((
FILE
*
));
extern
int
pop3d_retr
__P
((
const
char
*
));
extern
int
pop3d_rset
__P
((
const
char
*
));
extern
RETSIGTYPE
pop3d_sigchld
__P
((
int
));
extern
RETSIGTYPE
pop3d_signal
__P
((
int
));
extern
int
pop3d_stat
__P
((
const
char
*
));
extern
int
pop3d_top
__P
((
const
char
*
));
extern
int
pop3d_touchlock
__P
((
void
));
extern
int
pop3d_uidl
__P
((
const
char
*
));
extern
int
pop3d_user
__P
((
const
char
*
));
extern
int
pop3d_apop
__P
((
const
char
*
));
extern
int
pop3d_auth
__P
((
const
char
*
));
extern
int
pop3d_capa
__P
((
const
char
*
));
extern
char
*
pop3d_args
__P
((
const
char
*
));
extern
char
*
pop3d_cmd
__P
((
const
char
*
));
extern
int
pop3d_abquit
__P
((
int
));
extern
int
pop3d_lock
__P
((
void
));
extern
int
pop3d_touchlock
__P
((
void
));
extern
int
pop3d_unlock
__P
((
void
));
extern
int
pop3d_mainloop
__P
((
int
,
int
));
extern
void
pop3d_daemon
__P
((
size_t
,
unsigned
int
));
extern
void
pop3d_usage
__P
((
char
*
));
extern
RETSIGTYPE
pop3d_signal
__P
((
int
));
extern
RETSIGTYPE
pop3d_sigchld
__P
((
int
));
extern
void
pop3d_daemon_init
__P
((
void
));
extern
char
*
pop3d_apopuser
__P
((
const
char
*
));
extern
char
*
pop3d_readline
__P
((
FILE
*
));
#endif
/* _POP3D_H */
...
...
pop3d/signal.c
View file @
b0f41a7
...
...
@@ -32,3 +32,21 @@ pop3d_sigchld (int signo)
signal
(
signo
,
pop3d_sigchld
);
#endif
}
/* Default signal handler to call the pop3d_abquit() function */
RETSIGTYPE
pop3d_signal
(
int
signo
)
{
syslog
(
LOG_CRIT
,
"got signal %d"
,
signo
);
/* Master process. */
if
(
!
ofile
)
{
syslog
(
LOG_CRIT
,
"MASTER: exiting on signal"
);
exit
(
EXIT_FAILURE
);
/* abort(); */
}
if
(
signo
==
SIGALRM
)
pop3d_abquit
(
ERR_TIMEOUT
);
pop3d_abquit
(
ERR_SIGNAL
);
}
...
...
Please
register
or
sign in
to post a comment