/[mailutils]/mailutils/mailbox/mbx_default.c
ViewVC logotype

Diff of /mailutils/mailbox/mbx_default.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.17 by gray, Tue Feb 19 17:06:49 2002 UTC revision 1.18 by gray, Wed Feb 27 11:55:52 2002 UTC
# Line 34  Line 34 
34  #include <mailutils/mutil.h>  #include <mailutils/mutil.h>
35  #include <mailutils/error.h>  #include <mailutils/error.h>
36    
37    char *mu_path_maildir = MU_PATH_MAILDIR;
38    
39  /* Is this a security risk?  */  /* Is this a security risk?  */
40  #define USE_ENVIRON 1  #define USE_ENVIRON 1
41    
42  static char * tilde_expansion      __P ((const char *));  static int
43  static char * plus_equal_expansion __P ((const char *));  split_shortcut (const char *file, const char pfx[], char **user, char **rest)
 static char * get_cwd              __P ((void));  
 static char * get_full_path        __P ((const char *));  
 static const char * get_homedir    __P ((const char *));  
   
 /* Do + and = expansion to ~/Mail, if necessary. */  
 static char *  
 plus_equal_expansion (const char *file)  
44  {  {
45    char *p = NULL;    *user = NULL;
46    if (file && (*file == '+' || *file == '='))    *rest = NULL;
47    
48      if (!strchr (pfx, file[0]))
49        return 0;
50    
51      if (*++file == 0)
52        return 0;
53      else
54        {
55          char *p = strchr (file, '/');
56          int len;
57          if (p)
58            len = p - file + 1;
59          else
60            len = strlen (file) + 1;
61          
62          *user = calloc (1, len);
63          if (!*user)
64            return ENOMEM;
65    
66          memcpy (*user, file, len);
67          (*user)[len-1] = 0;
68          file += len-1;
69          if (file[0] == '/')
70            file++;
71        }
72    
73      if (file[0])
74      {      {
75        char *folder;        *rest = strdup (file);
76        /* Skip '+' or '='.  */        if (!*rest)
77        file++;          {
78        folder = tilde_expansion ("~/Mail");            free (*user);
79        if (folder)            return ENOMEM;
80          {          }
81            p = malloc (strlen (folder) + 1 + strlen (file) + 1);      }
82            if (p)    
83              sprintf(p, "%s/%s", folder, file);    return 0;
           free (folder);  
         }  
     }  
   
   if (!p)  
     p = strdup (file);  
   return p;  
84  }  }
85    
86  static const char *  static const char *
# Line 77  get_homedir (const char *user) Line 92  get_homedir (const char *user)
92      {      {
93        pw = mu_getpwnam (user);        pw = mu_getpwnam (user);
94        if (pw)        if (pw)
95          homedir = pw->pw_dir;          homedir = pw->pw_dir;
96      }      }
97    else    else
98      {      {
# Line 85  get_homedir (const char *user) Line 100  get_homedir (const char *user)
100        /* NOTE: Should we honor ${HOME}?  */        /* NOTE: Should we honor ${HOME}?  */
101        homedir = getenv ("HOME");        homedir = getenv ("HOME");
102        if (homedir == NULL)        if (homedir == NULL)
103          {          {
104            pw = mu_getpwuid (getuid ());            pw = mu_getpwuid (getuid ());
105            if (pw)            if (pw)
106              homedir = pw->pw_dir;              homedir = pw->pw_dir;
107          }          }
108  #else  #else
109        pw = mu_getpwuid (getuid ());        pw = mu_getpwuid (getuid ());
110        if (pw)        if (pw)
111          homedir = pw->pw_dir;          homedir = pw->pw_dir;
112  #endif  #endif
113      }      }
114    return homedir;    return homedir;
115  }  }
116    
117  /* Do ~ , if necessary.  We do not use $HOME. */  static int
118  static char *  user_mailbox_name (const char *user, char **mailbox_name)
 tilde_expansion (const char *file)  
