Reworked samba/vsftpd start/stop/restart logic, prevent racing condition between...
[tomato.git] / release / src / router / rc / services.c
blob8ec528e1b9b882e6d0adedfafc74dbebb178cfd9
1 /*
3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Copyright 2005, Broadcom Corporation
22 All Rights Reserved.
24 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
25 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
26 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
27 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32 Modified for Tomato Firmware
33 Portions, Copyright (C) 2006-2009 Jonathan Zarate
36 #include "rc.h"
38 #include <arpa/inet.h>
39 #include <time.h>
40 #include <sys/time.h>
41 #include <errno.h>
43 // !!TB
44 #include <sys/mount.h>
45 #include <mntent.h>
46 #include <dirent.h>
48 #define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
49 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
51 // -----------------------------------------------------------------------------
53 static const char dmhosts[] = "/etc/hosts.dnsmasq";
54 static const char dmresolv[] = "/etc/resolv.dnsmasq";
55 static const char dmpid[] = "/var/run/dnsmasq.pid";
57 static pid_t pid_dnsmasq = -1;
60 void start_dnsmasq()
62 FILE *f;
63 const char *nv;
64 char buf[512];
65 char lan[24];
66 const char *router_ip;
67 const char *lan_ifname;
68 char sdhcp_lease[32];
69 char *e;
70 int n;
71 char *mac, *ip, *name;
72 char *p;
73 int ipn;
74 char ipbuf[32];
75 FILE *hf;
76 int dhcp_start;
77 int dhcp_count;
78 int dhcp_lease;
79 int do_dhcpd;
80 int do_dns;
82 TRACE_PT("begin\n");
84 if (getpid() != 1) {
85 start_service("dnsmasq");
86 return;
89 stop_dnsmasq();
91 if (nvram_match("wl_mode", "wet")) return;
92 if ((f = fopen("/etc/dnsmasq.conf", "w")) == NULL) return;
94 lan_ifname = nvram_safe_get("lan_ifname");
95 router_ip = nvram_safe_get("lan_ipaddr");
96 strlcpy(lan, router_ip, sizeof(lan));
97 if ((p = strrchr(lan, '.')) != NULL) *(p + 1) = 0;
99 fprintf(f,
100 "pid-file=%s\n"
101 "interface=%s\n",
102 dmpid, lan_ifname);
103 if (((nv = nvram_get("wan_domain")) != NULL) || ((nv = nvram_get("wan_get_domain")) != NULL)) {
104 if (*nv) fprintf(f, "domain=%s\n", nv);
107 // dns
108 if (((nv = nvram_get("dns_minport")) != NULL) && (*nv)) n = atoi(nv);
109 else n = 4096;
110 fprintf(f,
111 "resolv-file=%s\n" // the real stuff is here
112 "addn-hosts=%s\n" // "
113 "expand-hosts\n" // expand hostnames in hosts file
114 "min-port=%u\n", // min port used for random src port
115 dmresolv, dmhosts, n);
116 do_dns = nvram_match("dhcpd_dmdns", "1");
119 // dhcp
120 do_dhcpd = nvram_match("lan_proto", "dhcp");
121 if (do_dhcpd) {
122 dhcp_lease = nvram_get_int("dhcp_lease");
123 if (dhcp_lease <= 0) dhcp_lease = 1440;
125 if ((e = nvram_get("dhcpd_slt")) != NULL) n = atoi(e); else n = 0;
126 if (n < 0) strcpy(sdhcp_lease, "infinite");
127 else sprintf(sdhcp_lease, "%dm", (n > 0) ? n : dhcp_lease);
129 if (!do_dns) {
130 // if not using dnsmasq for dns
132 const dns_list_t *dns = get_dns(); // this always points to a static buffer
133 if ((dns->count == 0) && (nvram_match("dhcpd_llndns", "1"))) {
134 // no DNS might be temporary. use a low lease time to force clients to update.
135 dhcp_lease = 2;
136 strcpy(sdhcp_lease, "2m");
137 do_dns = 1;
139 else {
140 // pass the dns directly
141 buf[0] = 0;
142 for (n = 0 ; n < dns->count; ++n) {
143 sprintf(buf + strlen(buf), ",%s", inet_ntoa(dns->dns[n]));
145 fprintf(f, "dhcp-option=6%s\n", buf);
149 if ((p = nvram_get("dhcpd_startip")) && (*p) && (e = nvram_get("dhcpd_endip")) && (*e)) {
150 fprintf(f, "dhcp-range=%s,%s,%s,%dm\n", p, e, nvram_safe_get("lan_netmask"), dhcp_lease);
152 else {
153 // for compatibility
154 dhcp_start = nvram_get_int("dhcp_start");
155 dhcp_count = nvram_get_int("dhcp_num");
156 fprintf(f, "dhcp-range=%s%d,%s%d,%s,%dm\n",
157 lan, dhcp_start, lan, dhcp_start + dhcp_count - 1, nvram_safe_get("lan_netmask"), dhcp_lease);
159 n = nvram_get_int("dhcpd_lmax");
160 fprintf(f,
161 "dhcp-option=3,%s\n" // gateway
162 "dhcp-lease-max=%d\n",
163 router_ip,
164 (n > 0) ? n : 255);
166 if (nvram_get_int("dhcpd_auth") >= 0) {
167 fprintf(f, "dhcp-authoritative\n");
170 if (((nv = nvram_get("wan_wins")) != NULL) && (*nv) && (strcmp(nv, "0.0.0.0") != 0)) {
171 fprintf(f, "dhcp-option=44,%s\n", nv);
174 else {
175 fprintf(f, "no-dhcp-interface=%s\n", lan_ifname);
178 // write static lease entries & create hosts file
180 if ((hf = fopen(dmhosts, "w")) != NULL) {
181 if (((nv = nvram_get("wan_hostname")) != NULL) && (*nv))
182 fprintf(hf, "%s %s\n", router_ip, nv);
183 #ifdef TCONFIG_SAMBASRV
184 else if (((nv = nvram_get("lan_hostname")) != NULL) && (*nv))
185 fprintf(hf, "%s %s\n", router_ip, nv);
186 #endif
189 // 00:aa:bb:cc:dd:ee<123<xxxxxxxxxxxxxxxxxxxxxxxxxx.xyz> = 53 w/ delim
190 // 00:aa:bb:cc:dd:ee<123.123.123.123<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xyz> = 85 w/ delim
191 p = nvram_safe_get("dhcpd_static");
192 while ((e = strchr(p, '>')) != NULL) {
193 n = (e - p);
194 if (n > 84) {
195 p = e + 1;
196 continue;
199 strncpy(buf, p, n);
200 buf[n] = 0;
201 p = e + 1;
203 if ((e = strchr(buf, '<')) == NULL) continue;
204 *e = 0;
205 mac = buf;
207 ip = e + 1;
208 if ((e = strchr(ip, '<')) == NULL) continue;
209 *e = 0;
210 if (strchr(ip, '.') == NULL) {
211 ipn = atoi(ip);
212 if ((ipn <= 0) || (ipn > 255)) continue;
213 sprintf(ipbuf, "%s%d", lan, ipn);
214 ip = ipbuf;
216 else {
217 if (inet_addr(ip) == INADDR_NONE) continue;
220 name = e + 1;
222 if ((hf) && (*name != 0)) {
223 fprintf(hf, "%s %s\n", ip, name);
226 if ((do_dhcpd) && (*mac != 0) && (strcmp(mac, "00:00:00:00:00:00") != 0)) {
227 fprintf(f, "dhcp-host=%s,%s,%s\n", mac, ip, sdhcp_lease);
231 if (hf) fclose(hf);
235 fprintf(f, "%s\n\n", nvram_safe_get("dnsmasq_custom"));
237 fappend(f, "/etc/dnsmasq.custom");
241 fclose(f);
243 if (do_dns) {
244 unlink("/etc/resolv.conf");
245 symlink("/rom/etc/resolv.conf", "/etc/resolv.conf"); // nameserver 127.0.0.1
248 TRACE_PT("run dnsmasq\n");
250 eval("dnsmasq");
252 if (!nvram_contains_word("debug_norestart", "dnsmasq")) {
253 f_read_string(dmpid, buf, sizeof(buf));
254 pid_dnsmasq = atol(buf);
257 TRACE_PT("end\n");
260 void stop_dnsmasq(void)
262 TRACE_PT("begin\n");
264 if (getpid() != 1) {
265 stop_service("dnsmasq");
266 return;
269 pid_dnsmasq = -1;
271 unlink("/etc/resolv.conf");
272 symlink(dmresolv, "/etc/resolv.conf");
274 killall_tk("dnsmasq");
276 TRACE_PT("end\n");
279 void clear_resolv(void)
281 _dprintf("%s\n", __FUNCTION__);
283 f_write(dmresolv, NULL, 0, 0, 0); // blank
286 void dns_to_resolv(void)
288 FILE *f;
289 const dns_list_t *dns;
290 int i;
291 mode_t m;
293 _dprintf("%s\n", __FUNCTION__);
295 m = umask(022); // 077 from pppoecd
296 if ((f = fopen(dmresolv, "w")) != NULL) {
297 dns = get_dns(); // static buffer
298 if (dns->count == 0) {
299 // Put a pseudo DNS IP to trigger Connect On Demand
300 if ((nvram_match("ppp_demand", "1")) &&
301 (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "pptp") || nvram_match("wan_proto", "l2tp"))) {
302 fprintf(f, "nameserver 1.1.1.1\n");
305 else {
306 for (i = 0; i < dns->count; i++) {
307 fprintf(f, "nameserver %s\n", inet_ntoa(dns->dns[i]));
310 fclose(f);
312 umask(m);
315 // -----------------------------------------------------------------------------
317 void start_httpd(void)
319 chdir("/www");
320 if (!nvram_match("http_enable", "0")) {
321 xstart("httpd");
323 if (!nvram_match("https_enable", "0")) {
324 xstart("httpd", "-s");
326 chdir("/");
329 void stop_httpd(void)
331 killall_tk("httpd");
334 // -----------------------------------------------------------------------------
336 void start_upnp(void)
338 if (get_wan_proto() == WP_DISABLED) return;
340 #ifdef USE_MINIUPNPD
341 int enable;
342 FILE *f;
343 int upnp_port;
345 if (((enable = nvram_get_int("upnp_enable")) & 3) != 0) {
346 mkdir("/etc/upnp", 0777);
347 if (f_exists("/etc/upnp/config.alt")) {
348 xstart("miniupnpd", "-f", "/etc/upnp/config.alt");
350 else {
351 if ((f = fopen("/etc/upnp/config", "w")) != NULL) {
352 upnp_port = nvram_get_int("upnp_port");
353 if ((upnp_port <= 0) || (upnp_port >= 0xFFFF)) upnp_port = 5000;
355 fprintf(f,
356 "ext_ifname=%s\n"
357 "listening_ip=%s\n"
358 "port=%d\n"
359 "enable_upnp=%s\n"
360 "enable_natpmp=%s\n"
361 "secure_mode=%s\n"
362 "upnp_forward_chain=upnp\n"
363 "upnp_nat_chain=upnp\n"
364 "system_uptime=yes\n"
365 "\n"
367 nvram_safe_get("wan_iface"),
368 nvram_safe_get("lan_ipaddr"),
369 upnp_port,
370 (enable & 1) ? "yes" : "no", // upnp enable
371 (enable & 2) ? "yes" : "no", // natpmp enable
372 nvram_get_int("upnp_secure") ? "yes" : "no" // secure_mode (only forward to self)
374 fappend(f, "/etc/upnp/config.custom");
375 fclose(f);
377 xstart("miniupnpd", "-f", "/etc/upnp/config");
381 #else
382 if (nvram_get_int("upnp_enable")) {
383 xstart("upnp",
384 "-D",
385 "-L", nvram_safe_get("lan_ifname"),
386 "-W", nvram_safe_get("wan_iface"),
387 "-I", nvram_safe_get("upnp_ssdp_interval"),
388 "-A", nvram_safe_get("upnp_max_age"));
390 #endif
393 void stop_upnp(void)
395 #ifdef USE_MINIUPNPD
396 killall_tk("miniupnpd");
397 #else
398 killall_tk("upnp");
399 #endif
402 // -----------------------------------------------------------------------------
404 static pid_t pid_crond = -1;
406 void start_cron(void)
408 char *argv[] = { "crond", "-l", "9", NULL };
410 stop_cron();
412 if (nvram_contains_word("log_events", "crond")) argv[1] = NULL;
413 _eval(argv, NULL, 0, NULL);
414 if (!nvram_contains_word("debug_norestart", "crond")) {
415 pid_crond = -2;
420 void stop_cron(void)
422 pid_crond = -1;
423 killall_tk("crond");
426 // -----------------------------------------------------------------------------
428 // Written by Sparq in 2002/07/16
429 void start_zebra(void)
431 #ifdef TCONFIG_ZEBRA
432 FILE *fp;
434 char *lan_tx = nvram_safe_get("dr_lan_tx");
435 char *lan_rx = nvram_safe_get("dr_lan_rx");
436 char *wan_tx = nvram_safe_get("dr_wan_tx");
437 char *wan_rx = nvram_safe_get("dr_wan_rx");
439 if ((*lan_tx == '0') && (*lan_rx == '0') && (*wan_tx == '0') && (*wan_rx == '0')) {
440 return;
443 // empty
444 if ((fp = fopen("/etc/zebra.conf", "w")) != NULL) {
445 fclose(fp);
449 if ((fp = fopen("/etc/ripd.conf", "w")) != NULL) {
450 char *lan_ifname = nvram_safe_get("lan_ifname");
451 char *wan_ifname = nvram_safe_get("wan_ifname");
453 fprintf(fp, "router rip\n");
454 fprintf(fp, "network %s\n", lan_ifname);
455 fprintf(fp, "network %s\n", wan_ifname);
456 fprintf(fp, "redistribute connected\n");
457 //fprintf(fp, "redistribute static\n");
459 // 43011: modify by zg 2006.10.18 for cdrouter3.3 item 173(cdrouter_rip_30) bug
460 // fprintf(fp, "redistribute kernel\n"); // 1.11: removed, redistributes indirect -- zzz
462 fprintf(fp, "interface %s\n", lan_ifname);
463 if (*lan_tx != '0') fprintf(fp, "ip rip send version %s\n", lan_tx);
464 if (*lan_rx != '0') fprintf(fp, "ip rip receive version %s\n", lan_rx);
466 fprintf(fp, "interface %s\n", wan_ifname);
467 if (*wan_tx != '0') fprintf(fp, "ip rip send version %s\n", wan_tx);
468 if (*wan_rx != '0') fprintf(fp, "ip rip receive version %s\n", wan_rx);
470 fprintf(fp, "router rip\n");
471 if (*lan_tx == '0') fprintf(fp, "distribute-list private out %s\n", lan_ifname);
472 if (*lan_rx == '0') fprintf(fp, "distribute-list private in %s\n", lan_ifname);
473 if (*wan_tx == '0') fprintf(fp, "distribute-list private out %s\n", wan_ifname);
474 if (*wan_rx == '0') fprintf(fp, "distribute-list private in %s\n", wan_ifname);
475 fprintf(fp, "access-list private deny any\n");
477 //fprintf(fp, "debug rip events\n");
478 //fprintf(fp, "log file /etc/ripd.log\n");
479 fclose(fp);
482 xstart("zebra", "-d", "-f", "/etc/zebra.conf");
483 xstart("ripd", "-d", "-f", "/etc/ripd.conf");
484 #endif
487 void stop_zebra(void)
489 #ifdef TCONFIG_ZEBRA
490 killall("zebra", SIGTERM);
491 killall("ripd", SIGTERM);
493 unlink("/etc/zebra.conf");
494 unlink("/etc/ripd.conf");
495 #endif
498 // -----------------------------------------------------------------------------
500 void start_syslog(void)
502 #if 1
503 char *argv[12];
504 int argc;
505 char *nv;
506 char rem[256];
507 int n;
508 char s[64];
510 argv[0] = "syslogd";
511 argc = 1;
513 if (nvram_match("log_remote", "1")) {
514 nv = nvram_safe_get("log_remoteip");
515 if (*nv) {
516 snprintf(rem, sizeof(rem), "%s:%s", nv, nvram_safe_get("log_remoteport"));
517 argv[argc++] = "-R";
518 argv[argc++] = rem;
522 if (nvram_match("log_file", "1")) {
523 argv[argc++] = "-L";
524 argv[argc++] = "-s";
525 argv[argc++] = "50";
528 if (argc > 1) {
529 argv[argc] = NULL;
530 _eval(argv, NULL, 0, NULL);
531 usleep(500000);
533 argv[0] = "klogd";
534 argv[1] = NULL;
535 _eval(argv, NULL, 0, NULL);
536 usleep(500000);
538 // used to be available in syslogd -m
539 n = nvram_get_int("log_mark");
540 if (n > 0) {
541 sprintf(s, "cru a syslogdmark \"%s %s * * * logger -p syslog.info -- -- MARK --\"",
542 (n < 60) ? "*/30" : "0", (n < 120) ? "*" : "*/2");
543 system(s);
545 else {
546 system("cru d syslogdmark");
550 #else
551 char *argv[12];
552 int argc;
553 char *nv;
554 char rem[256];
556 argv[0] = "syslogd";
557 argv[1] = "-m";
558 argv[2] = nvram_get("log_mark");
559 argc = 3;
561 if (nvram_match("log_remote", "1")) {
562 nv = nvram_safe_get("log_remoteip");
563 if (*nv) {
564 snprintf(rem, sizeof(rem), "%s:%s", nv, nvram_safe_get("log_remoteport"));
565 argv[argc++] = "-R";
566 argv[argc++] = rem;
570 if (nvram_match("log_file", "1")) {
571 argv[argc++] = "-L";
572 argv[argc++] = "-s";
573 argv[argc++] = "50";
576 if (argc > 3) {
577 argv[argc] = NULL;
578 _eval(argv, NULL, 0, NULL);
579 usleep(500000);
581 argv[0] = "klogd";
582 argv[1] = NULL;
583 _eval(argv, NULL, 0, NULL);
584 usleep(500000);
586 #endif
589 void stop_syslog(void)
591 killall("klogd", SIGTERM);
592 killall("syslogd", SIGTERM);
595 // -----------------------------------------------------------------------------
597 static pid_t pid_igmp = -1;
599 void start_igmp_proxy(void)
601 static char *igmpproxy_conf = "/etc/igmpproxy.conf";
602 FILE *fp;
603 char *p;
605 pid_igmp = -1;
606 if (nvram_match("multicast_pass", "1")) {
607 switch (get_wan_proto()) {
608 case WP_PPPOE:
609 case WP_PPTP:
610 case WP_L2TP:
611 p = "wan_iface";
612 break;
613 default:
614 p = "wan_ifname";
615 break;
618 if ((fp = fopen(igmpproxy_conf, "w")) != NULL) {
619 fprintf(fp,
620 "quickleave\n"
621 "phyint %s upstream\n"
622 "\taltnet %s\n"
623 "phyint %s downstream ratelimit 0\n",
624 nvram_safe_get(p),
625 nvram_get("multicast_altnet") ? : "0.0.0.0/0",
626 nvram_safe_get("lan_ifname") ? : "br0");
627 fclose(fp);
628 xstart("igmpproxy", igmpproxy_conf);
630 if (!nvram_contains_word("debug_norestart", "igmprt")) {
631 pid_igmp = -2;
637 void stop_igmp_proxy(void)
639 pid_igmp = -1;
640 killall("igmpproxy", SIGTERM);
644 // -----------------------------------------------------------------------------
646 void set_tz(void)
648 f_write_string("/etc/TZ", nvram_safe_get("tm_tz"), FW_CREATE|FW_NEWLINE, 0644);
651 void start_ntpc(void)
653 set_tz();
655 stop_ntpc();
657 if (nvram_get_int("ntp_updates") >= 0) {
658 xstart("ntpsync", "--init");
662 void stop_ntpc(void)
664 killall("ntpsync", SIGTERM);
667 // -----------------------------------------------------------------------------
669 static void stop_rstats(void)
671 int n;
672 int pid;
674 n = 60;
675 while ((n-- > 0) && ((pid = pidof("rstats")) > 0)) {
676 if (kill(pid, SIGTERM) != 0) break;
677 sleep(1);
681 static void start_rstats(int new)
683 if (nvram_match("rstats_enable", "1")) {
684 stop_rstats();
685 if (new) xstart("rstats", "--new");
686 else xstart("rstats");
690 // -----------------------------------------------------------------------------
692 // !!TB - FTP Server
695 * Return non-zero if we created the directory,
696 * and zero if it already existed.
698 int mkdir_if_none(char *dir)
700 DIR *dp;
701 if (!(dp=opendir(dir))) {
702 umask(0000);
703 mkdir(dir, 0777);
704 return 1;
706 closedir(dp);
707 return 0;
710 char *get_full_storage_path(char *val)
712 static char buf[128];
713 int len;
715 if (val[0] == '/')
716 len = sprintf(buf, "%s", val);
717 else
718 len = sprintf(buf, "%s/%s", MOUNT_ROOT, val);
720 if (len > 1 && buf[len - 1] == '/')
721 buf[len - 1] = 0;
723 return buf;
726 char *nvram_storage_path(char *var)
728 char *val = nvram_safe_get(var);
729 return get_full_storage_path(val);
732 #ifdef TCONFIG_FTP
734 char vsftpd_conf[] = "/etc/vsftpd.conf";
735 char vsftpd_users[] = "/etc/vsftpd.users";
736 char vsftpd_passwd[] = "/etc/vsftpd.passwd";
737 #endif
739 #ifdef TCONFIG_FTP
740 /* VSFTPD code mostly stolen from Oleg's ASUS Custom Firmware GPL sources */
741 static void do_start_stop_ftpd(int stop, int start)
743 if (stop) killall("vsftpd", SIGTERM);
745 char tmp[256];
746 FILE *fp, *f;
748 if (!start || !nvram_get_int("ftp_enable")) return;
750 mkdir_if_none(vsftpd_users);
751 mkdir_if_none("/var/run/vsftpd");
753 if ((fp = fopen(vsftpd_conf, "w")) == NULL)
754 return;
756 if (nvram_get_int("ftp_super"))
758 /* rights */
759 sprintf(tmp, "%s/%s", vsftpd_users, "admin");
760 if ((f = fopen(tmp, "w")))
762 fprintf(f,
763 "dirlist_enable=yes\n"
764 "write_enable=yes\n"
765 "download_enable=yes\n");
766 fclose(f);
770 #ifdef TCONFIG_SAMBASRV
771 if (nvram_match("smbd_cset", "utf8"))
772 fprintf(fp, "utf8=yes\n");
773 #endif
775 if (nvram_invmatch("ftp_anonymous", "0"))
777 fprintf(fp,
778 "anon_allow_writable_root=yes\n"
779 "anon_world_readable_only=no\n"
780 "anon_umask=022\n");
782 /* rights */
783 sprintf(tmp, "%s/ftp", vsftpd_users);
784 if ((f = fopen(tmp, "w")))
786 if (nvram_match("ftp_dirlist", "0"))
787 fprintf(f, "dirlist_enable=yes\n");
788 if (nvram_match("ftp_anonymous", "1") ||
789 nvram_match("ftp_anonymous", "3"))
790 fprintf(f, "write_enable=yes\n");
791 if (nvram_match("ftp_anonymous", "1") ||
792 nvram_match("ftp_anonymous", "2"))
793 fprintf(f, "download_enable=yes\n");
794 fclose(f);
796 if (nvram_match("ftp_anonymous", "1") ||
797 nvram_match("ftp_anonymous", "3"))
798 fprintf(fp,
799 "anon_upload_enable=yes\n"
800 "anon_mkdir_write_enable=yes\n"
801 "anon_other_write_enable=yes\n");
802 } else {
803 fprintf(fp, "anonymous_enable=no\n");
806 fprintf(fp,
807 "dirmessage_enable=yes\n"
808 "download_enable=no\n"
809 "dirlist_enable=no\n"
810 "hide_ids=yes\n"
811 "syslog_enable=yes\n"
812 "local_enable=yes\n"
813 "local_umask=022\n"
814 "chmod_enable=no\n"
815 "chroot_local_user=yes\n"
816 "check_shell=no\n"
817 "user_config_dir=%s\n"
818 "passwd_file=%s\n",
819 vsftpd_users, vsftpd_passwd);
821 if (nvram_get_int("log_ftp")) {
822 fprintf(fp, "log_ftp_protocol=yes\n");
824 else {
825 fprintf(fp, "log_ftp_protocol=no\n");
828 fprintf(fp, "listen=yes\nlisten_port=%s\nbackground=yes\n",
829 nvram_get("ftp_port") ? : "21");
830 fprintf(fp, "max_clients=%s\n", nvram_get("ftp_max") ? : "0");
831 fprintf(fp, "max_per_ip=%s\n", nvram_get("ftp_ipmax") ? : "0");
832 fprintf(fp, "idle_session_timeout=%s\n", nvram_get("ftp_staytimeout") ? : "300");
833 fprintf(fp, "use_sendfile=no\n");
834 //fprintf(fp, "ftpd_banner=Welcome to the %s FTP service.\n", nvram_get("t_model_name") ? : "router");
836 /* bandwidth */
837 fprintf(fp, "anon_max_rate=%d\nlocal_max_rate=%d\n",
838 atoi(nvram_safe_get("ftp_anonrate")) * 1024,
839 atoi(nvram_safe_get("ftp_rate")) * 1024);
841 fprintf(fp, "%s\n\n", nvram_safe_get("ftp_custom"));
843 fclose(fp);
845 /* prepare passwd file and default users */
846 if ((fp = fopen(vsftpd_passwd, "w")) == NULL)
847 return;
849 fprintf(fp, /* anonymous, admin, nobody */
850 "ftp:x:0:0:ftp:%s:/sbin/nologin\n"
851 "%s:%s:0:0:root:/:/sbin/nologin\n"
852 "nobody:x:65534:65534:nobody:%s/:/sbin/nologin\n",
853 nvram_storage_path("ftp_anonroot"), "admin",
854 nvram_get_int("ftp_super") ? crypt(nvram_safe_get("http_passwd"), "$1$") : "x",
855 MOUNT_ROOT);
857 char *buf;
858 char *p, *q;
859 char *user, *pass, *rights;
861 if ((buf = strdup(nvram_safe_get("ftp_users"))) != NULL)
864 username<password<rights
865 rights:
866 Read/Write
867 Read Only
868 View Only
869 Private
871 p = buf;
872 while ((q = strsep(&p, ">")) != NULL) {
873 if (vstrsep(q, "<", &user, &pass, &rights) != 3) continue;
874 if (!user || !pass) continue;
876 /* directory */
877 if (strncmp(rights, "Private", 7) == 0)
879 sprintf(tmp, "%s/%s", nvram_storage_path("ftp_pvtroot"), user);
880 mkdir_if_none(tmp);
882 else
883 sprintf(tmp, "%s", nvram_storage_path("ftp_pubroot"));
885 fprintf(fp, "%s:%s:0:0:%s:%s:/sbin/nologin\n",
886 user, crypt(pass, "$1$"), user, tmp);
888 /* rights */
889 sprintf(tmp, "%s/%s", vsftpd_users, user);
890 if ((f = fopen(tmp, "w")))
892 tmp[0] = 0;
893 if (nvram_invmatch("ftp_dirlist", "1"))
894 strcat(tmp, "dirlist_enable=yes\n");
895 if (strstr(rights, "Read") || !strcmp(rights, "Private"))
896 strcat(tmp, "download_enable=yes\n");
897 if (strstr(rights, "Write") || !strncmp(rights, "Private", 7))
898 strcat(tmp, "write_enable=yes\n");
900 fputs(tmp, f);
901 fclose(f);
904 free(buf);
907 fclose(fp);
908 killall("vsftpd", SIGHUP);
910 /* start vsftpd if it's not already running */
911 if (pidof("vsftpd") <= 0)
912 eval("vsftpd");
914 #endif
916 void start_ftpd(void)
918 #ifdef TCONFIG_FTP
919 int fd = file_lock("usb");
920 do_start_stop_ftpd(0, 1);
921 file_unlock(fd);
922 #endif
925 void stop_ftpd(void)
927 #ifdef TCONFIG_FTP
928 int fd = file_lock("usb");
929 do_start_stop_ftpd(1, 0);
930 unlink(vsftpd_passwd);
931 unlink(vsftpd_conf);
932 eval("rm", "-rf", vsftpd_users);
933 file_unlock(fd);
934 #endif
937 // -----------------------------------------------------------------------------
939 // !!TB - Samba
941 #ifdef TCONFIG_SAMBASRV
942 void kill_samba(int sig)
944 killall("smbd", sig);
945 killall("nmbd", sig);
947 #endif
949 #ifdef TCONFIG_SAMBASRV
950 static void do_start_stop_samba(int stop, int start)
952 if (stop) kill_samba(SIGTERM);
954 FILE *fp;
955 DIR *dir = NULL;
956 struct dirent *dp;
957 char nlsmod[15];
958 int mode;
960 mode = nvram_get_int("smbd_enable");
961 if (!start || !mode || !nvram_invmatch("lan_hostname", ""))
962 return;
964 if ((fp = fopen("/etc/smb.conf", "w")) == NULL)
965 return;
967 fprintf(fp, "[global]\n"
968 " interfaces = %s\n"
969 " bind interfaces only = yes\n"
970 " workgroup = %s\n"
971 " server string = %s\n"
972 " guest account = nobody\n"
973 " security = %s\n"
974 " browseable = yes\n"
975 " guest ok = yes\n"
976 " guest only = no\n"
977 " log level = %d\n"
978 " syslog only = yes\n"
979 " syslog = 1\n"
980 " encrypt passwords = yes\n"
981 " preserve case = yes\n"
982 " short preserve case = yes\n",
983 nvram_get("lan_ifname") ? : "br0",
984 nvram_get("smbd_wgroup") ? : "WORKGROUP",
985 nvram_get("router_name") ? : "Tomato",
986 mode == 2 ? "user" : "share",
987 nvram_get_int("smbd_loglevel")
990 if (nvram_invmatch("smbd_master", "")) {
991 char *master = nvram_get_int("smbd_master") ? "yes" : "no";
992 fprintf(fp,
993 " local master = %s\n"
994 " preferred master = %s\n",
995 master, master);
998 if (nvram_invmatch("smbd_cpage", "")) {
999 char *cp = nvram_get("smbd_cpage");
1001 fprintf(fp, " client code page = %s\n", cp);
1002 sprintf(nlsmod, "nls_cp%s", cp);
1004 cp = nvram_get("smbd_nlsmod");
1005 if ((cp) && (*cp != 0) && (strcmp(cp, nlsmod) != 0))
1006 modprobe_r(cp);
1008 modprobe(nlsmod);
1009 nvram_set("smbd_nlsmod", nlsmod);
1012 if (nvram_match("smbd_cset", "utf8"))
1013 fprintf(fp, " coding system = utf8\n");
1014 else if (nvram_invmatch("smbd_cset", ""))
1015 fprintf(fp, " character set = %s\n", nvram_get("smbd_cset"));
1017 fprintf(fp, "%s\n\n", nvram_safe_get("smbd_custom"));
1019 /* configure shares */
1021 char *buf;
1022 char *p, *q;
1023 char *name, *path, *comment, *writeable, *hidden;
1024 int cnt = 0;
1026 if ((buf = strdup(nvram_safe_get("smbd_shares"))) != NULL)
1028 /* sharename<path<comment<writeable[0|1]<hidden[0|1] */
1030 p = buf;
1031 while ((q = strsep(&p, ">")) != NULL) {
1032 if (vstrsep(q, "<", &name, &path, &comment, &writeable, &hidden) != 5) continue;
1033 if (!path || !name) continue;
1035 /* share name */
1036 fprintf(fp, "\n[%s]\n", name);
1038 /* path */
1039 fprintf(fp, " path = %s\n", path);
1041 /* access level */
1042 if (!strcmp(writeable, "1"))
1043 fprintf(fp, " writable = yes\n force user = %s\n", "root");
1044 if (!strcmp(hidden, "1"))
1045 fprintf(fp, " browseable = no\n");
1047 /* comment */
1048 if (comment)
1049 fprintf(fp, " comment = %s\n", comment);
1051 cnt++;
1053 free(buf);
1056 /* share everything below MOUNT_ROOT */
1057 if (nvram_get_int("smbd_autoshare") && (dir = opendir(MOUNT_ROOT))) {
1058 while ((dp = readdir(dir))) {
1059 if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
1061 /* smbd_autoshare: 0 - disable, 1 - read-only, 2 - writable, 3 - hidden writable */
1062 fprintf(fp, "\n[%s]\n path = %s/%s\n comment = %s\n",
1063 dp->d_name, MOUNT_ROOT, dp->d_name, dp->d_name);
1064 if (nvram_match("smbd_autoshare", "3")) // Hidden
1065 fprintf(fp, "\n[%s$]\n path = %s/%s\n browseable = no\n",
1066 dp->d_name, MOUNT_ROOT, dp->d_name);
1067 if (nvram_match("smbd_autoshare", "2") || nvram_match("smbd_autoshare", "3")) // RW
1068 fprintf(fp, " writable = yes\n force user = %s\n", "root");
1070 cnt++;
1074 if (dir) closedir(dir);
1076 if (cnt == 0) {
1077 /* by default share MOUNT_ROOT as read-only */
1078 fprintf(fp, "\n[share]\n"
1079 " path = %s\n"
1080 " writable = no\n",
1081 MOUNT_ROOT);
1084 fclose(fp);
1086 mkdir_if_none("/var/run/samba");
1087 mkdir_if_none("/etc/samba");
1089 /* write smbpasswd */
1090 eval("smbpasswd", "-a", "nobody", "\"\"");
1091 if (mode == 2) {
1092 char *smbd_user;
1093 if (((smbd_user = nvram_get("smbd_user")) == NULL) || (*smbd_user == 0) || !strcmp(smbd_user, "root"))
1094 smbd_user = "nas";
1095 eval("smbpasswd", "-a", smbd_user, nvram_safe_get("smbd_passwd"));
1098 kill_samba(SIGHUP);
1099 int ret1 = 0, ret2 = 0;
1100 /* start samba if it's not already running */
1101 if (pidof("nmbd") <= 0)
1102 ret1 = eval("nmbd", "-D");
1103 if (pidof("smbd") <= 0)
1104 ret2 = eval("smbd", "-D");
1106 if (ret1 || ret2) kill_samba(SIGTERM);
1108 #endif
1110 void start_samba(void)
1112 #ifdef TCONFIG_SAMBASRV
1113 int fd = file_lock("usb");
1114 do_start_stop_samba(0, 1);
1115 file_unlock(fd);
1116 #endif
1119 void stop_samba(void)
1121 #ifdef TCONFIG_SAMBASRV
1122 int fd = file_lock("usb");
1123 do_start_stop_samba(1, 0);
1124 sleep(2); /* wait for smbd to finish */
1126 if (nvram_invmatch("smbd_nlsmod", "")) {
1127 modprobe_r(nvram_get("smbd_nlsmod"));
1128 nvram_set("smbd_nlsmod", "");
1131 /* clean up */
1132 unlink("/var/log/smb");
1133 unlink("/var/log/nmb");
1134 eval("rm", "-rf", "/var/run/samba");
1135 file_unlock(fd);
1136 #endif
1139 void restart_nas_services(int start)
1141 /* restart all NAS applications */
1142 #if TCONFIG_SAMBASRV || TCONFIG_FTP
1143 int fd = file_lock("usb");
1144 #ifdef TCONFIG_SAMBASRV
1145 if (start && nvram_get_int("smbd_enable"))
1146 do_start_stop_samba(0, 1);
1147 else
1148 do_start_stop_samba(1, 0);
1149 #endif
1150 #ifdef TCONFIG_FTP
1151 if (start && nvram_get_int("ftp_enable"))
1152 do_start_stop_ftpd(0, 1);
1153 else
1154 do_start_stop_ftpd(1, 0);
1155 #endif
1156 file_unlock(fd);
1157 #endif // TCONFIG_SAMBASRV || TCONFIG_FTP
1160 // -----------------------------------------------------------------------------
1162 static void _check(pid_t *pid, const char *name, void (*func)(void) )
1164 if (*pid != -1) {
1165 if (kill(*pid, 0) != 0) {
1166 if ((*pid = pidof(name)) == -1) func();
1171 void check_services(void)
1173 _check(&pid_dnsmasq, "dnsmasq", start_dnsmasq);
1174 _check(&pid_crond, "crond", start_cron);
1175 _check(&pid_igmp, "igmpproxy", start_igmp_proxy);
1178 // -----------------------------------------------------------------------------
1180 void start_services(void)
1182 static int once = 1;
1184 if (once) {
1185 once = 0;
1187 create_passwd();
1188 if (nvram_get_int("telnetd_eas")) start_telnetd();
1189 if (nvram_get_int("sshd_eas")) start_sshd();
1192 start_syslog();
1193 #if TOMATO_SL
1194 start_usbevent();
1195 #endif
1196 start_nas();
1197 start_zebra();
1198 start_dnsmasq();
1199 start_cifs();
1200 start_httpd();
1201 start_cron();
1202 start_upnp();
1203 start_rstats(0);
1204 start_sched();
1205 #ifdef TCONFIG_SAMBA
1206 start_smbd();
1207 #endif
1208 start_samba(); // !!TB - Samba
1209 start_ftpd(); // !!TB - FTP Server
1212 void stop_services(void)
1214 clear_resolv();
1216 stop_ftpd(); // !!TB - FTP Server
1217 stop_samba(); // !!TB - Samba
1218 #ifdef TCONFIG_SAMBA
1219 stop_smbd();
1220 #endif
1221 stop_sched();
1222 stop_rstats();
1223 stop_upnp();
1224 stop_cron();
1225 stop_httpd();
1226 stop_cifs();
1227 stop_dnsmasq();
1228 stop_zebra();
1229 stop_nas();
1230 #if TOMATO_SL
1231 stop_usbevent();
1232 #endif
1233 stop_syslog();
1236 // -----------------------------------------------------------------------------
1238 void exec_service(void)
1240 const int A_START = 1;
1241 const int A_STOP = 2;
1242 const int A_RESTART = 1|2;
1243 char buffer[128];
1244 char *service;
1245 char *act;
1246 char *next;
1247 int action;
1248 int i;
1250 strlcpy(buffer, nvram_safe_get("action_service"), sizeof(buffer));
1251 next = buffer;
1253 TOP:
1254 act = strsep(&next, ",");
1255 service = strsep(&act, "-");
1256 if (act == NULL) {
1257 next = NULL;
1258 goto CLEAR;
1261 TRACE_PT("service=%s action=%s\n", service, act);
1263 if (strcmp(act, "start") == 0) action = A_START;
1264 else if (strcmp(act, "stop") == 0) action = A_STOP;
1265 else if (strcmp(act, "restart") == 0) action = A_RESTART;
1266 else action = 0;
1269 if (strcmp(service, "dhcpc") == 0) {
1270 if (action & A_STOP) stop_dhcpc();
1271 if (action & A_START) start_dhcpc();
1272 goto CLEAR;
1275 if ((strcmp(service, "dhcpd") == 0) || (strcmp(service, "dns") == 0) || (strcmp(service, "dnsmasq") == 0)) {
1276 if (action & A_STOP) stop_dnsmasq();
1277 if (action & A_START) {
1278 dns_to_resolv();
1279 start_dnsmasq();
1281 goto CLEAR;
1284 if (strcmp(service, "firewall") == 0) {
1285 if (action & A_STOP) {
1286 stop_firewall();
1287 stop_igmp_proxy();
1289 if (action & A_START) {
1290 start_firewall();
1291 start_igmp_proxy();
1293 goto CLEAR;
1296 if (strcmp(service, "restrict") == 0) {
1297 if (action & A_STOP) {
1298 stop_firewall();
1300 if (action & A_START) {
1301 i = nvram_get_int("rrules_radio"); // -1 = not used, 0 = enabled by rule, 1 = disabled by rule
1303 start_firewall();
1305 // if radio was disabled by access restriction, but no rule is handling it now, enable it
1306 if (i == 1) {
1307 if (nvram_get_int("rrules_radio") < 0) {
1308 if (!get_radio()) eval("radio", "on");
1312 goto CLEAR;
1315 if (strcmp(service, "qos") == 0) {
1316 if (action & A_STOP) {
1317 stop_qos();
1319 stop_firewall(); start_firewall(); // always restarted
1320 if (action & A_START) {
1321 start_qos();
1322 if (nvram_match("qos_reset", "1")) f_write_string("/proc/net/clear_marks", "1", 0, 0);
1324 goto CLEAR;
1327 if (strcmp(service, "upnp") == 0) {
1328 if (action & A_STOP) {
1329 stop_upnp();
1331 stop_firewall(); start_firewall(); // always restarted
1332 if (action & A_START) {
1333 start_upnp();
1335 goto CLEAR;
1338 if (strcmp(service, "telnetd") == 0) {
1339 if (action & A_STOP) stop_telnetd();
1340 if (action & A_START) start_telnetd();
1341 goto CLEAR;
1344 if (strcmp(service, "sshd") == 0) {
1345 if (action & A_STOP) stop_sshd();
1346 if (action & A_START) start_sshd();
1347 goto CLEAR;
1350 if (strcmp(service, "httpd") == 0) {
1351 if (action & A_STOP) stop_httpd();
1352 if (action & A_START) start_httpd();
1353 goto CLEAR;
1356 if (strcmp(service, "admin") == 0) {
1357 if (action & A_STOP) {
1358 stop_sshd();
1359 stop_telnetd();
1360 stop_httpd();
1362 stop_firewall(); start_firewall(); // always restarted
1363 if (action & A_START) {
1364 start_httpd();
1365 create_passwd();
1366 if (nvram_match("telnetd_eas", "1")) start_telnetd();
1367 if (nvram_match("sshd_eas", "1")) start_sshd();
1369 goto CLEAR;
1372 if (strcmp(service, "ddns") == 0) {
1373 if (action & A_STOP) stop_ddns();
1374 if (action & A_START) start_ddns();
1375 goto CLEAR;
1378 if (strcmp(service, "ntpc") == 0) {
1379 if (action & A_STOP) stop_ntpc();
1380 if (action & A_START) start_ntpc();
1381 goto CLEAR;
1384 if (strcmp(service, "logging") == 0) {
1385 if (action & A_STOP) {
1386 stop_syslog();
1387 stop_cron();
1389 stop_firewall(); start_firewall(); // always restarted
1390 if (action & A_START) {
1391 start_cron();
1392 start_syslog();
1394 goto CLEAR;
1397 if (strcmp(service, "crond") == 0) {
1398 if (action & A_STOP) {
1399 stop_cron();
1401 if (action & A_START) {
1402 start_cron();
1404 goto CLEAR;
1407 if (strcmp(service, "upgrade") == 0) {
1408 if (action & A_START) {
1409 #if TOMATO_SL
1410 stop_usbevent();
1411 stop_smbd();
1412 #endif
1413 stop_ftpd(); // !!TB - FTP Server
1414 stop_samba(); // !!TB - Samba
1415 stop_jffs2();
1416 // stop_cifs();
1417 stop_zebra();
1418 stop_cron();
1419 stop_ntpc();
1420 stop_upnp();
1421 // stop_dhcpc();
1422 killall("rstats", SIGTERM);
1423 killall("buttons", SIGTERM);
1424 stop_syslog();
1425 remove_storage_main(); // !!TB - USB Support
1426 stop_usb(); // !!TB - USB Support
1428 goto CLEAR;
1431 #ifdef TCONFIG_CIFS
1432 if (strcmp(service, "cifs") == 0) {
1433 if (action & A_STOP) stop_cifs();
1434 if (action & A_START) start_cifs();
1435 goto CLEAR;
1437 #endif
1439 #ifdef TCONFIG_JFFS2
1440 if (strcmp(service, "jffs2") == 0) {
1441 if (action & A_STOP) stop_jffs2();
1442 if (action & A_START) start_jffs2();
1443 goto CLEAR;
1445 #endif
1447 if (strcmp(service, "routing") == 0) {
1448 if (action & A_STOP) {
1449 stop_zebra();
1450 do_static_routes(0); // remove old '_saved'
1451 eval("brctl", "stp", nvram_safe_get("lan_ifname"), "0");
1453 stop_firewall();
1454 start_firewall();
1455 if (action & A_START) {
1456 do_static_routes(1); // add new
1457 start_zebra();
1458 eval("brctl", "stp", nvram_safe_get("lan_ifname"), nvram_safe_get("lan_stp"));
1460 goto CLEAR;
1463 if (strcmp(service, "ctnf") == 0) {
1464 if (action & A_START) {
1465 setup_conntrack();
1466 stop_firewall();
1467 start_firewall();
1469 goto CLEAR;
1472 if (strcmp(service, "wan") == 0) {
1473 if (action & A_STOP) {
1474 if (get_wan_proto() == WP_PPPOE) {
1475 stop_dnsmasq();
1476 stop_redial();
1477 stop_singe_pppoe(PPPOE0);
1478 if (((action & A_START) == 0) && (nvram_match("ppp_demand", "1"))) {
1479 sleep(1);
1480 start_pppoe(PPPOE0);
1482 start_dnsmasq();
1484 else {
1485 stop_wan();
1489 if (action & A_START) {
1490 rename("/tmp/ppp/log", "/tmp/ppp/log.~");
1492 if (get_wan_proto() == WP_PPPOE) {
1493 stop_singe_pppoe(PPPOE0);
1494 start_pppoe(PPPOE0);
1495 if (nvram_invmatch("ppp_demand", "1")) {
1496 start_redial();
1499 else {
1500 start_wan(BOOT);
1502 sleep(2);
1503 force_to_dial();
1505 goto CLEAR;
1508 if (strcmp(service, "net") == 0) {
1509 if (action & A_STOP) {
1510 stop_wan();
1511 stop_lan();
1512 stop_vlan();
1514 if (action & A_START) {
1515 start_vlan();
1516 start_lan();
1517 start_wan(BOOT);
1519 goto CLEAR;
1522 if (strcmp(service, "rstats") == 0) {
1523 if (action & A_STOP) stop_rstats();
1524 if (action & A_START) start_rstats(0);
1525 goto CLEAR;
1528 if (strcmp(service, "rstatsnew") == 0) {
1529 if (action & A_STOP) stop_rstats();
1530 if (action & A_START) start_rstats(1);
1531 goto CLEAR;
1534 if (strcmp(service, "sched") == 0) {
1535 if (action & A_STOP) stop_sched();
1536 if (action & A_START) start_sched();
1537 goto CLEAR;
1540 // !!TB - USB Support
1541 if (strcmp(service, "usb") == 0) {
1542 if (action & A_STOP) stop_usb();
1543 if (action & A_START) {
1544 start_usb();
1545 // restart Samba and ftp since they may be killed by stop_usb()
1546 restart_nas_services(1);
1548 goto CLEAR;
1551 #ifdef TCONFIG_FTP
1552 // !!TB - FTP Server
1553 if (strcmp(service, "ftpd") == 0) {
1554 if (action & A_STOP) stop_ftpd();
1555 setup_conntrack();
1556 stop_firewall();
1557 start_firewall();
1558 if (action & A_START) start_ftpd();
1559 goto CLEAR;
1561 #endif
1563 #ifdef TCONFIG_SAMBASRV
1564 // !!TB - Samba
1565 if (strcmp(service, "samba") == 0) {
1566 if (action & A_STOP) stop_samba();
1567 if (action & A_START) {
1568 create_passwd();
1569 start_samba();
1571 goto CLEAR;
1573 #endif
1575 CLEAR:
1576 if (next) goto TOP;
1578 // some functions check action_service and must be cleared at end -- zzz
1579 nvram_set("action_service", "");
1582 static void do_service(const char *name, const char *action, int user)
1584 int n;
1585 char s[64];
1587 n = 15;
1588 while (!nvram_match("action_service", "")) {
1589 if (user) {
1590 putchar('*');
1591 fflush(stdout);
1593 else if (--n < 0) break;
1594 sleep(1);
1597 snprintf(s, sizeof(s), "%s-%s", name, action);
1598 nvram_set("action_service", s);
1599 kill(1, SIGUSR1);
1601 n = 15;
1602 while (nvram_match("action_service", s)) {
1603 if (user) {
1604 putchar('.');
1605 fflush(stdout);
1607 else if (--n < 0) {
1608 break;
1610 sleep(1);
1614 int service_main(int argc, char *argv[])
1616 if (argc != 3) usage_exit(argv[0], "<service> <action>");
1617 do_service(argv[1], argv[2], 1);
1618 printf("\nDone.\n");
1619 return 0;
1622 void start_service(const char *name)
1624 do_service(name, "start", 0);
1627 void stop_service(const char *name)
1629 do_service(name, "stop", 0);
1633 void restart_service(const char *name)
1635 do_service(name, "restart", 0);