1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 2017-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library; If not, see
16    <http://www.gnu.org/licenses/>.  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include <string.h>
26 #include <mailutils/errno.h>
27 #include <mailutils/alloc.h>
28 
29 #define SID_ABC "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
30 #define SID_LEN (sizeof (SID_ABC) - 1)
31 #define SID_LEN_SQR (SID_LEN * SID_LEN)
32 
33 /* Generate (almost) unique session ID.  The idea borrowed from Sendmail
34    queue ID.
35  */
36 int
mu_sid(char ** res)37 mu_sid (char **res)
38 {
39   static int init;
40   static unsigned int seqno = 0;
41   static char abc[] = SID_ABC;
42 
43   struct timeval t;
44   struct tm *tm;
45   unsigned int n;
46   char sidbuf[9];
47   char *p;
48 
49   if (!res)
50     return MU_ERR_OUT_PTR_NULL;
51 
52   gettimeofday (&t, NULL);
53 
54   if (!init)
55     {
56       seqno = getpid () + t.tv_sec + t.tv_usec;
57       init = 1;
58     }
59 
60   n = seqno++ % SID_LEN_SQR;
61   tm = gmtime (&t.tv_sec);
62   sidbuf[0] = abc[tm->tm_year % SID_LEN];
63   sidbuf[1] = abc[tm->tm_mon];
64   sidbuf[2] = abc[tm->tm_mday];
65   sidbuf[3] = abc[tm->tm_hour];
66   sidbuf[4] = abc[tm->tm_min % SID_LEN];
67   sidbuf[5] = abc[tm->tm_sec % SID_LEN];
68   sidbuf[6] = abc[n / SID_LEN];
69   sidbuf[7] = abc[n % SID_LEN];
70   sidbuf[8] = 0;
71 
72   p = strdup (sidbuf);
73   if (!p)
74     return errno;
75   *res = p;
76   return 0;
77 }
78