acmecert: Handle application/problem responses better.
[utils.git] / nextep.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <libgen.h>
6 #include <dirent.h>
7 #include <errno.h>
8 #include <sys/stat.h>
9
10 static int ensuredir(char *base, char *dir)
11 {
12     if(access(dir, X_OK)) {
13         if((mkdir(base, 0777) && (errno != EEXIST)) || mkdir(dir, 0777))
14             return(1);
15     }
16     return(0);
17 }
18
19 static void checkempty(char *dir)
20 {
21     DIR *dh;
22     int empty;
23     struct dirent *de;
24     
25     if((dh = opendir(dir)) == NULL)
26         return;
27     empty = 1;
28     while((de = readdir(dh)) != NULL) {
29         if(de->d_name[0] != '.') {
30             empty = 0;
31             break;
32         }
33     }
34     closedir(dh);
35     if(empty)
36         rmdir(dir);
37 }
38
39 static void usage(FILE *out)
40 {
41     fprintf(out, "usage: nextep [-h] [-f FILE] [-s SET-VALUE] [DIR]\n");
42 }
43
44 int main(int argc, char **argv)
45 {
46     int c;
47     char buf[1024], dbuf[1024], *p;
48     char *file, *value, *dir;
49     char base[1024], fpath[1024];
50     FILE *fp;
51     
52     file = "nextep";
53     value = NULL;
54     while((c = getopt(argc, argv, "hf:s:")) >= 0) {
55         switch(c) {
56         case 'f':
57             file = optarg;
58             break;
59         case 's':
60             value = optarg;
61             break;
62         case 'h':
63             usage(stdout);
64             exit(0);
65         default:
66             usage(stderr);
67             exit(1);
68         }
69     }
70     if(optind < argc) {
71         if(chdir(argv[optind])) {
72             fprintf(stderr, "nextep: %s: %s\n", argv[optind], strerror(errno));
73             exit(1);
74         }
75         optind++;
76     }
77     if(!getcwd(dbuf, sizeof(dbuf))) {
78         fprintf(stderr, "nextep: getcwd: %s\n", strerror(errno));
79         exit(1);
80     }
81     dir = basename(dbuf);
82     if((p = getenv("HOME")) == NULL) {
83         fprintf(stderr, "nextep: $HOME is not set\n");
84         exit(1);
85     }
86     snprintf(buf, sizeof(buf), "%s/.nextep", p);
87     snprintf(base, sizeof(base), "%s/%s", buf, dir);
88     snprintf(fpath, sizeof(fpath), "%s/%s", base, file);
89     if(value == NULL) {
90         if((fp = fopen(fpath, "r")) == NULL) {
91             if(errno != ENOENT) {
92                 fprintf(stderr, "nextep: %s: %s\n", fpath, strerror(errno));
93                 exit(1);
94             }
95         } else {
96             while(fgets(buf, sizeof(buf), fp) != NULL)
97                 printf(buf);
98             fclose(fp);
99         }
100     } else if(!*value) {
101         if(unlink(fpath) && (errno != ENOENT)) {
102             fprintf(stderr, "nextep: %s: %s\n", fpath, strerror(errno));
103             exit(1);
104         }
105         checkempty(base);
106     } else {
107         if(ensuredir(buf, base)) {
108             fprintf(stderr, "nextep: %s: %s\n", base, strerror(errno));
109             exit(1);
110         }
111         if((fp = fopen(fpath, "w")) == NULL) {
112             fprintf(stderr, "nextep: %s: %s\n", fpath, strerror(errno));
113             exit(1);
114         }
115         fprintf(fp, "%s\n", value);
116         fclose(fp);
117     }
118     return(0);
119 }
120
121 /*
122  * Local Variables:
123  * compile-command: "gcc -Wall -g -o nextep nextep.c"
124  * End:
125  */