Annotation of tftpd/src/tftpd.c, revision 1.1
1.1 ! misho 1: #include "global.h"
! 2: #include "srv.h"
! 3:
! 4:
! 5: intptr_t Kill;
! 6: struct tagCli cli;
! 7: cfg_root_t cfg;
! 8: sched_root_task_t *root;
! 9: char szCfgName[PATH_MAX] = DEFAULT_CFGNAME;
! 10: struct timespec timeout = { DEFAULT_TIMEOUT, 0 };
! 11: extern char compiled[], compiledby[], compilehost[];
! 12:
! 13: const struct tagErr errs[9] = {
! 14: { 0, "Not defined" },
! 15: { 1, "File not found" },
! 16: { 2, "Access violation" },
! 17: { 3, "Disk full or allocation exceeded" },
! 18: { 4, "Illegal TFTP operation" },
! 19: { 5, "Unknown transfer ID" },
! 20: { 6, "File already exists" },
! 21: { 7, "No such user" },
! 22: { 8, "Option not supported" },
! 23: };
! 24:
! 25: static void
! 26: Usage()
! 27: {
! 28: printf( " -= TFTPd =- ELWIX extended TFTP service\n"
! 29: "=== %s === %s@%s ===\n\n"
! 30: " Syntax: TFTPd [options]\n\n"
! 31: "\t-c <config>\tConfig file [default=/etc/tftpd.conf]\n"
! 32: "\t-w\t\tSwitch to read-write mode [default=read-only]\n"
! 33: "\t-b\t\tRun into batch mode (default is daemon mode)\n"
! 34: "\t-v\t\tVerbose (more -v, more verbosity ...)\n"
! 35: "\t-h\t\tThis help screen!\n"
! 36: "\n", compiled, compiledby, compilehost);
! 37: }
! 38:
! 39: static void *
! 40: sigHandler(sched_task_t *task)
! 41: {
! 42: int stat;
! 43: const char *str;
! 44:
! 45: switch (TASK_VAL(task)) {
! 46: case SIGHUP:
! 47: cfgUnloadConfig(&cfg);
! 48: if (cfgLoadConfig(szCfgName, &cfg)) {
! 49: ELIBERR(cfg);
! 50: Kill++;
! 51: } else
! 52: EVERBOSE(1, "Reloading config ...");
! 53:
! 54: str = cfg_getAttribute(&cfg, "tftpd", "timeout");
! 55: if (str)
! 56: timeout.tv_sec = strtol(str, NULL, 10);
! 57: break;
! 58: case SIGINT:
! 59: case SIGTERM:
! 60: EVERBOSE(1, "Terminate service ...");
! 61: Kill++;
! 62: break;
! 63: case SIGCHLD:
! 64: while (waitpid(-1, &stat, WNOHANG) > 0);
! 65: break;
! 66: default:
! 67: EERROR(EINVAL, "Unknown signal #%lu?", TASK_VAL(task));
! 68: break;
! 69: }
! 70:
! 71: schedSignalSelf(task);
! 72: taskExit(task, NULL);
! 73: }
! 74:
! 75: int
! 76: main(int argc, char **argv)
! 77: {
! 78: char ch, m = 0, b = 0;
! 79: const char *str;
! 80: int fd, uid = 0, ret = 0;
! 81: struct passwd *pass;
! 82: pid_t pid;
! 83: sockaddr_t sa;
! 84: rpack_t *pkt = NULL;
! 85:
! 86: while ((ch = getopt(argc, argv, "hvbwc:")) != -1)
! 87: switch (ch) {
! 88: case 'c':
! 89: strlcpy(szCfgName, optarg, sizeof szCfgName);
! 90: break;
! 91: case 'w':
! 92: m = 42; /* rw mode */
! 93: break;
! 94: case 'v':
! 95: e_incVerbose;
! 96: break;
! 97: case 'b':
! 98: b = 42;
! 99: break;
! 100: case 'h':
! 101: default:
! 102: Usage();
! 103: return 1;
! 104: }
! 105: argc -= optind;
! 106: argv += optind;
! 107:
! 108: openlog("TFTPd", LOG_PID | LOG_CONS, LOG_FTP);
! 109: if (cfgLoadConfig(szCfgName, &cfg)) {
! 110: ELIBERR(cfg);
! 111: return 2;
! 112: }
! 113:
! 114: str = cfg_getAttribute(&cfg, "tftpd", "user");
! 115: if (str) {
! 116: pass = getpwnam(str);
! 117: if (!pass) {
! 118: EERROR(EINVAL, "User %s not found!\n", str);
! 119: ret = 2;
! 120: goto end;
! 121: } else
! 122: uid = pass->pw_uid;
! 123: endpwent();
! 124: }
! 125:
! 126: if (!b) /* service mode */
! 127: switch ((pid = fork())) {
! 128: case -1:
! 129: ret = 3;
! 130: goto end;
! 131: case 0:
! 132: setsid();
! 133: chdir("/");
! 134:
! 135: fd = open(_PATH_DEVNULL, O_RDWR);
! 136: if (fd > 2) {
! 137: dup2(fd, STDIN_FILENO);
! 138: dup2(fd, STDOUT_FILENO);
! 139: dup2(fd, STDERR_FILENO);
! 140: close(fd);
! 141: }
! 142: EVERBOSE(1, "Welcome to the shadow-land!\n");
! 143: break;
! 144: default:
! 145: EVERBOSE(1, "Starting service with pid=%d ...\n", pid);
! 146: goto end;
! 147: }
! 148:
! 149: root = schedBegin();
! 150: if (!root) {
! 151: ELIBERR(sched);
! 152: ret = 3;
! 153: goto end;
! 154: }
! 155:
! 156: str = cfg_getAttribute(&cfg, "tftpd", "timeout");
! 157: if (str)
! 158: timeout.tv_sec = strtol(str, NULL, 10);
! 159:
! 160: str = cfg_getAttribute(&cfg, "tftpd", "port");
! 161: if (str)
! 162: fd = strtol(str, NULL, 10);
! 163: else
! 164: fd = 69;
! 165: str = cfg_getAttribute(&cfg, "tftpd", "bind");
! 166: e_gethostbyname(str ? str : "0.0.0.0", fd, &sa);
! 167: fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
! 168: if (fd == -1) {
! 169: ESYSERR(0);
! 170: ret = 4;
! 171: goto end;
! 172: }
! 173: if (bind(fd, &sa.sa, sa.sa.sa_len) == -1) {
! 174: ESYSERR(0);
! 175: close(fd);
! 176: ret = 4;
! 177: goto end;
! 178: }
! 179:
! 180: str = cfg_getAttribute(&cfg, "tftpd", "chroot");
! 181: if (str && chroot(str) == -1) {
! 182: ESYSERR(0);
! 183: close(fd);
! 184: ret = 3;
! 185: goto end;
! 186: } else {
! 187: setuid(uid);
! 188: str = cfg_getAttribute(&cfg, "tftpd", "dir");
! 189: if (str)
! 190: chdir(str);
! 191: }
! 192:
! 193: if (!(pkt = rpack_create(NULL, 0))) {
! 194: ELIBERR(elwix);
! 195: close(fd);
! 196: ret = 5;
! 197: goto end;
! 198: }
! 199: if (rpack_attach(pkt, TFTP_PKT_MAX)) {
! 200: ELIBERR(elwix);
! 201: close(fd);
! 202: ret = 5;
! 203: goto end;
! 204: }
! 205:
! 206: memset(&cli, 0, sizeof cli);
! 207: schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
! 208: schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
! 209: schedSignal(root, sigHandler, NULL, SIGINT, NULL, 0);
! 210: schedSignal(root, sigHandler, NULL, SIGCHLD, NULL, 0);
! 211: schedRead(root, rxPkt, NULL, fd, pkt, sizeof(rpack_t));
! 212: schedRun(root, &Kill);
! 213:
! 214: close(fd);
! 215: end:
! 216: schedEnd(&root);
! 217: rpack_detach(pkt);
! 218: rpack_destroy(&pkt);
! 219: cfgUnloadConfig(&cfg);
! 220: closelog();
! 221: return ret;
! 222: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>