rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | LICENSE

path.c (4206B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #include <unistd.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <sys/stat.h>
     10 #include <sys/types.h>
     11 #include <stdarg.h>
     12 #include <fcntl.h>
     13 #include <string.h>
     14 
     15 #include "arg.h"
     16 #include "ind.h"
     17 #include "path.h"
     18 
     19 enum {
     20 	PATH_MKFILE = 0x00,
     21 	PATH_MKDIR
     22 };
     23 
     24 char *
     25 path_chkmk(char *base, char *spath, int mode, int cmode)
     26 {
     27 	struct stat sbuf;
     28 	char *path, *home;
     29 	int fd;
     30 
     31 	if (base != NULL) {
     32 		home = expandhome(base);
     33 		path = smprintf("%s/%s", home, spath);
     34 		free(home);
     35 	} else {
     36 		path = memdup(spath, strlen(spath)+1);
     37 	}
     38 
     39 	if (stat(path, &sbuf) < 0) {
     40 		switch(mode) {
     41 		case PATH_MKFILE:
     42 			fd = open(path, O_WRONLY|O_CREAT|O_TRUNC,
     43 					(cmode >= 0)? \
     44 					cmode : (S_IRUSR|S_IWUSR));
     45 			if (fd < 0)
     46 				edie("open");
     47 			close(fd);
     48 			break;
     49 		case PATH_MKDIR:
     50 			if (mkdir(path, (cmode >= 0)? \
     51 					cmode : S_IRWXU) < 0) {
     52 				edie("mkdir");
     53 			}
     54 			break;
     55 		default:
     56 			die("path_chkmkdir: Unknown mode.\n");
     57 		}
     58 	}
     59 
     60 	return path;
     61 }
     62 
     63 char *
     64 path_chkmkfile(char *base, char *path, int mode)
     65 {
     66 	return path_chkmk(base, path, PATH_MKFILE, mode);
     67 }
     68 
     69 char *
     70 path_chkmkdir(char *base, char *path, int mode)
     71 {
     72 	return path_chkmk(base, path, PATH_MKDIR, mode);
     73 }
     74 
     75 char *
     76 path_mkrppath(char *rppath)
     77 {
     78 	return path_chkmkdir("~", (rppath)? rppath : RPPATH, -1);
     79 }
     80 
     81 char *
     82 path_mkbasepath(char *cfgn)
     83 {
     84 	char *path, *rpath, *cwd;
     85 	struct stat sbuf;
     86 
     87 	cwd = getcwd(NULL, 0);
     88 	if (cwd == NULL)
     89 		edie("getcwd");
     90 
     91 	path = path_mkrppath(NULL);
     92 	if (chdir(path) < 0)
     93 		edie("chdir");
     94 	if (lstat("default", &sbuf) < 0) {
     95 		if (cfgn == NULL || !strcmp(cfgn, "default")) {
     96 			die("You are trying to create a 'default'"
     97 				" configuration while no other configuration"
     98 				" exists."
     99 				" Please use _rppath -ic somecfg_ to"
    100 				" initialize the configuration 'somecfg' and"
    101 				" make it the default using _rpcfg -e"
    102 				" somecfg_. Then this error message"
    103 				" disappears.\n");
    104 		}
    105 	} else {
    106 		if (!S_ISLNK(sbuf.st_mode)) {
    107 			die("There seems to be some 'default' configuration"
    108 				" folder. This should be a symlink. Please go"
    109 				" to '%s' and check this. If no other folder"
    110 				" exists, it might help to run"
    111 				" _mv default somecfg_ and _rpcfg -e"
    112 				" somecfg_. The last command will create the"
    113 				" symlink to 'default' and this error message"
    114 				" disappears. If nothing helps, remove the"
    115 				" 'default' directory and reinitialize your"
    116 				" configuration using a different name.\n",
    117 				path);
    118 		}
    119 	}
    120 
    121 	rpath = path_chkmkdir(path, (cfgn)? cfgn : "default", -1);
    122 	free(path);
    123 
    124 	if (chdir(cwd) < 0)
    125 		edie("chdir");
    126 	free(cwd);
    127 
    128 	return rpath;
    129 }
    130 
    131 char *
    132 path_mkcfgfile(char *cfgn)
    133 {
    134 	char *path, *rpath;
    135 
    136 	path = path_mkbasepath(cfgn);
    137 	rpath = path_chkmkfile(path, "config", -1);
    138 	free(path);
    139 
    140 	return rpath;
    141 }
    142 
    143 char *
    144 path_mkmarkfile(char *cfgn, char *markn)
    145 {
    146 	char *path, *mpath;
    147 
    148 	if (markn == NULL)
    149 		return NULL;
    150 
    151 	path = path_mkbasepath(cfgn);
    152 	mpath = path_chkmkdir(path, "marks", -1);
    153 	free(path);
    154 
    155 	path = path_chkmkfile(mpath, markn, -1);
    156 	free(mpath);
    157 
    158 	return path;
    159 }
    160 
    161 char *
    162 path_mkincfile(char *cfgn)
    163 {
    164 	char *path, *rpath;
    165 
    166 	path = path_mkbasepath(cfgn);
    167 	rpath = path_chkmkfile(path, "status", -1);
    168 	free(path);
    169 
    170 	return rpath;
    171 }
    172 
    173 void
    174 pathusage(char *argv0)
    175 {
    176 	die("usage: %s [-bhi] [-c cfg]\n", argv0);
    177 }
    178 
    179 int
    180 pathmain(int argc, char *argv[])
    181 {
    182 	int status;
    183 	char *cfgn, *path, *argv0;
    184 
    185 	enum {
    186 		PRINTBASE = 0x01,
    187 		INITBASE = 0x02,
    188 	};
    189 
    190 	status = 0;
    191 	cfgn = NULL;
    192 
    193 	ARGBEGIN(argv0) {
    194 	case 'b':
    195 		status |= PRINTBASE;
    196 		break;
    197 	case 'c':
    198 		cfgn = EARGF(pathusage(argv0));
    199 		break;
    200 	case 'i':
    201 		status |= INITBASE;
    202 		break;
    203 	default:
    204 		pathusage(argv0);
    205 	} ARGEND;
    206 
    207 	if (status & PRINTBASE) {
    208 		path = path_mkbasepath(cfgn);
    209 		printf("%s\n", path);
    210 		free(path);
    211 		return 0;
    212 	}
    213 
    214 	if (status & INITBASE) {
    215 		/* Will initialize all subpathnames. */
    216 		path = path_mkbasepath(cfgn);
    217 		free(path_chkmkfile(path, "config", -1));
    218 		free(path_chkmkfile(path, "status", -1));
    219 		free(path_chkmkdir(path, "drafts", -1));
    220 		free(path_chkmkdir(path, "marks", -1));
    221 		free(path_chkmkdir(path, "tmpl", -1));
    222 
    223 		printf("The directory '%s' has been initialized.\n", path);
    224 		free(path);
    225 		return 0;
    226 	}
    227 
    228 	pathusage(argv0);
    229 
    230 	return 0;
    231 }
    232