119  {  {
120    char *p = NULL;  #ifdef USE_ENVIRON
121    const char *homedir = NULL;    if (!user)
122    const char delim = '/'; /* Not portable.  */      user = (getenv ("LOGNAME")) ? getenv ("LOGNAME") : getenv ("USER");
123    #endif
124    if (file && *file == '~')    if (user == NULL)
125      {      {
126        /* Skip the tilde.  */        struct passwd *pw;
127        file++;        pw = mu_getpwuid (getuid ());
128          if (pw)
129        /* This means we have ~ or ~/something.  */          user = pw->pw_name;
       if (*file == delim || *file == '\0')  
         {  
           homedir = get_homedir (NULL);  
           if (homedir)  
             {  
               p = calloc (strlen (homedir) + strlen (file) + 1, 1);  
               if (p)  
                 {  
                   strcpy (p, homedir);  
                   strcat (p, file);  
                 }  
             }  
         }  
       /* Means we have ~user or ~user/something.  */  
130        else        else
131          {          {
132            const char *s = file;            mu_error ("Who am I ?\n");
133              return EINVAL;
134            }
135        }
136      *mailbox_name = malloc (strlen (user) + strlen (mu_path_maildir) + 2);
137      if (*mailbox_name == NULL)
138        return ENOMEM;
139      sprintf (*mailbox_name, "%s%s", mu_path_maildir, user);
140      return 0;
141    }
142    
143            /* Move  to the first delim.  */  #define MPREFIX "Mail"
           while (*s && *s != delim) s++;  
144    
145            /* Get the username homedir.  */  static int
146            {  plus_expand (const char *file, char **buf)
147              char *name;  {
148              name = calloc (s - file + 1, 1);    char *user = NULL;
149              if (name)    char *path = NULL;
150                {    const char *home;
151                  memcpy (name, file, s - file);    int status, len;
152                  name [s - file] = '\0';    
153                }    if ((status = split_shortcut (file, "+=", &user, &path)))
154              homedir = get_homedir (name);      return status;
155              free (name);  
156            }    if (!path)
157        {
158            if (homedir)        free (user);
159              {        return ENOENT;
160                p = calloc (strlen (homedir) + strlen (s) + 1, 1);      }
161                if (p)    
162                  {    home = get_homedir (user);
163                    strcpy (p, homedir);    if (!home)
164                    strcat (p, s);      {
165                  }        free (user);
166              }        free (path);
167          }        return ENOENT;
168      }      }
169    
170    if (!p)    len = strlen (home) + sizeof (MPREFIX) + strlen (path) + 3;
171      p = strdup (file);    *buf = malloc (len);
172    return p;    sprintf (*buf, "%s/%s/%s", home, MPREFIX, path);
173      (*buf)[len-1] = 0;
174      free (user);
175      free (path);
176      return 0;
177  }  }
178    
179  static char *  /* Do ~ , if necessary.  We do not use $HOME. */
180  get_cwd ()  static int
181    tilde_expand (const char *file, char **buf)
182  {  {
183    char *ret;    char *user = NULL;
184    unsigned path_max;    char *path = NULL;
185    char buf[128];    const char *home;
186      int status;
187    errno = 0;    int len;
188    ret = getcwd (buf, sizeof (buf));    
189    if (ret != NULL)    if ((status = split_shortcut (file, "~", &user, &path)))
190      return strdup (buf);      return status;
191    
192    if (errno != ERANGE)    if (!user)
193      return NULL;      return ENOENT;
194      if (!path)
195    path_max = 128;      {
196    path_max += 2;                /* The getcwd docs say to do this. */        free (user);
197          return ENOENT;
198    for (;;)      }
199      {    
200        char *cwd = (char *) malloc (path_max);    home = get_homedir (user);
201      if (!home)
202        errno = 0;      {
203        ret = getcwd (cwd, path_max);        free (user);
204        if (ret != NULL)        free (path);
205          return ret;        return ENOENT;
206        if (errno != ERANGE)      }
         {  
           int save_errno = errno;  
           free (cwd);  
           errno = save_errno;  
           return NULL;  
         }  
   
       free (cwd);  
207    
208        path_max += path_max / 16;    free (user); /* not needed anymore */
209        path_max += 32;        
210      len = strlen (home) + strlen (path) + 2;
211      *buf = malloc (len);
212      if (*buf)
213        {
214          sprintf (*buf, "%s/%s", home, path);
215          (*buf)[len-1] = 0;
216      }      }
217    /* oops?  */  
218    return NULL;    free (path);
219      free (user);
220      return *buf ? 0 : ENOMEM;
221  }  }
222    
223  static char *  static int
224  get_full_path (const char *file)  percent_expand (const char *file, char **mbox)
225  {  {
226    char *p = NULL;    char *user = NULL;
227      char *path = NULL;
228      int status;
229      
230      if ((status = split_shortcut (file, "%", &user, &path)))
231        return status;
232    
233    if (!file)    if (path)
234      p = get_cwd ();      {
235    else if (*file != '/')        free (user);
236      {        free (path);
237        char *cwd = get_cwd ();        return ENOENT;
238        if (cwd)      }
239          {  
240            p = calloc (strlen (cwd) + 1 + strlen (file) + 1, 1);    status = user_mailbox_name (user, mbox);
241            if (p)    free (user);
242              sprintf (p, "%s/%s", cwd, file);    return status;
           free (cwd);  
         }  
     }  
   
   if (!p)  
     p = strdup (file);  
   return p;  
243  }  }
244    
245  /* We are trying to be smart about the location of the mail.  /* We are trying to be smart about the location of the mail.
246     mailbox_create() is not doing this.     mailbox_create() is not doing this.
247     ~/file  --> /home/user/file     %           --> system mailbox for the real uid
248     ~user/file --> /home/user/file     %user       --> system mailbox for the given user
249     +file --> /home/user/Mail/file     ~/file      --> /home/user/file
250     =file --> /home/user/Mail/file     ~user/file  --> /home/user/file
251       +file       --> /home/user/Mail/file
252       =file       --> /home/user/Mail/file
253  */  */
254  int  int
255  mailbox_create_default (mailbox_t *pmbox, const char *mail)  mailbox_create_default (mailbox_t *pmbox, const char *mail)
256  {  {
257    char *mbox = NULL;    char *mbox = NULL;
258    int status;    char *tmp_mbox = NULL;
259      int status = 0;
260    
261    /* Sanity.  */    /* Sanity.  */
262    if (pmbox == NULL)    if (pmbox == NULL)
# Line 251  mailbox_create_default (mailbox_t *pmbox Line 265  mailbox_create_default (mailbox_t *pmbox
265    /* Other utilities may not understand GNU mailutils url namespace, so    /* Other utilities may not understand GNU mailutils url namespace, so
266       use FOLDER instead, to not confuse others by using MAIL.  */       use FOLDER instead, to not confuse others by using MAIL.  */
267    if (mail == NULL || *mail == '\0')    if (mail == NULL || *mail == '\0')
     mail = getenv ("FOLDER");  
   
   /* Fallback to wellknown environment.  */  
   if (mail == NULL)  
     mail = getenv ("MAIL");  
   
   /* FIXME: This is weak, it would be better to check  
      for all the known schemes to detect presence of URLs.  */  
   if (mail && *mail && strchr (mail, ':') == NULL)  
268      {      {
269        char *mail0;        mail = getenv ("FOLDER");
       char *mail2;  
270    
271        mail0 = tilde_expansion (mail);        /* Fallback to wellknown environment.  */
272        mail2 = plus_equal_expansion (mail0);        if (!mail)
273        free (mail0);          mail = getenv ("MAIL");
274        mbox = get_full_path (mail2);  
275        free (mail2);        if (!mail)
276            {
277              if (status = user_mailbox_name (NULL, &tmp_mbox))
278                return status;
279              mail = tmp_mbox;
280            }
281      }      }
   else if (mail)  
     mbox = strdup (mail);  
282    
283    /* Search the spooldir.  */    switch (mail[0])
   if (mbox == NULL)  
284      {      {
285        const char *user = NULL;      case '%':
286  #ifdef USE_ENVIRON        status = percent_expand (mail, &mbox);
287        user = (getenv ("LOGNAME")) ? getenv ("LOGNAME") : getenv ("USER");        break;
288  #endif      case '~':
289        if (user == NULL)        status = tilde_expand (mail, &mbox);
290          {        break;
291            struct passwd *pw;      case '+':
292            pw = mu_getpwuid (getuid ());      case '=':
293            if (pw)        status = plus_expand (mail, &mbox);
294              user = pw->pw_name;        break;
295            else      default:
296              {        mbox = strdup (mail);
297                mu_error ("Who am I ?\n");        break;
               return EINVAL;  
             }  
         }  
       mbox = malloc (strlen (user) + strlen (MU_PATH_MAILDIR) + 2);  
       if (mbox == NULL)  
         return ENOMEM;  
       sprintf (mbox, "%s%s", MU_PATH_MAILDIR, user);  
298      }      }
299    
300      if (tmp_mbox)
301        free (tmp_mbox);
302    
303      if (status)
304        return status;
305      
306    status = mailbox_create (pmbox, mbox);    status = mailbox_create (pmbox, mbox);
307    free (mbox);    free (mbox);
308    return status;    return status;

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26